1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
6 // TODO(cw): ListenPacket test, Read() test, ipv6 test &
7 // Dial()/Listen() level tests
18 const ICMP_ECHO_REQUEST
= 8
19 const ICMP_ECHO_REPLY
= 0
21 // returns a suitable 'ping request' packet, with id & seq and a
22 // payload length of pktlen
23 func makePingRequest(id
, seq
, pktlen
int, filler
[]byte) []byte {
24 p
:= make([]byte, pktlen
)
25 copy(p
[8:], bytes
.Repeat(filler
, (pktlen
-8)/len(filler
)+1))
27 p
[0] = ICMP_ECHO_REQUEST
// type
31 p
[4] = uint8(id
>> 8) // id
32 p
[5] = uint8(id
& 0xff) // id
33 p
[6] = uint8(seq
>> 8) // sequence
34 p
[7] = uint8(seq
& 0xff) // sequence
36 // calculate icmp checksum
39 for i
:= 0; i
< (cklen
- 1); i
+= 2 {
40 s
+= uint32(p
[i
+1])<<8 |
uint32(p
[i
])
43 s
+= uint32(p
[cklen
-1])
45 s
= (s
>> 16) + (s
& 0xffff)
48 // place checksum back in header; using ^= avoids the
49 // assumption the checksum bytes are zero
50 p
[2] ^= uint8(^s
& 0xff)
51 p
[3] ^= uint8(^s
>> 8)
56 func parsePingReply(p
[]byte) (id
, seq
int) {
57 id
= int(p
[4])<<8 |
int(p
[5])
58 seq
= int(p
[6])<<8 |
int(p
[7])
62 var srchost
= flag
.String("srchost", "", "Source of the ICMP ECHO request")
63 var dsthost
= flag
.String("dsthost", "localhost", "Destination for the ICMP ECHO request")
65 // test (raw) IP socket using ICMP
66 func TestICMP(t
*testing
.T
) {
68 t
.Logf("test disabled; must be root")
74 laddr
, err
:= ResolveIPAddr(*srchost
)
76 t
.Fatalf(`net.ResolveIPAddr("%v") = %v, %v`, *srchost
, laddr
, err
)
80 raddr
, err
:= ResolveIPAddr(*dsthost
)
82 t
.Fatalf(`net.ResolveIPAddr("%v") = %v, %v`, *dsthost
, raddr
, err
)
85 c
, err
:= ListenIP("ip4:icmp", laddr
)
87 t
.Fatalf(`net.ListenIP("ip4:icmp", %v) = %v, %v`, *srchost
, c
, err
)
90 sendid
:= os
.Getpid() & 0xffff
92 const pingpktlen
= 128
93 sendpkt
:= makePingRequest(sendid
, sendseq
, pingpktlen
, []byte("Go Go Gadget Ping!!!"))
95 n
, err
:= c
.WriteToIP(sendpkt
, raddr
)
96 if err
!= nil || n
!= pingpktlen
{
97 t
.Fatalf(`net.WriteToIP(..., %v) = %v, %v`, raddr
, n
, err
)
101 resp
:= make([]byte, 1024)
103 n
, from
, err
:= c
.ReadFrom(resp
)
105 t
.Fatalf(`ReadFrom(...) = %v, %v, %v`, n
, from
, err
)
107 if resp
[0] != ICMP_ECHO_REPLY
{
110 rcvid
, rcvseq
:= parsePingReply(resp
)
111 if rcvid
!= sendid || rcvseq
!= sendseq
{
112 t
.Fatalf(`Ping reply saw id,seq=0x%x,0x%x (expected 0x%x, 0x%x)`, rcvid
, rcvseq
, sendid
, sendseq
)
116 t
.Fatalf("saw no ping return")