github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/net/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/hxx258456/ccgo/net/icmp" 16 "github.com/hxx258456/ccgo/net/internal/iana" 17 "github.com/hxx258456/ccgo/net/ipv6" 18 "github.com/hxx258456/ccgo/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 cm.HopLimit = i + 1 104 105 backoff := time.Millisecond 106 for { 107 n, err := p.WriteTo(wb, &cm, &grp) 108 if err != nil { 109 if n == 0 && isENOBUFS(err) { 110 time.Sleep(backoff) 111 backoff *= 2 112 continue 113 } 114 t.Fatal(err) 115 } 116 if n != len(wb) { 117 t.Fatalf("wrote %v bytes; want %v", n, len(wb)) 118 } 119 break 120 } 121 122 rb := make([]byte, 128) 123 if n, _, _, err := p.ReadFrom(rb); err != nil { 124 t.Fatal(err) 125 } else if !bytes.Equal(rb[:n], wb) { 126 t.Fatalf("got %v; want %v", rb[:n], wb) 127 } 128 } 129 } 130 } 131 132 var packetConnReadWriteMulticastICMPTests = []struct { 133 grp, src *net.IPAddr 134 }{ 135 {&net.IPAddr{IP: net.ParseIP("ff02::114")}, nil}, // see RFC 4727 136 137 {&net.IPAddr{IP: net.ParseIP("ff30::8000:1")}, &net.IPAddr{IP: net.IPv6loopback}}, // see RFC 5771 138 } 139 140 func TestPacketConnReadWriteMulticastICMP(t *testing.T) { 141 if os.Getenv("GO_BUILDER_NAME") == "openbsd-amd64-68" || 142 os.Getenv("GO_BUILDER_NAME") == "openbsd-386-68" { 143 t.Skip(`this test is currently failing on OpenBSD 6.8 builders with "raw-read ip6: i/o timeout" ` + 144 `and needs investigation, see golang.org/issue/42064`) 145 } 146 switch runtime.GOOS { 147 case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": 148 t.Skipf("not supported on %s", runtime.GOOS) 149 } 150 if !nettest.SupportsIPv6() { 151 t.Skip("ipv6 is not supported") 152 } 153 if m, ok := supportsIPv6MulticastDeliveryOnLoopback(); !ok { 154 t.Skip(m) 155 } 156 if !nettest.SupportsRawSocket() { 157 t.Skipf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH) 158 } 159 ifi, err := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagMulticast|net.FlagLoopback) 160 if err != nil { 161 t.Skipf("not available on %s", runtime.GOOS) 162 } 163 164 for _, tt := range packetConnReadWriteMulticastICMPTests { 165 c, err := net.ListenPacket("ip6:ipv6-icmp", "::") 166 if err != nil { 167 t.Fatal(err) 168 } 169 defer c.Close() 170 171 pshicmp := icmp.IPv6PseudoHeader(c.LocalAddr().(*net.IPAddr).IP, tt.grp.IP) 172 p := ipv6.NewPacketConn(c) 173 defer p.Close() 174 if tt.src == nil { 175 if err := p.JoinGroup(ifi, tt.grp); err != nil { 176 t.Fatal(err) 177 } 178 defer p.LeaveGroup(ifi, tt.grp) 179 } else { 180 if err := p.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil { 181 switch runtime.GOOS { 182 case "freebsd", "linux": 183 default: // platforms that don't support MLDv2 fail here 184 t.Logf("not supported on %s", runtime.GOOS) 185 continue 186 } 187 t.Fatal(err) 188 } 189 defer p.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src) 190 } 191 if err := p.SetMulticastInterface(ifi); err != nil { 192 t.Fatal(err) 193 } 194 if _, err := p.MulticastInterface(); err != nil { 195 t.Fatal(err) 196 } 197 if err := p.SetMulticastLoopback(true); err != nil { 198 t.Fatal(err) 199 } 200 if _, err := p.MulticastLoopback(); err != nil { 201 t.Fatal(err) 202 } 203 204 cm := ipv6.ControlMessage{ 205 TrafficClass: iana.DiffServAF11 | iana.CongestionExperienced, 206 Src: net.IPv6loopback, 207 IfIndex: ifi.Index, 208 } 209 cf := ipv6.FlagTrafficClass | ipv6.FlagHopLimit | ipv6.FlagSrc | ipv6.FlagDst | ipv6.FlagInterface | ipv6.FlagPathMTU 210 211 var f ipv6.ICMPFilter 212 f.SetAll(true) 213 f.Accept(ipv6.ICMPTypeEchoReply) 214 if err := p.SetICMPFilter(&f); err != nil { 215 t.Fatal(err) 216 } 217 218 var psh []byte 219 for i, toggle := range []bool{true, false, true} { 220 if toggle { 221 psh = nil 222 if err := p.SetChecksum(true, 2); err != nil { 223 // Illumos and Solaris never allow 224 // modification of ICMP properties. 225 if runtime.GOOS != "illumos" && runtime.GOOS != "solaris" { 226 t.Fatal(err) 227 } 228 } 229 } else { 230 psh = pshicmp 231 // Some platforms never allow to 232 // disable the kernel checksum 233 // processing. 234 p.SetChecksum(false, -1) 235 } 236 wb, err := (&icmp.Message{ 237 Type: ipv6.ICMPTypeEchoRequest, Code: 0, 238 Body: &icmp.Echo{ 239 ID: os.Getpid() & 0xffff, Seq: i + 1, 240 Data: []byte("HELLO-R-U-THERE"), 241 }, 242 }).Marshal(psh) 243 if err != nil { 244 t.Fatal(err) 245 } 246 if err := p.SetControlMessage(cf, toggle); err != nil { 247 if protocolNotSupported(err) { 248 t.Logf("not supported on %s", runtime.GOOS) 249 continue 250 } 251 t.Fatal(err) 252 } 253 cm.HopLimit = i + 1 254 if n, err := p.WriteTo(wb, &cm, tt.grp); err != nil { 255 t.Fatal(err) 256 } else if n != len(wb) { 257 t.Fatalf("got %v; want %v", n, len(wb)) 258 } 259 rb := make([]byte, 128) 260 if n, _, _, err := p.ReadFrom(rb); err != nil { 261 switch runtime.GOOS { 262 case "darwin", "ios": // older darwin kernels have some limitation on receiving icmp packet through raw socket 263 t.Logf("not supported on %s", runtime.GOOS) 264 continue 265 } 266 t.Fatal(err) 267 } else { 268 if m, err := icmp.ParseMessage(iana.ProtocolIPv6ICMP, rb[:n]); err != nil { 269 t.Fatal(err) 270 } else if m.Type != ipv6.ICMPTypeEchoReply || m.Code != 0 { 271 t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv6.ICMPTypeEchoReply, 0) 272 } 273 } 274 } 275 } 276 }