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.
18 func (ln
*TCPListener
) port() string {
19 _
, port
, err
:= SplitHostPort(ln
.Addr().String())
26 func (c
*UDPConn
) port() string {
27 _
, port
, err
:= SplitHostPort(c
.LocalAddr().String())
34 var tcpListenerTests
= []struct {
40 {"tcp", "::ffff:0.0.0.0"},
44 {"tcp", "::ffff:127.0.0.1"},
49 {"tcp4", "::ffff:0.0.0.0"},
51 {"tcp4", "127.0.0.1"},
52 {"tcp4", "::ffff:127.0.0.1"},
60 // TestTCPListener tests both single and double listen to a test
61 // listener with same address family, same listening address and
63 func TestTCPListener(t
*testing
.T
) {
66 t
.Skipf("not supported on %s", runtime
.GOOS
)
69 for _
, tt
:= range tcpListenerTests
{
70 if !testableListenArgs(tt
.network
, JoinHostPort(tt
.address
, "0"), "") {
71 t
.Logf("skipping %s test", tt
.network
+" "+tt
.address
)
75 ln1
, err
:= Listen(tt
.network
, JoinHostPort(tt
.address
, "0"))
79 if err
:= checkFirstListener(tt
.network
, ln1
); err
!= nil {
83 ln2
, err
:= Listen(tt
.network
, JoinHostPort(tt
.address
, ln1
.(*TCPListener
).port()))
87 if err
:= checkSecondListener(tt
.network
, tt
.address
, err
); err
!= nil {
95 var udpListenerTests
= []struct {
101 {"udp", "::ffff:0.0.0.0"},
104 {"udp", "127.0.0.1"},
105 {"udp", "::ffff:127.0.0.1"},
110 {"udp4", "::ffff:0.0.0.0"},
112 {"udp4", "127.0.0.1"},
113 {"udp4", "::ffff:127.0.0.1"},
121 // TestUDPListener tests both single and double listen to a test
122 // listener with same address family, same listening address and
124 func TestUDPListener(t
*testing
.T
) {
125 switch runtime
.GOOS
{
127 t
.Skipf("not supported on %s", runtime
.GOOS
)
130 for _
, tt
:= range udpListenerTests
{
131 if !testableListenArgs(tt
.network
, JoinHostPort(tt
.address
, "0"), "") {
132 t
.Logf("skipping %s test", tt
.network
+" "+tt
.address
)
136 c1
, err
:= ListenPacket(tt
.network
, JoinHostPort(tt
.address
, "0"))
140 if err
:= checkFirstListener(tt
.network
, c1
); err
!= nil {
144 c2
, err
:= ListenPacket(tt
.network
, JoinHostPort(tt
.address
, c1
.(*UDPConn
).port()))
148 if err
:= checkSecondListener(tt
.network
, tt
.address
, err
); err
!= nil {
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
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
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)
195 {"tcp", "", "tcp", "", syscall
.EADDRINUSE
},
196 {"tcp", "", "tcp", "0.0.0.0", syscall
.EADDRINUSE
},
197 {"tcp", "0.0.0.0", "tcp", "", syscall
.EADDRINUSE
},
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
},
206 {"tcp4", "", "tcp6", "", nil},
207 {"tcp6", "", "tcp4", "", nil},
208 {"tcp4", "0.0.0.0", "tcp6", "::", nil},
209 {"tcp6", "::", "tcp4", "0.0.0.0", nil},
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},
217 // TestDualStackTCPListener tests both single and double listen
218 // to a test listener with various address families, different
219 // listening address and same port.
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
)
228 if !supportsIPv4 ||
!supportsIPv6
{
229 t
.Skip("both IPv4 and IPv6 are required")
232 for _
, tt
:= range dualStackTCPListenerTests
{
233 if !testableListenArgs(tt
.network1
, JoinHostPort(tt
.address1
, "0"), "") {
234 t
.Logf("skipping %s test", tt
.network1
+" "+tt
.address1
)
238 if !supportsIPv4map
&& differentWildcardAddr(tt
.address1
, tt
.address2
) {
241 var firstErr
, secondErr error
242 for i
:= 0; i
< 5; i
++ {
243 lns
, err
:= newDualStackListener()
247 port
:= lns
[0].port()
248 for _
, ln
:= range lns
{
252 ln1
, firstErr
= Listen(tt
.network1
, JoinHostPort(tt
.address1
, port
))
256 if err
:= checkFirstListener(tt
.network1
, ln1
); err
!= nil {
260 ln2
, err
:= Listen(tt
.network2
, JoinHostPort(tt
.address2
, ln1
.(*TCPListener
).port()))
264 if secondErr
= checkDualStackSecondListener(tt
.network2
, tt
.address2
, err
, tt
.xerr
); secondErr
!= nil {
274 if secondErr
!= nil {
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
285 {"udp", "", "udp", "", syscall
.EADDRINUSE
},
286 {"udp", "", "udp", "0.0.0.0", syscall
.EADDRINUSE
},
287 {"udp", "0.0.0.0", "udp", "", syscall
.EADDRINUSE
},
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
},
296 {"udp4", "", "udp6", "", nil},
297 {"udp6", "", "udp4", "", nil},
298 {"udp4", "0.0.0.0", "udp6", "::", nil},
299 {"udp6", "::", "udp4", "0.0.0.0", nil},
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},
307 // TestDualStackUDPListener tests both single and double listen
308 // to a test listener with various address families, different
309 // listening address and same port.
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
)
318 if !supportsIPv4 ||
!supportsIPv6
{
319 t
.Skip("both IPv4 and IPv6 are required")
322 for _
, tt
:= range dualStackUDPListenerTests
{
323 if !testableListenArgs(tt
.network1
, JoinHostPort(tt
.address1
, "0"), "") {
324 t
.Logf("skipping %s test", tt
.network1
+" "+tt
.address1
)
328 if !supportsIPv4map
&& differentWildcardAddr(tt
.address1
, tt
.address2
) {
331 var firstErr
, secondErr error
332 for i
:= 0; i
< 5; i
++ {
333 cs
, err
:= newDualStackPacketListener()
338 for _
, c
:= range cs
{
342 c1
, firstErr
= ListenPacket(tt
.network1
, JoinHostPort(tt
.address1
, port
))
346 if err
:= checkFirstListener(tt
.network1
, c1
); err
!= nil {
350 c2
, err
:= ListenPacket(tt
.network2
, JoinHostPort(tt
.address2
, c1
.(*UDPConn
).port()))
354 if secondErr
= checkDualStackSecondListener(tt
.network2
, tt
.address2
, err
, tt
.xerr
); secondErr
!= nil {
364 if secondErr
!= nil {
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") {
374 if i
== "[::]" && j
== "[::]" {
380 func checkFirstListener(network
string, ln
interface{}) error
{
383 fd
:= ln
.(*TCPListener
).fd
384 if err
:= checkDualStackAddrFamily(fd
); err
!= nil {
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
)
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
)
398 fd
:= ln
.(*UDPConn
).fd
399 if err
:= checkDualStackAddrFamily(fd
); err
!= nil {
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
)
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
)
413 return UnknownNetworkError(network
)
418 func checkSecondListener(network
, address
string, err error
) error
{
420 case "tcp", "tcp4", "tcp6":
422 return fmt
.Errorf("%s should fail", network
+" "+address
)
424 case "udp", "udp4", "udp6":
426 return fmt
.Errorf("%s should fail", network
+" "+address
)
429 return UnknownNetworkError(network
)
434 func checkDualStackSecondListener(network
, address
string, err
, xerr error
) error
{
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
)
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
)
445 return UnknownNetworkError(network
)
450 func checkDualStackAddrFamily(fd
*netFD
) error
{
451 switch a
:= fd
.laddr
.(type) {
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
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
)
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())
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
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
)
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())
481 return fmt
.Errorf("unexpected protocol address type: %T", a
)
486 func TestWildWildcardListener(t
*testing
.T
) {
487 testenv
.MustHaveExternalNetwork(t
)
489 switch runtime
.GOOS
{
491 t
.Skipf("not supported on %s", runtime
.GOOS
)
495 if p
:= recover(); p
!= nil {
496 t
.Fatalf("panicked: %v", p
)
500 if ln
, err
:= Listen("tcp", ""); err
== nil {
503 if ln
, err
:= ListenPacket("udp", ""); err
== nil {
506 if ln
, err
:= ListenTCP("tcp", nil); err
== nil {
509 if ln
, err
:= ListenUDP("udp", nil); err
== nil {
512 if ln
, err
:= ListenIP("ip:icmp", nil); err
== nil {
517 var ipv4MulticastListenerTests
= []struct {
519 gaddr
*UDPAddr
// see RFC 4727
521 {"udp", &UDPAddr
{IP
: IPv4(224, 0, 0, 254), Port
: 12345}},
523 {"udp4", &UDPAddr
{IP
: IPv4(224, 0, 0, 254), Port
: 12345}},
526 // TestIPv4MulticastListener tests both single and double listen to a
527 // test listener with same address family, same group address and same
529 func TestIPv4MulticastListener(t
*testing
.T
) {
530 testenv
.MustHaveExternalNetwork(t
)
532 switch runtime
.GOOS
{
533 case "android", "nacl", "plan9":
534 t
.Skipf("not supported on %s", runtime
.GOOS
)
536 t
.Skipf("not supported on solaris, see golang.org/issue/7399")
539 t
.Skip("IPv4 is not supported")
542 closer
:= func(cs
[]*UDPConn
) {
543 for _
, c
:= range cs
{
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
556 if ifi
== nil ||
!*testIPv4
{
559 for _
, tt
:= range ipv4MulticastListenerTests
{
561 cs
:= make([]*UDPConn
, 2)
562 if cs
[0], err
= ListenMulticastUDP(tt
.net
, ifi
, tt
.gaddr
); err
!= nil {
565 if err
:= checkMulticastListener(cs
[0], tt
.gaddr
.IP
); err
!= nil {
569 if cs
[1], err
= ListenMulticastUDP(tt
.net
, ifi
, tt
.gaddr
); err
!= nil {
573 if err
:= checkMulticastListener(cs
[1], tt
.gaddr
.IP
); err
!= nil {
582 var ipv6MulticastListenerTests
= []struct {
584 gaddr
*UDPAddr
// see RFC 4727
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}},
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}},
601 // TestIPv6MulticastListener tests both single and double listen to a
602 // test listener with same address family, same group address and same
604 func TestIPv6MulticastListener(t
*testing
.T
) {
605 testenv
.MustHaveExternalNetwork(t
)
607 switch runtime
.GOOS
{
609 t
.Skipf("not supported on %s", runtime
.GOOS
)
611 t
.Skipf("not supported on solaris, see issue 7399")
614 t
.Skip("IPv6 is not supported")
616 if os
.Getuid() != 0 {
617 t
.Skip("must be root")
620 closer
:= func(cs
[]*UDPConn
) {
621 for _
, c
:= range cs
{
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
634 if ifi
== nil && !*testIPv6
{
637 for _
, tt
:= range ipv6MulticastListenerTests
{
639 cs
:= make([]*UDPConn
, 2)
640 if cs
[0], err
= ListenMulticastUDP(tt
.net
, ifi
, tt
.gaddr
); err
!= nil {
643 if err
:= checkMulticastListener(cs
[0], tt
.gaddr
.IP
); err
!= nil {
647 if cs
[1], err
= ListenMulticastUDP(tt
.net
, ifi
, tt
.gaddr
); err
!= nil {
651 if err
:= checkMulticastListener(cs
[1], tt
.gaddr
.IP
); err
!= nil {
660 func checkMulticastListener(c
*UDPConn
, ip IP
) error
{
661 if ok
, err
:= multicastRIBContains(ip
); err
!= nil {
664 return fmt
.Errorf("%s not found in multicast rib", ip
.String())
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
)
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
678 if runtime
.GOARCH
== "arm" || runtime
.GOARCH
== "alpha" {
679 return true, nil // not implemented yet
682 ift
, err
:= Interfaces()
686 for _
, ifi
:= range ift
{
687 ifmat
, err
:= ifi
.MulticastAddrs()
691 for _
, ifma
:= range ifmat
{
692 if ifma
.(*IPAddr
).IP
.Equal(ip
) {