interface_unix_test.go 4.7 KB

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