Goでpingコマンドを書いてみた

最近読んだUNIX Network Programmingに触発されてpingコマンドを書いてみた。

ping command in golang, just for fun

本家pingと違って、統計情報とかは保存していない。MessageのPack/Unpack周りの実装はnet/dnsmsg.goをかなり参考にしている。

Linux環境で実行してみる。Raw socketを使っているので、実行にはroot権限が必要。

# go run ping.go golang.org
23 bytes from 216.58.197.177: seq=1, ttl=61, rtt=10.816086ms
23 bytes from 172.217.25.241: seq=2, ttl=61, rtt=10.120621ms
23 bytes from 216.58.197.177: seq=3, ttl=61, rtt=8.431578ms

一応tcpdumpを確認してみる。

# tcpdump -v icmp
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
10:02:34.835872 IP (tos 0x0, ttl 64, id 23326, offset 0, flags [DF], proto ICMP (1), length 43)
    6f3d0f1790c6 > nrt12s02-in-f177.1e100.net: ICMP echo request, id 1531, seq 1, length 23
10:02:34.845779 IP (tos 0x0, ttl 61, id 17225, offset 0, flags [DF], proto ICMP (1), length 43)
    nrt12s02-in-f177.1e100.net > 6f3d0f1790c6: ICMP echo reply, id 1531, seq 1, length 23

DFビットがONになっているのが謎だったけど、これはpath mtu discoveryをしているためらしい。試しにnet.ipv4.ip_no_pmtu_disc=1 にしたらOFFになった。TCPじゃなくてもdiscoveryするんだね。