github.com/Andyfoo/golang/x/net@v0.0.0-20190901054642-57c1bf301704/ipv6/multicast_test.go (about) 1 // Copyright 2013 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 ipv6_test 6 7 import ( 8 "bytes" 9 "net" 10 "os" 11 "runtime" 12 "testing" 13 "time" 14 15 "github.com/Andyfoo/golang/x/net/icmp" 16 "github.com/Andyfoo/golang/x/net/internal/iana" 17 "github.com/Andyfoo/golang/x/net/ipv6" 18 "github.com/Andyfoo/golang/x/net/nettest" 19 ) 20 21 var packetConnReadWriteMulticastUDPTests = []struct { 22 addr string 23 grp, src *net.UDPAddr 24 }{ 25 {"[ff02::]:0", &net.UDPAddr{IP: net.ParseIP("ff02::114")}, nil}, // see RFC 4727 26 27 {"[ff30::8000:0]:0", &net.UDPAddr{IP: net.ParseIP("ff30::8000:1")}, &net.UDPAddr{IP: net.IPv6loopback}}, // see RFC 5771 28 } 29 30 func TestPacketConnReadWriteMulticastUDP(t *testing.T) { 31 switch runtime.GOOS { 32 case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": 33 t.Skipf("not supported on %s", runtime.GOOS) 34 } 35 if !nettest.SupportsIPv6() { 36 t.Skip("ipv6 is not supported") 37 } 38 if m, ok := supportsIPv6MulticastDeliveryOnLoopback(); !ok { 39 t.Skip(m) 40 } 41 ifi, err := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagMulticast|net.FlagLoopback) 42 if err != nil { 43 t.Skipf("not available on %s", runtime.GOOS) 44 } 45 46 for _, tt := range packetConnReadWriteMulticastUDPTests { 47 c, err := net.ListenPacket("udp6", tt.addr) 48 if err != nil { 49 t.Fatal(err) 50 } 51 defer c.Close() 52 53 grp := *tt.grp 54 grp.Port = c.LocalAddr().(*net.UDPAddr).Port 55 p := ipv6.NewPacketConn(c) 56 defer p.Close() 57 if tt.src == nil { 58 if err := p.JoinGroup(ifi, &grp); err != nil { 59 t.Fatal(err) 60 } 61 defer p.LeaveGroup(ifi, &grp) 62 } else { 63 if err := p.JoinSourceSpecificGroup(ifi, &grp, tt.src); err != nil { 64 switch runtime.GOOS { 65 case "freebsd", "linux": 66 default: // platforms that don't support MLDv2 fail here 67 t.Logf("not supported on %s", runtime.GOOS) 68 continue 69 } 70 t.Fatal(err) 71 } 72 defer p.LeaveSourceSpecificGroup(ifi, &grp, tt.src) 73 } 74 if err := p.SetMulticastInterface(ifi); err != nil { 75 t.Fatal(err) 76 } 77 if _, err := p.MulticastInterface(); err != nil { 78 t.Fatal(err) 79 } 80 if err := p.SetMulticastLoopback(true); err != nil { 81 t.Fatal(err) 82 } 83 if _, err := p.MulticastLoopback(); err != nil { 84 t.Fatal(err) 85 } 86 87 cm := ipv6.ControlMessage{ 88 TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, 89 Src: net.IPv6loopback, 90 IfIndex: ifi.Index, 91 } 92 cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU 93 wb := []byte("HELLO-R-U-THERE") 94 95 for i, toggle := range []bool{true, false, true} { 96 if err := p.SetControlMessage(cf, toggle); err != nil { 97 if protocolNotSupported(err) { 98 t.Logf("not supported on %s", runtime.GOOS) 99 continue 100 } 101 t.Fatal(err) 102 } 103 if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil { 104 t.Fatal(err) 105 } 106 cm.HopLimit = i + 1 107 if n, err := p.WriteTo(wb, &cm, &grp); err != nil { 108 t.Fatal(err) 109 } else if n != len(wb) { 110 t.Fatal(err) 111 } 112 rb := make([]byte, 128) 113 if n, _, _, err := p.ReadFrom(rb); err != nil { 114 t.Fatal(err) 115 } else if !bytes.Equal(rb[:n], wb) { 116 t.Fatalf("got %v; want %v", rb[:n], wb) 117 } 118 } 119 } 120 } 121 122 var packetConnReadWriteMulticastICMPTests = []struct { 123 grp, src *net.IPAddr 124 }{ 125 {&net.IPAddr{IP: net.ParseIP("ff02::114")}, nil}, // see RFC 4727 126 127 {&net.IPAddr{IP: net.ParseIP("ff30::8000:1")}, &net.IPAddr{IP: net.IPv6loopback}}, // see RFC 5771 128 } 129 130 func TestPacketConnReadWriteMulticastICMP(t *testing.T) { 131 switch runtime.GOOS { 132 case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": 133 t.Skipf("not supported on %s", runtime.GOOS) 134 } 135 if !nettest.SupportsIPv6() { 136 t.Skip("ipv6 is not supported") 137 } 138 if m, ok := supportsIPv6MulticastDeliveryOnLoopback(); !ok { 139 t.Skip(m) 140 } 141 if !nettest.SupportsRawSocket() { 142 t.Skipf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH) 143 } 144 ifi, err := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagMulticast|net.FlagLoopback) 145 if err != nil { 146 t.Skipf("not available on %s", runtime.GOOS) 147 } 148 149 for _, tt := range packetConnReadWriteMulticastICMPTests { 150 c, err := net.ListenPacket("ip6:ipv6-icmp", "::") 151 if err != nil { 152 t.Fatal(err) 153 } 154 defer c.Close() 155 156 pshicmp := icmp.IPv6PseudoHeader(c.LocalAddr().(*net.IPAddr).IP, tt.grp.IP) 157 p := ipv6.NewPacketConn(c) 158 defer p.Close() 159 if tt.src == nil { 160 if err := p.JoinGroup(ifi, tt.grp); err != nil { 161 t.Fatal(err) 162 } 163 defer p.LeaveGroup(ifi, tt.grp) 164 } else { 165 if err := p.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil { 166 switch runtime.GOOS { 167 case "freebsd", "linux": 168 default: // platforms that don't support MLDv2 fail here 169 t.Logf("not supported on %s", runtime.GOOS) 170 continue 171 } 172 t.Fatal(err) 173 } 174 defer p.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src) 175 } 176 if err := p.SetMulticastInterface(ifi); err != nil { 177 t.Fatal(err) 178 } 179 if _, err := p.MulticastInterface(); err != nil { 180 t.Fatal(err) 181 } 182 if err := p.SetMulticastLoopback(true); err != nil { 183 t.Fatal(err) 184 } 185 if _, err := p.MulticastLoopback(); err != nil { 186 t.Fatal(err) 187 } 188 189 cm := ipv6.ControlMessage{ 190 TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, 191 Src: net.IPv6loopback, 192 IfIndex: ifi.Index, 193 } 194 cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU 195 196 var f ipv6.ICMPFilter 197 f.SetAll(true) 198 f.Accept(ipv6.ICMPTypeEchoReply) 199 if err := p.SetICMPFilter(&f); err != nil { 200 t.Fatal(err) 201 } 202 203 var psh []byte 204 for i, toggle := range []bool{true, false, true} { 205 if toggle { 206 psh = nil 207 if err := p.SetChecksum(true, 2); err != nil { 208 // Illumos and Solaris never allow 209 // modification of ICMP properties. 210 if runtime.GOOS != "illumos" && runtime.GOOS != "solaris" { 211 t.Fatal(err) 212 } 213 } 214 } else { 215 psh = pshicmp 216 // Some platforms never allow to 217 // disable the kernel checksum 218 // processing. 219 p.SetChecksum(false, -1) 220 } 221 wb, err := (&icmp.Message{ 222 Type: ipv6.ICMPTypeEchoRequest, Code: 0, 223 Body: &icmp.Echo{ 224 ID: os.Getpid() & 0xffff, Seq: i + 1, 225 Data: []byte("HELLO-R-U-THERE"), 226 }, 227 }).Marshal(psh) 228 if err != nil { 229 t.Fatal(err) 230 } 231 if err := p.SetControlMessage(cf, toggle); err != nil { 232 if protocolNotSupported(err) { 233 t.Logf("not supported on %s", runtime.GOOS) 234 continue 235 } 236 t.Fatal(err) 237 } 238 if err := p.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil { 239 t.Fatal(err) 240 } 241 cm.HopLimit = i + 1 242 if n, err := p.WriteTo(wb, &cm, tt.grp); err != nil { 243 t.Fatal(err) 244 } else if n != len(wb) { 245 t.Fatalf("got %v; want %v", n, len(wb)) 246 } 247 rb := make([]byte, 128) 248 if n, _, _, err := p.ReadFrom(rb); err != nil { 249 switch runtime.GOOS { 250 case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket 251 t.Logf("not supported on %s", runtime.GOOS) 252 continue 253 } 254 t.Fatal(err) 255 } else { 256 if m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, rb[:n]); err != nil { 257 t.Fatal(err) 258 } else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 { 259 t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0) 260 } 261 } 262 } 263 } 264 }