blob: 9d4de24c2a9d070f1390e72af0071ad9e6d707a3 [file] [log] [blame]
Dmitri Shuralyov5d997792016-11-07 15:05:57 -08001// Copyright 2013 The Go Authors. All rights reserved.
Mikio Haracdfc4ce2013-06-04 17:42:58 +09002// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package ipv6_test
6
7import (
Mikio Haracdfc4ce2013-06-04 17:42:58 +09008 "net"
Mikio Haracdfc4ce2013-06-04 17:42:58 +09009 "runtime"
10 "testing"
Mikio Hara77ebfc52014-11-09 20:14:20 +090011
Andrew Gerrandfbe893d2014-11-10 09:04:43 +110012 "golang.org/x/net/ipv6"
Mikio Hara63eda1e2018-07-11 01:05:18 +090013 "golang.org/x/net/nettest"
Mikio Haracdfc4ce2013-06-04 17:42:58 +090014)
15
16var packetConnMulticastSocketOptionTests = []struct {
17 net, proto, addr string
Mikio Hara40ad15c2014-11-14 17:45:32 +090018 grp, src net.Addr
Mikio Haracdfc4ce2013-06-04 17:42:58 +090019}{
Mikio Hara40ad15c2014-11-14 17:45:32 +090020 {"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
Mikio Haracdfc4ce2013-06-04 17:42:58 +090025}
26
27func TestPacketConnMulticastSocketOptions(t *testing.T) {
28 switch runtime.GOOS {
Tobias Klauser938ff152023-04-18 13:22:30 +020029 case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "windows":
Mikio Hara9dd48c22015-01-30 09:55:20 +090030 t.Skipf("not supported on %s", runtime.GOOS)
Mikio Haracdfc4ce2013-06-04 17:42:58 +090031 }
Mikio Hara63eda1e2018-07-11 01:05:18 +090032 if !nettest.SupportsIPv6() {
Mikio Haraa46af892013-06-06 17:12:18 +090033 t.Skip("ipv6 is not supported")
34 }
Mikio Hara63eda1e2018-07-11 01:05:18 +090035 ifi, err := nettest.RoutedInterface("ip6", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
36 if err != nil {
Mikio Hara9dd48c22015-01-30 09:55:20 +090037 t.Skipf("not available on %s", runtime.GOOS)
Mikio Haracdfc4ce2013-06-04 17:42:58 +090038 }
39
Mikio Hara63eda1e2018-07-11 01:05:18 +090040 ok := nettest.SupportsRawSocket()
Mikio Haracdfc4ce2013-06-04 17:42:58 +090041 for _, tt := range packetConnMulticastSocketOptionTests {
Mikio Hara1439fec2015-01-28 12:10:59 +090042 if tt.net == "ip6" && !ok {
Mikio Hara63eda1e2018-07-11 01:05:18 +090043 t.Logf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH)
Mikio Hara40ad15c2014-11-14 17:45:32 +090044 continue
Mikio Haracdfc4ce2013-06-04 17:42:58 +090045 }
46 c, err := net.ListenPacket(tt.net+tt.proto, tt.addr)
47 if err != nil {
Mikio Hara40ad15c2014-11-14 17:45:32 +090048 t.Fatal(err)
Mikio Haracdfc4ce2013-06-04 17:42:58 +090049 }
50 defer c.Close()
Mikio Haracdfc4ce2013-06-04 17:42:58 +090051 p := ipv6.NewPacketConn(c)
Mikio Hara40ad15c2014-11-14 17:45:32 +090052 defer p.Close()
Mikio Haracdfc4ce2013-06-04 17:42:58 +090053
Mikio Hara40ad15c2014-11-14 17:45:32 +090054 if tt.src == nil {
55 testMulticastSocketOptions(t, p, ifi, tt.grp)
56 } else {
57 testSourceSpecificMulticastSocketOptions(t, p, ifi, tt.grp, tt.src)
Mikio Haracdfc4ce2013-06-04 17:42:58 +090058 }
Mikio Hara40ad15c2014-11-14 17:45:32 +090059 }
60}
Mikio Haracdfc4ce2013-06-04 17:42:58 +090061
Mikio Hara40ad15c2014-11-14 17:45:32 +090062type 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}
Mikio Haracdfc4ce2013-06-04 17:42:58 +090074
Mikio Hara40ad15c2014-11-14 17:45:32 +090075func testMulticastSocketOptions(t *testing.T, c testIPv6MulticastConn, ifi *net.Interface, grp net.Addr) {
Mikio Hara9f648a62019-03-13 15:50:29 +090076 t.Helper()
77
Mikio Hara40ad15c2014-11-14 17:45:32 +090078 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 {
Mikio Harab56b6092014-11-16 11:31:00 +090087 t.Errorf("got %v; want %v", v, hoplim)
Mikio Hara40ad15c2014-11-14 17:45:32 +090088 return
89 }
90
91 for _, toggle := range []bool{true, false} {
92 if err := c.SetMulticastLoopback(toggle); err != nil {
93 t.Error(err)
94 return
Mikio Haracdfc4ce2013-06-04 17:42:58 +090095 }
Mikio Hara40ad15c2014-11-14 17:45:32 +090096 if v, err := c.MulticastLoopback(); err != nil {
97 t.Error(err)
98 return
99 } else if v != toggle {
Mikio Harab56b6092014-11-16 11:31:00 +0900100 t.Errorf("got %v; want %v", v, toggle)
Mikio Hara40ad15c2014-11-14 17:45:32 +0900101 return
Mikio Haracdfc4ce2013-06-04 17:42:58 +0900102 }
103 }
Mikio Hara40ad15c2014-11-14 17:45:32 +0900104
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
115func testSourceSpecificMulticastSocketOptions(t *testing.T, c testIPv6MulticastConn, ifi *net.Interface, grp, src net.Addr) {
Mikio Hara9f648a62019-03-13 15:50:29 +0900116 t.Helper()
117
Mikio Hara40ad15c2014-11-14 17:45:32 +0900118 // 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":
Mikio Harab56b6092014-11-16 11:31:00 +0900126 default: // platforms that don't support MLDv2 fail here
Mikio Hara9dd48c22015-01-30 09:55:20 +0900127 t.Logf("not supported on %s", runtime.GOOS)
Mikio Hara40ad15c2014-11-14 17:45:32 +0900128 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 }
Mikio Haracdfc4ce2013-06-04 17:42:58 +0900161}