libgo: Update to Go 1.1.1.
[official-gcc.git] / libgo / go / net / ipraw_test.go
blob12c199d1cf4d5cbbfb580b427a10328e2f0218b0
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.
5 package net
7 import (
8 "bytes"
9 "errors"
10 "fmt"
11 "os"
12 "reflect"
13 "testing"
14 "time"
17 type resolveIPAddrTest struct {
18 net string
19 litAddr string
20 addr *IPAddr
21 err error
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")},
44 func init() {
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},
50 }...)
54 func TestResolveIPAddr(t *testing.T) {
55 for _, tt := range resolveIPAddrTests {
56 addr, err := ResolveIPAddr(tt.net, tt.litAddr)
57 if err != tt.err {
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 {
66 net string
67 laddr string
68 raddr string
70 {"ip4:icmp", "0.0.0.0", "127.0.0.1"},
71 {"ip6:ipv6-icmp", "::", "::1"},
74 func TestConnICMPEcho(t *testing.T) {
75 if os.Getuid() != 0 {
76 t.Skip("skipping test; must be root")
79 for i, tt := range icmpEchoTests {
80 net, _, err := parseNetwork(tt.net)
81 if err != nil {
82 t.Fatalf("parseNetwork failed: %v", err)
84 if net == "ip6" && !supportsIPv6 {
85 continue
88 c, err := Dial(tt.net, tt.raddr)
89 if err != nil {
90 t.Fatalf("Dial failed: %v", err)
92 c.SetDeadline(time.Now().Add(100 * time.Millisecond))
93 defer c.Close()
95 typ := icmpv4EchoRequest
96 if net == "ip6" {
97 typ = icmpv6EchoRequest
99 xid, xseq := os.Getpid()&0xffff, i+1
100 b, err := (&icmpMessage{
101 Type: typ, Code: 0,
102 Body: &icmpEcho{
103 ID: xid, Seq: xseq,
104 Data: bytes.Repeat([]byte("Go Go Gadget Ping!!!"), 3),
106 }).Marshal()
107 if err != nil {
108 t.Fatalf("icmpMessage.Marshal failed: %v", err)
110 if _, err := c.Write(b); err != nil {
111 t.Fatalf("Conn.Write failed: %v", err)
113 var m *icmpMessage
114 for {
115 if _, err := c.Read(b); err != nil {
116 t.Fatalf("Conn.Read failed: %v", err)
118 if net == "ip4" {
119 b = ipv4Payload(b)
121 if m, err = parseICMPMessage(b); err != nil {
122 t.Fatalf("parseICMPMessage failed: %v", err)
124 switch m.Type {
125 case icmpv4EchoRequest, icmpv6EchoRequest:
126 continue
128 break
130 switch p := m.Body.(type) {
131 case *icmpEcho:
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)
135 default:
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)
148 if err != nil {
149 t.Fatalf("parseNetwork failed: %v", err)
151 if net == "ip6" && !supportsIPv6 {
152 continue
155 c, err := ListenPacket(tt.net, tt.laddr)
156 if err != nil {
157 t.Fatalf("ListenPacket failed: %v", err)
159 c.SetDeadline(time.Now().Add(100 * time.Millisecond))
160 defer c.Close()
162 ra, err := ResolveIPAddr(tt.net, tt.raddr)
163 if err != nil {
164 t.Fatalf("ResolveIPAddr failed: %v", err)
166 typ := icmpv4EchoRequest
167 if net == "ip6" {
168 typ = icmpv6EchoRequest
170 xid, xseq := os.Getpid()&0xffff, i+1
171 b, err := (&icmpMessage{
172 Type: typ, Code: 0,
173 Body: &icmpEcho{
174 ID: xid, Seq: xseq,
175 Data: bytes.Repeat([]byte("Go Go Gadget Ping!!!"), 3),
177 }).Marshal()
178 if err != nil {
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)
184 var m *icmpMessage
185 for {
186 if _, _, err := c.ReadFrom(b); err != nil {
187 t.Fatalf("PacketConn.ReadFrom failed: %v", err)
189 // TODO: fix issue 3944
190 //if net == "ip4" {
191 // b = ipv4Payload(b)
193 if m, err = parseICMPMessage(b); err != nil {
194 t.Fatalf("parseICMPMessage failed: %v", err)
196 switch m.Type {
197 case icmpv4EchoRequest, icmpv6EchoRequest:
198 continue
200 break
202 switch p := m.Body.(type) {
203 case *icmpEcho:
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)
207 default:
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 {
214 if len(b) < 20 {
215 return b
217 hdrlen := int(b[0]&0x0f) << 2
218 return b[hdrlen:]
221 const (
222 icmpv4EchoRequest = 8
223 icmpv4EchoReply = 0
224 icmpv6EchoRequest = 128
225 icmpv6EchoReply = 129
228 // icmpMessage represents an ICMP message.
229 type icmpMessage struct {
230 Type int // type
231 Code int // code
232 Checksum int // checksum
233 Body icmpMessageBody // body
236 // icmpMessageBody represents an ICMP message body.
237 type icmpMessageBody interface {
238 Len() int
239 Marshal() ([]byte, error)
242 // Marshal returns the binary enconding of the ICMP echo request or
243 // reply message m.
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()
248 if err != nil {
249 return nil, err
251 b = append(b, mb...)
253 switch m.Type {
254 case icmpv6EchoRequest, icmpv6EchoReply:
255 return b, nil
257 csumcv := len(b) - 1 // checksum coverage
258 s := uint32(0)
259 for i := 0; i < csumcv; i += 2 {
260 s += uint32(b[i+1])<<8 | uint32(b[i])
262 if csumcv&1 == 0 {
263 s += uint32(b[csumcv])
265 s = s>>16 + s&0xffff
266 s = s + s>>16
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)
271 return b, nil
274 // parseICMPMessage parses b as an ICMP message.
275 func parseICMPMessage(b []byte) (*icmpMessage, error) {
276 msglen := len(b)
277 if msglen < 4 {
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])}
281 if msglen > 4 {
282 var err error
283 switch m.Type {
284 case icmpv4EchoRequest, icmpv4EchoReply, icmpv6EchoRequest, icmpv6EchoReply:
285 m.Body, err = parseICMPEcho(b[4:])
286 if err != nil {
287 return nil, err
291 return m, nil
294 // imcpEcho represenets an ICMP echo request or reply message body.
295 type icmpEcho struct {
296 ID int // identifier
297 Seq int // sequence number
298 Data []byte // data
301 func (p *icmpEcho) Len() int {
302 if p == nil {
303 return 0
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)
314 copy(b[4:], p.Data)
315 return b, nil
318 // parseICMPEcho parses b as an ICMP echo request or reply message
319 // body.
320 func parseICMPEcho(b []byte) (*icmpEcho, error) {
321 bodylen := len(b)
322 p := &icmpEcho{ID: int(b[0])<<8 | int(b[1]), Seq: int(b[2])<<8 | int(b[3])}
323 if bodylen > 4 {
324 p.Data = make([]byte, bodylen-4)
325 copy(p.Data, b[4:])
327 return p, nil
330 var ipConnLocalNameTests = []struct {
331 net string
332 laddr *IPAddr
334 {"ip4:icmp", &IPAddr{IP: IPv4(127, 0, 0, 1)}},
335 {"ip4:icmp", &IPAddr{}},
336 {"ip4:icmp", nil},
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)
346 if err != nil {
347 t.Fatalf("ListenIP failed: %v", err)
349 defer c.Close()
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)
363 if err != nil {
364 t.Fatalf("DialIP failed: %v", err)
366 defer c.Close()
367 if !reflect.DeepEqual(raddr, c.RemoteAddr()) {
368 t.Fatalf("got %#v, expected %#v", c.RemoteAddr(), raddr)