github.com/slayercat/go@v0.0.0-20170428012452-c51559813f61/src/net/listen_test.go (about)

     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.
     4  
     5  // +build !plan9
     6  
     7  package net
     8  
     9  import (
    10  	"fmt"
    11  	"internal/testenv"
    12  	"os"
    13  	"runtime"
    14  	"syscall"
    15  	"testing"
    16  )
    17  
    18  func (ln *TCPListener) port() string {
    19  	_, port, err := SplitHostPort(ln.Addr().String())
    20  	if err != nil {
    21  		return ""
    22  	}
    23  	return port
    24  }
    25  
    26  func (c *UDPConn) port() string {
    27  	_, port, err := SplitHostPort(c.LocalAddr().String())
    28  	if err != nil {
    29  		return ""
    30  	}
    31  	return port
    32  }
    33  
    34  var tcpListenerTests = []struct {
    35  	network string
    36  	address string
    37  }{
    38  	{"tcp", ""},
    39  	{"tcp", "0.0.0.0"},
    40  	{"tcp", "::ffff:0.0.0.0"},
    41  	{"tcp", "::"},
    42  
    43  	{"tcp", "127.0.0.1"},
    44  	{"tcp", "::ffff:127.0.0.1"},
    45  	{"tcp", "::1"},
    46  
    47  	{"tcp4", ""},
    48  	{"tcp4", "0.0.0.0"},
    49  	{"tcp4", "::ffff:0.0.0.0"},
    50  
    51  	{"tcp4", "127.0.0.1"},
    52  	{"tcp4", "::ffff:127.0.0.1"},
    53  
    54  	{"tcp6", ""},
    55  	{"tcp6", "::"},
    56  
    57  	{"tcp6", "::1"},
    58  }
    59  
    60  // TestTCPListener tests both single and double listen to a test
    61  // listener with same address family, same listening address and
    62  // same port.
    63  func TestTCPListener(t *testing.T) {
    64  	switch runtime.GOOS {
    65  	case "plan9":
    66  		t.Skipf("not supported on %s", runtime.GOOS)
    67  	}
    68  
    69  	for _, tt := range tcpListenerTests {
    70  		if !testableListenArgs(tt.network, JoinHostPort(tt.address, "0"), "") {
    71  			t.Logf("skipping %s test", tt.network+" "+tt.address)
    72  			continue
    73  		}
    74  
    75  		ln1, err := Listen(tt.network, JoinHostPort(tt.address, "0"))
    76  		if err != nil {
    77  			t.Fatal(err)
    78  		}
    79  		if err := checkFirstListener(tt.network, ln1); err != nil {
    80  			ln1.Close()
    81  			t.Fatal(err)
    82  		}
    83  		ln2, err := Listen(tt.network, JoinHostPort(tt.address, ln1.(*TCPListener).port()))
    84  		if err == nil {
    85  			ln2.Close()
    86  		}
    87  		if err := checkSecondListener(tt.network, tt.address, err); err != nil {
    88  			ln1.Close()
    89  			t.Fatal(err)
    90  		}
    91  		ln1.Close()
    92  	}
    93  }
    94  
    95  var udpListenerTests = []struct {
    96  	network string
    97  	address string
    98  }{
    99  	{"udp", ""},
   100  	{"udp", "0.0.0.0"},
   101  	{"udp", "::ffff:0.0.0.0"},
   102  	{"udp", "::"},
   103  
   104  	{"udp", "127.0.0.1"},
   105  	{"udp", "::ffff:127.0.0.1"},
   106  	{"udp", "::1"},
   107  
   108  	{"udp4", ""},
   109  	{"udp4", "0.0.0.0"},
   110  	{"udp4", "::ffff:0.0.0.0"},
   111  
   112  	{"udp4", "127.0.0.1"},
   113  	{"udp4", "::ffff:127.0.0.1"},
   114  
   115  	{"udp6", ""},
   116  	{"udp6", "::"},
   117  
   118  	{"udp6", "::1"},
   119  }
   120  
   121  // TestUDPListener tests both single and double listen to a test
   122  // listener with same address family, same listening address and
   123  // same port.
   124  func TestUDPListener(t *testing.T) {
   125  	switch runtime.GOOS {
   126  	case "plan9":
   127  		t.Skipf("not supported on %s", runtime.GOOS)
   128  	}
   129  
   130  	for _, tt := range udpListenerTests {
   131  		if !testableListenArgs(tt.network, JoinHostPort(tt.address, "0"), "") {
   132  			t.Logf("skipping %s test", tt.network+" "+tt.address)
   133  			continue
   134  		}
   135  
   136  		c1, err := ListenPacket(tt.network, JoinHostPort(tt.address, "0"))
   137  		if err != nil {
   138  			t.Fatal(err)
   139  		}
   140  		if err := checkFirstListener(tt.network, c1); err != nil {
   141  			c1.Close()
   142  			t.Fatal(err)
   143  		}
   144  		c2, err := ListenPacket(tt.network, JoinHostPort(tt.address, c1.(*UDPConn).port()))
   145  		if err == nil {
   146  			c2.Close()
   147  		}
   148  		if err := checkSecondListener(tt.network, tt.address, err); err != nil {
   149  			c1.Close()
   150  			t.Fatal(err)
   151  		}
   152  		c1.Close()
   153  	}
   154  }
   155  
   156  var dualStackTCPListenerTests = []struct {
   157  	network1, address1 string // first listener
   158  	network2, address2 string // second listener
   159  	xerr               error  // expected error value, nil or other
   160  }{
   161  	// Test cases and expected results for the attempting 2nd listen on the same port
   162  	// 1st listen                2nd listen                 darwin  freebsd  linux  openbsd
   163  	// ------------------------------------------------------------------------------------
   164  	// "tcp"  ""                 "tcp"  ""                    -        -       -       -
   165  	// "tcp"  ""                 "tcp"  "0.0.0.0"             -        -       -       -
   166  	// "tcp"  "0.0.0.0"          "tcp"  ""                    -        -       -       -
   167  	// ------------------------------------------------------------------------------------
   168  	// "tcp"  ""                 "tcp"  "[::]"                -        -       -       ok
   169  	// "tcp"  "[::]"             "tcp"  ""                    -        -       -       ok
   170  	// "tcp"  "0.0.0.0"          "tcp"  "[::]"                -        -       -       ok
   171  	// "tcp"  "[::]"             "tcp"  "0.0.0.0"             -        -       -       ok
   172  	// "tcp"  "[::ffff:0.0.0.0]" "tcp"  "[::]"                -        -       -       ok
   173  	// "tcp"  "[::]"             "tcp"  "[::ffff:0.0.0.0]"    -        -       -       ok
   174  	// ------------------------------------------------------------------------------------
   175  	// "tcp4" ""                 "tcp6" ""                    ok       ok      ok      ok
   176  	// "tcp6" ""                 "tcp4" ""                    ok       ok      ok      ok
   177  	// "tcp4" "0.0.0.0"          "tcp6" "[::]"                ok       ok      ok      ok
   178  	// "tcp6" "[::]"             "tcp4" "0.0.0.0"             ok       ok      ok      ok
   179  	// ------------------------------------------------------------------------------------
   180  	// "tcp"  "127.0.0.1"        "tcp"  "[::1]"               ok       ok      ok      ok
   181  	// "tcp"  "[::1]"            "tcp"  "127.0.0.1"           ok       ok      ok      ok
   182  	// "tcp4" "127.0.0.1"        "tcp6" "[::1]"               ok       ok      ok      ok
   183  	// "tcp6" "[::1]"            "tcp4" "127.0.0.1"           ok       ok      ok      ok
   184  	//
   185  	// Platform default configurations:
   186  	// darwin, kernel version 11.3.0
   187  	//	net.inet6.ip6.v6only=0 (overridable by sysctl or IPV6_V6ONLY option)
   188  	// freebsd, kernel version 8.2
   189  	//	net.inet6.ip6.v6only=1 (overridable by sysctl or IPV6_V6ONLY option)
   190  	// linux, kernel version 3.0.0
   191  	//	net.ipv6.bindv6only=0 (overridable by sysctl or IPV6_V6ONLY option)
   192  	// openbsd, kernel version 5.0
   193  	//	net.inet6.ip6.v6only=1 (overriding is prohibited)
   194  
   195  	{"tcp", "", "tcp", "", syscall.EADDRINUSE},
   196  	{"tcp", "", "tcp", "0.0.0.0", syscall.EADDRINUSE},
   197  	{"tcp", "0.0.0.0", "tcp", "", syscall.EADDRINUSE},
   198  
   199  	{"tcp", "", "tcp", "::", syscall.EADDRINUSE},
   200  	{"tcp", "::", "tcp", "", syscall.EADDRINUSE},
   201  	{"tcp", "0.0.0.0", "tcp", "::", syscall.EADDRINUSE},
   202  	{"tcp", "::", "tcp", "0.0.0.0", syscall.EADDRINUSE},
   203  	{"tcp", "::ffff:0.0.0.0", "tcp", "::", syscall.EADDRINUSE},
   204  	{"tcp", "::", "tcp", "::ffff:0.0.0.0", syscall.EADDRINUSE},
   205  
   206  	{"tcp4", "", "tcp6", "", nil},
   207  	{"tcp6", "", "tcp4", "", nil},
   208  	{"tcp4", "0.0.0.0", "tcp6", "::", nil},
   209  	{"tcp6", "::", "tcp4", "0.0.0.0", nil},
   210  
   211  	{"tcp", "127.0.0.1", "tcp", "::1", nil},
   212  	{"tcp", "::1", "tcp", "127.0.0.1", nil},
   213  	{"tcp4", "127.0.0.1", "tcp6", "::1", nil},
   214  	{"tcp6", "::1", "tcp4", "127.0.0.1", nil},
   215  }
   216  
   217  // TestDualStackTCPListener tests both single and double listen
   218  // to a test listener with various address families, different
   219  // listening address and same port.
   220  //
   221  // On DragonFly BSD, we expect the kernel version of node under test
   222  // to be greater than or equal to 4.4.
   223  func TestDualStackTCPListener(t *testing.T) {
   224  	switch runtime.GOOS {
   225  	case "nacl", "plan9":
   226  		t.Skipf("not supported on %s", runtime.GOOS)
   227  	}
   228  	if !supportsIPv4() || !supportsIPv6() {
   229  		t.Skip("both IPv4 and IPv6 are required")
   230  	}
   231  
   232  	for _, tt := range dualStackTCPListenerTests {
   233  		if !testableListenArgs(tt.network1, JoinHostPort(tt.address1, "0"), "") {
   234  			t.Logf("skipping %s test", tt.network1+" "+tt.address1)
   235  			continue
   236  		}
   237  
   238  		if !supportsIPv4map() && differentWildcardAddr(tt.address1, tt.address2) {
   239  			tt.xerr = nil
   240  		}
   241  		var firstErr, secondErr error
   242  		for i := 0; i < 5; i++ {
   243  			lns, err := newDualStackListener()
   244  			if err != nil {
   245  				t.Fatal(err)
   246  			}
   247  			port := lns[0].port()
   248  			for _, ln := range lns {
   249  				ln.Close()
   250  			}
   251  			var ln1 Listener
   252  			ln1, firstErr = Listen(tt.network1, JoinHostPort(tt.address1, port))
   253  			if firstErr != nil {
   254  				continue
   255  			}
   256  			if err := checkFirstListener(tt.network1, ln1); err != nil {
   257  				ln1.Close()
   258  				t.Fatal(err)
   259  			}
   260  			ln2, err := Listen(tt.network2, JoinHostPort(tt.address2, ln1.(*TCPListener).port()))
   261  			if err == nil {
   262  				ln2.Close()
   263  			}
   264  			if secondErr = checkDualStackSecondListener(tt.network2, tt.address2, err, tt.xerr); secondErr != nil {
   265  				ln1.Close()
   266  				continue
   267  			}
   268  			ln1.Close()
   269  			break
   270  		}
   271  		if firstErr != nil {
   272  			t.Error(firstErr)
   273  		}
   274  		if secondErr != nil {
   275  			t.Error(secondErr)
   276  		}
   277  	}
   278  }
   279  
   280  var dualStackUDPListenerTests = []struct {
   281  	network1, address1 string // first listener
   282  	network2, address2 string // second listener
   283  	xerr               error  // expected error value, nil or other
   284  }{
   285  	{"udp", "", "udp", "", syscall.EADDRINUSE},
   286  	{"udp", "", "udp", "0.0.0.0", syscall.EADDRINUSE},
   287  	{"udp", "0.0.0.0", "udp", "", syscall.EADDRINUSE},
   288  
   289  	{"udp", "", "udp", "::", syscall.EADDRINUSE},
   290  	{"udp", "::", "udp", "", syscall.EADDRINUSE},
   291  	{"udp", "0.0.0.0", "udp", "::", syscall.EADDRINUSE},
   292  	{"udp", "::", "udp", "0.0.0.0", syscall.EADDRINUSE},
   293  	{"udp", "::ffff:0.0.0.0", "udp", "::", syscall.EADDRINUSE},
   294  	{"udp", "::", "udp", "::ffff:0.0.0.0", syscall.EADDRINUSE},
   295  
   296  	{"udp4", "", "udp6", "", nil},
   297  	{"udp6", "", "udp4", "", nil},
   298  	{"udp4", "0.0.0.0", "udp6", "::", nil},
   299  	{"udp6", "::", "udp4", "0.0.0.0", nil},
   300  
   301  	{"udp", "127.0.0.1", "udp", "::1", nil},
   302  	{"udp", "::1", "udp", "127.0.0.1", nil},
   303  	{"udp4", "127.0.0.1", "udp6", "::1", nil},
   304  	{"udp6", "::1", "udp4", "127.0.0.1", nil},
   305  }
   306  
   307  // TestDualStackUDPListener tests both single and double listen
   308  // to a test listener with various address families, different
   309  // listening address and same port.
   310  //
   311  // On DragonFly BSD, we expect the kernel version of node under test
   312  // to be greater than or equal to 4.4.
   313  func TestDualStackUDPListener(t *testing.T) {
   314  	switch runtime.GOOS {
   315  	case "nacl", "plan9":
   316  		t.Skipf("not supported on %s", runtime.GOOS)
   317  	}
   318  	if !supportsIPv4() || !supportsIPv6() {
   319  		t.Skip("both IPv4 and IPv6 are required")
   320  	}
   321  
   322  	for _, tt := range dualStackUDPListenerTests {
   323  		if !testableListenArgs(tt.network1, JoinHostPort(tt.address1, "0"), "") {
   324  			t.Logf("skipping %s test", tt.network1+" "+tt.address1)
   325  			continue
   326  		}
   327  
   328  		if !supportsIPv4map() && differentWildcardAddr(tt.address1, tt.address2) {
   329  			tt.xerr = nil
   330  		}
   331  		var firstErr, secondErr error
   332  		for i := 0; i < 5; i++ {
   333  			cs, err := newDualStackPacketListener()
   334  			if err != nil {
   335  				t.Fatal(err)
   336  			}
   337  			port := cs[0].port()
   338  			for _, c := range cs {
   339  				c.Close()
   340  			}
   341  			var c1 PacketConn
   342  			c1, firstErr = ListenPacket(tt.network1, JoinHostPort(tt.address1, port))
   343  			if firstErr != nil {
   344  				continue
   345  			}
   346  			if err := checkFirstListener(tt.network1, c1); err != nil {
   347  				c1.Close()
   348  				t.Fatal(err)
   349  			}
   350  			c2, err := ListenPacket(tt.network2, JoinHostPort(tt.address2, c1.(*UDPConn).port()))
   351  			if err == nil {
   352  				c2.Close()
   353  			}
   354  			if secondErr = checkDualStackSecondListener(tt.network2, tt.address2, err, tt.xerr); secondErr != nil {
   355  				c1.Close()
   356  				continue
   357  			}
   358  			c1.Close()
   359  			break
   360  		}
   361  		if firstErr != nil {
   362  			t.Error(firstErr)
   363  		}
   364  		if secondErr != nil {
   365  			t.Error(secondErr)
   366  		}
   367  	}
   368  }
   369  
   370  func differentWildcardAddr(i, j string) bool {
   371  	if (i == "" || i == "0.0.0.0" || i == "::ffff:0.0.0.0") && (j == "" || j == "0.0.0.0" || j == "::ffff:0.0.0.0") {
   372  		return false
   373  	}
   374  	if i == "[::]" && j == "[::]" {
   375  		return false
   376  	}
   377  	return true
   378  }
   379  
   380  func checkFirstListener(network string, ln interface{}) error {
   381  	switch network {
   382  	case "tcp":
   383  		fd := ln.(*TCPListener).fd
   384  		if err := checkDualStackAddrFamily(fd); err != nil {
   385  			return err
   386  		}
   387  	case "tcp4":
   388  		fd := ln.(*TCPListener).fd
   389  		if fd.family != syscall.AF_INET {
   390  			return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET)
   391  		}
   392  	case "tcp6":
   393  		fd := ln.(*TCPListener).fd
   394  		if fd.family != syscall.AF_INET6 {
   395  			return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET6)
   396  		}
   397  	case "udp":
   398  		fd := ln.(*UDPConn).fd
   399  		if err := checkDualStackAddrFamily(fd); err != nil {
   400  			return err
   401  		}
   402  	case "udp4":
   403  		fd := ln.(*UDPConn).fd
   404  		if fd.family != syscall.AF_INET {
   405  			return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET)
   406  		}
   407  	case "udp6":
   408  		fd := ln.(*UDPConn).fd
   409  		if fd.family != syscall.AF_INET6 {
   410  			return fmt.Errorf("%v got %v; want %v", fd.laddr, fd.family, syscall.AF_INET6)
   411  		}
   412  	default:
   413  		return UnknownNetworkError(network)
   414  	}
   415  	return nil
   416  }
   417  
   418  func checkSecondListener(network, address string, err error) error {
   419  	switch network {
   420  	case "tcp", "tcp4", "tcp6":
   421  		if err == nil {
   422  			return fmt.Errorf("%s should fail", network+" "+address)
   423  		}
   424  	case "udp", "udp4", "udp6":
   425  		if err == nil {
   426  			return fmt.Errorf("%s should fail", network+" "+address)
   427  		}
   428  	default:
   429  		return UnknownNetworkError(network)
   430  	}
   431  	return nil
   432  }
   433  
   434  func checkDualStackSecondListener(network, address string, err, xerr error) error {
   435  	switch network {
   436  	case "tcp", "tcp4", "tcp6":
   437  		if xerr == nil && err != nil || xerr != nil && err == nil {
   438  			return fmt.Errorf("%s got %v; want %v", network+" "+address, err, xerr)
   439  		}
   440  	case "udp", "udp4", "udp6":
   441  		if xerr == nil && err != nil || xerr != nil && err == nil {
   442  			return fmt.Errorf("%s got %v; want %v", network+" "+address, err, xerr)
   443  		}
   444  	default:
   445  		return UnknownNetworkError(network)
   446  	}
   447  	return nil
   448  }
   449  
   450  func checkDualStackAddrFamily(fd *netFD) error {
   451  	switch a := fd.laddr.(type) {
   452  	case *TCPAddr:
   453  		// If a node under test supports both IPv6 capability
   454  		// and IPv6 IPv4-mapping capability, we can assume
   455  		// that the node listens on a wildcard address with an
   456  		// AF_INET6 socket.
   457  		if supportsIPv4map() && fd.laddr.(*TCPAddr).isWildcard() {
   458  			if fd.family != syscall.AF_INET6 {
   459  				return fmt.Errorf("Listen(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, syscall.AF_INET6)
   460  			}
   461  		} else {
   462  			if fd.family != a.family() {
   463  				return fmt.Errorf("Listen(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, a.family())
   464  			}
   465  		}
   466  	case *UDPAddr:
   467  		// If a node under test supports both IPv6 capability
   468  		// and IPv6 IPv4-mapping capability, we can assume
   469  		// that the node listens on a wildcard address with an
   470  		// AF_INET6 socket.
   471  		if supportsIPv4map() && fd.laddr.(*UDPAddr).isWildcard() {
   472  			if fd.family != syscall.AF_INET6 {
   473  				return fmt.Errorf("ListenPacket(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, syscall.AF_INET6)
   474  			}
   475  		} else {
   476  			if fd.family != a.family() {
   477  				return fmt.Errorf("ListenPacket(%s, %v) returns %v; want %v", fd.net, fd.laddr, fd.family, a.family())
   478  			}
   479  		}
   480  	default:
   481  		return fmt.Errorf("unexpected protocol address type: %T", a)
   482  	}
   483  	return nil
   484  }
   485  
   486  func TestWildWildcardListener(t *testing.T) {
   487  	testenv.MustHaveExternalNetwork(t)
   488  
   489  	switch runtime.GOOS {
   490  	case "plan9":
   491  		t.Skipf("not supported on %s", runtime.GOOS)
   492  	}
   493  
   494  	defer func() {
   495  		if p := recover(); p != nil {
   496  			t.Fatalf("panicked: %v", p)
   497  		}
   498  	}()
   499  
   500  	if ln, err := Listen("tcp", ""); err == nil {
   501  		ln.Close()
   502  	}
   503  	if ln, err := ListenPacket("udp", ""); err == nil {
   504  		ln.Close()
   505  	}
   506  	if ln, err := ListenTCP("tcp", nil); err == nil {
   507  		ln.Close()
   508  	}
   509  	if ln, err := ListenUDP("udp", nil); err == nil {
   510  		ln.Close()
   511  	}
   512  	if ln, err := ListenIP("ip:icmp", nil); err == nil {
   513  		ln.Close()
   514  	}
   515  }
   516  
   517  var ipv4MulticastListenerTests = []struct {
   518  	net   string
   519  	gaddr *UDPAddr // see RFC 4727
   520  }{
   521  	{"udp", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}},
   522  
   523  	{"udp4", &UDPAddr{IP: IPv4(224, 0, 0, 254), Port: 12345}},
   524  }
   525  
   526  // TestIPv4MulticastListener tests both single and double listen to a
   527  // test listener with same address family, same group address and same
   528  // port.
   529  func TestIPv4MulticastListener(t *testing.T) {
   530  	testenv.MustHaveExternalNetwork(t)
   531  
   532  	switch runtime.GOOS {
   533  	case "android", "nacl", "plan9":
   534  		t.Skipf("not supported on %s", runtime.GOOS)
   535  	case "solaris":
   536  		t.Skipf("not supported on solaris, see golang.org/issue/7399")
   537  	}
   538  	if !supportsIPv4() {
   539  		t.Skip("IPv4 is not supported")
   540  	}
   541  
   542  	closer := func(cs []*UDPConn) {
   543  		for _, c := range cs {
   544  			if c != nil {
   545  				c.Close()
   546  			}
   547  		}
   548  	}
   549  
   550  	for _, ifi := range []*Interface{loopbackInterface(), nil} {
   551  		// Note that multicast interface assignment by system
   552  		// is not recommended because it usually relies on
   553  		// routing stuff for finding out an appropriate
   554  		// nexthop containing both network and link layer
   555  		// adjacencies.
   556  		if ifi == nil || !*testIPv4 {
   557  			continue
   558  		}
   559  		for _, tt := range ipv4MulticastListenerTests {
   560  			var err error
   561  			cs := make([]*UDPConn, 2)
   562  			if cs[0], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
   563  				t.Fatal(err)
   564  			}
   565  			if err := checkMulticastListener(cs[0], tt.gaddr.IP); err != nil {
   566  				closer(cs)
   567  				t.Fatal(err)
   568  			}
   569  			if cs[1], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
   570  				closer(cs)
   571  				t.Fatal(err)
   572  			}
   573  			if err := checkMulticastListener(cs[1], tt.gaddr.IP); err != nil {
   574  				closer(cs)
   575  				t.Fatal(err)
   576  			}
   577  			closer(cs)
   578  		}
   579  	}
   580  }
   581  
   582  var ipv6MulticastListenerTests = []struct {
   583  	net   string
   584  	gaddr *UDPAddr // see RFC 4727
   585  }{
   586  	{"udp", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}},
   587  	{"udp", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}},
   588  	{"udp", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}},
   589  	{"udp", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}},
   590  	{"udp", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}},
   591  	{"udp", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}},
   592  
   593  	{"udp6", &UDPAddr{IP: ParseIP("ff01::114"), Port: 12345}},
   594  	{"udp6", &UDPAddr{IP: ParseIP("ff02::114"), Port: 12345}},
   595  	{"udp6", &UDPAddr{IP: ParseIP("ff04::114"), Port: 12345}},
   596  	{"udp6", &UDPAddr{IP: ParseIP("ff05::114"), Port: 12345}},
   597  	{"udp6", &UDPAddr{IP: ParseIP("ff08::114"), Port: 12345}},
   598  	{"udp6", &UDPAddr{IP: ParseIP("ff0e::114"), Port: 12345}},
   599  }
   600  
   601  // TestIPv6MulticastListener tests both single and double listen to a
   602  // test listener with same address family, same group address and same
   603  // port.
   604  func TestIPv6MulticastListener(t *testing.T) {
   605  	testenv.MustHaveExternalNetwork(t)
   606  
   607  	switch runtime.GOOS {
   608  	case "plan9":
   609  		t.Skipf("not supported on %s", runtime.GOOS)
   610  	case "solaris":
   611  		t.Skipf("not supported on solaris, see issue 7399")
   612  	}
   613  	if !supportsIPv6() {
   614  		t.Skip("IPv6 is not supported")
   615  	}
   616  	if os.Getuid() != 0 {
   617  		t.Skip("must be root")
   618  	}
   619  
   620  	closer := func(cs []*UDPConn) {
   621  		for _, c := range cs {
   622  			if c != nil {
   623  				c.Close()
   624  			}
   625  		}
   626  	}
   627  
   628  	for _, ifi := range []*Interface{loopbackInterface(), nil} {
   629  		// Note that multicast interface assignment by system
   630  		// is not recommended because it usually relies on
   631  		// routing stuff for finding out an appropriate
   632  		// nexthop containing both network and link layer
   633  		// adjacencies.
   634  		if ifi == nil && !*testIPv6 {
   635  			continue
   636  		}
   637  		for _, tt := range ipv6MulticastListenerTests {
   638  			var err error
   639  			cs := make([]*UDPConn, 2)
   640  			if cs[0], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
   641  				t.Fatal(err)
   642  			}
   643  			if err := checkMulticastListener(cs[0], tt.gaddr.IP); err != nil {
   644  				closer(cs)
   645  				t.Fatal(err)
   646  			}
   647  			if cs[1], err = ListenMulticastUDP(tt.net, ifi, tt.gaddr); err != nil {
   648  				closer(cs)
   649  				t.Fatal(err)
   650  			}
   651  			if err := checkMulticastListener(cs[1], tt.gaddr.IP); err != nil {
   652  				closer(cs)
   653  				t.Fatal(err)
   654  			}
   655  			closer(cs)
   656  		}
   657  	}
   658  }
   659  
   660  func checkMulticastListener(c *UDPConn, ip IP) error {
   661  	if ok, err := multicastRIBContains(ip); err != nil {
   662  		return err
   663  	} else if !ok {
   664  		return fmt.Errorf("%s not found in multicast rib", ip.String())
   665  	}
   666  	la := c.LocalAddr()
   667  	if la, ok := la.(*UDPAddr); !ok || la.Port == 0 {
   668  		return fmt.Errorf("got %v; want a proper address with non-zero port number", la)
   669  	}
   670  	return nil
   671  }
   672  
   673  func multicastRIBContains(ip IP) (bool, error) {
   674  	switch runtime.GOOS {
   675  	case "dragonfly", "netbsd", "openbsd", "plan9", "solaris", "windows":
   676  		return true, nil // not implemented yet
   677  	case "linux":
   678  		if runtime.GOARCH == "arm" || runtime.GOARCH == "alpha" {
   679  			return true, nil // not implemented yet
   680  		}
   681  	}
   682  	ift, err := Interfaces()
   683  	if err != nil {
   684  		return false, err
   685  	}
   686  	for _, ifi := range ift {
   687  		ifmat, err := ifi.MulticastAddrs()
   688  		if err != nil {
   689  			return false, err
   690  		}
   691  		for _, ifma := range ifmat {
   692  			if ifma.(*IPAddr).IP.Equal(ip) {
   693  				return true, nil
   694  			}
   695  		}
   696  	}
   697  	return false, nil
   698  }