...

Source file src/net/listen_test.go

Documentation: net

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

View as plain text