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 }