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.
17 type resolveIPAddrTest
struct {
24 var resolveIPAddrTests
= []resolveIPAddrTest
{
25 {"ip", "127.0.0.1", &IPAddr
{IP
: IPv4(127, 0, 0, 1)}, nil},
26 {"ip4", "127.0.0.1", &IPAddr
{IP
: IPv4(127, 0, 0, 1)}, nil},
27 {"ip4:icmp", "127.0.0.1", &IPAddr
{IP
: IPv4(127, 0, 0, 1)}, nil},
29 {"ip", "::1", &IPAddr
{IP
: ParseIP("::1")}, nil},
30 {"ip6", "::1", &IPAddr
{IP
: ParseIP("::1")}, nil},
31 {"ip6:ipv6-icmp", "::1", &IPAddr
{IP
: ParseIP("::1")}, nil},
33 {"ip", "::1%en0", &IPAddr
{IP
: ParseIP("::1"), Zone
: "en0"}, nil},
34 {"ip6", "::1%911", &IPAddr
{IP
: ParseIP("::1"), Zone
: "911"}, nil},
36 {"", "127.0.0.1", &IPAddr
{IP
: IPv4(127, 0, 0, 1)}, nil}, // Go 1.0 behavior
37 {"", "::1", &IPAddr
{IP
: ParseIP("::1")}, nil}, // Go 1.0 behavior
39 {"l2tp", "127.0.0.1", nil, UnknownNetworkError("l2tp")},
40 {"l2tp:gre", "127.0.0.1", nil, UnknownNetworkError("l2tp:gre")},
41 {"tcp", "1.2.3.4:123", nil, UnknownNetworkError("tcp")},
45 if ifi
:= loopbackInterface(); ifi
!= nil {
46 index
:= fmt
.Sprintf("%v", ifi
.Index
)
47 resolveIPAddrTests
= append(resolveIPAddrTests
, []resolveIPAddrTest
{
48 {"ip6", "fe80::1%" + ifi
.Name
, &IPAddr
{IP
: ParseIP("fe80::1"), Zone
: zoneToString(ifi
.Index
)}, nil},
49 {"ip6", "fe80::1%" + index
, &IPAddr
{IP
: ParseIP("fe80::1"), Zone
: index
}, nil},
54 func TestResolveIPAddr(t
*testing
.T
) {
55 for _
, tt
:= range resolveIPAddrTests
{
56 addr
, err
:= ResolveIPAddr(tt
.net
, tt
.litAddr
)
58 condFatalf(t
, "ResolveIPAddr(%v, %v) failed: %v", tt
.net
, tt
.litAddr
, err
)
59 } else if !reflect
.DeepEqual(addr
, tt
.addr
) {
60 t
.Fatalf("got %#v; expected %#v", addr
, tt
.addr
)
65 var icmpEchoTests
= []struct {
70 {"ip4:icmp", "0.0.0.0", "127.0.0.1"},
71 {"ip6:ipv6-icmp", "::", "::1"},
74 func TestConnICMPEcho(t
*testing
.T
) {
76 t
.Skip("skipping test; must be root")
79 for i
, tt
:= range icmpEchoTests
{
80 net
, _
, err
:= parseNetwork(tt
.net
)
82 t
.Fatalf("parseNetwork failed: %v", err
)
84 if net
== "ip6" && !supportsIPv6
{
88 c
, err
:= Dial(tt
.net
, tt
.raddr
)
90 t
.Fatalf("Dial failed: %v", err
)
92 c
.SetDeadline(time
.Now().Add(100 * time
.Millisecond
))
95 typ
:= icmpv4EchoRequest
97 typ
= icmpv6EchoRequest
99 xid
, xseq
:= os
.Getpid()&0xffff, i
+1
100 b
, err
:= (&icmpMessage
{
104 Data
: bytes
.Repeat([]byte("Go Go Gadget Ping!!!"), 3),
108 t
.Fatalf("icmpMessage.Marshal failed: %v", err
)
110 if _
, err
:= c
.Write(b
); err
!= nil {
111 t
.Fatalf("Conn.Write failed: %v", err
)
115 if _
, err
:= c
.Read(b
); err
!= nil {
116 t
.Fatalf("Conn.Read failed: %v", err
)
121 if m
, err
= parseICMPMessage(b
); err
!= nil {
122 t
.Fatalf("parseICMPMessage failed: %v", err
)
125 case icmpv4EchoRequest
, icmpv6EchoRequest
:
130 switch p
:= m
.Body
.(type) {
132 if p
.ID
!= xid || p
.Seq
!= xseq
{
133 t
.Fatalf("got id=%v, seqnum=%v; expected id=%v, seqnum=%v", p
.ID
, p
.Seq
, xid
, xseq
)
136 t
.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m
.Type
, m
.Code
, typ
, 0)
141 func TestPacketConnICMPEcho(t
*testing
.T
) {
142 if os
.Getuid() != 0 {
143 t
.Skip("skipping test; must be root")
146 for i
, tt
:= range icmpEchoTests
{
147 net
, _
, err
:= parseNetwork(tt
.net
)
149 t
.Fatalf("parseNetwork failed: %v", err
)
151 if net
== "ip6" && !supportsIPv6
{
155 c
, err
:= ListenPacket(tt
.net
, tt
.laddr
)
157 t
.Fatalf("ListenPacket failed: %v", err
)
159 c
.SetDeadline(time
.Now().Add(100 * time
.Millisecond
))
162 ra
, err
:= ResolveIPAddr(tt
.net
, tt
.raddr
)
164 t
.Fatalf("ResolveIPAddr failed: %v", err
)
166 typ
:= icmpv4EchoRequest
168 typ
= icmpv6EchoRequest
170 xid
, xseq
:= os
.Getpid()&0xffff, i
+1
171 b
, err
:= (&icmpMessage
{
175 Data
: bytes
.Repeat([]byte("Go Go Gadget Ping!!!"), 3),
179 t
.Fatalf("icmpMessage.Marshal failed: %v", err
)
181 if _
, err
:= c
.WriteTo(b
, ra
); err
!= nil {
182 t
.Fatalf("PacketConn.WriteTo failed: %v", err
)
186 if _
, _
, err
:= c
.ReadFrom(b
); err
!= nil {
187 t
.Fatalf("PacketConn.ReadFrom failed: %v", err
)
189 // TODO: fix issue 3944
191 // b = ipv4Payload(b)
193 if m
, err
= parseICMPMessage(b
); err
!= nil {
194 t
.Fatalf("parseICMPMessage failed: %v", err
)
197 case icmpv4EchoRequest
, icmpv6EchoRequest
:
202 switch p
:= m
.Body
.(type) {
204 if p
.ID
!= xid || p
.Seq
!= xseq
{
205 t
.Fatalf("got id=%v, seqnum=%v; expected id=%v, seqnum=%v", p
.ID
, p
.Seq
, xid
, xseq
)
208 t
.Fatalf("got type=%v, code=%v; expected type=%v, code=%v", m
.Type
, m
.Code
, typ
, 0)
213 func ipv4Payload(b
[]byte) []byte {
217 hdrlen
:= int(b
[0]&0x0f) << 2
222 icmpv4EchoRequest
= 8
224 icmpv6EchoRequest
= 128
225 icmpv6EchoReply
= 129
228 // icmpMessage represents an ICMP message.
229 type icmpMessage
struct {
232 Checksum
int // checksum
233 Body icmpMessageBody
// body
236 // icmpMessageBody represents an ICMP message body.
237 type icmpMessageBody
interface {
239 Marshal() ([]byte, error
)
242 // Marshal returns the binary enconding of the ICMP echo request or
244 func (m
*icmpMessage
) Marshal() ([]byte, error
) {
245 b
:= []byte{byte(m
.Type
), byte(m
.Code
), 0, 0}
246 if m
.Body
!= nil && m
.Body
.Len() != 0 {
247 mb
, err
:= m
.Body
.Marshal()
254 case icmpv6EchoRequest
, icmpv6EchoReply
:
257 csumcv
:= len(b
) - 1 // checksum coverage
259 for i
:= 0; i
< csumcv
; i
+= 2 {
260 s
+= uint32(b
[i
+1])<<8 |
uint32(b
[i
])
263 s
+= uint32(b
[csumcv
])
267 // Place checksum back in header; using ^= avoids the
268 // assumption the checksum bytes are zero.
269 b
[2] ^= byte(^s
& 0xff)
270 b
[3] ^= byte(^s
>> 8)
274 // parseICMPMessage parses b as an ICMP message.
275 func parseICMPMessage(b
[]byte) (*icmpMessage
, error
) {
278 return nil, errors
.New("message too short")
280 m
:= &icmpMessage
{Type
: int(b
[0]), Code
: int(b
[1]), Checksum
: int(b
[2])<<8 |
int(b
[3])}
284 case icmpv4EchoRequest
, icmpv4EchoReply
, icmpv6EchoRequest
, icmpv6EchoReply
:
285 m
.Body
, err
= parseICMPEcho(b
[4:])
294 // imcpEcho represenets an ICMP echo request or reply message body.
295 type icmpEcho
struct {
297 Seq
int // sequence number
301 func (p
*icmpEcho
) Len() int {
305 return 4 + len(p
.Data
)
308 // Marshal returns the binary enconding of the ICMP echo request or
309 // reply message body p.
310 func (p
*icmpEcho
) Marshal() ([]byte, error
) {
311 b
:= make([]byte, 4+len(p
.Data
))
312 b
[0], b
[1] = byte(p
.ID
>>8), byte(p
.ID
&0xff)
313 b
[2], b
[3] = byte(p
.Seq
>>8), byte(p
.Seq
&0xff)
318 // parseICMPEcho parses b as an ICMP echo request or reply message
320 func parseICMPEcho(b
[]byte) (*icmpEcho
, error
) {
322 p
:= &icmpEcho
{ID
: int(b
[0])<<8 |
int(b
[1]), Seq
: int(b
[2])<<8 |
int(b
[3])}
324 p
.Data
= make([]byte, bodylen
-4)
330 var ipConnLocalNameTests
= []struct {
334 {"ip4:icmp", &IPAddr
{IP
: IPv4(127, 0, 0, 1)}},
335 {"ip4:icmp", &IPAddr
{}},
339 func TestIPConnLocalName(t
*testing
.T
) {
340 if os
.Getuid() != 0 {
341 t
.Skip("skipping test; must be root")
344 for _
, tt
:= range ipConnLocalNameTests
{
345 c
, err
:= ListenIP(tt
.net
, tt
.laddr
)
347 t
.Fatalf("ListenIP failed: %v", err
)
350 if la
:= c
.LocalAddr(); la
== nil {
351 t
.Fatal("IPConn.LocalAddr failed")
356 func TestIPConnRemoteName(t
*testing
.T
) {
357 if os
.Getuid() != 0 {
358 t
.Skip("skipping test; must be root")
361 raddr
:= &IPAddr
{IP
: IPv4(127, 0, 0, 10).To4()}
362 c
, err
:= DialIP("ip:tcp", &IPAddr
{IP
: IPv4(127, 0, 0, 1)}, raddr
)
364 t
.Fatalf("DialIP failed: %v", err
)
367 if !reflect
.DeepEqual(raddr
, c
.RemoteAddr()) {
368 t
.Fatalf("got %#v, expected %#v", c
.RemoteAddr(), raddr
)