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. 4 5 // +build darwin dragonfly freebsd linux netbsd openbsd 6 7 package net 8 9 import ( 10 "fmt" 11 "os" 12 "os/exec" 13 "runtime" 14 "testing" 15 "time" 16 ) 17 18 type testInterface struct { 19 name string 20 local string 21 remote string 22 setupCmds []*exec.Cmd 23 teardownCmds []*exec.Cmd 24 } 25 26 func (ti *testInterface) setup() error { 27 for _, cmd := range ti.setupCmds { 28 if out, err := cmd.CombinedOutput(); err != nil { 29 return fmt.Errorf("args=%v out=%q err=%v", cmd.Args, string(out), err) 30 } 31 } 32 return nil 33 } 34 35 func (ti *testInterface) teardown() error { 36 for _, cmd := range ti.teardownCmds { 37 if out, err := cmd.CombinedOutput(); err != nil { 38 return fmt.Errorf("args=%v out=%q err=%v ", cmd.Args, string(out), err) 39 } 40 } 41 return nil 42 } 43 44 func TestPointToPointInterface(t *testing.T) { 45 if testing.Short() { 46 t.Skip("avoid external network") 47 } 48 if runtime.GOOS == "darwin" { 49 t.Skipf("not supported on %s", runtime.GOOS) 50 } 51 if os.Getuid() != 0 { 52 t.Skip("must be root") 53 } 54 55 // We suppose that using IPv4 link-local addresses doesn't 56 // harm anyone. 57 local, remote := "169.254.0.1", "169.254.0.254" 58 ip := ParseIP(remote) 59 for i := 0; i < 3; i++ { 60 ti := &testInterface{local: local, remote: remote} 61 if err := ti.setPointToPoint(5963 + i); err != nil { 62 t.Skipf("test requires external command: %v", err) 63 } 64 if err := ti.setup(); err != nil { 65 t.Fatal(err) 66 } else { 67 time.Sleep(3 * time.Millisecond) 68 } 69 ift, err := Interfaces() 70 if err != nil { 71 ti.teardown() 72 t.Fatal(err) 73 } 74 for _, ifi := range ift { 75 if ti.name != ifi.Name { 76 continue 77 } 78 ifat, err := ifi.Addrs() 79 if err != nil { 80 ti.teardown() 81 t.Fatal(err) 82 } 83 for _, ifa := range ifat { 84 if ip.Equal(ifa.(*IPNet).IP) { 85 ti.teardown() 86 t.Fatalf("got %v", ifa) 87 } 88 } 89 } 90 if err := ti.teardown(); err != nil { 91 t.Fatal(err) 92 } else { 93 time.Sleep(3 * time.Millisecond) 94 } 95 } 96 } 97 98 func TestInterfaceArrivalAndDeparture(t *testing.T) { 99 if testing.Short() { 100 t.Skip("avoid external network") 101 } 102 if os.Getuid() != 0 { 103 t.Skip("must be root") 104 } 105 106 // We suppose that using IPv4 link-local addresses and the 107 // dot1Q ID for Token Ring and FDDI doesn't harm anyone. 108 local, remote := "169.254.0.1", "169.254.0.254" 109 ip := ParseIP(remote) 110 for _, vid := range []int{1002, 1003, 1004, 1005} { 111 ift1, err := Interfaces() 112 if err != nil { 113 t.Fatal(err) 114 } 115 ti := &testInterface{local: local, remote: remote} 116 if err := ti.setBroadcast(vid); err != nil { 117 t.Skipf("test requires external command: %v", err) 118 } 119 if err := ti.setup(); err != nil { 120 t.Fatal(err) 121 } else { 122 time.Sleep(3 * time.Millisecond) 123 } 124 ift2, err := Interfaces() 125 if err != nil { 126 ti.teardown() 127 t.Fatal(err) 128 } 129 if len(ift2) <= len(ift1) { 130 for _, ifi := range ift1 { 131 t.Logf("before: %v", ifi) 132 } 133 for _, ifi := range ift2 { 134 t.Logf("after: %v", ifi) 135 } 136 ti.teardown() 137 t.Fatalf("got %v; want gt %v", len(ift2), len(ift1)) 138 } 139 for _, ifi := range ift2 { 140 if ti.name != ifi.Name { 141 continue 142 } 143 ifat, err := ifi.Addrs() 144 if err != nil { 145 ti.teardown() 146 t.Fatal(err) 147 } 148 for _, ifa := range ifat { 149 if ip.Equal(ifa.(*IPNet).IP) { 150 ti.teardown() 151 t.Fatalf("got %v", ifa) 152 } 153 } 154 } 155 if err := ti.teardown(); err != nil { 156 t.Fatal(err) 157 } else { 158 time.Sleep(3 * time.Millisecond) 159 } 160 ift3, err := Interfaces() 161 if err != nil { 162 t.Fatal(err) 163 } 164 if len(ift3) >= len(ift2) { 165 for _, ifi := range ift2 { 166 t.Logf("before: %v", ifi) 167 } 168 for _, ifi := range ift3 { 169 t.Logf("after: %v", ifi) 170 } 171 t.Fatalf("got %v; want lt %v", len(ift3), len(ift2)) 172 } 173 } 174 } 175