Source file src/net/interface_unix_test.go

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

View as plain text