1 // 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.
14 var ipv4MulticastListenerTests
= []struct {
16 gaddr
*UDPAddr
// see RFC 4727
18 {"udp", &UDPAddr
{IP
: IPv4(224, 0, 0, 254), Port
: 12345}},
20 {"udp4", &UDPAddr
{IP
: IPv4(224, 0, 0, 254), Port
: 12345}},
23 // TestIPv4MulticastListener tests both single and double listen to a
24 // test listener with same address family, same group address and same
26 func TestIPv4MulticastListener(t
*testing
.T
) {
29 t
.Skipf("skipping test on %q", runtime
.GOOS
)
31 t
.Skipf("skipping test on solaris, see issue 7399")
34 closer
:= func(cs
[]*UDPConn
) {
35 for _
, c
:= range cs
{
42 for _
, ifi
:= range []*Interface
{loopbackInterface(), nil} {
43 // Note that multicast interface assignment by system
44 // is not recommended because it usually relies on
45 // routing stuff for finding out an appropriate
46 // nexthop containing both network and link layer
48 if ifi
== nil && !*testExternal
{
51 for _
, tt
:= range ipv4MulticastListenerTests
{
53 cs
:= make([]*UDPConn
, 2)
54 if cs
[0], err
= ListenMulticastUDP(tt
.net
, ifi
, tt
.gaddr
); err
!= nil {
55 t
.Fatalf("First ListenMulticastUDP on %v failed: %v", ifi
, err
)
57 if err
:= checkMulticastListener(cs
[0], tt
.gaddr
.IP
); err
!= nil {
61 if cs
[1], err
= ListenMulticastUDP(tt
.net
, ifi
, tt
.gaddr
); err
!= nil {
63 t
.Fatalf("Second ListenMulticastUDP on %v failed: %v", ifi
, err
)
65 if err
:= checkMulticastListener(cs
[1], tt
.gaddr
.IP
); err
!= nil {
74 var ipv6MulticastListenerTests
= []struct {
76 gaddr
*UDPAddr
// see RFC 4727
78 {"udp", &UDPAddr
{IP
: ParseIP("ff01::114"), Port
: 12345}},
79 {"udp", &UDPAddr
{IP
: ParseIP("ff02::114"), Port
: 12345}},
80 {"udp", &UDPAddr
{IP
: ParseIP("ff04::114"), Port
: 12345}},
81 {"udp", &UDPAddr
{IP
: ParseIP("ff05::114"), Port
: 12345}},
82 {"udp", &UDPAddr
{IP
: ParseIP("ff08::114"), Port
: 12345}},
83 {"udp", &UDPAddr
{IP
: ParseIP("ff0e::114"), Port
: 12345}},
85 {"udp6", &UDPAddr
{IP
: ParseIP("ff01::114"), Port
: 12345}},
86 {"udp6", &UDPAddr
{IP
: ParseIP("ff02::114"), Port
: 12345}},
87 {"udp6", &UDPAddr
{IP
: ParseIP("ff04::114"), Port
: 12345}},
88 {"udp6", &UDPAddr
{IP
: ParseIP("ff05::114"), Port
: 12345}},
89 {"udp6", &UDPAddr
{IP
: ParseIP("ff08::114"), Port
: 12345}},
90 {"udp6", &UDPAddr
{IP
: ParseIP("ff0e::114"), Port
: 12345}},
93 // TestIPv6MulticastListener tests both single and double listen to a
94 // test listener with same address family, same group address and same
96 func TestIPv6MulticastListener(t
*testing
.T
) {
99 t
.Skipf("skipping test on %q", runtime
.GOOS
)
101 t
.Skipf("skipping test on solaris, see issue 7399")
104 t
.Skip("ipv6 is not supported")
106 if os
.Getuid() != 0 {
107 t
.Skip("skipping test; must be root")
110 closer
:= func(cs
[]*UDPConn
) {
111 for _
, c
:= range cs
{
118 for _
, ifi
:= range []*Interface
{loopbackInterface(), nil} {
119 // Note that multicast interface assignment by system
120 // is not recommended because it usually relies on
121 // routing stuff for finding out an appropriate
122 // nexthop containing both network and link layer
124 if ifi
== nil && (!*testExternal ||
!*testIPv6
) {
127 for _
, tt
:= range ipv6MulticastListenerTests
{
129 cs
:= make([]*UDPConn
, 2)
130 if cs
[0], err
= ListenMulticastUDP(tt
.net
, ifi
, tt
.gaddr
); err
!= nil {
131 t
.Fatalf("First ListenMulticastUDP on %v failed: %v", ifi
, err
)
133 if err
:= checkMulticastListener(cs
[0], tt
.gaddr
.IP
); err
!= nil {
137 if cs
[1], err
= ListenMulticastUDP(tt
.net
, ifi
, tt
.gaddr
); err
!= nil {
139 t
.Fatalf("Second ListenMulticastUDP on %v failed: %v", ifi
, err
)
141 if err
:= checkMulticastListener(cs
[1], tt
.gaddr
.IP
); err
!= nil {
150 func checkMulticastListener(c
*UDPConn
, ip IP
) error
{
151 if ok
, err
:= multicastRIBContains(ip
); err
!= nil {
154 return fmt
.Errorf("%q not found in multicast RIB", ip
.String())
157 if la
, ok
:= la
.(*UDPAddr
); !ok || la
.Port
== 0 {
158 return fmt
.Errorf("got %v; expected a proper address with non-zero port number", la
)
163 func multicastRIBContains(ip IP
) (bool, error
) {
164 switch runtime
.GOOS
{
165 case "dragonfly", "netbsd", "openbsd", "plan9", "solaris", "windows":
166 return true, nil // not implemented yet
168 if runtime
.GOARCH
== "arm" || runtime
.GOARCH
== "alpha" {
169 return true, nil // not implemented yet
172 ift
, err
:= Interfaces()
176 for _
, ifi
:= range ift
{
177 ifmat
, err
:= ifi
.MulticastAddrs()
181 for _
, ifma
:= range ifmat
{
182 if ifma
.(*IPAddr
).IP
.Equal(ip
) {