github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/net/ipv4/multicast_test.go (about) 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.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface 170 171 for i, toggle := range []bool{true, false, true} { 172 wb, err := (&icmp.Message{ 173 Type: ipv4.ICMPTypeEcho, Code: 0, 174 Body: &icmp.Echo{ 175 ID: os.Getpid() & 0xffff, Seq: i + 1, 176 Data: []byte("HELLO-R-U-THERE"), 177 }, 178 }).Marshal(nil) 179 if err != nil { 180 t.Fatal(err) 181 } 182 if err := p.SetControlMessage(cf, toggle); err != nil { 183 if nettest.ProtocolNotSupported(err) { 184 t.Logf("not supported on %s", runtime.GOOS) 185 continue 186 } 187 t.Fatal(err) 188 } 189 if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil { 190 t.Fatal(err) 191 } 192 p.SetMulticastTTL(i + 1) 193 if n, err := p.WriteTo(wb, nil, tt.grp); err != nil { 194 t.Fatal(err) 195 } else if n != len(wb) { 196 t.Fatalf("got %v; want %v", n, len(wb)) 197 } 198 rb := make([]byte, 128) 199 if n, _, _, err := p.ReadFrom(rb); err != nil { 200 t.Fatal(err) 201 } else { 202 m, err := icmp.ParseMessage(iana.ProtocolICMP, rb[:n]) 203 if err != nil { 204 t.Fatal(err) 205 } 206 switch { 207 case m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1 208 case m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0 209 default: 210 t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0) 211 } 212 } 213 } 214 } 215 } 216 217 var rawConnReadWriteMulticastICMPTests = []struct { 218 grp, src *net.IPAddr 219 }{ 220 {&net.IPAddr{IP: net.IPv4(224, 0, 0, 254)}, nil}, // see RFC 4727 221 222 {&net.IPAddr{IP: net.IPv4(232, 0, 1, 254)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771 223 } 224 225 func TestRawConnReadWriteMulticastICMP(t *testing.T) { 226 if testing.Short() { 227 t.Skip("to avoid external network") 228 } 229 if m, ok := nettest.SupportsRawIPSocket(); !ok { 230 t.Skip(m) 231 } 232 ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback) 233 if ifi == nil { 234 t.Skipf("not available on %s", runtime.GOOS) 235 } 236 237 for _, tt := range rawConnReadWriteMulticastICMPTests { 238 c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") 239 if err != nil { 240 t.Fatal(err) 241 } 242 defer c.Close() 243 244 r, err := ipv4.NewRawConn(c) 245 if err != nil { 246 t.Fatal(err) 247 } 248 defer r.Close() 249 if tt.src == nil { 250 if err := r.JoinGroup(ifi, tt.grp); err != nil { 251 t.Fatal(err) 252 } 253 defer r.LeaveGroup(ifi, tt.grp) 254 } else { 255 if err := r.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil { 256 switch runtime.GOOS { 257 case "freebsd", "linux": 258 default: // platforms that don't support IGMPv2/3 fail here 259 t.Logf("not supported on %s", runtime.GOOS) 260 continue 261 } 262 t.Fatal(err) 263 } 264 defer r.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src) 265 } 266 if err := r.SetMulticastInterface(ifi); err != nil { 267 t.Fatal(err) 268 } 269 if _, err := r.MulticastInterface(); err != nil { 270 t.Fatal(err) 271 } 272 if err := r.SetMulticastLoopback(true); err != nil { 273 t.Fatal(err) 274 } 275 if _, err := r.MulticastLoopback(); err != nil { 276 t.Fatal(err) 277 } 278 cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface 279 280 for i, toggle := range []bool{true, false, true} { 281 wb, err := (&icmp.Message{ 282 Type: ipv4.ICMPTypeEcho, Code: 0, 283 Body: &icmp.Echo{ 284 ID: os.Getpid() & 0xffff, Seq: i + 1, 285 Data: []byte("HELLO-R-U-THERE"), 286 }, 287 }).Marshal(nil) 288 if err != nil { 289 t.Fatal(err) 290 } 291 wh := &ipv4.Header{ 292 Version: ipv4.Version, 293 Len: ipv4.HeaderLen, 294 TOS: i + 1, 295 TotalLen: ipv4.HeaderLen + len(wb), 296 Protocol: 1, 297 Dst: tt.grp.IP, 298 } 299 if err := r.SetControlMessage(cf, toggle); err != nil { 300 if nettest.ProtocolNotSupported(err) { 301 t.Logf("not supported on %s", runtime.GOOS) 302 continue 303 } 304 t.Fatal(err) 305 } 306 if err := r.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil { 307 t.Fatal(err) 308 } 309 r.SetMulticastTTL(i + 1) 310 if err := r.WriteTo(wh, wb, nil); err != nil { 311 t.Fatal(err) 312 } 313 rb := make([]byte, ipv4.HeaderLen+128) 314 if rh, b, _, err := r.ReadFrom(rb); err != nil { 315 t.Fatal(err) 316 } else { 317 m, err := icmp.ParseMessage(iana.ProtocolICMP, b) 318 if err != nil { 319 t.Fatal(err) 320 } 321 switch { 322 case (rh.Dst.IsLoopback() || rh.Dst.IsLinkLocalUnicast() || rh.Dst.IsGlobalUnicast()) && m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1 323 case rh.Dst.IsMulticast() && m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0 324 default: 325 t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0) 326 } 327 } 328 } 329 } 330 }