github.com/lianghucheng/zrddz@v0.0.0-20200923083010-c71f680932e2/src/golang.org/x/net/ipv6/multicastsockopt_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 "net" 9 "runtime" 10 "testing" 11 12 "golang.org/x/net/ipv6" 13 "golang.org/x/net/nettest" 14 ) 15 16 var packetConnMulticastSocketOptionTests = []struct { 17 net, proto, addr string 18 grp, src net.Addr 19 }{ 20 {"udp6", "", "[ff02::]:0", &net.UDPAddr{IP: net.ParseIP("ff02::114")}, nil}, // see RFC 4727 21 {"ip6", ":ipv6-icmp", "::", &net.IPAddr{IP: net.ParseIP("ff02::115")}, nil}, // see RFC 4727 22 23 {"udp6", "", "[ff30::8000:0]:0", &net.UDPAddr{IP: net.ParseIP("ff30::8000:1")}, &net.UDPAddr{IP: net.IPv6loopback}}, // see RFC 5771 24 {"ip6", ":ipv6-icmp", "::", &net.IPAddr{IP: net.ParseIP("ff30::8000:2")}, &net.IPAddr{IP: net.IPv6loopback}}, // see RFC 5771 25 } 26 27 func TestPacketConnMulticastSocketOptions(t *testing.T) { 28 switch runtime.GOOS { 29 case "fuchsia", "hurd", "js", "nacl", "plan9", "windows": 30 t.Skipf("not supported on %s", runtime.GOOS) 31 } 32 if !nettest.SupportsIPv6() { 33 t.Skip("ipv6 is not supported") 34 } 35 ifi, err := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagMulticast|net.FlagLoopback) 36 if err != nil { 37 t.Skipf("not available on %s", runtime.GOOS) 38 } 39 40 ok := nettest.SupportsRawSocket() 41 for _, tt := range packetConnMulticastSocketOptionTests { 42 if tt.net == "ip6" && !ok { 43 t.Logf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH) 44 continue 45 } 46 c, err := net.ListenPacket(tt.net+tt.proto, tt.addr) 47 if err != nil { 48 t.Fatal(err) 49 } 50 defer c.Close() 51 p := ipv6.NewPacketConn(c) 52 defer p.Close() 53 54 if tt.src == nil { 55 testMulticastSocketOptions(t, p, ifi, tt.grp) 56 } else { 57 testSourceSpecificMulticastSocketOptions(t, p, ifi, tt.grp, tt.src) 58 } 59 } 60 } 61 62 type testIPv6MulticastConn interface { 63 MulticastHopLimit() (int, error) 64 SetMulticastHopLimit(ttl int) error 65 MulticastLoopback() (bool, error) 66 SetMulticastLoopback(bool) error 67 JoinGroup(*net.Interface, net.Addr) error 68 LeaveGroup(*net.Interface, net.Addr) error 69 JoinSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error 70 LeaveSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error 71 ExcludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error 72 IncludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error 73 } 74 75 func testMulticastSocketOptions(t *testing.T, c testIPv6MulticastConn, ifi *net.Interface, grp net.Addr) { 76 t.Helper() 77 78 const hoplim = 255 79 if err := c.SetMulticastHopLimit(hoplim); err != nil { 80 t.Error(err) 81 return 82 } 83 if v, err := c.MulticastHopLimit(); err != nil { 84 t.Error(err) 85 return 86 } else if v != hoplim { 87 t.Errorf("got %v; want %v", v, hoplim) 88 return 89 } 90 91 for _, toggle := range []bool{true, false} { 92 if err := c.SetMulticastLoopback(toggle); err != nil { 93 t.Error(err) 94 return 95 } 96 if v, err := c.MulticastLoopback(); err != nil { 97 t.Error(err) 98 return 99 } else if v != toggle { 100 t.Errorf("got %v; want %v", v, toggle) 101 return 102 } 103 } 104 105 if err := c.JoinGroup(ifi, grp); err != nil { 106 t.Error(err) 107 return 108 } 109 if err := c.LeaveGroup(ifi, grp); err != nil { 110 t.Error(err) 111 return 112 } 113 } 114 115 func testSourceSpecificMulticastSocketOptions(t *testing.T, c testIPv6MulticastConn, ifi *net.Interface, grp, src net.Addr) { 116 t.Helper() 117 118 // MCAST_JOIN_GROUP -> MCAST_BLOCK_SOURCE -> MCAST_UNBLOCK_SOURCE -> MCAST_LEAVE_GROUP 119 if err := c.JoinGroup(ifi, grp); err != nil { 120 t.Error(err) 121 return 122 } 123 if err := c.ExcludeSourceSpecificGroup(ifi, grp, src); err != nil { 124 switch runtime.GOOS { 125 case "freebsd", "linux": 126 default: // platforms that don't support MLDv2 fail here 127 t.Logf("not supported on %s", runtime.GOOS) 128 return 129 } 130 t.Error(err) 131 return 132 } 133 if err := c.IncludeSourceSpecificGroup(ifi, grp, src); err != nil { 134 t.Error(err) 135 return 136 } 137 if err := c.LeaveGroup(ifi, grp); err != nil { 138 t.Error(err) 139 return 140 } 141 142 // MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_SOURCE_GROUP 143 if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil { 144 t.Error(err) 145 return 146 } 147 if err := c.LeaveSourceSpecificGroup(ifi, grp, src); err != nil { 148 t.Error(err) 149 return 150 } 151 152 // MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_GROUP 153 if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil { 154 t.Error(err) 155 return 156 } 157 if err := c.LeaveGroup(ifi, grp); err != nil { 158 t.Error(err) 159 return 160 } 161 }