123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- // Copyright 2013 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd
- package net
- import (
- "fmt"
- "os"
- "os/exec"
- "runtime"
- "strings"
- "testing"
- "time"
- )
- type testInterface struct {
- name string
- local string
- remote string
- setupCmds []*exec.Cmd
- teardownCmds []*exec.Cmd
- }
- func (ti *testInterface) setup() error {
- for _, cmd := range ti.setupCmds {
- if out, err := cmd.CombinedOutput(); err != nil {
- return fmt.Errorf("args=%v out=%q err=%v", cmd.Args, string(out), err)
- }
- }
- return nil
- }
- func (ti *testInterface) teardown() error {
- for _, cmd := range ti.teardownCmds {
- if out, err := cmd.CombinedOutput(); err != nil {
- return fmt.Errorf("args=%v out=%q err=%v ", cmd.Args, string(out), err)
- }
- }
- return nil
- }
- func TestPointToPointInterface(t *testing.T) {
- if testing.Short() {
- t.Skip("avoid external network")
- }
- if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
- t.Skipf("not supported on %s", runtime.GOOS)
- }
- if os.Getuid() != 0 {
- t.Skip("must be root")
- }
- // We suppose that using IPv4 link-local addresses doesn't
- // harm anyone.
- local, remote := "169.254.0.1", "169.254.0.254"
- ip := ParseIP(remote)
- for i := 0; i < 3; i++ {
- ti := &testInterface{local: local, remote: remote}
- if err := ti.setPointToPoint(5963 + i); err != nil {
- t.Skipf("test requires external command: %v", err)
- }
- if err := ti.setup(); err != nil {
- if e := err.Error(); strings.Contains(e, "No such device") && strings.Contains(e, "gre0") {
- t.Skip("skipping test; no gre0 device. likely running in container?")
- }
- t.Fatal(err)
- } else {
- time.Sleep(3 * time.Millisecond)
- }
- ift, err := Interfaces()
- if err != nil {
- ti.teardown()
- t.Fatal(err)
- }
- for _, ifi := range ift {
- if ti.name != ifi.Name {
- continue
- }
- ifat, err := ifi.Addrs()
- if err != nil {
- ti.teardown()
- t.Fatal(err)
- }
- for _, ifa := range ifat {
- if ip.Equal(ifa.(*IPNet).IP) {
- ti.teardown()
- t.Fatalf("got %v", ifa)
- }
- }
- }
- if err := ti.teardown(); err != nil {
- t.Fatal(err)
- } else {
- time.Sleep(3 * time.Millisecond)
- }
- }
- }
- func TestInterfaceArrivalAndDeparture(t *testing.T) {
- if testing.Short() {
- t.Skip("avoid external network")
- }
- if os.Getuid() != 0 {
- t.Skip("must be root")
- }
- // We suppose that using IPv4 link-local addresses and the
- // dot1Q ID for Token Ring and FDDI doesn't harm anyone.
- local, remote := "169.254.0.1", "169.254.0.254"
- ip := ParseIP(remote)
- for _, vid := range []int{1002, 1003, 1004, 1005} {
- ift1, err := Interfaces()
- if err != nil {
- t.Fatal(err)
- }
- ti := &testInterface{local: local, remote: remote}
- if err := ti.setBroadcast(vid); err != nil {
- t.Skipf("test requires external command: %v", err)
- }
- if err := ti.setup(); err != nil {
- t.Fatal(err)
- } else {
- time.Sleep(3 * time.Millisecond)
- }
- ift2, err := Interfaces()
- if err != nil {
- ti.teardown()
- t.Fatal(err)
- }
- if len(ift2) <= len(ift1) {
- for _, ifi := range ift1 {
- t.Logf("before: %v", ifi)
- }
- for _, ifi := range ift2 {
- t.Logf("after: %v", ifi)
- }
- ti.teardown()
- t.Fatalf("got %v; want gt %v", len(ift2), len(ift1))
- }
- for _, ifi := range ift2 {
- if ti.name != ifi.Name {
- continue
- }
- ifat, err := ifi.Addrs()
- if err != nil {
- ti.teardown()
- t.Fatal(err)
- }
- for _, ifa := range ifat {
- if ip.Equal(ifa.(*IPNet).IP) {
- ti.teardown()
- t.Fatalf("got %v", ifa)
- }
- }
- }
- if err := ti.teardown(); err != nil {
- t.Fatal(err)
- } else {
- time.Sleep(3 * time.Millisecond)
- }
- ift3, err := Interfaces()
- if err != nil {
- t.Fatal(err)
- }
- if len(ift3) >= len(ift2) {
- for _, ifi := range ift2 {
- t.Logf("before: %v", ifi)
- }
- for _, ifi := range ift3 {
- t.Logf("after: %v", ifi)
- }
- t.Fatalf("got %v; want lt %v", len(ift3), len(ift2))
- }
- }
- }
- func TestInterfaceArrivalAndDepartureZoneCache(t *testing.T) {
- if testing.Short() {
- t.Skip("avoid external network")
- }
- if os.Getuid() != 0 {
- t.Skip("must be root")
- }
- // Ensure zoneCache is filled:
- _, _ = Listen("tcp", "[fe80::1%nonexistent]:0")
- ti := &testInterface{local: "fe80::1"}
- if err := ti.setLinkLocal(0); err != nil {
- t.Skipf("test requires external command: %v", err)
- }
- if err := ti.setup(); err != nil {
- t.Fatal(err)
- }
- defer ti.teardown()
- time.Sleep(3 * time.Millisecond)
- // If Listen fails (on Linux with “bind: invalid argument”), zoneCache was
- // not updated when encountering a nonexistent interface:
- ln, err := Listen("tcp", "[fe80::1%"+ti.name+"]:0")
- if err != nil {
- t.Fatal(err)
- }
- ln.Close()
- if err := ti.teardown(); err != nil {
- t.Fatal(err)
- }
- }
|