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
)
32 closer
:= func(cs
[]*UDPConn
) {
33 for _
, c
:= range cs
{
40 for _
, ifi
:= range []*Interface
{loopbackInterface(), nil} {
41 // Note that multicast interface assignment by system
42 // is not recommended because it usually relies on
43 // routing stuff for finding out an appropriate
44 // nexthop containing both network and link layer
46 if ifi
== nil && !*testExternal
{
49 for _
, tt
:= range ipv4MulticastListenerTests
{
51 cs
:= make([]*UDPConn
, 2)
52 if cs
[0], err
= ListenMulticastUDP(tt
.net
, ifi
, tt
.gaddr
); err
!= nil {
53 t
.Fatalf("First ListenMulticastUDP on %v failed: %v", ifi
, err
)
55 if err
:= checkMulticastListener(cs
[0], tt
.gaddr
.IP
); err
!= nil {
59 if cs
[1], err
= ListenMulticastUDP(tt
.net
, ifi
, tt
.gaddr
); err
!= nil {
61 t
.Fatalf("Second ListenMulticastUDP on %v failed: %v", ifi
, err
)
63 if err
:= checkMulticastListener(cs
[1], tt
.gaddr
.IP
); err
!= nil {
72 var ipv6MulticastListenerTests
= []struct {
74 gaddr
*UDPAddr
// see RFC 4727
76 {"udp", &UDPAddr
{IP
: ParseIP("ff01::114"), Port
: 12345}},
77 {"udp", &UDPAddr
{IP
: ParseIP("ff02::114"), Port
: 12345}},
78 {"udp", &UDPAddr
{IP
: ParseIP("ff04::114"), Port
: 12345}},
79 {"udp", &UDPAddr
{IP
: ParseIP("ff05::114"), Port
: 12345}},
80 {"udp", &UDPAddr
{IP
: ParseIP("ff08::114"), Port
: 12345}},
81 {"udp", &UDPAddr
{IP
: ParseIP("ff0e::114"), Port
: 12345}},
83 {"udp6", &UDPAddr
{IP
: ParseIP("ff01::114"), Port
: 12345}},
84 {"udp6", &UDPAddr
{IP
: ParseIP("ff02::114"), Port
: 12345}},
85 {"udp6", &UDPAddr
{IP
: ParseIP("ff04::114"), Port
: 12345}},
86 {"udp6", &UDPAddr
{IP
: ParseIP("ff05::114"), Port
: 12345}},
87 {"udp6", &UDPAddr
{IP
: ParseIP("ff08::114"), Port
: 12345}},
88 {"udp6", &UDPAddr
{IP
: ParseIP("ff0e::114"), Port
: 12345}},
91 // TestIPv6MulticastListener tests both single and double listen to a
92 // test listener with same address family, same group address and same
94 func TestIPv6MulticastListener(t
*testing
.T
) {
96 case "plan9", "solaris":
97 t
.Skipf("skipping test on %q", runtime
.GOOS
)
100 t
.Skip("ipv6 is not supported")
102 if os
.Getuid() != 0 {
103 t
.Skip("skipping test; must be root")
106 closer
:= func(cs
[]*UDPConn
) {
107 for _
, c
:= range cs
{
114 for _
, ifi
:= range []*Interface
{loopbackInterface(), nil} {
115 // Note that multicast interface assignment by system
116 // is not recommended because it usually relies on
117 // routing stuff for finding out an appropriate
118 // nexthop containing both network and link layer
120 if ifi
== nil && (!*testExternal ||
!*testIPv6
) {
123 for _
, tt
:= range ipv6MulticastListenerTests
{
125 cs
:= make([]*UDPConn
, 2)
126 if cs
[0], err
= ListenMulticastUDP(tt
.net
, ifi
, tt
.gaddr
); err
!= nil {
127 t
.Fatalf("First ListenMulticastUDP on %v failed: %v", ifi
, err
)
129 if err
:= checkMulticastListener(cs
[0], tt
.gaddr
.IP
); err
!= nil {
133 if cs
[1], err
= ListenMulticastUDP(tt
.net
, ifi
, tt
.gaddr
); err
!= nil {
135 t
.Fatalf("Second ListenMulticastUDP on %v failed: %v", ifi
, err
)
137 if err
:= checkMulticastListener(cs
[1], tt
.gaddr
.IP
); err
!= nil {
146 func checkMulticastListener(c
*UDPConn
, ip IP
) error
{
147 if ok
, err
:= multicastRIBContains(ip
); err
!= nil {
150 return fmt
.Errorf("%q not found in multicast RIB", ip
.String())
153 if la
, ok
:= la
.(*UDPAddr
); !ok || la
.Port
== 0 {
154 return fmt
.Errorf("got %v; expected a proper address with non-zero port number", la
)
159 func multicastRIBContains(ip IP
) (bool, error
) {
160 switch runtime
.GOOS
{
161 case "netbsd", "openbsd", "plan9", "solaris", "windows":
162 return true, nil // not implemented yet
164 if runtime
.GOARCH
== "arm" || runtime
.GOARCH
== "alpha" {
165 return true, nil // not implemented yet
168 ift
, err
:= Interfaces()
172 for _
, ifi
:= range ift
{
173 ifmat
, err
:= ifi
.MulticastAddrs()
177 for _
, ifma
:= range ifmat
{
178 if ifma
.(*IPAddr
).IP
.Equal(ip
) {