git: 35dc7f8f5dcd - main - dhclient: test against a real (ISC) dhcp server

From: John-Mark Gurney <jmg_at_FreeBSD.org>
Date: Thu, 26 May 2022 00:07:40 UTC
The branch main has been updated by jmg:

URL: https://cgit.FreeBSD.org/src/commit/?id=35dc7f8f5dcd6a061b53b7c526d200320f41c014

commit 35dc7f8f5dcd6a061b53b7c526d200320f41c014
Author:     John-Mark Gurney <jmg@FreeBSD.org>
AuthorDate: 2022-05-12 00:04:14 +0000
Commit:     John-Mark Gurney <jmg@FreeBSD.org>
CommitDate: 2022-05-26 00:02:38 +0000

    dhclient: test against a real (ISC) dhcp server
    
    This tests both both normal (untagged), and pcp tagged (VLAN 0)
    networks which are now common for fiber ISPs.
    
    Reviewed by: markj, kp
    Differential Revision: https://reviews.freebsd.org/D35178
---
 sbin/dhclient/tests/Makefile |   2 +
 sbin/dhclient/tests/pcp.sh   | 196 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 198 insertions(+)

diff --git a/sbin/dhclient/tests/Makefile b/sbin/dhclient/tests/Makefile
index 822699c9dd01..ce4c7acb822e 100644
--- a/sbin/dhclient/tests/Makefile
+++ b/sbin/dhclient/tests/Makefile
@@ -2,6 +2,8 @@
 
 .PATH:	${.CURDIR:H}
 
+ATF_TESTS_SH=	pcp
+
 PLAIN_TESTS_C=				option-domain-search_test
 SRCS.option-domain-search_test=		alloc.c convert.c hash.c options.c \
 					tables.c fake.c option-domain-search.c
diff --git a/sbin/dhclient/tests/pcp.sh b/sbin/dhclient/tests/pcp.sh
new file mode 100644
index 000000000000..88c39f452f7f
--- /dev/null
+++ b/sbin/dhclient/tests/pcp.sh
@@ -0,0 +1,196 @@
+#!/usr/bin/env atf-sh
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright 2022 John-Mark Gurney
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#
+# Run the tests:
+# make WITH_TESTS=yes -j 4 all install && kyua test -k /usr/tests/Kyuafile  sbin/dhclient/pcp
+#
+# Output last run:
+# kyua report --verbose -r $(ls -tr ~/.kyua/store/results.*.db | tail -n 1)
+
+. $(atf_get_srcdir)/../../sys/common/vnet.subr
+
+generic_dhcp_cleanup()
+{
+
+	# clean up programs
+	kill $(cat dhclient.test.pid) $(cat dhcpd.pid)
+
+	# clean up files
+	rm -f dhclient.dhcpd.conf lease.dhclient.test dhclient.test.pid
+
+	vnet_cleanup
+}
+
+atf_test_case normal cleanup
+normal_head()
+{
+	atf_set descr 'test dhclient against a server'
+	atf_set require.user root
+}
+
+normal_body()
+{
+	dhcpd=$(which dhcpd)
+
+	if ! [ -x "$dhcpd" ]; then
+		atf_skip "ISC dhcp server (isc-dhcp44-server) not installed"
+	fi
+
+	vnet_init
+
+	epair=$(vnet_mkepair)
+
+	vnet_mkjail dhclient_normal_test ${epair}b
+
+	# Set IP on server iface
+	ifconfig ${epair}a 192.0.2.2/24 up
+
+	# Create dhcp server config
+	cat > dhclient.dhcpd.conf << EOF
+default-lease-time 36000;
+max-lease-time 86400;
+authoritative;
+subnet 192.0.2.0 netmask 255.255.255.0 {
+	range 192.0.2.10 192.0.2.10;
+	option routers 192.0.2.2;
+	option domain-name-servers 192.0.2.2;
+}
+EOF
+
+	# Start dhcp server
+	touch dhcpd.leases.conf
+	atf_check -e ignore ${dhcpd} -cf ./dhclient.dhcpd.conf -lf ./dhcpd.leases.conf -pf ./dhcpd.pid ${epair}a
+
+	# Expect that we get an IP assigned
+	atf_check -e match:'DHCPACK from 192.0.2.2' jexec dhclient_normal_test dhclient -c /dev/null -l ./lease.dhclient.test -p ./dhclient.test.pid ${epair}b
+
+	# And it's the correct one
+	atf_check -o match:'inet 192.0.2.10' jexec dhclient_normal_test ifconfig ${epair}b
+
+}
+
+normal_cleanup()
+{
+
+	generic_dhcp_cleanup
+}
+
+atf_test_case pcp cleanup
+pcp_head()
+{
+	atf_set descr 'test dhclient on pcp interface'
+	atf_set require.user root
+}
+
+pcp_body()
+{
+	dhcpd=$(which dhcpd)
+
+	if ! [ -x "$dhcpd" ]; then
+		atf_skip "ISC dhcp server (isc-dhcp44-server) not installed"
+	fi
+
+	vnet_init
+
+	epair=$(vnet_mkepair)
+
+	# Server side needs to be up to pass packets
+	ifconfig ${epair}a up
+
+	# Make sure necessary netgraph modules are loaded
+	kldstat -q -n ng_ether || kldload ng_ether
+	kldstat -q -n ng_iface || kldload ng_iface
+	kldstat -q -n ng_vlan || kldload ng_vlan
+
+	# create vlan, and attach epair to it (has incoming/outgoing vlan
+	# 0 tagged frames)
+	ngctl mkpeer ${epair}a: vlan lower downstream
+
+	# create new interface on other side of vlan (untagged/pcp)
+	ngctl mkpeer ${epair}a:lower. eiface vlan0 ether
+
+	# get the interface created
+	ngiface=$(ngctl show ${epair}a:lower.vlan0 | head -n 1 | awk '{ print $2}')
+
+	# schedule it for clean up
+	echo ${ngiface} >> ngctl.shutdown
+
+	# set the filter on it
+	ngctl msg ${epair}a:lower. 'addfilter { vlan=0 hook="vlan0" }'
+
+	vnet_mkjail dhclient_pcp_test ${epair}b
+
+	# Set IP on server iface
+	ifconfig ${ngiface} up 192.0.2.2/24
+
+	# Set pcp in jail
+	jexec dhclient_pcp_test ifconfig ${epair}b pcp 0 up
+
+	# Create dhcp server config
+	cat > dhclient.dhcpd.conf << EOF
+default-lease-time 36000;
+max-lease-time 86400;
+authoritative;
+subnet 192.0.2.0 netmask 255.255.255.0 {
+	range 192.0.2.10 192.0.2.10;
+	option routers 192.0.2.2;
+	option domain-name-servers 192.0.2.2;
+}
+EOF
+
+	# Start dhcp server
+	touch dhcpd.leases.conf
+	atf_check -e ignore ${dhcpd} -cf ./dhclient.dhcpd.conf -lf ./dhcpd.leases.conf -pf ./dhcpd.pid ${ngiface}
+
+	# Expect that we get an IP assigned
+	atf_check -e match:'DHCPACK from 192.0.2.2' jexec dhclient_pcp_test dhclient -c /dev/null -l ./lease.dhclient.test -p ./dhclient.test.pid ${epair}b
+
+	# And it's the correct one
+	atf_check -o match:'inet 192.0.2.10' jexec dhclient_pcp_test ifconfig ${epair}b
+}
+
+pcp_cleanup()
+{
+
+	generic_dhcp_cleanup
+
+	# Clean up netgraph nodes
+	for i in $(cat ngctl.shutdown); do
+		ngctl shutdown ${i}:
+	done
+	rm ngctl.shutdown
+}
+
+atf_init_test_cases()
+{
+	atf_add_test_case normal
+	atf_add_test_case pcp
+}
+