github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/integration/generic-tests/dhclient_test.go (about)

     1  // Copyright 2018 the u-root 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 !race
     6  // +build !race
     7  
     8  package integration
     9  
    10  import (
    11  	"fmt"
    12  	"net"
    13  	"net/http"
    14  	"os"
    15  	"path/filepath"
    16  	"sync"
    17  	"testing"
    18  	"time"
    19  
    20  	"github.com/mvdan/u-root-coreutils/pkg/qemu"
    21  	"github.com/mvdan/u-root-coreutils/pkg/testutil"
    22  	"github.com/mvdan/u-root-coreutils/pkg/vmtest"
    23  )
    24  
    25  // TestDhclientQEMU4 uses QEMU's DHCP server to test dhclient.
    26  func TestDhclientQEMU4(t *testing.T) {
    27  	// TODO: support arm
    28  	if vmtest.TestArch() != "amd64" && vmtest.TestArch() != "arm64" {
    29  		t.Skipf("test not supported on %s", vmtest.TestArch())
    30  	}
    31  
    32  	// Create the file to download
    33  	dir := t.TempDir()
    34  
    35  	want := "conteeent"
    36  	foobarFile := filepath.Join(dir, "foobar")
    37  	if err := os.WriteFile(foobarFile, []byte(want), 0o644); err != nil {
    38  		t.Fatal(err)
    39  	}
    40  
    41  	// Serve HTTP on the host on a random port.
    42  	http.Handle("/", http.FileServer(http.Dir(dir)))
    43  	ln, err := net.Listen("tcp", ":0")
    44  	if err != nil {
    45  		t.Fatal(err)
    46  	}
    47  
    48  	var wg sync.WaitGroup
    49  	s := &http.Server{}
    50  	wg.Add(1)
    51  	go func() {
    52  		_ = s.Serve(ln)
    53  		wg.Done()
    54  	}()
    55  	defer wg.Wait()
    56  	defer s.Close()
    57  
    58  	port := ln.Addr().(*net.TCPAddr).Port
    59  
    60  	dhcpClient, ccleanup := vmtest.QEMUTest(t, &vmtest.Options{
    61  		QEMUOpts: qemu.Options{
    62  			SerialOutput: vmtest.TestLineWriter(t, "client"),
    63  			Timeout:      30 * time.Second,
    64  			Devices: []qemu.Device{
    65  				qemu.ArbitraryArgs{
    66  					"-device", "e1000,netdev=host0",
    67  					"-netdev", "user,id=host0,net=192.168.0.0/24,dhcpstart=192.168.0.10,ipv6=off",
    68  				},
    69  			},
    70  		},
    71  		TestCmds: []string{
    72  			"dhclient -ipv6=false -v",
    73  			"ip a",
    74  			// Download a file to make sure dhclient configures kernel networking correctly.
    75  			fmt.Sprintf("wget http://192.168.0.2:%d/foobar", port),
    76  			"cat ./foobar",
    77  			"sleep 5",
    78  			"shutdown -h",
    79  		},
    80  	})
    81  	defer ccleanup()
    82  
    83  	if err := dhcpClient.Expect("Configured eth0 with IPv4 DHCP Lease"); err != nil {
    84  		t.Errorf("%s: %v", testutil.NowLog(), err)
    85  	}
    86  	if err := dhcpClient.Expect("inet 192.168.0.10"); err != nil {
    87  		t.Errorf("%s: %v", testutil.NowLog(), err)
    88  	}
    89  	// "cat ./foobar" should be outputting this.
    90  	if err := dhcpClient.Expect(want); err != nil {
    91  		t.Errorf("%s: %v", testutil.NowLog(), err)
    92  	}
    93  }
    94  
    95  func TestDhclientTimesOut(t *testing.T) {
    96  	// TODO: support arm
    97  	if vmtest.TestArch() != "amd64" && vmtest.TestArch() != "arm64" {
    98  		t.Skipf("test not supported on %s", vmtest.TestArch())
    99  	}
   100  
   101  	network := qemu.NewNetwork()
   102  	dhcpClient, ccleanup := vmtest.QEMUTest(t, &vmtest.Options{
   103  		Name: "TestQEMUDHCPTimesOut",
   104  		QEMUOpts: qemu.Options{
   105  			Timeout: 50 * time.Second,
   106  			Devices: []qemu.Device{
   107  				// An empty new network is easier than
   108  				// configuring QEMU not to expose any
   109  				// networking. At the moment.
   110  				network.NewVM(),
   111  			},
   112  		},
   113  		TestCmds: []string{
   114  			"dhclient -v -retry 2 -timeout 10",
   115  			"echo \"DHCP timed out\"",
   116  			"sleep 5",
   117  			"shutdown -h",
   118  		},
   119  	})
   120  	defer ccleanup()
   121  
   122  	if err := dhcpClient.Expect("Could not configure eth0 for IPv"); err != nil {
   123  		t.Error(err)
   124  	}
   125  	if err := dhcpClient.Expect("Could not configure eth0 for IPv"); err != nil {
   126  		t.Error(err)
   127  	}
   128  	if err := dhcpClient.Expect("DHCP timed out"); err != nil {
   129  		t.Error(err)
   130  	}
   131  }
   132  
   133  func TestDhclient6(t *testing.T) {
   134  	// TODO: support arm
   135  	if vmtest.TestArch() != "amd64" && vmtest.TestArch() != "arm64" {
   136  		t.Skipf("test not supported on %s", vmtest.TestArch())
   137  	}
   138  
   139  	// QEMU doesn't support DHCPv6 for getting IP configuration, so we have
   140  	// to supply our own server.
   141  	//
   142  	// We don't currently have a radvd server we can use, so we also cannot
   143  	// try to download a file using the DHCP configuration.
   144  	network := qemu.NewNetwork()
   145  	dhcpServer, scleanup := vmtest.QEMUTest(t, &vmtest.Options{
   146  		Name: "TestDhclient6_Server",
   147  		TestCmds: []string{
   148  			"ip link set eth0 up",
   149  			"pxeserver -6 -your-ip6=fec0::3 -4=false",
   150  		},
   151  		QEMUOpts: qemu.Options{
   152  			SerialOutput: vmtest.TestLineWriter(t, "server"),
   153  			Timeout:      30 * time.Second,
   154  			Devices: []qemu.Device{
   155  				network.NewVM(),
   156  			},
   157  		},
   158  	})
   159  	defer scleanup()
   160  
   161  	dhcpClient, ccleanup := vmtest.QEMUTest(t, &vmtest.Options{
   162  		Name: "TestDhclient6_Client",
   163  		TestCmds: []string{
   164  			"dhclient -ipv4=false -vv",
   165  			"ip a",
   166  			"shutdown -h",
   167  		},
   168  		QEMUOpts: qemu.Options{
   169  			SerialOutput: vmtest.TestLineWriter(t, "client"),
   170  			Timeout:      30 * time.Second,
   171  			Devices: []qemu.Device{
   172  				network.NewVM(),
   173  			},
   174  		},
   175  	})
   176  	defer ccleanup()
   177  
   178  	if err := dhcpServer.Expect("starting dhcpv6 server"); err != nil {
   179  		t.Errorf("%s dhcpv6 server: %v", testutil.NowLog(), err)
   180  	}
   181  	if err := dhcpClient.Expect("Configured eth0 with IPv6 DHCP Lease IP fec0::3"); err != nil {
   182  		t.Errorf("%s configure: %v", testutil.NowLog(), err)
   183  	}
   184  	if err := dhcpClient.Expect("inet6 fec0::3"); err != nil {
   185  		t.Errorf("%s ip: %v", testutil.NowLog(), err)
   186  	}
   187  }