1 // Copyright 2013 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.
5 //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd
19 type testInterface
struct {
24 teardownCmds
[]*exec
.Cmd
27 func (ti
*testInterface
) setup() error
{
28 for _
, cmd
:= range ti
.setupCmds
{
29 if out
, err
:= cmd
.CombinedOutput(); err
!= nil {
30 return fmt
.Errorf("args=%v out=%q err=%v", cmd
.Args
, string(out
), err
)
36 func (ti
*testInterface
) teardown() error
{
37 for _
, cmd
:= range ti
.teardownCmds
{
38 if out
, err
:= cmd
.CombinedOutput(); err
!= nil {
39 return fmt
.Errorf("args=%v out=%q err=%v ", cmd
.Args
, string(out
), err
)
45 func TestPointToPointInterface(t
*testing
.T
) {
47 t
.Skip("avoid external network")
49 if runtime
.GOOS
== "darwin" || runtime
.GOOS
== "ios" {
50 t
.Skipf("not supported on %s", runtime
.GOOS
)
53 t
.Skip("must be root")
56 // We suppose that using IPv4 link-local addresses doesn't
58 local
, remote
:= "169.254.0.1", "169.254.0.254"
60 for i
:= 0; i
< 3; i
++ {
61 ti
:= &testInterface
{local
: local
, remote
: remote
}
62 if err
:= ti
.setPointToPoint(5963 + i
); err
!= nil {
63 t
.Skipf("test requires external command: %v", err
)
65 if err
:= ti
.setup(); err
!= nil {
66 if e
:= err
.Error(); strings
.Contains(e
, "No such device") && strings
.Contains(e
, "gre0") {
67 t
.Skip("skipping test; no gre0 device. likely running in container?")
71 time
.Sleep(3 * time
.Millisecond
)
73 ift
, err
:= Interfaces()
78 for _
, ifi
:= range ift
{
79 if ti
.name
!= ifi
.Name
{
82 ifat
, err
:= ifi
.Addrs()
87 for _
, ifa
:= range ifat
{
88 if ip
.Equal(ifa
.(*IPNet
).IP
) {
90 t
.Fatalf("got %v", ifa
)
94 if err
:= ti
.teardown(); err
!= nil {
97 time
.Sleep(3 * time
.Millisecond
)
102 func TestInterfaceArrivalAndDeparture(t
*testing
.T
) {
104 t
.Skip("avoid external network")
106 if os
.Getuid() != 0 {
107 t
.Skip("must be root")
110 // We suppose that using IPv4 link-local addresses and the
111 // dot1Q ID for Token Ring and FDDI doesn't harm anyone.
112 local
, remote
:= "169.254.0.1", "169.254.0.254"
113 ip
:= ParseIP(remote
)
114 for _
, vid
:= range []int{1002, 1003, 1004, 1005} {
115 ift1
, err
:= Interfaces()
119 ti
:= &testInterface
{local
: local
, remote
: remote
}
120 if err
:= ti
.setBroadcast(vid
); err
!= nil {
121 t
.Skipf("test requires external command: %v", err
)
123 if err
:= ti
.setup(); err
!= nil {
126 time
.Sleep(3 * time
.Millisecond
)
128 ift2
, err
:= Interfaces()
133 if len(ift2
) <= len(ift1
) {
134 for _
, ifi
:= range ift1
{
135 t
.Logf("before: %v", ifi
)
137 for _
, ifi
:= range ift2
{
138 t
.Logf("after: %v", ifi
)
141 t
.Fatalf("got %v; want gt %v", len(ift2
), len(ift1
))
143 for _
, ifi
:= range ift2
{
144 if ti
.name
!= ifi
.Name
{
147 ifat
, err
:= ifi
.Addrs()
152 for _
, ifa
:= range ifat
{
153 if ip
.Equal(ifa
.(*IPNet
).IP
) {
155 t
.Fatalf("got %v", ifa
)
159 if err
:= ti
.teardown(); err
!= nil {
162 time
.Sleep(3 * time
.Millisecond
)
164 ift3
, err
:= Interfaces()
168 if len(ift3
) >= len(ift2
) {
169 for _
, ifi
:= range ift2
{
170 t
.Logf("before: %v", ifi
)
172 for _
, ifi
:= range ift3
{
173 t
.Logf("after: %v", ifi
)
175 t
.Fatalf("got %v; want lt %v", len(ift3
), len(ift2
))
180 func TestInterfaceArrivalAndDepartureZoneCache(t
*testing
.T
) {
182 t
.Skip("avoid external network")
184 if os
.Getuid() != 0 {
185 t
.Skip("must be root")
188 // Ensure zoneCache is filled:
189 _
, _
= Listen("tcp", "[fe80::1%nonexistent]:0")
191 ti
:= &testInterface
{local
: "fe80::1"}
192 if err
:= ti
.setLinkLocal(0); err
!= nil {
193 t
.Skipf("test requires external command: %v", err
)
195 if err
:= ti
.setup(); err
!= nil {
200 time
.Sleep(3 * time
.Millisecond
)
202 // If Listen fails (on Linux with “bind: invalid argument”), zoneCache was
203 // not updated when encountering a nonexistent interface:
204 ln
, err
:= Listen("tcp", "[fe80::1%"+ti
.name
+"]:0")
209 if err
:= ti
.teardown(); err
!= nil {