OLD | NEW |
1 // Copyright 2012 The Go Authors. All rights reserved. | 1 // Copyright 2012 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // +build darwin freebsd linux netbsd openbsd | 5 // +build darwin freebsd linux netbsd openbsd |
6 | 6 |
7 package ipv4_test | 7 package ipv4_test |
8 | 8 |
9 import ( | 9 import ( |
10 "code.google.com/p/go.net/ipv4" | 10 "code.google.com/p/go.net/ipv4" |
11 "net" | 11 "net" |
12 "testing" | 12 "testing" |
13 "time" | 13 "time" |
14 ) | 14 ) |
15 | 15 |
16 // runPayloadTransponder transmits IPv4 datagram payloads to the | 16 // writeThenReadPayload transmits IPv4 datagram payloads to the |
17 // loopback address or interface and captures the loopback'd datagram | 17 // loopback address or interface and captures the loopback'd datagram |
18 // payloads. | 18 // payloads. |
19 func runPayloadTransponder(t *testing.T, c *ipv4.PacketConn, wb []byte, dst net.
Addr) { | 19 func writeThenReadPayload(t *testing.T, i int, c *ipv4.PacketConn, wb []byte, ds
t net.Addr) []byte { |
20 » cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface | |
21 rb := make([]byte, 1500) | 20 rb := make([]byte, 1500) |
22 » for i, toggle := range []bool{true, false, true} { | 21 » c.SetTOS(i + 1) |
23 » » if err := c.SetControlMessage(cf, toggle); err != nil { | 22 » var ip net.IP |
24 » » » t.Fatalf("ipv4.PacketConn.SetControlMessage failed: %v",
err) | 23 » switch v := dst.(type) { |
25 » » } | 24 » case *net.UDPAddr: |
26 » » c.SetTOS(i + 1) | 25 » » ip = v.IP |
27 » » var ip net.IP | 26 » case *net.IPAddr: |
28 » » switch v := dst.(type) { | 27 » » ip = v.IP |
29 » » case *net.UDPAddr: | |
30 » » » ip = v.IP | |
31 » » case *net.IPAddr: | |
32 » » » ip = v.IP | |
33 » » } | |
34 » » if ip.IsMulticast() { | |
35 » » » c.SetMulticastTTL(i + 1) | |
36 » » } else { | |
37 » » » c.SetTTL(i + 1) | |
38 » » } | |
39 » » c.SetDeadline(time.Now().Add(100 * time.Millisecond)) | |
40 » » if _, err := c.WriteTo(wb, nil, dst); err != nil { | |
41 » » » t.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err) | |
42 » » } | |
43 » » _, cm, _, err := c.ReadFrom(rb) | |
44 » » if err != nil { | |
45 » » » t.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err) | |
46 » » } | |
47 » » t.Logf("rcvd cmsg: %v", cm) | |
48 } | 28 } |
| 29 if ip.IsMulticast() { |
| 30 c.SetMulticastTTL(i + 1) |
| 31 } else { |
| 32 c.SetTTL(i + 1) |
| 33 } |
| 34 c.SetDeadline(time.Now().Add(100 * time.Millisecond)) |
| 35 if _, err := c.WriteTo(wb, nil, dst); err != nil { |
| 36 t.Fatalf("ipv4.PacketConn.WriteTo failed: %v", err) |
| 37 } |
| 38 n, cm, _, err := c.ReadFrom(rb) |
| 39 if err != nil { |
| 40 t.Fatalf("ipv4.PacketConn.ReadFrom failed: %v", err) |
| 41 } |
| 42 t.Logf("rcvd cmsg: %v", cm) |
| 43 return rb[:n] |
49 } | 44 } |
50 | 45 |
51 // runDatagramTransponder transmits ICMP for IPv4 datagrams to the | 46 // writeThenReadDatagram transmits ICMP for IPv4 datagrams to the |
52 // loopback address or interface and captures the response datagrams | 47 // loopback address or interface and captures the response datagrams |
53 // from the protocol stack within the kernel. | 48 // from the protocol stack within the kernel. |
54 func runDatagramTransponder(t *testing.T, c *ipv4.RawConn, wb []byte, src, dst n
et.Addr) { | 49 func writeThenReadDatagram(t *testing.T, i int, c *ipv4.RawConn, wb []byte, src,
dst net.Addr) []byte { |
55 » cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface | |
56 rb := make([]byte, ipv4.HeaderLen+len(wb)) | 50 rb := make([]byte, ipv4.HeaderLen+len(wb)) |
57 » for i, toggle := range []bool{true, false, true} { | 51 » wh := &ipv4.Header{ |
58 » » if err := c.SetControlMessage(cf, toggle); err != nil { | 52 » » Version: ipv4.Version, |
59 » » » t.Fatalf("ipv4.RawConn.SetControlMessage failed: %v", er
r) | 53 » » Len: ipv4.HeaderLen, |
60 » » } | 54 » » TOS: i + 1, |
61 » » wh := &ipv4.Header{} | 55 » » TotalLen: ipv4.HeaderLen + len(wb), |
62 » » wh.Version = ipv4.Version | 56 » » TTL: i + 1, |
63 » » wh.Len = ipv4.HeaderLen | 57 » » Protocol: 1, |
64 » » wh.TOS = i + 1 | |
65 » » wh.TotalLen = ipv4.HeaderLen + len(wb) | |
66 » » wh.TTL = i + 1 | |
67 » » wh.Protocol = 1 | |
68 » » if src != nil { | |
69 » » » wh.Src = src.(*net.IPAddr).IP | |
70 » » } | |
71 » » if dst != nil { | |
72 » » » wh.Dst = dst.(*net.IPAddr).IP | |
73 » » } | |
74 » » c.SetDeadline(time.Now().Add(100 * time.Millisecond)) | |
75 » » if err := c.WriteTo(wh, wb, nil); err != nil { | |
76 » » » t.Fatalf("ipv4.RawConn.WriteTo failed: %v", err) | |
77 » » } | |
78 » » rh, _, cm, err := c.ReadFrom(rb) | |
79 » » if err != nil { | |
80 » » » t.Fatalf("ipv4.RawConn.ReadFrom failed: %v", err) | |
81 » » } | |
82 » » t.Logf("rcvd cmsg: %v", cm.String()) | |
83 » » t.Logf("rcvd hdr: %v", rh.String()) | |
84 } | 58 } |
| 59 if src != nil { |
| 60 wh.Src = src.(*net.IPAddr).IP |
| 61 } |
| 62 if dst != nil { |
| 63 wh.Dst = dst.(*net.IPAddr).IP |
| 64 } |
| 65 c.SetDeadline(time.Now().Add(100 * time.Millisecond)) |
| 66 if err := c.WriteTo(wh, wb, nil); err != nil { |
| 67 t.Fatalf("ipv4.RawConn.WriteTo failed: %v", err) |
| 68 } |
| 69 rh, b, cm, err := c.ReadFrom(rb) |
| 70 if err != nil { |
| 71 t.Fatalf("ipv4.RawConn.ReadFrom failed: %v", err) |
| 72 } |
| 73 t.Logf("rcvd cmsg: %v", cm.String()) |
| 74 t.Logf("rcvd hdr: %v", rh.String()) |
| 75 return b |
85 } | 76 } |
86 | 77 |
| 78 // LoopbackInterface returns a logical network interface for loopback |
| 79 // tests. |
87 func loopbackInterface() *net.Interface { | 80 func loopbackInterface() *net.Interface { |
88 ift, err := net.Interfaces() | 81 ift, err := net.Interfaces() |
89 if err != nil { | 82 if err != nil { |
90 return nil | 83 return nil |
91 } | 84 } |
92 for _, ifi := range ift { | 85 for _, ifi := range ift { |
93 if ifi.Flags&net.FlagLoopback != 0 { | 86 if ifi.Flags&net.FlagLoopback != 0 { |
94 return &ifi | 87 return &ifi |
95 } | 88 } |
96 } | 89 } |
97 return nil | 90 return nil |
98 } | 91 } |
99 | 92 |
100 func isGoodForMulticast(ifi *net.Interface) (net.IP, bool) { | 93 // isMulticastAvailable returns true if ifi is a multicast access |
101 » if ifi.Flags&net.FlagUp == 0 { | 94 // enabled network interface. It also returns a unicast IPv4 address |
| 95 // that can be used for listening on ifi. |
| 96 func isMulticastAvailable(ifi *net.Interface) (net.IP, bool) { |
| 97 » if ifi.Flags&net.FlagUp == 0 || ifi.Flags&net.FlagMulticast == 0 { |
102 return nil, false | 98 return nil, false |
103 } | 99 } |
104 // We need a unicast IPv4 address that can be used to specify | |
105 // the IPv4 multicast interface. | |
106 ifat, err := ifi.Addrs() | 100 ifat, err := ifi.Addrs() |
107 if err != nil { | 101 if err != nil { |
108 return nil, false | 102 return nil, false |
109 } | 103 } |
110 if len(ifat) == 0 { | 104 if len(ifat) == 0 { |
111 return nil, false | 105 return nil, false |
112 } | 106 } |
113 var ip net.IP | 107 var ip net.IP |
114 for _, ifa := range ifat { | 108 for _, ifa := range ifat { |
115 switch v := ifa.(type) { | 109 switch v := ifa.(type) { |
116 case *net.IPAddr: | 110 case *net.IPAddr: |
117 ip = v.IP | 111 ip = v.IP |
118 case *net.IPNet: | 112 case *net.IPNet: |
119 ip = v.IP | 113 ip = v.IP |
120 default: | 114 default: |
121 continue | 115 continue |
122 } | 116 } |
123 if ip.To4() == nil { | 117 if ip.To4() == nil { |
124 ip = nil | 118 ip = nil |
125 continue | 119 continue |
126 } | 120 } |
127 break | 121 break |
128 } | 122 } |
129 if ip == nil { | |
130 return nil, false | |
131 } | |
132 return ip, true | 123 return ip, true |
133 } | 124 } |
OLD | NEW |