OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / net / ipv4 / multicast_test.go
1 // Copyright 2012 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.
4
5 package ipv4_test
6
7 import (
8         "bytes"
9         "net"
10         "os"
11         "runtime"
12         "testing"
13         "time"
14
15         "golang.org/x/net/icmp"
16         "golang.org/x/net/internal/iana"
17         "golang.org/x/net/internal/nettest"
18         "golang.org/x/net/ipv4"
19 )
20
21 var packetConnReadWriteMulticastUDPTests = []struct {
22         addr     string
23         grp, src *net.UDPAddr
24 }{
25         {"224.0.0.0:0", &net.UDPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727
26
27         {"232.0.1.0:0", &net.UDPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
28 }
29
30 func TestPacketConnReadWriteMulticastUDP(t *testing.T) {
31         switch runtime.GOOS {
32         case "nacl", "plan9", "solaris", "windows":
33                 t.Skipf("not supported on %s", runtime.GOOS)
34         }
35         ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
36         if ifi == nil {
37                 t.Skipf("not available on %s", runtime.GOOS)
38         }
39
40         for _, tt := range packetConnReadWriteMulticastUDPTests {
41                 c, err := net.ListenPacket("udp4", tt.addr)
42                 if err != nil {
43                         t.Fatal(err)
44                 }
45                 defer c.Close()
46
47                 grp := *tt.grp
48                 grp.Port = c.LocalAddr().(*net.UDPAddr).Port
49                 p := ipv4.NewPacketConn(c)
50                 defer p.Close()
51                 if tt.src == nil {
52                         if err := p.JoinGroup(ifi, &grp); err != nil {
53                                 t.Fatal(err)
54                         }
55                         defer p.LeaveGroup(ifi, &grp)
56                 } else {
57                         if err := p.JoinSourceSpecificGroup(ifi, &grp, tt.src); err != nil {
58                                 switch runtime.GOOS {
59                                 case "freebsd", "linux":
60                                 default: // platforms that don't support IGMPv2/3 fail here
61                                         t.Logf("not supported on %s", runtime.GOOS)
62                                         continue
63                                 }
64                                 t.Fatal(err)
65                         }
66                         defer p.LeaveSourceSpecificGroup(ifi, &grp, tt.src)
67                 }
68                 if err := p.SetMulticastInterface(ifi); err != nil {
69                         t.Fatal(err)
70                 }
71                 if _, err := p.MulticastInterface(); err != nil {
72                         t.Fatal(err)
73                 }
74                 if err := p.SetMulticastLoopback(true); err != nil {
75                         t.Fatal(err)
76                 }
77                 if _, err := p.MulticastLoopback(); err != nil {
78                         t.Fatal(err)
79                 }
80                 cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
81                 wb := []byte("HELLO-R-U-THERE")
82
83                 for i, toggle := range []bool{true, false, true} {
84                         if err := p.SetControlMessage(cf, toggle); err != nil {
85                                 if nettest.ProtocolNotSupported(err) {
86                                         t.Logf("not supported on %s", runtime.GOOS)
87                                         continue
88                                 }
89                                 t.Fatal(err)
90                         }
91                         if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
92                                 t.Fatal(err)
93                         }
94                         p.SetMulticastTTL(i + 1)
95                         if n, err := p.WriteTo(wb, nil, &grp); err != nil {
96                                 t.Fatal(err)
97                         } else if n != len(wb) {
98                                 t.Fatalf("got %v; want %v", n, len(wb))
99                         }
100                         rb := make([]byte, 128)
101                         if n, _, _, err := p.ReadFrom(rb); err != nil {
102                                 t.Fatal(err)
103                         } else if !bytes.Equal(rb[:n], wb) {
104                                 t.Fatalf("got %v; want %v", rb[:n], wb)
105                         }
106                 }
107         }
108 }
109
110 var packetConnReadWriteMulticastICMPTests = []struct {
111         grp, src *net.IPAddr
112 }{
113         {&net.IPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727
114
115         {&net.IPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
116 }
117
118 func TestPacketConnReadWriteMulticastICMP(t *testing.T) {
119         switch runtime.GOOS {
120         case "nacl", "plan9", "solaris", "windows":
121                 t.Skipf("not supported on %s", runtime.GOOS)
122         }
123         if m, ok := nettest.SupportsRawIPSocket(); !ok {
124                 t.Skip(m)
125         }
126         ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
127         if ifi == nil {
128                 t.Skipf("not available on %s", runtime.GOOS)
129         }
130
131         for _, tt := range packetConnReadWriteMulticastICMPTests {
132                 c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
133                 if err != nil {
134                         t.Fatal(err)
135                 }
136                 defer c.Close()
137
138                 p := ipv4.NewPacketConn(c)
139                 defer p.Close()
140                 if tt.src == nil {
141                         if err := p.JoinGroup(ifi, tt.grp); err != nil {
142                                 t.Fatal(err)
143                         }
144                         defer p.LeaveGroup(ifi, tt.grp)
145                 } else {
146                         if err := p.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil {
147                                 switch runtime.GOOS {
148                                 case "freebsd", "linux":
149                                 default: // platforms that don't support IGMPv2/3 fail here
150                                         t.Logf("not supported on %s", runtime.GOOS)
151                                         continue
152                                 }
153                                 t.Fatal(err)
154                         }
155                         defer p.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src)
156                 }
157                 if err := p.SetMulticastInterface(ifi); err != nil {
158                         t.Fatal(err)
159                 }
160                 if _, err := p.MulticastInterface(); err != nil {
161                         t.Fatal(err)
162                 }
163                 if err := p.SetMulticastLoopback(true); err != nil {
164                         t.Fatal(err)
165                 }
166                 if _, err := p.MulticastLoopback(); err != nil {
167                         t.Fatal(err)
168                 }
169                 cf := ipv4.FlagDst | ipv4.FlagInterface
170                 if runtime.GOOS != "solaris" {
171                         // Solaris never allows to modify ICMP properties.
172                         cf |= ipv4.FlagTTL
173                 }
174
175                 for i, toggle := range []bool{true, false, true} {
176                         wb, err := (&icmp.Message{
177                                 Type: ipv4.ICMPTypeEcho, Code: 0,
178                                 Body: &icmp.Echo{
179                                         ID: os.Getpid() & 0xffff, Seq: i + 1,
180                                         Data: []byte("HELLO-R-U-THERE"),
181                                 },
182                         }).Marshal(nil)
183                         if err != nil {
184                                 t.Fatal(err)
185                         }
186                         if err := p.SetControlMessage(cf, toggle); err != nil {
187                                 if nettest.ProtocolNotSupported(err) {
188                                         t.Logf("not supported on %s", runtime.GOOS)
189                                         continue
190                                 }
191                                 t.Fatal(err)
192                         }
193                         if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
194                                 t.Fatal(err)
195                         }
196                         p.SetMulticastTTL(i + 1)
197                         if n, err := p.WriteTo(wb, nil, tt.grp); err != nil {
198                                 t.Fatal(err)
199                         } else if n != len(wb) {
200                                 t.Fatalf("got %v; want %v", n, len(wb))
201                         }
202                         rb := make([]byte, 128)
203                         if n, _, _, err := p.ReadFrom(rb); err != nil {
204                                 t.Fatal(err)
205                         } else {
206                                 m, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n])
207                                 if err != nil {
208                                         t.Fatal(err)
209                                 }
210                                 switch {
211                                 case m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1
212                                 case m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0
213                                 default:
214                                         t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
215                                 }
216                         }
217                 }
218         }
219 }
220
221 var rawConnReadWriteMulticastICMPTests = []struct {
222         grp, src *net.IPAddr
223 }{
224         {&net.IPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727
225
226         {&net.IPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
227 }
228
229 func TestRawConnReadWriteMulticastICMP(t *testing.T) {
230         if testing.Short() {
231                 t.Skip("to avoid external network")
232         }
233         if m, ok := nettest.SupportsRawIPSocket(); !ok {
234                 t.Skip(m)
235         }
236         ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
237         if ifi == nil {
238                 t.Skipf("not available on %s", runtime.GOOS)
239         }
240
241         for _, tt := range rawConnReadWriteMulticastICMPTests {
242                 c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
243                 if err != nil {
244                         t.Fatal(err)
245                 }
246                 defer c.Close()
247
248                 r, err := ipv4.NewRawConn(c)
249                 if err != nil {
250                         t.Fatal(err)
251                 }
252                 defer r.Close()
253                 if tt.src == nil {
254                         if err := r.JoinGroup(ifi, tt.grp); err != nil {
255                                 t.Fatal(err)
256                         }
257                         defer r.LeaveGroup(ifi, tt.grp)
258                 } else {
259                         if err := r.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil {
260                                 switch runtime.GOOS {
261                                 case "freebsd", "linux":
262                                 default: // platforms that don't support IGMPv2/3 fail here
263                                         t.Logf("not supported on %s", runtime.GOOS)
264                                         continue
265                                 }
266                                 t.Fatal(err)
267                         }
268                         defer r.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src)
269                 }
270                 if err := r.SetMulticastInterface(ifi); err != nil {
271                         t.Fatal(err)
272                 }
273                 if _, err := r.MulticastInterface(); err != nil {
274                         t.Fatal(err)
275                 }
276                 if err := r.SetMulticastLoopback(true); err != nil {
277                         t.Fatal(err)
278                 }
279                 if _, err := r.MulticastLoopback(); err != nil {
280                         t.Fatal(err)
281                 }
282                 cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface
283
284                 for i, toggle := range []bool{true, false, true} {
285                         wb, err := (&icmp.Message{
286                                 Type: ipv4.ICMPTypeEcho, Code: 0,
287                                 Body: &icmp.Echo{
288                                         ID: os.Getpid() & 0xffff, Seq: i + 1,
289                                         Data: []byte("HELLO-R-U-THERE"),
290                                 },
291                         }).Marshal(nil)
292                         if err != nil {
293                                 t.Fatal(err)
294                         }
295                         wh := &ipv4.Header{
296                                 Version:  ipv4.Version,
297                                 Len:      ipv4.HeaderLen,
298                                 TOS:      i + 1,
299                                 TotalLen: ipv4.HeaderLen + len(wb),
300                                 Protocol: 1,
301                                 Dst:      tt.grp.IP,
302                         }
303                         if err := r.SetControlMessage(cf, toggle); err != nil {
304                                 if nettest.ProtocolNotSupported(err) {
305                                         t.Logf("not supported on %s", runtime.GOOS)
306                                         continue
307                                 }
308                                 t.Fatal(err)
309                         }
310                         if err := r.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil {
311                                 t.Fatal(err)
312                         }
313                         r.SetMulticastTTL(i + 1)
314                         if err := r.WriteTo(wh, wb, nil); err != nil {
315                                 t.Fatal(err)
316                         }
317                         rb := make([]byte, ipv4.HeaderLen+128)
318                         if rh, b, _, err := r.ReadFrom(rb); err != nil {
319                                 t.Fatal(err)
320                         } else {
321                                 m, err := icmp.ParseMessage(iana.ProtocolICMP, b)
322                                 if err != nil {
323                                         t.Fatal(err)
324                                 }
325                                 switch {
326                                 case (rh.Dst.IsLoopback() || rh.Dst.IsLinkLocalUnicast() || rh.Dst.IsGlobalUnicast()) && m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1
327                                 case rh.Dst.IsMulticast() && m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0
328                                 default:
329                                         t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0)
330                                 }
331                         }
332                 }
333         }
334 }