net: join and leave a IPv6 group address, on a specific interface
This CL changes both JoinGroup and LeaveGroup methods
to take an interface as an argument for enabling IPv6
group address join/leave, join a group address on a
specific interface.
R=rsc, dave
CC=golang-dev
https://golang.org/cl/4815074
diff --git a/src/pkg/net/multicast_test.go b/src/pkg/net/multicast_test.go
index be6dbf2..a66250c 100644
--- a/src/pkg/net/multicast_test.go
+++ b/src/pkg/net/multicast_test.go
@@ -6,13 +6,33 @@
import (
"flag"
+ "os"
"runtime"
"testing"
)
var multicast = flag.Bool("multicast", false, "enable multicast tests")
-func TestMulticastJoinAndLeave(t *testing.T) {
+var joinAndLeaveGroupUDPTests = []struct {
+ net string
+ laddr IP
+ gaddr IP
+ flags Flags
+ ipv6 bool
+}{
+ // cf. RFC 4727: Experimental Values in IPv4, IPv6, ICMPv4, ICMPv6, UDP, and TCP Headers
+ {"udp", IPv4zero, IPv4(224, 0, 0, 254), (FlagUp | FlagLoopback), false},
+ {"udp4", IPv4zero, IPv4(224, 0, 0, 254), (FlagUp | FlagLoopback), false},
+ {"udp", IPv6unspecified, ParseIP("ff0e::114"), (FlagUp | FlagLoopback), true},
+ {"udp6", IPv6unspecified, ParseIP("ff01::114"), (FlagUp | FlagLoopback), true},
+ {"udp6", IPv6unspecified, ParseIP("ff02::114"), (FlagUp | FlagLoopback), true},
+ {"udp6", IPv6unspecified, ParseIP("ff04::114"), (FlagUp | FlagLoopback), true},
+ {"udp6", IPv6unspecified, ParseIP("ff05::114"), (FlagUp | FlagLoopback), true},
+ {"udp6", IPv6unspecified, ParseIP("ff08::114"), (FlagUp | FlagLoopback), true},
+ {"udp6", IPv6unspecified, ParseIP("ff0e::114"), (FlagUp | FlagLoopback), true},
+}
+
+func TestJoinAndLeaveGroupUDP(t *testing.T) {
if runtime.GOOS == "windows" {
return
}
@@ -21,53 +41,51 @@
return
}
- addr := &UDPAddr{
- IP: IPv4zero,
- Port: 0,
+ for _, tt := range joinAndLeaveGroupUDPTests {
+ var (
+ ifi *Interface
+ found bool
+ )
+ if tt.ipv6 && (!supportsIPv6 || os.Getuid() != 0) {
+ continue
+ }
+ ift, err := Interfaces()
+ if err != nil {
+ t.Fatalf("Interfaces() failed: %v", err)
+ }
+ for _, x := range ift {
+ if x.Flags&tt.flags == tt.flags {
+ ifi = &x
+ break
+ }
+ }
+ if ifi == nil {
+ t.Logf("an appropriate multicast interface not found")
+ return
+ }
+ c, err := ListenUDP(tt.net, &UDPAddr{IP: tt.laddr})
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer c.Close()
+ if err := c.JoinGroup(ifi, tt.gaddr); err != nil {
+ t.Fatal(err)
+ }
+ ifmat, err := ifi.MulticastAddrs()
+ if err != nil {
+ t.Fatalf("MulticastAddrs() failed: %v", err)
+ }
+ for _, ifma := range ifmat {
+ if ifma.(*IPAddr).IP.Equal(tt.gaddr) {
+ found = true
+ break
+ }
+ }
+ if !found {
+ t.Fatalf("%q not found in RIB", tt.gaddr.String())
+ }
+ if err := c.LeaveGroup(ifi, tt.gaddr); err != nil {
+ t.Fatal(err)
+ }
}
- // open a UDPConn
- conn, err := ListenUDP("udp4", addr)
- if err != nil {
- t.Fatal(err)
- }
- defer conn.Close()
-
- // try to join group
- mcast := IPv4(224, 0, 0, 254)
- err = conn.JoinGroup(mcast)
- if err != nil {
- t.Fatal(err)
- }
-
- // try to leave group
- err = conn.LeaveGroup(mcast)
- if err != nil {
- t.Fatal(err)
- }
-}
-
-func TestJoinFailureWithIPv6Address(t *testing.T) {
- if !*multicast {
- t.Logf("test disabled; use --multicast to enable")
- return
- }
- addr := &UDPAddr{
- IP: IPv4zero,
- Port: 0,
- }
-
- // open a UDPConn
- conn, err := ListenUDP("udp4", addr)
- if err != nil {
- t.Fatal(err)
- }
- defer conn.Close()
-
- // try to join group
- mcast := ParseIP("ff02::1")
- err = conn.JoinGroup(mcast)
- if err == nil {
- t.Fatal("JoinGroup succeeded, should fail")
- }
- t.Logf("%s", err)
}