blob: b6a2fa6c88a995bf86d50d9260ba070c9f3e2779 [file] [log] [blame]
Dave Cheney08567312011-02-16 15:07:13 -05001// Copyright 2011 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
5package net
6
7import (
Dave Cheney8b8b54a2011-04-11 10:39:21 +10008 "flag"
Mikio Harafca50822011-08-18 12:22:02 -04009 "os"
Alex Brainman6cf98a42011-02-17 12:00:02 +110010 "runtime"
Dave Cheney08567312011-02-16 15:07:13 -050011 "testing"
12)
13
Dave Cheney8b8b54a2011-04-11 10:39:21 +100014var multicast = flag.Bool("multicast", false, "enable multicast tests")
15
Mikio Haracbdbdc42012-01-11 09:53:32 +090016var multicastUDPTests = []struct {
Mikio Harafca50822011-08-18 12:22:02 -040017 net string
18 laddr IP
19 gaddr IP
20 flags Flags
21 ipv6 bool
22}{
23 // cf. RFC 4727: Experimental Values in IPv4, IPv6, ICMPv4, ICMPv6, UDP, and TCP Headers
24 {"udp", IPv4zero, IPv4(224, 0, 0, 254), (FlagUp | FlagLoopback), false},
25 {"udp4", IPv4zero, IPv4(224, 0, 0, 254), (FlagUp | FlagLoopback), false},
26 {"udp", IPv6unspecified, ParseIP("ff0e::114"), (FlagUp | FlagLoopback), true},
27 {"udp6", IPv6unspecified, ParseIP("ff01::114"), (FlagUp | FlagLoopback), true},
28 {"udp6", IPv6unspecified, ParseIP("ff02::114"), (FlagUp | FlagLoopback), true},
29 {"udp6", IPv6unspecified, ParseIP("ff04::114"), (FlagUp | FlagLoopback), true},
30 {"udp6", IPv6unspecified, ParseIP("ff05::114"), (FlagUp | FlagLoopback), true},
31 {"udp6", IPv6unspecified, ParseIP("ff08::114"), (FlagUp | FlagLoopback), true},
32 {"udp6", IPv6unspecified, ParseIP("ff0e::114"), (FlagUp | FlagLoopback), true},
33}
34
Mikio Haracbdbdc42012-01-11 09:53:32 +090035func TestMulticastUDP(t *testing.T) {
36 if runtime.GOOS == "plan9" || runtime.GOOS == "windows" {
Alex Brainman6cf98a42011-02-17 12:00:02 +110037 return
38 }
Dave Cheney8b8b54a2011-04-11 10:39:21 +100039 if !*multicast {
40 t.Logf("test disabled; use --multicast to enable")
41 return
42 }
Dave Cheney90847a82011-02-18 13:48:13 -050043
Mikio Haracbdbdc42012-01-11 09:53:32 +090044 for _, tt := range multicastUDPTests {
Mikio Harafca50822011-08-18 12:22:02 -040045 if tt.ipv6 && (!supportsIPv6 || os.Getuid() != 0) {
46 continue
47 }
48 ift, err := Interfaces()
49 if err != nil {
Mikio Haracbdbdc42012-01-11 09:53:32 +090050 t.Fatalf("Interfaces failed: %v", err)
Mikio Harafca50822011-08-18 12:22:02 -040051 }
Mikio Hara28397be2012-02-01 00:36:45 +090052 var ifi *Interface
Mikio Harafca50822011-08-18 12:22:02 -040053 for _, x := range ift {
54 if x.Flags&tt.flags == tt.flags {
55 ifi = &x
56 break
57 }
58 }
59 if ifi == nil {
60 t.Logf("an appropriate multicast interface not found")
61 return
62 }
63 c, err := ListenUDP(tt.net, &UDPAddr{IP: tt.laddr})
64 if err != nil {
Mikio Haracbdbdc42012-01-11 09:53:32 +090065 t.Fatalf("ListenUDP failed: %v", err)
Mikio Harafca50822011-08-18 12:22:02 -040066 }
67 defer c.Close()
68 if err := c.JoinGroup(ifi, tt.gaddr); err != nil {
Mikio Haracbdbdc42012-01-11 09:53:32 +090069 t.Fatalf("JoinGroup failed: %v", err)
70 }
71 if !tt.ipv6 {
72 testIPv4MulticastSocketOptions(t, c.fd, ifi)
73 } else {
74 testIPv6MulticastSocketOptions(t, c.fd, ifi)
Mikio Harafca50822011-08-18 12:22:02 -040075 }
76 ifmat, err := ifi.MulticastAddrs()
77 if err != nil {
Mikio Haracbdbdc42012-01-11 09:53:32 +090078 t.Fatalf("MulticastAddrs failed: %v", err)
Mikio Harafca50822011-08-18 12:22:02 -040079 }
Mikio Hara28397be2012-02-01 00:36:45 +090080 var found bool
Mikio Harafca50822011-08-18 12:22:02 -040081 for _, ifma := range ifmat {
82 if ifma.(*IPAddr).IP.Equal(tt.gaddr) {
83 found = true
84 break
85 }
86 }
87 if !found {
88 t.Fatalf("%q not found in RIB", tt.gaddr.String())
89 }
90 if err := c.LeaveGroup(ifi, tt.gaddr); err != nil {
Mikio Haracbdbdc42012-01-11 09:53:32 +090091 t.Fatalf("LeaveGroup failed: %v", err)
Mikio Harafca50822011-08-18 12:22:02 -040092 }
Dave Cheney08567312011-02-16 15:07:13 -050093 }
Dave Cheney08567312011-02-16 15:07:13 -050094}
Mikio Haracbdbdc42012-01-11 09:53:32 +090095
Mikio Hara74199212012-01-15 14:19:44 +090096func TestSimpleMulticastUDP(t *testing.T) {
97 if runtime.GOOS == "plan9" {
98 return
99 }
100 if !*multicast {
101 t.Logf("test disabled; use --multicast to enable")
102 return
103 }
104
105 for _, tt := range multicastUDPTests {
106 var ifi *Interface
107 if tt.ipv6 {
108 continue
109 }
110 tt.flags = FlagUp | FlagMulticast
111 ift, err := Interfaces()
112 if err != nil {
113 t.Fatalf("Interfaces failed: %v", err)
114 }
115 for _, x := range ift {
116 if x.Flags&tt.flags == tt.flags {
117 ifi = &x
118 break
119 }
120 }
121 if ifi == nil {
122 t.Logf("an appropriate multicast interface not found")
123 return
124 }
125 c, err := ListenUDP(tt.net, &UDPAddr{IP: tt.laddr})
126 if err != nil {
127 t.Fatalf("ListenUDP failed: %v", err)
128 }
129 defer c.Close()
130 if err := c.JoinGroup(ifi, tt.gaddr); err != nil {
131 t.Fatalf("JoinGroup failed: %v", err)
132 }
133 if err := c.LeaveGroup(ifi, tt.gaddr); err != nil {
134 t.Fatalf("LeaveGroup failed: %v", err)
135 }
136 }
137}
138
Mikio Haracbdbdc42012-01-11 09:53:32 +0900139func testIPv4MulticastSocketOptions(t *testing.T, fd *netFD, ifi *Interface) {
140 ifmc, err := ipv4MulticastInterface(fd)
141 if err != nil {
142 t.Fatalf("ipv4MulticastInterface failed: %v", err)
143 }
144 t.Logf("IPv4 multicast interface: %v", ifmc)
145 err = setIPv4MulticastInterface(fd, ifi)
146 if err != nil {
147 t.Fatalf("setIPv4MulticastInterface failed: %v", err)
148 }
149
150 ttl, err := ipv4MulticastTTL(fd)
151 if err != nil {
152 t.Fatalf("ipv4MulticastTTL failed: %v", err)
153 }
154 t.Logf("IPv4 multicast TTL: %v", ttl)
155 err = setIPv4MulticastTTL(fd, 1)
156 if err != nil {
157 t.Fatalf("setIPv4MulticastTTL failed: %v", err)
158 }
159
160 loop, err := ipv4MulticastLoopback(fd)
161 if err != nil {
162 t.Fatalf("ipv4MulticastLoopback failed: %v", err)
163 }
164 t.Logf("IPv4 multicast loopback: %v", loop)
165 err = setIPv4MulticastLoopback(fd, false)
166 if err != nil {
167 t.Fatalf("setIPv4MulticastLoopback failed: %v", err)
168 }
169}
170
171func testIPv6MulticastSocketOptions(t *testing.T, fd *netFD, ifi *Interface) {
172 ifmc, err := ipv6MulticastInterface(fd)
173 if err != nil {
174 t.Fatalf("ipv6MulticastInterface failed: %v", err)
175 }
176 t.Logf("IPv6 multicast interface: %v", ifmc)
177 err = setIPv6MulticastInterface(fd, ifi)
178 if err != nil {
179 t.Fatalf("setIPv6MulticastInterface failed: %v", err)
180 }
181
182 hoplim, err := ipv6MulticastHopLimit(fd)
183 if err != nil {
184 t.Fatalf("ipv6MulticastHopLimit failed: %v", err)
185 }
186 t.Logf("IPv6 multicast hop limit: %v", hoplim)
187 err = setIPv6MulticastHopLimit(fd, 1)
188 if err != nil {
189 t.Fatalf("setIPv6MulticastHopLimit failed: %v", err)
190 }
191
192 loop, err := ipv6MulticastLoopback(fd)
193 if err != nil {
194 t.Fatalf("ipv6MulticastLoopback failed: %v", err)
195 }
196 t.Logf("IPv6 multicast loopback: %v", loop)
197 err = setIPv6MulticastLoopback(fd, false)
198 if err != nil {
199 t.Fatalf("setIPv6MulticastLoopback failed: %v", err)
200 }
201}