Dmitri Shuralyov | 5d99779 | 2016-11-07 15:05:57 -0800 | [diff] [blame] | 1 | // Copyright 2012 The Go Authors. All rights reserved. |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 5 | package ipv4_test |
| 6 | |
| 7 | import ( |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 8 | "net" |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 9 | "runtime" |
| 10 | "testing" |
Mikio Hara | e5dac17 | 2014-10-07 06:35:16 +0900 | [diff] [blame] | 11 | |
Andrew Gerrand | fbe893d | 2014-11-10 09:04:43 +1100 | [diff] [blame] | 12 | "golang.org/x/net/ipv4" |
Mikio Hara | 63eda1e | 2018-07-11 01:05:18 +0900 | [diff] [blame] | 13 | "golang.org/x/net/nettest" |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 14 | ) |
| 15 | |
Mikio Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 16 | var packetConnMulticastSocketOptionTests = []struct { |
| 17 | net, proto, addr string |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 18 | grp, src net.Addr |
Mikio Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 19 | }{ |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 20 | {"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 Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 25 | } |
| 26 | |
| 27 | func TestPacketConnMulticastSocketOptions(t *testing.T) { |
| 28 | switch runtime.GOOS { |
Tobias Klauser | 938ff15 | 2023-04-18 13:22:30 +0200 | [diff] [blame] | 29 | case "fuchsia", "hurd", "js", "nacl", "plan9", "wasip1", "zos": |
Mikio Hara | 200fa7c | 2015-01-30 09:49:48 +0900 | [diff] [blame] | 30 | t.Skipf("not supported on %s", runtime.GOOS) |
Mikio Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 31 | } |
Mikio Hara | 63eda1e | 2018-07-11 01:05:18 +0900 | [diff] [blame] | 32 | ifi, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback) |
| 33 | if err != nil { |
Mikio Hara | 200fa7c | 2015-01-30 09:49:48 +0900 | [diff] [blame] | 34 | t.Skipf("not available on %s", runtime.GOOS) |
Mikio Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 35 | } |
| 36 | |
Mikio Hara | 63eda1e | 2018-07-11 01:05:18 +0900 | [diff] [blame] | 37 | ok := nettest.SupportsRawSocket() |
Mikio Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 38 | for _, tt := range packetConnMulticastSocketOptionTests { |
Mikio Hara | 99928be | 2015-01-28 12:12:10 +0900 | [diff] [blame] | 39 | if tt.net == "ip4" && !ok { |
Mikio Hara | 63eda1e | 2018-07-11 01:05:18 +0900 | [diff] [blame] | 40 | t.Logf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH) |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 41 | continue |
Mikio Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 42 | } |
| 43 | c, err := net.ListenPacket(tt.net+tt.proto, tt.addr) |
| 44 | if err != nil { |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 45 | t.Fatal(err) |
Mikio Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 46 | } |
| 47 | defer c.Close() |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 48 | p := ipv4.NewPacketConn(c) |
| 49 | defer p.Close() |
Mikio Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 50 | |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 51 | if tt.src == nil { |
| 52 | testMulticastSocketOptions(t, p, ifi, tt.grp) |
| 53 | } else { |
| 54 | testSourceSpecificMulticastSocketOptions(t, p, ifi, tt.grp, tt.src) |
| 55 | } |
Mikio Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 56 | } |
| 57 | } |
| 58 | |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 59 | var 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 Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 67 | func TestRawConnMulticastSocketOptions(t *testing.T) { |
Mikio Hara | 63eda1e | 2018-07-11 01:05:18 +0900 | [diff] [blame] | 68 | if !nettest.SupportsRawSocket() { |
| 69 | t.Skipf("not supported on %s/%s", runtime.GOOS, runtime.GOARCH) |
Mikio Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 70 | } |
Mikio Hara | 63eda1e | 2018-07-11 01:05:18 +0900 | [diff] [blame] | 71 | ifi, err := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback) |
| 72 | if err != nil { |
Mikio Hara | 200fa7c | 2015-01-30 09:49:48 +0900 | [diff] [blame] | 73 | t.Skipf("not available on %s", runtime.GOOS) |
Mikio Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 74 | } |
| 75 | |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 76 | 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 Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 87 | |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 88 | if tt.src == nil { |
| 89 | testMulticastSocketOptions(t, r, ifi, tt.grp) |
| 90 | } else { |
| 91 | testSourceSpecificMulticastSocketOptions(t, r, ifi, tt.grp, tt.src) |
| 92 | } |
Mikio Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 93 | } |
Mikio Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 94 | } |
| 95 | |
| 96 | type testIPv4MulticastConn interface { |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 97 | 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 Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 103 | 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 Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 107 | } |
| 108 | |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 109 | func testMulticastSocketOptions(t *testing.T, c testIPv4MulticastConn, ifi *net.Interface, grp net.Addr) { |
Mikio Hara | 7949ac6 | 2019-03-13 15:46:54 +0900 | [diff] [blame] | 110 | t.Helper() |
| 111 | |
Mikio Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 112 | const ttl = 255 |
| 113 | if err := c.SetMulticastTTL(ttl); err != nil { |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 114 | t.Error(err) |
| 115 | return |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 116 | } |
| 117 | if v, err := c.MulticastTTL(); err != nil { |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 118 | t.Error(err) |
| 119 | return |
Mikio Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 120 | } else if v != ttl { |
Mikio Hara | c25a4f3 | 2014-11-16 11:30:27 +0900 | [diff] [blame] | 121 | t.Errorf("got %v; want %v", v, ttl) |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 122 | return |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 123 | } |
| 124 | |
Mikio Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 125 | for _, toggle := range []bool{true, false} { |
| 126 | if err := c.SetMulticastLoopback(toggle); err != nil { |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 127 | t.Error(err) |
| 128 | return |
Mikio Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 129 | } |
| 130 | if v, err := c.MulticastLoopback(); err != nil { |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 131 | t.Error(err) |
| 132 | return |
Mikio Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 133 | } else if v != toggle { |
Mikio Hara | c25a4f3 | 2014-11-16 11:30:27 +0900 | [diff] [blame] | 134 | t.Errorf("got %v; want %v", v, toggle) |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 135 | return |
Mikio Hara | 8ecd624 | 2014-04-27 19:26:58 +0900 | [diff] [blame] | 136 | } |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 137 | } |
| 138 | |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 139 | if err := c.JoinGroup(ifi, grp); err != nil { |
| 140 | t.Error(err) |
| 141 | return |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 142 | } |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 143 | if err := c.LeaveGroup(ifi, grp); err != nil { |
| 144 | t.Error(err) |
| 145 | return |
| 146 | } |
| 147 | } |
| 148 | |
| 149 | func testSourceSpecificMulticastSocketOptions(t *testing.T, c testIPv4MulticastConn, ifi *net.Interface, grp, src net.Addr) { |
Mikio Hara | 7949ac6 | 2019-03-13 15:46:54 +0900 | [diff] [blame] | 150 | t.Helper() |
| 151 | |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 152 | // 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 Hara | 200fa7c | 2015-01-30 09:49:48 +0900 | [diff] [blame] | 161 | t.Logf("not supported on %s", runtime.GOOS) |
Mikio Hara | a33e90a | 2014-11-13 17:23:46 +0900 | [diff] [blame] | 162 | 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 Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 194 | } |
| 195 | } |