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