blob: ddf9e60236d9f3a411bf88d6bd4680b7be0d31af [file] [log] [blame]
Dmitri Shuralyov5d997792016-11-07 15:05:57 -08001// Copyright 2012 The Go Authors. All rights reserved.
Mikio Harad2e5a122012-09-26 21:03:09 +09002// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Mikio Harad2e5a122012-09-26 21:03:09 +09005package ipv4_test
6
7import (
Mikio Harad2e5a122012-09-26 21:03:09 +09008 "net"
Mikio Harad2e5a122012-09-26 21:03:09 +09009 "runtime"
10 "testing"
Mikio Harae5dac172014-10-07 06:35:16 +090011
Andrew Gerrandfbe893d2014-11-10 09:04:43 +110012 "golang.org/x/net/ipv4"
Mikio Hara63eda1e2018-07-11 01:05:18 +090013 "golang.org/x/net/nettest"
Mikio Harad2e5a122012-09-26 21:03:09 +090014)
15
Mikio Hara8ecd6242014-04-27 19:26:58 +090016var packetConnMulticastSocketOptionTests = []struct {
17 net, proto, addr string
Mikio Haraa33e90a2014-11-13 17:23:46 +090018 grp, src net.Addr
Mikio Hara8ecd6242014-04-27 19:26:58 +090019}{
Mikio Haraa33e90a2014-11-13 17:23:46 +090020 {"udp4", "", "224.0.0.0:0", &net.UDPAddr{IP: net.IPv4(224, 0, 0, 249)}, nil}, // see RFC 4727
21 {"ip4", ":icmp", "0.0.0.0", &net.IPAddr{IP: net.IPv4(224, 0, 0, 250)}, nil}, // see RFC 4727
22
23 {"udp4", "", "232.0.0.0:0", &net.UDPAddr{IP: net.IPv4(232, 0, 1, 249)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
24 {"ip4", ":icmp", "0.0.0.0", &net.IPAddr{IP: net.IPv4(232, 0, 1, 250)}, &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
Mikio Hara8ecd6242014-04-27 19:26: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", "zos":
Mikio Hara200fa7c2015-01-30 09:49:48 +090030 t.Skipf("not supported on %s", runtime.GOOS)
Mikio Hara8ecd6242014-04-27 19:26:58 +090031 }
Mikio Hara63eda1e2018-07-11 01:05:18 +090032 ifi, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
33 if err != nil {
Mikio Hara200fa7c2015-01-30 09:49:48 +090034 t.Skipf("not available on %s", runtime.GOOS)
Mikio Hara8ecd6242014-04-27 19:26:58 +090035 }
36
Mikio Hara63eda1e2018-07-11 01:05:18 +090037 ok := nettest.SupportsRawSocket()
Mikio Hara8ecd6242014-04-27 19:26:58 +090038 for _, tt := range packetConnMulticastSocketOptionTests {
Mikio Hara99928be2015-01-28 12:12:10 +090039 if tt.net == "ip4" && !ok {
Mikio Hara63eda1e2018-07-11 01:05:18 +090040 t.Logf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH)
Mikio Haraa33e90a2014-11-13 17:23:46 +090041 continue
Mikio Hara8ecd6242014-04-27 19:26:58 +090042 }
43 c, err := net.ListenPacket(tt.net+tt.proto, tt.addr)
44 if err != nil {
Mikio Haraa33e90a2014-11-13 17:23:46 +090045 t.Fatal(err)
Mikio Hara8ecd6242014-04-27 19:26:58 +090046 }
47 defer c.Close()
Mikio Haraa33e90a2014-11-13 17:23:46 +090048 p := ipv4.NewPacketConn(c)
49 defer p.Close()
Mikio Hara8ecd6242014-04-27 19:26:58 +090050
Mikio Haraa33e90a2014-11-13 17:23:46 +090051 if tt.src == nil {
52 testMulticastSocketOptions(t, p, ifi, tt.grp)
53 } else {
54 testSourceSpecificMulticastSocketOptions(t, p, ifi, tt.grp, tt.src)
55 }
Mikio Hara8ecd6242014-04-27 19:26:58 +090056 }
57}
58
Mikio Haraa33e90a2014-11-13 17:23:46 +090059var rawConnMulticastSocketOptionTests = []struct {
60 grp, src net.Addr
61}{
62 {&net.IPAddr{IP: net.IPv4(224, 0, 0, 250)}, nil}, // see RFC 4727
63
64 {&net.IPAddr{IP: net.IPv4(232, 0, 1, 250)}, &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)}}, // see RFC 5771
65}
66
Mikio Hara8ecd6242014-04-27 19:26:58 +090067func TestRawConnMulticastSocketOptions(t *testing.T) {
Mikio Hara63eda1e2018-07-11 01:05:18 +090068 if !nettest.SupportsRawSocket() {
69 t.Skipf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH)
Mikio Hara8ecd6242014-04-27 19:26:58 +090070 }
Mikio Hara63eda1e2018-07-11 01:05:18 +090071 ifi, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback)
72 if err != nil {
Mikio Hara200fa7c2015-01-30 09:49:48 +090073 t.Skipf("not available on %s", runtime.GOOS)
Mikio Hara8ecd6242014-04-27 19:26:58 +090074 }
75
Mikio Haraa33e90a2014-11-13 17:23:46 +090076 for _, tt := range rawConnMulticastSocketOptionTests {
77 c, err := net.ListenPacket("ip4:icmp", "0.0.0.0")
78 if err != nil {
79 t.Fatal(err)
80 }
81 defer c.Close()
82 r, err := ipv4.NewRawConn(c)
83 if err != nil {
84 t.Fatal(err)
85 }
86 defer r.Close()
Mikio Hara8ecd6242014-04-27 19:26:58 +090087
Mikio Haraa33e90a2014-11-13 17:23:46 +090088 if tt.src == nil {
89 testMulticastSocketOptions(t, r, ifi, tt.grp)
90 } else {
91 testSourceSpecificMulticastSocketOptions(t, r, ifi, tt.grp, tt.src)
92 }
Mikio Hara8ecd6242014-04-27 19:26:58 +090093 }
Mikio Hara8ecd6242014-04-27 19:26:58 +090094}
95
96type testIPv4MulticastConn interface {
Mikio Harad2e5a122012-09-26 21:03:09 +090097 MulticastTTL() (int, error)
98 SetMulticastTTL(ttl int) error
99 MulticastLoopback() (bool, error)
100 SetMulticastLoopback(bool) error
101 JoinGroup(*net.Interface, net.Addr) error
102 LeaveGroup(*net.Interface, net.Addr) error
Mikio Haraa33e90a2014-11-13 17:23:46 +0900103 JoinSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
104 LeaveSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
105 ExcludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
106 IncludeSourceSpecificGroup(*net.Interface, net.Addr, net.Addr) error
Mikio Harad2e5a122012-09-26 21:03:09 +0900107}
108
Mikio Haraa33e90a2014-11-13 17:23:46 +0900109func testMulticastSocketOptions(t *testing.T, c testIPv4MulticastConn, ifi *net.Interface, grp net.Addr) {
Mikio Hara7949ac62019-03-13 15:46:54 +0900110 t.Helper()
111
Mikio Hara8ecd6242014-04-27 19:26:58 +0900112 const ttl = 255
113 if err := c.SetMulticastTTL(ttl); err != nil {
Mikio Haraa33e90a2014-11-13 17:23:46 +0900114 t.Error(err)
115 return
Mikio Harad2e5a122012-09-26 21:03:09 +0900116 }
117 if v, err := c.MulticastTTL(); err != nil {
Mikio Haraa33e90a2014-11-13 17:23:46 +0900118 t.Error(err)
119 return
Mikio Hara8ecd6242014-04-27 19:26:58 +0900120 } else if v != ttl {
Mikio Harac25a4f32014-11-16 11:30:27 +0900121 t.Errorf("got %v; want %v", v, ttl)
Mikio Haraa33e90a2014-11-13 17:23:46 +0900122 return
Mikio Harad2e5a122012-09-26 21:03:09 +0900123 }
124
Mikio Hara8ecd6242014-04-27 19:26:58 +0900125 for _, toggle := range []bool{true, false} {
126 if err := c.SetMulticastLoopback(toggle); err != nil {
Mikio Haraa33e90a2014-11-13 17:23:46 +0900127 t.Error(err)
128 return
Mikio Hara8ecd6242014-04-27 19:26:58 +0900129 }
130 if v, err := c.MulticastLoopback(); err != nil {
Mikio Haraa33e90a2014-11-13 17:23:46 +0900131 t.Error(err)
132 return
Mikio Hara8ecd6242014-04-27 19:26:58 +0900133 } else if v != toggle {
Mikio Harac25a4f32014-11-16 11:30:27 +0900134 t.Errorf("got %v; want %v", v, toggle)
Mikio Haraa33e90a2014-11-13 17:23:46 +0900135 return
Mikio Hara8ecd6242014-04-27 19:26:58 +0900136 }
Mikio Harad2e5a122012-09-26 21:03:09 +0900137 }
138
Mikio Haraa33e90a2014-11-13 17:23:46 +0900139 if err := c.JoinGroup(ifi, grp); err != nil {
140 t.Error(err)
141 return
Mikio Harad2e5a122012-09-26 21:03:09 +0900142 }
Mikio Haraa33e90a2014-11-13 17:23:46 +0900143 if err := c.LeaveGroup(ifi, grp); err != nil {
144 t.Error(err)
145 return
146 }
147}
148
149func testSourceSpecificMulticastSocketOptions(t *testing.T, c testIPv4MulticastConn, ifi *net.Interface, grp, src net.Addr) {
Mikio Hara7949ac62019-03-13 15:46:54 +0900150 t.Helper()
151
Mikio Haraa33e90a2014-11-13 17:23:46 +0900152 // MCAST_JOIN_GROUP -> MCAST_BLOCK_SOURCE -> MCAST_UNBLOCK_SOURCE -> MCAST_LEAVE_GROUP
153 if err := c.JoinGroup(ifi, grp); err != nil {
154 t.Error(err)
155 return
156 }
157 if err := c.ExcludeSourceSpecificGroup(ifi, grp, src); err != nil {
158 switch runtime.GOOS {
159 case "freebsd", "linux":
160 default: // platforms that don't support IGMPv2/3 fail here
Mikio Hara200fa7c2015-01-30 09:49:48 +0900161 t.Logf("not supported on %s", runtime.GOOS)
Mikio Haraa33e90a2014-11-13 17:23:46 +0900162 return
163 }
164 t.Error(err)
165 return
166 }
167 if err := c.IncludeSourceSpecificGroup(ifi, grp, src); err != nil {
168 t.Error(err)
169 return
170 }
171 if err := c.LeaveGroup(ifi, grp); err != nil {
172 t.Error(err)
173 return
174 }
175
176 // MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_SOURCE_GROUP
177 if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil {
178 t.Error(err)
179 return
180 }
181 if err := c.LeaveSourceSpecificGroup(ifi, grp, src); err != nil {
182 t.Error(err)
183 return
184 }
185
186 // MCAST_JOIN_SOURCE_GROUP -> MCAST_LEAVE_GROUP
187 if err := c.JoinSourceSpecificGroup(ifi, grp, src); err != nil {
188 t.Error(err)
189 return
190 }
191 if err := c.LeaveGroup(ifi, grp); err != nil {
192 t.Error(err)
193 return
Mikio Harad2e5a122012-09-26 21:03:09 +0900194 }
195}