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