Loading...
tests/net_test_lib.c xnu-12377.121.6 /dev/null
--- xnu/xnu-12377.121.6/tests/net_test_lib.c
+++ /dev/null
@@ -1,1170 +0,0 @@
-/*
- * Copyright (c) 2019-2025 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-
-#include "net_test_lib.h"
-#include "inet_transfer.h"
-#include "bpflib.h"
-#include "in_cksum.h"
-#include <net/if_fake_var.h>
-#include <net/if_vlan_var.h>
-#include <net/if_bridgevar.h>
-
-#define RTM_BUFLEN (sizeof(struct rt_msghdr) + 6 * SOCK_MAXADDRLEN)
-
-#define ROUNDUP(a) \
-((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint32_t) - 1))) : sizeof(uint32_t))
-
-bool G_debug;
-
-struct in_addr inet_class_c_subnet_mask = {
-	.s_addr = htonl(IN_CLASSC_NET)
-};
-
-ether_addr_t ether_broadcast = {
-	{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
-};
-
-/*
- * local utility functions
- */
-static void
-siocll_start(int s, const char * ifname)
-{
-	struct in6_aliasreq     ifra_in6;
-	int                     result;
-
-	bzero(&ifra_in6, sizeof(ifra_in6));
-	strncpy(ifra_in6.ifra_name, ifname, sizeof(ifra_in6.ifra_name));
-	result = ioctl(s, SIOCLL_START, &ifra_in6);
-	T_QUIET;
-	T_ASSERT_POSIX_SUCCESS(result, "SIOCLL_START %s", ifname);
-}
-
-static void
-nd_flags_set(int s, const char * if_name,
-    uint32_t set_flags, uint32_t clear_flags)
-{
-	uint32_t                new_flags;
-	struct in6_ndireq       nd;
-	int                     result;
-
-	bzero(&nd, sizeof(nd));
-	strncpy(nd.ifname, if_name, sizeof(nd.ifname));
-	result = ioctl(s, SIOCGIFINFO_IN6, &nd);
-	T_ASSERT_POSIX_SUCCESS(result, "SIOCGIFINFO_IN6(%s)", if_name);
-	new_flags = nd.ndi.flags;
-	if (set_flags) {
-		new_flags |= set_flags;
-	}
-	if (clear_flags) {
-		new_flags &= ~clear_flags;
-	}
-	if (new_flags != nd.ndi.flags) {
-		nd.ndi.flags = new_flags;
-		result = ioctl(s, SIOCSIFINFO_FLAGS, (caddr_t)&nd);
-		T_ASSERT_POSIX_SUCCESS(result,
-		    "SIOCSIFINFO_FLAGS(%s) 0x%x",
-		    if_name, nd.ndi.flags);
-	}
-}
-
-
-static void
-siocprotoattach_in6(int s, const char * name)
-{
-	struct in6_aliasreq ifra;
-	int                 result;
-
-	bzero(&ifra, sizeof(ifra));
-	strncpy(ifra.ifra_name, name, sizeof(ifra.ifra_name));
-	result = ioctl(s, SIOCPROTOATTACH_IN6, &ifra);
-	T_ASSERT_POSIX_SUCCESS(result, "SIOCPROTOATTACH_IN6(%s)", name);
-}
-
-static void
-sioc_a_or_d_ifaddr(int s, char *ifname, struct in_addr addr, struct in_addr mask,
-    bool add)
-{
-	struct ifaliasreq       ifra;
-	char                    ntopbuf_ip[INET_ADDRSTRLEN];
-	char                    ntopbuf_mask[INET_ADDRSTRLEN];
-	unsigned long           request;
-	const char *            request_str;
-	int                     ret;
-	struct sockaddr_in *    sin;
-
-	bzero(&ifra, sizeof(ifra));
-	strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
-
-	sin = (struct sockaddr_in *)(void *)&ifra.ifra_addr;
-	sin->sin_len = sizeof(*sin);
-	sin->sin_family = AF_INET;
-	sin->sin_addr = addr;
-
-	sin = (struct sockaddr_in *)(void *)&ifra.ifra_mask;
-	sin->sin_len = sizeof(*sin);
-	sin->sin_family = AF_INET;
-	sin->sin_addr = mask;
-
-	if (add) {
-		request = SIOCAIFADDR;
-		request_str = "SIOCAIFADDR";
-	} else {
-		request = SIOCDIFADDR;
-		request_str = "SIOCDIFADDR";
-	}
-	ret = ioctl(s, request, &ifra);
-	inet_ntop(AF_INET, &addr, ntopbuf_ip, sizeof(ntopbuf_ip));
-	inet_ntop(AF_INET, &sin->sin_addr, ntopbuf_mask, sizeof(ntopbuf_mask));
-	T_ASSERT_POSIX_SUCCESS(ret, "%s %s %s %s", request_str,
-	    ifname, ntopbuf_ip, ntopbuf_mask);
-}
-
-static void
-siocaifaddr(int s, char *ifname, struct in_addr addr, struct in_addr mask)
-{
-	sioc_a_or_d_ifaddr(s, ifname, addr, mask, true);
-}
-
-static void
-siocdifaddr(int s, char *ifname, struct in_addr addr, struct in_addr mask)
-{
-	sioc_a_or_d_ifaddr(s, ifname, addr, mask, false);
-}
-
-
-/*
- * utility functions
- */
-
-#define NO_SOCKET       (-1)
-
-static int
-_dgram_socket_get(int * sock_p, int af)
-{
-	int     sock = *sock_p;
-
-	if (sock != NO_SOCKET) {
-		goto done;
-	}
-	sock = *sock_p = socket(af, SOCK_DGRAM, 0);
-	T_QUIET;
-	T_ASSERT_POSIX_SUCCESS(sock,
-	    "socket(SOCK_DGRAM, %s, 0)",
-	    af == AF_INET ? "AF_INET" : "AF_INET6");
-done:
-	return sock;
-}
-
-static void
-_socket_close(int * sock_p)
-{
-	int sock = *sock_p;
-
-	if (sock != NO_SOCKET) {
-		close(sock);
-		*sock_p = NO_SOCKET;
-	}
-}
-
-static int inet_dgram_socket = NO_SOCKET;
-
-int
-inet_dgram_socket_get(void)
-{
-	return _dgram_socket_get(&inet_dgram_socket, AF_INET);
-}
-
-void
-inet_dgram_socket_close(void)
-{
-	_socket_close(&inet_dgram_socket);
-}
-
-
-static int inet6_dgram_socket = NO_SOCKET;
-
-int
-inet6_dgram_socket_get(void)
-{
-	return _dgram_socket_get(&inet6_dgram_socket, AF_INET6);
-}
-
-void
-inet6_dgram_socket_close(void)
-{
-	_socket_close(&inet6_dgram_socket);
-}
-
-u_int
-ethernet_udp4_frame_populate(void * buf, size_t buf_len,
-    const ether_addr_t * src,
-    struct in_addr src_ip,
-    uint16_t src_port,
-    const ether_addr_t * dst,
-    struct in_addr dst_ip,
-    uint16_t dst_port,
-    const void * data, u_int data_len)
-{
-	ether_header_t *        eh_p;
-	u_int                   frame_length;
-	static int              ip_id;
-	ip_udp_header_t *       ip_udp;
-	char *                  payload;
-	udp_pseudo_hdr_t *      udp_pseudo;
-
-	frame_length = (u_int)(sizeof(*eh_p) + sizeof(*ip_udp)) + data_len;
-	if (buf_len < frame_length) {
-		return 0;
-	}
-
-	/* determine frame offsets */
-	eh_p = (ether_header_t *)buf;
-	ip_udp = (ip_udp_header_t *)(void *)(eh_p + 1);
-	udp_pseudo = (udp_pseudo_hdr_t *)(void *)
-	    (((char *)&ip_udp->udp) - sizeof(*udp_pseudo));
-	payload = (char *)(eh_p + 1) + sizeof(*ip_udp);
-
-	/* ethernet_header */
-	bcopy(src, eh_p->ether_shost, ETHER_ADDR_LEN);
-	bcopy(dst, eh_p->ether_dhost, ETHER_ADDR_LEN);
-	eh_p->ether_type = htons(ETHERTYPE_IP);
-
-	/* copy the data */
-	bcopy(data, payload, data_len);
-
-	/* fill in UDP pseudo header (gets overwritten by IP header below) */
-	bcopy(&src_ip, &udp_pseudo->src_ip, sizeof(src_ip));
-	bcopy(&dst_ip, &udp_pseudo->dst_ip, sizeof(dst_ip));
-	udp_pseudo->zero = 0;
-	udp_pseudo->proto = IPPROTO_UDP;
-	udp_pseudo->length = htons(sizeof(ip_udp->udp) + data_len);
-
-	/* fill in UDP header */
-	ip_udp->udp.uh_sport = htons(src_port);
-	ip_udp->udp.uh_dport = htons(dst_port);
-	ip_udp->udp.uh_ulen = htons(sizeof(ip_udp->udp) + data_len);
-	ip_udp->udp.uh_sum = 0;
-	ip_udp->udp.uh_sum = in_cksum(udp_pseudo, (int)(sizeof(*udp_pseudo)
-	    + sizeof(ip_udp->udp) + data_len));
-
-	/* fill in IP header */
-	bzero(ip_udp, sizeof(ip_udp->ip));
-	ip_udp->ip.ip_v = IPVERSION;
-	ip_udp->ip.ip_hl = sizeof(struct ip) >> 2;
-	ip_udp->ip.ip_ttl = MAXTTL;
-	ip_udp->ip.ip_p = IPPROTO_UDP;
-	bcopy(&src_ip, &ip_udp->ip.ip_src, sizeof(src_ip));
-	bcopy(&dst_ip, &ip_udp->ip.ip_dst, sizeof(dst_ip));
-	ip_udp->ip.ip_len = htons(sizeof(*ip_udp) + data_len);
-	ip_udp->ip.ip_id = htons(ip_id++);
-
-	/* compute the IP checksum */
-	ip_udp->ip.ip_sum = 0; /* needs to be zero for checksum */
-	ip_udp->ip.ip_sum = in_cksum(&ip_udp->ip, sizeof(ip_udp->ip));
-
-	return frame_length;
-}
-
-u_int
-ethernet_udp6_frame_populate(void * buf, size_t buf_len,
-    const ether_addr_t * src,
-    struct in6_addr *src_ip,
-    uint16_t src_port,
-    const ether_addr_t * dst,
-    struct in6_addr * dst_ip,
-    uint16_t dst_port,
-    const void * data, u_int data_len)
-{
-	ether_header_t *        eh_p;
-	u_int                   frame_length;
-	ip6_udp_header_t *      ip6_udp;
-	char *                  payload;
-	udp6_pseudo_hdr_t *     udp6_pseudo;
-
-	frame_length = (u_int)(sizeof(*eh_p) + sizeof(*ip6_udp)) + data_len;
-	if (buf_len < frame_length) {
-		return 0;
-	}
-
-	/* determine frame offsets */
-	eh_p = (ether_header_t *)buf;
-	ip6_udp = (ip6_udp_header_t *)(void *)(eh_p + 1);
-	udp6_pseudo = (udp6_pseudo_hdr_t *)(void *)
-	    (((char *)&ip6_udp->udp) - sizeof(*udp6_pseudo));
-	payload = (char *)(eh_p + 1) + sizeof(*ip6_udp);
-
-	/* ethernet_header */
-	bcopy(src, eh_p->ether_shost, ETHER_ADDR_LEN);
-	bcopy(dst, eh_p->ether_dhost, ETHER_ADDR_LEN);
-	eh_p->ether_type = htons(ETHERTYPE_IPV6);
-
-	/* copy the data */
-	bcopy(data, payload, data_len);
-
-	/* fill in UDP pseudo header (gets overwritten by IP header below) */
-	bcopy(src_ip, &udp6_pseudo->src_ip, sizeof(*src_ip));
-	bcopy(dst_ip, &udp6_pseudo->dst_ip, sizeof(*dst_ip));
-	udp6_pseudo->zero = 0;
-	udp6_pseudo->proto = IPPROTO_UDP;
-	udp6_pseudo->length = htons(sizeof(ip6_udp->udp) + data_len);
-
-	/* fill in UDP header */
-	ip6_udp->udp.uh_sport = htons(src_port);
-	ip6_udp->udp.uh_dport = htons(dst_port);
-	ip6_udp->udp.uh_ulen = htons(sizeof(ip6_udp->udp) + data_len);
-	ip6_udp->udp.uh_sum = 0;
-	ip6_udp->udp.uh_sum = in_cksum(udp6_pseudo, (int)(sizeof(*udp6_pseudo)
-	    + sizeof(ip6_udp->udp) + data_len));
-
-	/* fill in IP header */
-	bzero(&ip6_udp->ip6, sizeof(ip6_udp->ip6));
-	ip6_udp->ip6.ip6_vfc = IPV6_VERSION;
-	ip6_udp->ip6.ip6_nxt = IPPROTO_UDP;
-	bcopy(src_ip, &ip6_udp->ip6.ip6_src, sizeof(*src_ip));
-	bcopy(dst_ip, &ip6_udp->ip6.ip6_dst, sizeof(*dst_ip));
-	ip6_udp->ip6.ip6_plen = htons(sizeof(struct udphdr) + data_len);
-	/* ip6_udp->ip6.ip6_flow = ? */
-	return frame_length;
-}
-
-/**
-** interface management
-**/
-
-void
-ifnet_get_lladdr(const char * ifname, ether_addr_t * eaddr)
-{
-	int err;
-	struct ifreq ifr;
-	int s = inet_dgram_socket_get();
-
-	bzero(&ifr, sizeof(ifr));
-	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-	ifr.ifr_addr.sa_family = AF_LINK;
-	ifr.ifr_addr.sa_len = ETHER_ADDR_LEN;
-	err = ioctl(s, SIOCGIFLLADDR, &ifr);
-	T_QUIET;
-	T_ASSERT_POSIX_SUCCESS(err, "SIOCGIFLLADDR %s", ifname);
-	bcopy(ifr.ifr_addr.sa_data, eaddr->octet, ETHER_ADDR_LEN);
-	return;
-}
-
-int
-ifnet_set_lladdr(const char * ifname, ether_addr_t * eaddr)
-{
-	int err;
-	int this_errno = 0;
-	struct ifreq ifr;
-	int s = inet_dgram_socket_get();
-
-	bzero(&ifr, sizeof(ifr));
-	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-	ifr.ifr_addr.sa_family = AF_LINK;
-	ifr.ifr_addr.sa_len = ETHER_ADDR_LEN;
-	bcopy(eaddr->octet, ifr.ifr_addr.sa_data, ETHER_ADDR_LEN);
-	err = ioctl(s, SIOCSIFLLADDR, &ifr);
-	if (err != 0) {
-		this_errno = errno;
-		T_LOG("SIOCSIFLLADDR %s %s (%d)", ifname,
-		    strerror(this_errno), this_errno);
-	} else {
-		T_LOG("SIOCSIFLLADDR %s success", ifname);
-	}
-	return err;
-}
-
-
-void
-ifnet_attach_ip(char * name)
-{
-	int             err;
-	struct ifreq    ifr;
-	int             s = inet_dgram_socket_get();
-
-	bzero(&ifr, sizeof(ifr));
-	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
-	err = ioctl(s, SIOCPROTOATTACH, &ifr);
-	T_QUIET;
-	T_ASSERT_POSIX_SUCCESS(err, "SIOCPROTOATTACH %s", ifr.ifr_name);
-	return;
-}
-
-void
-ifnet_start_ipv6(const char * ifname)
-{
-	int             s6 = inet6_dgram_socket_get();
-
-	/* attach IPv6 */
-	siocprotoattach_in6(s6, ifname);
-
-	/* disable DAD to avoid 1 second delay (rdar://problem/73270401) */
-	nd_flags_set(s6, ifname, 0, ND6_IFF_DAD);
-
-	/* start IPv6LL */
-	siocll_start(s6, ifname);
-
-	return;
-}
-
-int
-ifnet_destroy(const char * ifname, bool fail_on_error)
-{
-	int             err;
-	struct ifreq    ifr;
-	int             s = inet_dgram_socket_get();
-
-	bzero(&ifr, sizeof(ifr));
-	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-	err = ioctl(s, SIOCIFDESTROY, &ifr);
-	if (fail_on_error) {
-		T_QUIET;
-		T_ASSERT_POSIX_SUCCESS(err, "SIOCSIFDESTROY %s", ifr.ifr_name);
-	}
-	if (err < 0) {
-		T_LOG("SIOCSIFDESTROY %s", ifr.ifr_name);
-	}
-	return err;
-}
-
-int
-ifnet_set_flags(const char * ifname, uint16_t flags_set, uint16_t flags_clear)
-{
-	uint16_t        flags_after;
-	uint16_t        flags_before;
-	struct ifreq    ifr;
-	int             ret;
-	int             s = inet_dgram_socket_get();
-
-	bzero(&ifr, sizeof(ifr));
-	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-	ret = ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr);
-	if (ret != 0) {
-		T_LOG("SIOCGIFFLAGS %s", ifr.ifr_name);
-		return ret;
-	}
-	flags_before = (uint16_t)ifr.ifr_flags;
-	ifr.ifr_flags |= flags_set;
-	ifr.ifr_flags &= ~(flags_clear);
-	flags_after = (uint16_t)ifr.ifr_flags;
-	if (flags_before == flags_after) {
-		/* nothing to do */
-		ret = 0;
-	} else {
-		/* issue the ioctl */
-		T_QUIET;
-		T_ASSERT_POSIX_SUCCESS(ioctl(s, SIOCSIFFLAGS, &ifr),
-		    "SIOCSIFFLAGS %s 0x%x",
-		    ifr.ifr_name, (uint16_t)ifr.ifr_flags);
-		if (G_debug) {
-			T_LOG("setflags(%s set 0x%x clear 0x%x) 0x%x => 0x%x",
-			    ifr.ifr_name, flags_set, flags_clear,
-			    flags_before, flags_after);
-		}
-	}
-	return ret;
-}
-
-/* On some platforms with DEBUG kernel, we need to wait a while */
-#define SIFCREATE_RETRY 600
-
-static int
-ifnet_create_common(const char * ifname, char *ifname_out, size_t ifname_out_len)
-{
-	int             error = 0;
-	struct ifreq    ifr;
-	int             s = inet_dgram_socket_get();
-
-	bzero(&ifr, sizeof(ifr));
-	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-
-	for (int i = 0; i < SIFCREATE_RETRY; i++) {
-		if (ioctl(s, SIOCIFCREATE, &ifr) < 0) {
-			error = errno;
-			T_LOG("SIOCSIFCREATE %s: %s", ifname,
-			    strerror(error));
-			if (error == EBUSY) {
-				/* interface is tearing down, try again */
-				usleep(10000);
-			} else if (error == EEXIST) {
-				/* interface exists, try destroying it */
-				(void)ifnet_destroy(ifname, false);
-			} else {
-				/* unexpected failure */
-				break;
-			}
-		} else {
-			if (ifname_out != NULL) {
-				strlcpy(ifname_out, ifr.ifr_name, ifname_out_len);
-			}
-			error = 0;
-			break;
-		}
-	}
-	if (error == 0) {
-		error = ifnet_set_flags(ifname, IFF_UP, 0);
-	}
-	return error;
-}
-
-int
-ifnet_create(const char * ifname)
-{
-	return ifnet_create_common(ifname, NULL, 0);
-}
-
-int
-ifnet_create_2(char * ifname, size_t len)
-{
-	return ifnet_create_common(ifname, ifname, len);
-}
-
-void
-ifnet_add_ip_address(char *ifname, struct in_addr addr, struct in_addr mask)
-{
-	int             s = inet_dgram_socket_get();
-
-	siocaifaddr(s, ifname, addr, mask);
-}
-
-void
-ifnet_remove_ip_address(char *ifname, struct in_addr addr, struct in_addr mask)
-{
-	int             s = inet_dgram_socket_get();
-
-	siocdifaddr(s, ifname, addr, mask);
-}
-
-int
-ifnet_set_mtu(const char *ifname, int mtu)
-{
-	int error = 0;
-	struct ifreq ifr = { 0 };
-	int s = inet_dgram_socket_get();
-
-	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-	ifr.ifr_mtu = mtu;
-
-	T_ASSERT_POSIX_SUCCESS(ioctl(s, SIOCSIFMTU, (caddr_t)&ifr), "set MTU");
-
-	return error;
-}
-
-int
-siocdrvspec(const char * ifname, u_long op, void *arg, size_t argsize, bool set)
-{
-	struct ifdrv    ifd;
-	int             s = inet_dgram_socket_get();
-
-	memset(&ifd, 0, sizeof(ifd));
-	strlcpy(ifd.ifd_name, ifname, sizeof(ifd.ifd_name));
-	ifd.ifd_cmd = op;
-	ifd.ifd_len = argsize;
-	ifd.ifd_data = arg;
-	return ioctl(s, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd);
-}
-
-void
-fake_set_peer(const char * feth, const char * feth_peer)
-{
-	struct if_fake_request  iffr;
-	int                     ret;
-
-	bzero((char *)&iffr, sizeof(iffr));
-	if (feth_peer != NULL) {
-		strlcpy(iffr.iffr_peer_name, feth_peer,
-		    sizeof(iffr.iffr_peer_name));
-	}
-	ret = siocdrvspec(feth, IF_FAKE_S_CMD_SET_PEER,
-	    &iffr, sizeof(iffr), true);
-	T_QUIET;
-	T_ASSERT_POSIX_SUCCESS(ret,
-	    "SIOCDRVSPEC(%s, IF_FAKE_S_CMD_SET_PEER, %s)",
-	    feth, (feth_peer != NULL) ? feth_peer : "<none>");
-	T_LOG("%s peer %s\n", feth, feth_peer);
-	return;
-}
-
-void
-ifnet_set_low_power_wake(const char * ifname, bool enable)
-{
-	struct ifreq ifr;
-	int s = inet_dgram_socket_get();
-	int ret;
-
-	bzero(&ifr, sizeof(ifr));
-	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-	ifr.ifr_intval = enable ? 1 : 0;
-
-	ret = ioctl(s, SIOCSLOWPOWERWAKE, &ifr);
-	T_QUIET;
-	T_ASSERT_POSIX_SUCCESS(ret, "SIOCSLOWPOWERWAKE(%s, %d)", ifname, enable);
-	T_LOG("%s low power wake %s\n", ifname, enable ? "enabled" : "disabled");
-	return;
-}
-
-void
-siocsifvlan(const char * vlan, const char * phys, uint16_t tag)
-{
-	int             result;
-	struct ifreq    ifr;
-	int             s = inet_dgram_socket_get();
-	struct vlanreq  vlr;
-
-	bzero(&ifr, sizeof(ifr));
-	strlcpy(ifr.ifr_name, vlan, sizeof(ifr.ifr_name));
-	ifr.ifr_data = (caddr_t)&vlr;
-	strlcpy(vlr.vlr_parent, phys, sizeof(vlr.vlr_parent));
-	vlr.vlr_tag = tag;
-	result = ioctl(s, SIOCSIFVLAN, &ifr);
-	T_ASSERT_POSIX_SUCCESS(result, "SIOCSIFVLAN(%s) %s %d",
-	    vlan, phys, tag);
-}
-
-u_int
-make_dhcp_payload(dhcp_min_payload_t payload, ether_addr_t *eaddr)
-{
-	struct bootp *  dhcp;
-	u_int           payload_length;
-
-	/* create a minimal BOOTP packet */
-	payload_length = sizeof(*payload);
-	dhcp = (struct bootp *)payload;
-	bzero(dhcp, payload_length);
-	dhcp->bp_op = BOOTREQUEST;
-	dhcp->bp_htype = ARPHRD_ETHER;
-	dhcp->bp_hlen = sizeof(*eaddr);
-	bcopy(eaddr->octet, dhcp->bp_chaddr, sizeof(eaddr->octet));
-	return payload_length;
-}
-
-
-
-/*
- * routing table
- */
-
-/*
- * Stolen/modified from IPMonitor/ip_plugin.c
- */
-/*
- * Define: ROUTE_MSG_ADDRS_SPACE
- * Purpose:
- *   Since sizeof(sockaddr_dl) > sizeof(sockaddr_in), we need space for
- *   3 sockaddr_in's and 2 sockaddr_dl's, but pad it just in case
- *   someone changes the code and doesn't think to modify this.
- */
-#define ROUTE_MSG_ADDRS_SPACE   (3 * sizeof(struct sockaddr_in) \
-	                         + 2 * sizeof(struct sockaddr_dl) \
-	                         + 128)
-typedef struct {
-	struct rt_msghdr    hdr;
-	char                addrs[ROUTE_MSG_ADDRS_SPACE];
-} route_msg;
-
-typedef unsigned short  IFIndex;
-
-typedef enum {
-	kRouteFlagsIsScoped         = 0x0001,
-	kRouteFlagsHasGateway       = 0x0002,
-	kRouteFlagsIsHost           = 0x0004,
-} RouteFlags;
-
-typedef struct {
-	IFIndex         ifindex;
-	RouteFlags      flags;
-	struct in_addr  dest;
-	struct in_addr  mask;
-	struct in_addr  gateway;
-	struct in_addr  ifa;
-} IPv4Route, * IPv4RouteRef;
-
-/*
- * Function: IPv4RouteApply
- * Purpose:
- *   Add or remove the specified route to/from the kernel routing table.
- */
-static int
-IPv4RouteApply(IPv4RouteRef route, uint8_t cmd, int s)
-{
-	size_t          len;
-	int             ret = 0;
-	route_msg       rtmsg;
-	union {
-		struct sockaddr_in *    in_p;
-		struct sockaddr_dl *    dl_p;
-		char *                  ptr;
-	} rtaddr;
-	static int      rtm_seq;
-	static bool     rtm_seq_inited;
-
-	if (!rtm_seq_inited) {
-		rtm_seq_inited = true;
-		rtm_seq = (int)arc4random();
-	}
-	if (route->ifindex == 0) {
-		T_LOG("no interface specified, ignoring %s",
-		    inet_ntoa(route->dest));
-		return ENXIO;
-	}
-	if (s < 0) {
-		T_LOG("invalid routing socket");
-		return EBADF;
-	}
-	memset(&rtmsg, 0, sizeof(rtmsg));
-	rtmsg.hdr.rtm_type = cmd;
-	rtmsg.hdr.rtm_version = RTM_VERSION;
-	rtmsg.hdr.rtm_seq = rtm_seq++;
-	rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_IFP;
-	if (route->ifa.s_addr != 0) {
-		rtmsg.hdr.rtm_addrs |= RTA_IFA;
-	}
-	rtmsg.hdr.rtm_flags = RTF_UP | RTF_STATIC;
-	if ((route->flags & kRouteFlagsIsHost) != 0) {
-		rtmsg.hdr.rtm_flags |= RTF_HOST;
-	} else {
-		rtmsg.hdr.rtm_addrs |= RTA_NETMASK;
-		if ((route->flags & kRouteFlagsHasGateway) == 0) {
-			rtmsg.hdr.rtm_flags |= RTF_CLONING;
-		}
-	}
-	if ((route->flags & kRouteFlagsHasGateway) != 0) {
-		rtmsg.hdr.rtm_flags |= RTF_GATEWAY;
-	}
-	if ((route->flags & kRouteFlagsIsScoped) != 0) {
-		rtmsg.hdr.rtm_index = route->ifindex;
-		rtmsg.hdr.rtm_flags |= RTF_IFSCOPE;
-	}
-
-	rtaddr.ptr = rtmsg.addrs;
-
-	/* dest */
-	rtaddr.in_p->sin_len = sizeof(*rtaddr.in_p);
-	rtaddr.in_p->sin_family = AF_INET;
-	rtaddr.in_p->sin_addr = route->dest;
-	rtaddr.ptr += sizeof(*rtaddr.in_p);
-
-	/* gateway */
-	if ((rtmsg.hdr.rtm_flags & RTF_GATEWAY) != 0) {
-		/* gateway is an IP address */
-		rtaddr.in_p->sin_len = sizeof(*rtaddr.in_p);
-		rtaddr.in_p->sin_family = AF_INET;
-		rtaddr.in_p->sin_addr = route->gateway;
-		rtaddr.ptr += sizeof(*rtaddr.in_p);
-	} else {
-		/* gateway is the interface itself */
-		rtaddr.dl_p->sdl_len = sizeof(*rtaddr.dl_p);
-		rtaddr.dl_p->sdl_family = AF_LINK;
-		rtaddr.dl_p->sdl_index = route->ifindex;
-		rtaddr.ptr += sizeof(*rtaddr.dl_p);
-	}
-
-	/* mask */
-	if ((rtmsg.hdr.rtm_addrs & RTA_NETMASK) != 0) {
-		rtaddr.in_p->sin_len = sizeof(*rtaddr.in_p);
-		rtaddr.in_p->sin_family = AF_INET;
-		rtaddr.in_p->sin_addr = route->mask;
-		rtaddr.ptr += sizeof(*rtaddr.in_p);
-	}
-
-	/* interface */
-	if ((rtmsg.hdr.rtm_addrs & RTA_IFP) != 0) {
-		rtaddr.dl_p->sdl_len = sizeof(*rtaddr.dl_p);
-		rtaddr.dl_p->sdl_family = AF_LINK;
-		rtaddr.dl_p->sdl_index = route->ifindex;
-		rtaddr.ptr += sizeof(*rtaddr.dl_p);
-	}
-	/* interface address */
-	if ((rtmsg.hdr.rtm_addrs & RTA_IFA) != 0) {
-		rtaddr.in_p->sin_len = sizeof(*rtaddr.in_p);
-		rtaddr.in_p->sin_family = AF_INET;
-		rtaddr.in_p->sin_addr = route->ifa;
-		rtaddr.ptr += sizeof(*rtaddr.in_p);
-	}
-
-	/* apply the route */
-	len = (sizeof(rtmsg.hdr)
-	    + (unsigned long)(rtaddr.ptr - (char *)rtmsg.addrs));
-	rtmsg.hdr.rtm_msglen = (u_short)len;
-	if (write(s, &rtmsg, len) == -1) {
-		ret = errno;
-		T_LOG("write routing socket failed, (%d) %s",
-		    errno, strerror(errno));
-	}
-	return ret;
-}
-
-static int routing_socket = -1;
-
-static int
-routing_socket_get(void)
-{
-	if (routing_socket != NO_SOCKET) {
-		goto done;
-	}
-	routing_socket = socket(PF_ROUTE, SOCK_RAW, PF_ROUTE);
-	T_QUIET;
-	T_ASSERT_POSIX_SUCCESS(routing_socket,
-	    "socket(PF_ROUTE, SOCK_RAW, PF_ROUTE)");
-done:
-	return routing_socket;
-}
-
-void
-route_add_inet_scoped_subnet(char * ifname, u_short if_index,
-    struct in_addr ifa, struct in_addr mask)
-{
-	int             error;
-	IPv4Route       route;
-	int             rs = routing_socket_get();
-
-	bzero(&route, sizeof(route));
-	route.flags |= kRouteFlagsIsScoped;
-	route.ifa = ifa;
-	route.ifindex = if_index;
-	route.mask = mask;
-	route.dest.s_addr = route.ifa.s_addr & route.mask.s_addr;
-	T_QUIET;
-	T_ASSERT_NE((int)route.ifindex, 0, "if_nametoindex(%s)", ifname);
-	error = IPv4RouteApply(&route, RTM_ADD, rs);
-	T_ASSERT_EQ(error, 0, "add scoped subnet route %s %s/24", ifname,
-	    inet_ntoa(route.dest));
-	return;
-}
-
-/**
-** network_interface
-**/
-
-void
-network_interface_create(network_interface_t if_p, const if_name_t name)
-{
-	int             error;
-	size_t          len = sizeof(if_p->if_name);
-
-	strlcpy(if_p->if_name, name, len);
-	error = ifnet_create_2(if_p->if_name, len);
-	T_ASSERT_POSIX_SUCCESS(error, "ifnet_create_2 %s", if_p->if_name);
-
-	if_p->if_index = (u_short)if_nametoindex(if_p->if_name);
-	T_QUIET;
-	T_ASSERT_TRUE(if_p->if_index != 0, NULL);
-	T_LOG("%s: created %s index %d\n",
-	    __func__, if_p->if_name, if_p->if_index);
-}
-
-void
-network_interface_destroy(network_interface_t if_p)
-{
-	if (if_p->if_index != 0) {
-		ifnet_destroy(if_p->if_name, false);
-		T_LOG("%s: destroyed %s\n", __func__, if_p->if_name);
-	}
-}
-
-static inline size_t
-network_interface_pair_list_size(size_t count)
-{
-	return offsetof(network_interface_pair_list, list[count]);
-}
-
-network_interface_pair_list_t
-network_interface_pair_list_alloc(u_int n)
-{
-	network_interface_pair_list_t   list;
-
-	list = (network_interface_pair_list_t)
-	    calloc(1, network_interface_pair_list_size(n));
-	list->count = n;
-	return list;
-}
-
-void
-network_interface_pair_list_destroy(network_interface_pair_list_t list)
-{
-	network_interface_pair_t        scan;
-
-	if (list == NULL) {
-		return;
-	}
-	scan = list->list;
-	for (size_t i = 0; i < list->count; i++, scan++) {
-		network_interface_destroy(&scan->one);
-		network_interface_destroy(&scan->two);
-	}
-}
-
-bool
-has_ipv4_default_route(void)
-{
-	bool result = false;
-	struct rt_msghdr *rtm = NULL;
-	struct sockaddr_in sin = { 0 };
-
-	sin.sin_len = sizeof(struct sockaddr_in);
-	sin.sin_family = AF_INET;
-	sin.sin_addr.s_addr = INADDR_ANY;
-
-	T_QUIET; T_ASSERT_NOTNULL(rtm = (struct rt_msghdr *)calloc(1, RTM_BUFLEN), NULL);
-
-	rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in);
-	rtm->rtm_version = RTM_VERSION;
-	rtm->rtm_type = RTM_GET;
-	rtm->rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY | RTF_HOST;
-	rtm->rtm_addrs = RTA_DST;
-	rtm->rtm_pid = getpid();
-	rtm->rtm_seq = 1;
-
-	uint8_t *cp = (unsigned char *)(rtm + 1);
-
-	bcopy(&sin, cp, sin.sin_len);
-	cp += ROUNDUP(sin.sin_len);
-
-	u_short len = (u_short)(cp - (uint8_t *)rtm);
-
-	rtm->rtm_msglen = len;
-
-	int fd;
-	T_QUIET; T_ASSERT_POSIX_SUCCESS(fd = socket(PF_ROUTE, SOCK_RAW, 0), NULL);
-
-	ssize_t sent = send(fd, rtm, len, 0);
-	if (sent == len) {
-		result = true;
-	} else {
-		result = false;
-	}
-
-	(void) close(fd);
-	free(rtm);
-
-	return result;
-}
-
-bool
-has_ipv6_default_route(void)
-{
-	bool result = false;
-	struct rt_msghdr *rtm = NULL;
-	struct sockaddr_in6 sin6 = { 0 };
-
-	sin6.sin6_len = sizeof(struct sockaddr_in6);
-	sin6.sin6_family = AF_INET6;
-
-	T_QUIET; T_ASSERT_NOTNULL(rtm = (struct rt_msghdr *)calloc(1, RTM_BUFLEN), NULL);
-
-	rtm->rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr_in6);
-	rtm->rtm_version = RTM_VERSION;
-	rtm->rtm_type = RTM_GET;
-	rtm->rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY | RTF_HOST;
-	rtm->rtm_addrs = RTA_DST;
-	rtm->rtm_pid = getpid();
-	rtm->rtm_seq = 1;
-
-	uint8_t *cp = (unsigned char *)(rtm + 1);
-
-	bcopy(&sin6, cp, sin6.sin6_len);
-	cp += ROUNDUP(sin6.sin6_len);
-
-	u_short len = (u_short)(cp - (uint8_t *)rtm);
-
-	rtm->rtm_msglen = len;
-
-	int fd;
-	T_QUIET; T_ASSERT_POSIX_SUCCESS(fd = socket(PF_ROUTE, SOCK_RAW, 0), NULL);
-
-	ssize_t sent = send(fd, rtm, len, 0);
-	if (sent == len) {
-		result = true;
-	} else {
-		result = false;
-	}
-
-	(void) close(fd);
-	free(rtm);
-
-	return result;
-}
-
-/*
- * Bridge management
- */
-int
-bridge_add_member(const char * bridge, const char * member)
-{
-	struct ifbreq           req;
-	int                     ret;
-
-	memset(&req, 0, sizeof(req));
-	strlcpy(req.ifbr_ifsname, member, sizeof(req.ifbr_ifsname));
-	ret = siocdrvspec(bridge, BRDGADD, &req, sizeof(req), true);
-	T_QUIET;
-	T_ASSERT_POSIX_SUCCESS(ret, "%s %s %s", __func__, bridge, member);
-	return ret;
-}
-
-/*
-**  stolen from bootp/bootplib/util.c
-**
-**/
-
-static int
-rt_xaddrs(char * cp, const char * cplim, struct rt_addrinfo * rtinfo)
-{
-	int         i;
-	struct sockaddr *   sa;
-
-	bzero(rtinfo->rti_info, sizeof(rtinfo->rti_info));
-	for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) {
-		if ((rtinfo->rti_addrs & (1 << i)) == 0) {
-			continue;
-		}
-		sa = (struct sockaddr *)cp;
-		if ((cp + sa->sa_len) > cplim) {
-			return EINVAL;
-		}
-		rtinfo->rti_info[i] = sa;
-		cp += ROUNDUP(sa->sa_len);
-	}
-	return 0;
-}
-
-/**
-**  stolen from bootp/IPConfiguration.bproj/iputil.c
-**
-** inet6_addrlist_*
-**/
-
-#define s6_addr16 __u6_addr.__u6_addr16
-
-static char *
-copy_if_info(unsigned int if_index, int af, int *ret_len_p)
-{
-	char *          buf = NULL;
-	size_t          buf_len = 0;
-	int             mib[6];
-
-	mib[0] = CTL_NET;
-	mib[1] = PF_ROUTE;
-	mib[2] = 0;
-	mib[3] = af;
-	mib[4] = NET_RT_IFLIST;
-	mib[5] = (int)if_index;
-
-	*ret_len_p = 0;
-	if (sysctl(mib, 6, NULL, &buf_len, NULL, 0) < 0) {
-		T_LOG("sysctl() size failed: %s", strerror(errno));
-		goto failed;
-	}
-	buf_len *= 2; /* just in case something changes */
-	buf = malloc(buf_len);
-	if (sysctl(mib, 6, buf, &buf_len, NULL, 0) < 0) {
-		free(buf);
-		buf = NULL;
-		T_LOG("sysctl() failed: %s", strerror(errno));
-		goto failed;
-	}
-	*ret_len_p = (int)buf_len;
-
-failed:
-	return buf;
-}
-
-bool
-inet6_get_linklocal_address(unsigned int if_index, struct in6_addr *ret_addr)
-{
-	char *          buf = NULL;
-	char *          buf_end;
-	int             buf_len;
-	bool            found = FALSE;
-	char *scan;
-	struct rt_msghdr *rtm;
-
-	bzero(ret_addr, sizeof(*ret_addr));
-	buf = copy_if_info(if_index, AF_INET6, &buf_len);
-	if (buf == NULL) {
-		goto done;
-	}
-	buf_end = buf + buf_len;
-	for (scan = buf; scan < buf_end; scan += rtm->rtm_msglen) {
-		struct ifa_msghdr * ifam;
-		struct rt_addrinfo  info;
-
-		/* ALIGN: buf aligned (from calling copy_if_info), scan aligned,
-		 * cast ok. */
-		rtm = (struct rt_msghdr *)(void *)scan;
-		T_LOG("rtm_version %d rtm_type %d", rtm->rtm_version, rtm->rtm_type);
-		if (rtm->rtm_version != RTM_VERSION) {
-			continue;
-		}
-		if (rtm->rtm_type == RTM_NEWADDR) {
-			errno_t         error;
-			struct sockaddr_in6 *sin6_p;
-
-			ifam = (struct ifa_msghdr *)rtm;
-			info.rti_addrs = ifam->ifam_addrs;
-			error = rt_xaddrs((char *)(ifam + 1),
-			    ((char *)ifam) + ifam->ifam_msglen,
-			    &info);
-			if (error) {
-				T_LOG("couldn't extract rt_addrinfo %s (%d)\n",
-				    strerror(error), error);
-				goto done;
-			}
-			/* ALIGN: info.rti_info aligned (sockaddr), cast ok. */
-			sin6_p = (struct sockaddr_in6 *)(void *)info.rti_info[RTAX_IFA];
-			if (sin6_p == NULL
-			    || sin6_p->sin6_len < sizeof(struct sockaddr_in6)) {
-				continue;
-			}
-			if (IN6_IS_ADDR_LINKLOCAL(&sin6_p->sin6_addr)) {
-				*ret_addr = sin6_p->sin6_addr;
-				ret_addr->s6_addr16[1] = 0; /* mask scope id */
-				found = TRUE;
-				break;
-			}
-		}
-	}
-
-done:
-	if (buf != NULL) {
-		free(buf);
-	}
-	return found;
-}
-
-void
-force_zone_gc(void)
-{
-	kern_return_t kr = mach_zone_force_gc(mach_host_self());
-
-	if (kr != KERN_SUCCESS) {
-		T_LOG("mach_zone_force_gc(): failed with error %s\n", mach_error_string(kr));
-	} else {
-		T_LOG("mach_zone_force_gc(): success\n");
-	}
-}