diff --git a/sbin/ifconfig/carp.c b/sbin/ifconfig/carp.c
index d6f8d78ba920..23a119e3b9d7 100644
--- a/sbin/ifconfig/carp.c
+++ b/sbin/ifconfig/carp.c
@@ -1,231 +1,224 @@
 /*	$FreeBSD$ */
 /*	from $OpenBSD: ifconfig.c,v 1.82 2003/10/19 05:43:35 mcbride Exp $ */
 
 /*-
  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  *
  * Copyright (c) 2002 Michael Shalayeff. All rights reserved.
  * Copyright (c) 2003 Ryan McBride. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. 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 AUTHOR ``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 AUTHOR OR HIS RELATIVES 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 MIND, 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.
  */
 
 #include <sys/param.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
 
 #include <stdlib.h>
 #include <unistd.h>
 
 #include <net/if.h>
 #include <netinet/in.h>
 #include <netinet/in_var.h>
 #include <netinet/ip_carp.h>
 
 #include <ctype.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <err.h>
 #include <errno.h>
 
 #include <libifconfig.h>
 
 #include "ifconfig.h"
 
 static const char *carp_states[] = { CARP_STATES };
 
 static void carp_status(int s);
 static void setcarp_vhid(const char *, int, int, const struct afswtch *rafp);
 static void setcarp_callback(int, void *);
 static void setcarp_advbase(const char *,int, int, const struct afswtch *rafp);
 static void setcarp_advskew(const char *, int, int, const struct afswtch *rafp);
 static void setcarp_passwd(const char *, int, int, const struct afswtch *rafp);
 
 static int carpr_vhid = -1;
 static int carpr_advskew = -1;
 static int carpr_advbase = -1;
 static int carpr_state = -1;
 static unsigned char const *carpr_key;
 
 static void
 carp_status(int s)
 {
 	struct carpreq carpr[CARP_MAXVHID];
-	ifconfig_handle_t *lifh;
-
-	lifh = ifconfig_open();
-	if (lifh == NULL)
-		return;
 
 	if (ifconfig_carp_get_info(lifh, name, carpr, CARP_MAXVHID) == -1)
-		goto close;
+		return;
 
 	for (size_t i = 0; i < carpr[0].carpr_count; i++) {
 		printf("\tcarp: %s vhid %d advbase %d advskew %d",
 		    carp_states[carpr[i].carpr_state], carpr[i].carpr_vhid,
 		    carpr[i].carpr_advbase, carpr[i].carpr_advskew);
 		if (printkeys && carpr[i].carpr_key[0] != '\0')
 			printf(" key \"%s\"\n", carpr[i].carpr_key);
 		else
 			printf("\n");
 	}
-close:
-	ifconfig_close(lifh);
 }
 
 static void
 setcarp_vhid(const char *val, int d, int s, const struct afswtch *afp)
 {
 
 	carpr_vhid = atoi(val);
 
 	if (carpr_vhid <= 0 || carpr_vhid > CARP_MAXVHID)
 		errx(1, "vhid must be greater than 0 and less than %u",
 		    CARP_MAXVHID);
 
 	switch (afp->af_af) {
 #ifdef INET
 	case AF_INET:
 	    {
 		struct in_aliasreq *ifra;
 
 		ifra = (struct in_aliasreq *)afp->af_addreq;
 		ifra->ifra_vhid = carpr_vhid;
 		break;
 	    }
 #endif
 #ifdef INET6
 	case AF_INET6:
 	    {
 		struct in6_aliasreq *ifra;
 
 		ifra = (struct in6_aliasreq *)afp->af_addreq;
 		ifra->ifra_vhid = carpr_vhid;
 		break;
 	    }
 #endif
 	default:
 		errx(1, "%s doesn't support carp(4)", afp->af_name);
 	}
 
 	callback_register(setcarp_callback, NULL);
 }
 
 static void
 setcarp_callback(int s, void *arg __unused)
 {
 	struct carpreq carpr;
 
 	bzero(&carpr, sizeof(struct carpreq));
 	carpr.carpr_vhid = carpr_vhid;
 	carpr.carpr_count = 1;
 	ifr.ifr_data = (caddr_t)&carpr;
 
 	if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1 && errno != ENOENT)
 		err(1, "SIOCGVH");
 
 	if (carpr_key != NULL)
 		/* XXX Should hash the password into the key here? */
 		strlcpy(carpr.carpr_key, carpr_key, CARP_KEY_LEN);
 	if (carpr_advskew > -1)
 		carpr.carpr_advskew = carpr_advskew;
 	if (carpr_advbase > -1)
 		carpr.carpr_advbase = carpr_advbase;
 	if (carpr_state > -1)
 		carpr.carpr_state = carpr_state;
 
 	if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1)
 		err(1, "SIOCSVH");
 }
 
 static void
 setcarp_passwd(const char *val, int d, int s, const struct afswtch *afp)
 {
 
 	if (carpr_vhid == -1)
 		errx(1, "passwd requires vhid");
 
 	carpr_key = val;
 }
 
 static void
 setcarp_advskew(const char *val, int d, int s, const struct afswtch *afp)
 {
 
 	if (carpr_vhid == -1)
 		errx(1, "advskew requires vhid");
 
 	carpr_advskew = atoi(val);
 }
 
 static void
 setcarp_advbase(const char *val, int d, int s, const struct afswtch *afp)
 {
 
 	if (carpr_vhid == -1)
 		errx(1, "advbase requires vhid");
 
 	carpr_advbase = atoi(val);
 }
 
 static void
 setcarp_state(const char *val, int d, int s, const struct afswtch *afp)
 {
 	int i;
 
 	if (carpr_vhid == -1)
 		errx(1, "state requires vhid");
 
 	for (i = 0; i <= CARP_MAXSTATE; i++)
 		if (strcasecmp(carp_states[i], val) == 0) {
 			carpr_state = i;
 			return;
 		}
 
 	errx(1, "unknown state");
 }
 
 static struct cmd carp_cmds[] = {
 	DEF_CMD_ARG("advbase",	setcarp_advbase),
 	DEF_CMD_ARG("advskew",	setcarp_advskew),
 	DEF_CMD_ARG("pass",	setcarp_passwd),
 	DEF_CMD_ARG("vhid",	setcarp_vhid),
 	DEF_CMD_ARG("state",	setcarp_state),
 };
 static struct afswtch af_carp = {
 	.af_name	= "af_carp",
 	.af_af		= AF_UNSPEC,
 	.af_other_status = carp_status,
 };
 
 static __constructor void
 carp_ctor(void)
 {
 	int i;
 
 	for (i = 0; i < nitems(carp_cmds);  i++)
 		cmd_register(&carp_cmds[i]);
 	af_register(&af_carp);
 }
diff --git a/sbin/ifconfig/ifbridge.c b/sbin/ifconfig/ifbridge.c
index cc1520a2e3f0..2bd9c96f2489 100644
--- a/sbin/ifconfig/ifbridge.c
+++ b/sbin/ifconfig/ifbridge.c
@@ -1,698 +1,691 @@
 /*-
  * SPDX-License-Identifier: BSD-4-Clause
  *
  * Copyright 2001 Wasabi Systems, Inc.
  * All rights reserved.
  *
  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. 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.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *	This product includes software developed for the NetBSD Project by
  *	Wasabi Systems, Inc.
  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
  *    or promote products derived from this software without specific prior
  *    written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
  * 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.
  */
 
 #ifndef lint
 static const char rcsid[] =
   "$FreeBSD$";
 #endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
 
 #include <stdlib.h>
 #include <unistd.h>
 
 #include <net/ethernet.h>
 #include <net/if.h>
 #include <net/if_bridgevar.h>
 #include <net/route.h>
 
 #include <ctype.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <err.h>
 #include <errno.h>
 
 #include <libifconfig.h>
 
 #include "ifconfig.h"
 
 static const char *stpstates[] = { STP_STATES };
 static const char *stpproto[] = { STP_PROTOS };
 static const char *stproles[] = { STP_ROLES };
 
 static int
 get_val(const char *cp, u_long *valp)
 {
 	char *endptr;
 	u_long val;
 
 	errno = 0;
 	val = strtoul(cp, &endptr, 0);
 	if (cp[0] == '\0' || endptr[0] != '\0' || errno == ERANGE)
 		return (-1);
 
 	*valp = val;
 	return (0);
 }
 
 static int
 do_cmd(int sock, u_long op, void *arg, size_t argsize, int set)
 {
 	struct ifdrv ifd;
 
 	memset(&ifd, 0, sizeof(ifd));
 
 	strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name));
 	ifd.ifd_cmd = op;
 	ifd.ifd_len = argsize;
 	ifd.ifd_data = arg;
 
 	return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd));
 }
 
 static void
 do_bridgeflag(int sock, const char *ifs, int flag, int set)
 {
 	struct ifbreq req;
 
 	strlcpy(req.ifbr_ifsname, ifs, sizeof(req.ifbr_ifsname));
 
 	if (do_cmd(sock, BRDGGIFFLGS, &req, sizeof(req), 0) < 0)
 		err(1, "unable to get bridge flags");
 
 	if (set)
 		req.ifbr_ifsflags |= flag;
 	else
 		req.ifbr_ifsflags &= ~flag;
 
 	if (do_cmd(sock, BRDGSIFFLGS, &req, sizeof(req), 1) < 0)
 		err(1, "unable to set bridge flags");
 }
 
 static void
 bridge_addresses(int s, const char *prefix)
 {
 	struct ifbaconf ifbac;
 	struct ifbareq *ifba;
 	char *inbuf = NULL, *ninbuf;
 	int i, len = 8192;
 	struct ether_addr ea;
 
 	for (;;) {
 		ninbuf = realloc(inbuf, len);
 		if (ninbuf == NULL)
 			err(1, "unable to allocate address buffer");
 		ifbac.ifbac_len = len;
 		ifbac.ifbac_buf = inbuf = ninbuf;
 		if (do_cmd(s, BRDGRTS, &ifbac, sizeof(ifbac), 0) < 0)
 			err(1, "unable to get address cache");
 		if ((ifbac.ifbac_len + sizeof(*ifba)) < len)
 			break;
 		len *= 2;
 	}
 
 	for (i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) {
 		ifba = ifbac.ifbac_req + i;
 		memcpy(ea.octet, ifba->ifba_dst,
 		    sizeof(ea.octet));
 		printf("%s%s Vlan%d %s %lu ", prefix, ether_ntoa(&ea),
 		    ifba->ifba_vlan, ifba->ifba_ifsname, ifba->ifba_expire);
 		printb("flags", ifba->ifba_flags, IFBAFBITS);
 		printf("\n");
 	}
 
 	free(inbuf);
 }
 
 static void
 bridge_status(int s)
 {
-	ifconfig_handle_t *lifh;
 	struct ifconfig_bridge_status *bridge;
 	struct ifbropreq *params;
 	const char *pad, *prefix;
 	uint8_t lladdr[ETHER_ADDR_LEN];
 	uint16_t bprio;
 
-	lifh = ifconfig_open();
-	if (lifh == NULL)
-		return;
-
 	if (ifconfig_bridge_get_bridge_status(lifh, name, &bridge) == -1)
-		goto close;
+		return;
 
 	params = bridge->params;
 
 	PV2ID(params->ifbop_bridgeid, bprio, lladdr);
 	printf("\tid %s priority %u hellotime %u fwddelay %u\n",
 	    ether_ntoa((struct ether_addr *)lladdr),
 	    params->ifbop_priority,
 	    params->ifbop_hellotime,
 	    params->ifbop_fwddelay);
 	printf("\tmaxage %u holdcnt %u proto %s maxaddr %u timeout %u\n",
 	    params->ifbop_maxage,
 	    params->ifbop_holdcount,
 	    stpproto[params->ifbop_protocol],
 	    bridge->cache_size,
 	    bridge->cache_lifetime);
 	PV2ID(params->ifbop_designated_root, bprio, lladdr);
 	printf("\troot id %s priority %d ifcost %u port %u\n",
 	    ether_ntoa((struct ether_addr *)lladdr),
 	    bprio,
 	    params->ifbop_root_path_cost,
 	    params->ifbop_root_port & 0xfff);
 
 	prefix = "\tmember: ";
 	pad    = "\t        ";
 	for (size_t i = 0; i < bridge->members_count; ++i) {
 		struct ifbreq *member = &bridge->members[i];
 
 		printf("%s%s ", prefix, member->ifbr_ifsname);
 		printb("flags", member->ifbr_ifsflags, IFBIFBITS);
 		printf("\n%s", pad);
 		printf("ifmaxaddr %u port %u priority %u path cost %u",
 		    member->ifbr_addrmax,
 		    member->ifbr_portno,
 		    member->ifbr_priority,
 		    member->ifbr_path_cost);
 		if (member->ifbr_ifsflags & IFBIF_STP) {
 			uint8_t proto = member->ifbr_proto;
 			uint8_t role = member->ifbr_role;
 			uint8_t state = member->ifbr_state;
 
 			if (proto < nitems(stpproto))
 				printf(" proto %s", stpproto[proto]);
 			else
 				printf(" <unknown proto %d>", proto);
 			printf("\n%s", pad);
 			if (role < nitems(stproles))
 				printf("role %s", stproles[role]);
 			else
 				printf("<unknown role %d>", role);
 			if (state < nitems(stpstates))
 				printf(" state %s", stpstates[state]);
 			else
 				printf(" <unknown state %d>", state);
 		}
 		printf("\n");
 	}
 
 	ifconfig_bridge_free_bridge_status(bridge);
-close:
-	ifconfig_close(lifh);
 }
 
 static void
 setbridge_add(const char *val, int d, int s, const struct afswtch *afp)
 {
 	struct ifbreq req;
 
 	memset(&req, 0, sizeof(req));
 	strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
 	if (do_cmd(s, BRDGADD, &req, sizeof(req), 1) < 0)
 		err(1, "BRDGADD %s",  val);
 }
 
 static void
 setbridge_delete(const char *val, int d, int s, const struct afswtch *afp)
 {
 	struct ifbreq req;
 
 	memset(&req, 0, sizeof(req));
 	strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
 	if (do_cmd(s, BRDGDEL, &req, sizeof(req), 1) < 0)
 		err(1, "BRDGDEL %s",  val);
 }
 
 static void
 setbridge_discover(const char *val, int d, int s, const struct afswtch *afp)
 {
 
 	do_bridgeflag(s, val, IFBIF_DISCOVER, 1);
 }
 
 static void
 unsetbridge_discover(const char *val, int d, int s, const struct afswtch *afp)
 {
 
 	do_bridgeflag(s, val, IFBIF_DISCOVER, 0);
 }
 
 static void
 setbridge_learn(const char *val, int d, int s, const struct afswtch *afp)
 {
 
 	do_bridgeflag(s, val, IFBIF_LEARNING,  1);
 }
 
 static void
 unsetbridge_learn(const char *val, int d, int s, const struct afswtch *afp)
 {
 
 	do_bridgeflag(s, val, IFBIF_LEARNING,  0);
 }
 
 static void
 setbridge_sticky(const char *val, int d, int s, const struct afswtch *afp)
 {
 
 	do_bridgeflag(s, val, IFBIF_STICKY,  1);
 }
 
 static void
 unsetbridge_sticky(const char *val, int d, int s, const struct afswtch *afp)
 {
 
 	do_bridgeflag(s, val, IFBIF_STICKY,  0);
 }
 
 static void
 setbridge_span(const char *val, int d, int s, const struct afswtch *afp)
 {
 	struct ifbreq req;
 
 	memset(&req, 0, sizeof(req));
 	strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
 	if (do_cmd(s, BRDGADDS, &req, sizeof(req), 1) < 0)
 		err(1, "BRDGADDS %s",  val);
 }
 
 static void
 unsetbridge_span(const char *val, int d, int s, const struct afswtch *afp)
 {
 	struct ifbreq req;
 
 	memset(&req, 0, sizeof(req));
 	strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
 	if (do_cmd(s, BRDGDELS, &req, sizeof(req), 1) < 0)
 		err(1, "BRDGDELS %s",  val);
 }
 
 static void
 setbridge_stp(const char *val, int d, int s, const struct afswtch *afp)
 {
 
 	do_bridgeflag(s, val, IFBIF_STP, 1);
 }
 
 static void
 unsetbridge_stp(const char *val, int d, int s, const struct afswtch *afp)
 {
 
 	do_bridgeflag(s, val, IFBIF_STP, 0);
 }
 
 static void
 setbridge_edge(const char *val, int d, int s, const struct afswtch *afp)
 {
 	do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 1);
 }
 
 static void
 unsetbridge_edge(const char *val, int d, int s, const struct afswtch *afp)
 {
 	do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 0);
 }
 
 static void
 setbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp)
 {
 	do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 1);
 }
 
 static void
 unsetbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp)
 {
 	do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 0);
 }
 
 static void
 setbridge_ptp(const char *val, int d, int s, const struct afswtch *afp)
 {
 	do_bridgeflag(s, val, IFBIF_BSTP_PTP, 1);
 }
 
 static void
 unsetbridge_ptp(const char *val, int d, int s, const struct afswtch *afp)
 {
 	do_bridgeflag(s, val, IFBIF_BSTP_PTP, 0);
 }
 
 static void
 setbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp)
 {
 	do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 1);
 }
 
 static void
 unsetbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp)
 {
 	do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 0);
 }
 
 static void
 setbridge_flush(const char *val, int d, int s, const struct afswtch *afp)
 {
 	struct ifbreq req;
 
 	memset(&req, 0, sizeof(req));
 	req.ifbr_ifsflags = IFBF_FLUSHDYN;
 	if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0)
 		err(1, "BRDGFLUSH");
 }
 
 static void
 setbridge_flushall(const char *val, int d, int s, const struct afswtch *afp)
 {
 	struct ifbreq req;
 
 	memset(&req, 0, sizeof(req));
 	req.ifbr_ifsflags = IFBF_FLUSHALL;
 	if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0)
 		err(1, "BRDGFLUSH");
 }
 
 static void
 setbridge_static(const char *val, const char *mac, int s,
     const struct afswtch *afp)
 {
 	struct ifbareq req;
 	struct ether_addr *ea;
 
 	memset(&req, 0, sizeof(req));
 	strlcpy(req.ifba_ifsname, val, sizeof(req.ifba_ifsname));
 
 	ea = ether_aton(mac);
 	if (ea == NULL)
 		errx(1, "%s: invalid address: %s", val, mac);
 
 	memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst));
 	req.ifba_flags = IFBAF_STATIC;
 	req.ifba_vlan = 1; /* XXX allow user to specify */
 
 	if (do_cmd(s, BRDGSADDR, &req, sizeof(req), 1) < 0)
 		err(1, "BRDGSADDR %s",  val);
 }
 
 static void
 setbridge_deladdr(const char *val, int d, int s, const struct afswtch *afp)
 {
 	struct ifbareq req;
 	struct ether_addr *ea;
 
 	memset(&req, 0, sizeof(req));
 
 	ea = ether_aton(val);
 	if (ea == NULL)
 		errx(1, "invalid address: %s",  val);
 
 	memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst));
 
 	if (do_cmd(s, BRDGDADDR, &req, sizeof(req), 1) < 0)
 		err(1, "BRDGDADDR %s",  val);
 }
 
 static void
 setbridge_addr(const char *val, int d, int s, const struct afswtch *afp)
 {
 
 	bridge_addresses(s, "");
 }
 
 static void
 setbridge_maxaddr(const char *arg, int d, int s, const struct afswtch *afp)
 {
 	struct ifbrparam param;
 	u_long val;
 
 	if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0)
 		errx(1, "invalid value: %s",  arg);
 
 	param.ifbrp_csize = val & 0xffffffff;
 
 	if (do_cmd(s, BRDGSCACHE, &param, sizeof(param), 1) < 0)
 		err(1, "BRDGSCACHE %s",  arg);
 }
 
 static void
 setbridge_hellotime(const char *arg, int d, int s, const struct afswtch *afp)
 {
 	struct ifbrparam param;
 	u_long val;
 
 	if (get_val(arg, &val) < 0 || (val & ~0xff) != 0)
 		errx(1, "invalid value: %s",  arg);
 
 	param.ifbrp_hellotime = val & 0xff;
 
 	if (do_cmd(s, BRDGSHT, &param, sizeof(param), 1) < 0)
 		err(1, "BRDGSHT %s",  arg);
 }
 
 static void
 setbridge_fwddelay(const char *arg, int d, int s, const struct afswtch *afp)
 {
 	struct ifbrparam param;
 	u_long val;
 
 	if (get_val(arg, &val) < 0 || (val & ~0xff) != 0)
 		errx(1, "invalid value: %s",  arg);
 
 	param.ifbrp_fwddelay = val & 0xff;
 
 	if (do_cmd(s, BRDGSFD, &param, sizeof(param), 1) < 0)
 		err(1, "BRDGSFD %s",  arg);
 }
 
 static void
 setbridge_maxage(const char *arg, int d, int s, const struct afswtch *afp)
 {
 	struct ifbrparam param;
 	u_long val;
 
 	if (get_val(arg, &val) < 0 || (val & ~0xff) != 0)
 		errx(1, "invalid value: %s",  arg);
 
 	param.ifbrp_maxage = val & 0xff;
 
 	if (do_cmd(s, BRDGSMA, &param, sizeof(param), 1) < 0)
 		err(1, "BRDGSMA %s",  arg);
 }
 
 static void
 setbridge_priority(const char *arg, int d, int s, const struct afswtch *afp)
 {
 	struct ifbrparam param;
 	u_long val;
 
 	if (get_val(arg, &val) < 0 || (val & ~0xffff) != 0)
 		errx(1, "invalid value: %s",  arg);
 
 	param.ifbrp_prio = val & 0xffff;
 
 	if (do_cmd(s, BRDGSPRI, &param, sizeof(param), 1) < 0)
 		err(1, "BRDGSPRI %s",  arg);
 }
 
 static void
 setbridge_protocol(const char *arg, int d, int s, const struct afswtch *afp)
 {
 	struct ifbrparam param;
 
 	if (strcasecmp(arg, "stp") == 0) {
 		param.ifbrp_proto = 0;
 	} else if (strcasecmp(arg, "rstp") == 0) {
 		param.ifbrp_proto = 2;
 	} else {
 		errx(1, "unknown stp protocol");
 	}
 
 	if (do_cmd(s, BRDGSPROTO, &param, sizeof(param), 1) < 0)
 		err(1, "BRDGSPROTO %s",  arg);
 }
 
 static void
 setbridge_holdcount(const char *arg, int d, int s, const struct afswtch *afp)
 {
 	struct ifbrparam param;
 	u_long val;
 
 	if (get_val(arg, &val) < 0 || (val & ~0xff) != 0)
 		errx(1, "invalid value: %s",  arg);
 
 	param.ifbrp_txhc = val & 0xff;
 
 	if (do_cmd(s, BRDGSTXHC, &param, sizeof(param), 1) < 0)
 		err(1, "BRDGSTXHC %s",  arg);
 }
 
 static void
 setbridge_ifpriority(const char *ifn, const char *pri, int s,
     const struct afswtch *afp)
 {
 	struct ifbreq req;
 	u_long val;
 
 	memset(&req, 0, sizeof(req));
 
 	if (get_val(pri, &val) < 0 || (val & ~0xff) != 0)
 		errx(1, "invalid value: %s",  pri);
 
 	strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
 	req.ifbr_priority = val & 0xff;
 
 	if (do_cmd(s, BRDGSIFPRIO, &req, sizeof(req), 1) < 0)
 		err(1, "BRDGSIFPRIO %s",  pri);
 }
 
 static void
 setbridge_ifpathcost(const char *ifn, const char *cost, int s,
     const struct afswtch *afp)
 {
 	struct ifbreq req;
 	u_long val;
 
 	memset(&req, 0, sizeof(req));
 
 	if (get_val(cost, &val) < 0)
 		errx(1, "invalid value: %s",  cost);
 
 	strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
 	req.ifbr_path_cost = val;
 
 	if (do_cmd(s, BRDGSIFCOST, &req, sizeof(req), 1) < 0)
 		err(1, "BRDGSIFCOST %s",  cost);
 }
 
 static void
 setbridge_ifmaxaddr(const char *ifn, const char *arg, int s,
     const struct afswtch *afp)
 {
 	struct ifbreq req;
 	u_long val;
 
 	memset(&req, 0, sizeof(req));
 
 	if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0)
 		errx(1, "invalid value: %s",  arg);
 
 	strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
 	req.ifbr_addrmax = val & 0xffffffff;
 
 	if (do_cmd(s, BRDGSIFAMAX, &req, sizeof(req), 1) < 0)
 		err(1, "BRDGSIFAMAX %s",  arg);
 }
 
 static void
 setbridge_timeout(const char *arg, int d, int s, const struct afswtch *afp)
 {
 	struct ifbrparam param;
 	u_long val;
 
 	if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0)
 		errx(1, "invalid value: %s",  arg);
 
 	param.ifbrp_ctime = val & 0xffffffff;
 
 	if (do_cmd(s, BRDGSTO, &param, sizeof(param), 1) < 0)
 		err(1, "BRDGSTO %s",  arg);
 }
 
 static void
 setbridge_private(const char *val, int d, int s, const struct afswtch *afp)
 {
 
 	do_bridgeflag(s, val, IFBIF_PRIVATE, 1);
 }
 
 static void
 unsetbridge_private(const char *val, int d, int s, const struct afswtch *afp)
 {
 
 	do_bridgeflag(s, val, IFBIF_PRIVATE, 0);
 }
 
 static struct cmd bridge_cmds[] = {
 	DEF_CMD_ARG("addm",		setbridge_add),
 	DEF_CMD_ARG("deletem",		setbridge_delete),
 	DEF_CMD_ARG("discover",		setbridge_discover),
 	DEF_CMD_ARG("-discover",	unsetbridge_discover),
 	DEF_CMD_ARG("learn",		setbridge_learn),
 	DEF_CMD_ARG("-learn",		unsetbridge_learn),
 	DEF_CMD_ARG("sticky",		setbridge_sticky),
 	DEF_CMD_ARG("-sticky",		unsetbridge_sticky),
 	DEF_CMD_ARG("span",		setbridge_span),
 	DEF_CMD_ARG("-span",		unsetbridge_span),
 	DEF_CMD_ARG("stp",		setbridge_stp),
 	DEF_CMD_ARG("-stp",		unsetbridge_stp),
 	DEF_CMD_ARG("edge",		setbridge_edge),
 	DEF_CMD_ARG("-edge",		unsetbridge_edge),
 	DEF_CMD_ARG("autoedge",		setbridge_autoedge),
 	DEF_CMD_ARG("-autoedge",	unsetbridge_autoedge),
 	DEF_CMD_ARG("ptp",		setbridge_ptp),
 	DEF_CMD_ARG("-ptp",		unsetbridge_ptp),
 	DEF_CMD_ARG("autoptp",		setbridge_autoptp),
 	DEF_CMD_ARG("-autoptp",		unsetbridge_autoptp),
 	DEF_CMD("flush", 0,		setbridge_flush),
 	DEF_CMD("flushall", 0,		setbridge_flushall),
 	DEF_CMD_ARG2("static",		setbridge_static),
 	DEF_CMD_ARG("deladdr",		setbridge_deladdr),
 	DEF_CMD("addr",	 1,		setbridge_addr),
 	DEF_CMD_ARG("maxaddr",		setbridge_maxaddr),
 	DEF_CMD_ARG("hellotime",	setbridge_hellotime),
 	DEF_CMD_ARG("fwddelay",		setbridge_fwddelay),
 	DEF_CMD_ARG("maxage",		setbridge_maxage),
 	DEF_CMD_ARG("priority",		setbridge_priority),
 	DEF_CMD_ARG("proto",		setbridge_protocol),
 	DEF_CMD_ARG("holdcnt",		setbridge_holdcount),
 	DEF_CMD_ARG2("ifpriority",	setbridge_ifpriority),
 	DEF_CMD_ARG2("ifpathcost",	setbridge_ifpathcost),
 	DEF_CMD_ARG2("ifmaxaddr",	setbridge_ifmaxaddr),
 	DEF_CMD_ARG("timeout",		setbridge_timeout),
 	DEF_CMD_ARG("private",		setbridge_private),
 	DEF_CMD_ARG("-private",		unsetbridge_private),
 };
 static struct afswtch af_bridge = {
 	.af_name	= "af_bridge",
 	.af_af		= AF_UNSPEC,
 	.af_other_status = bridge_status,
 };
 
 static __constructor void
 bridge_ctor(void)
 {
 	int i;
 
 	for (i = 0; i < nitems(bridge_cmds);  i++)
 		cmd_register(&bridge_cmds[i]);
 	af_register(&af_bridge);
 }
diff --git a/sbin/ifconfig/ifclone.c b/sbin/ifconfig/ifclone.c
index ad39bd43757a..9cacff239967 100644
--- a/sbin/ifconfig/ifclone.c
+++ b/sbin/ifconfig/ifclone.c
@@ -1,206 +1,200 @@
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
  * Copyright (c) 1983, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. 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.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
  */
 
 #ifndef lint
 static const char rcsid[] =
   "$FreeBSD$";
 #endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/ioctl.h>
 #include <sys/queue.h>
 #include <sys/socket.h>
 #include <net/if.h>
 
 #include <err.h>
 #include <libifconfig.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "ifconfig.h"
 
 typedef enum {
 	MT_PREFIX,
 	MT_FILTER,
 } clone_match_type;
 
 static void
 list_cloners(void)
 {
-	ifconfig_handle_t *lifh;
 	char *cloners;
 	size_t cloners_count;
 
-	lifh = ifconfig_open();
-	if (lifh == NULL)
-		return;
-
 	if (ifconfig_list_cloners(lifh, &cloners, &cloners_count) < 0)
 		errc(1, ifconfig_err_errno(lifh), "unable to list cloners");
-	ifconfig_close(lifh);
 
 	for (const char *name = cloners;
 	    name < cloners + cloners_count * IFNAMSIZ;
 	    name += IFNAMSIZ) {
 		if (name > cloners)
 			putchar(' ');
 		printf("%s", name);
 	}
 	putchar('\n');
 	free(cloners);
 }
 
 struct clone_defcb {
 	union {
 		char ifprefix[IFNAMSIZ];
 		clone_match_func *ifmatch;
 	};
 	clone_match_type clone_mt;
 	clone_callback_func *clone_cb;
 	SLIST_ENTRY(clone_defcb) next;
 };
 
 static SLIST_HEAD(, clone_defcb) clone_defcbh =
    SLIST_HEAD_INITIALIZER(clone_defcbh);
 
 void
 clone_setdefcallback_prefix(const char *ifprefix, clone_callback_func *p)
 {
 	struct clone_defcb *dcp;
 
 	dcp = malloc(sizeof(*dcp));
 	strlcpy(dcp->ifprefix, ifprefix, IFNAMSIZ-1);
 	dcp->clone_mt = MT_PREFIX;
 	dcp->clone_cb = p;
 	SLIST_INSERT_HEAD(&clone_defcbh, dcp, next);
 }
 
 void
 clone_setdefcallback_filter(clone_match_func *filter, clone_callback_func *p)
 {
 	struct clone_defcb *dcp;
 
 	dcp = malloc(sizeof(*dcp));
 	dcp->ifmatch  = filter;
 	dcp->clone_mt = MT_FILTER;
 	dcp->clone_cb = p;
 	SLIST_INSERT_HEAD(&clone_defcbh, dcp, next);
 }
 
 /*
  * Do the actual clone operation.  Any parameters must have been
  * setup by now.  If a callback has been setup to do the work
  * then defer to it; otherwise do a simple create operation with
  * no parameters.
  */
 static void
 ifclonecreate(int s, void *arg)
 {
 	struct ifreq ifr;
 	struct clone_defcb *dcp;
 
 	memset(&ifr, 0, sizeof(ifr));
 	(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
 
 	/* Try to find a default callback by filter */
 	SLIST_FOREACH(dcp, &clone_defcbh, next) {
 		if (dcp->clone_mt == MT_FILTER &&
 		    dcp->ifmatch(ifr.ifr_name) != 0)
 			break;
 	}
 
 	if (dcp == NULL) {
 		/* Try to find a default callback by prefix */
 		SLIST_FOREACH(dcp, &clone_defcbh, next) {
 			if (dcp->clone_mt == MT_PREFIX &&
 			    strncmp(dcp->ifprefix, ifr.ifr_name,
 			    strlen(dcp->ifprefix)) == 0)
 				break;
 		}
 	}
 
 	if (dcp == NULL || dcp->clone_cb == NULL) {
 		/* NB: no parameters */
 	  	ioctl_ifcreate(s, &ifr);
 	} else {
 		dcp->clone_cb(s, &ifr);
 	}
 
 	/*
 	 * If we get a different name back than we put in, update record and
 	 * indicate it should be printed later.
 	 */
 	if (strncmp(name, ifr.ifr_name, sizeof(name)) != 0) {
 		strlcpy(name, ifr.ifr_name, sizeof(name));
 		printifname = 1;
 	}
 }
 
 static
 DECL_CMD_FUNC(clone_create, arg, d)
 {
 	callback_register(ifclonecreate, NULL);
 }
 
 static
 DECL_CMD_FUNC(clone_destroy, arg, d)
 {
 	(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
 	if (ioctl(s, SIOCIFDESTROY, &ifr) < 0)
 		err(1, "SIOCIFDESTROY");
 }
 
 static struct cmd clone_cmds[] = {
 	DEF_CLONE_CMD("create",	0,	clone_create),
 	DEF_CMD("destroy",	0,	clone_destroy),
 	DEF_CLONE_CMD("plumb",	0,	clone_create),
 	DEF_CMD("unplumb",	0,	clone_destroy),
 };
 
 static void
 clone_Copt_cb(const char *optarg __unused)
 {
 	list_cloners();
 	exit(exit_code);
 }
 static struct option clone_Copt = { .opt = "C", .opt_usage = "[-C]", .cb = clone_Copt_cb };
 
 static __constructor void
 clone_ctor(void)
 {
 	size_t i;
 
 	for (i = 0; i < nitems(clone_cmds);  i++)
 		cmd_register(&clone_cmds[i]);
 	opt_register(&clone_Copt);
 }
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index 5b12baa0656e..fc5351bd420e 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -1,1719 +1,1728 @@
 /*-
  * SPDX-License-Identifier: BSD-3-Clause
  *
  * Copyright (c) 1983, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. 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.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
  */
 
 #ifndef lint
 static const char copyright[] =
 "@(#) Copyright (c) 1983, 1993\n\
 	The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
 #if 0
 static char sccsid[] = "@(#)ifconfig.c	8.2 (Berkeley) 2/16/94";
 #endif
 static const char rcsid[] =
   "$FreeBSD$";
 #endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/ioctl.h>
 #include <sys/module.h>
 #include <sys/linker.h>
 #include <sys/queue.h>
 #include <sys/socket.h>
 #include <sys/time.h>
 
 #include <net/ethernet.h>
 #include <net/if.h>
 #include <net/if_dl.h>
 #include <net/if_types.h>
 #include <net/route.h>
 
 /* IP */
 #include <netinet/in.h>
 #include <netinet/in_var.h>
 #include <arpa/inet.h>
 #include <netdb.h>
 
 #include <fnmatch.h>
 #include <ifaddrs.h>
 #include <ctype.h>
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
 #ifdef JAIL
 #include <jail.h>
 #endif
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
+#include <libifconfig.h>
+
 #include "ifconfig.h"
 
+ifconfig_handle_t *lifh;
+
 /*
  * Since "struct ifreq" is composed of various union members, callers
  * should pay special attention to interpret the value.
  * (.e.g. little/big endian difference in the structure.)
  */
 struct	ifreq ifr;
 
 char	name[IFNAMSIZ];
 char	*descr = NULL;
 size_t	descrlen = 64;
 int	setaddr;
 int	setmask;
 int	doalias;
 int	clearaddr;
 int	newaddr = 1;
 int	verbose;
 int	noload;
 int	printifname = 0;
 
 int	supmedia = 0;
 int	printkeys = 0;		/* Print keying material for interfaces. */
 int	exit_code = 0;
 
 /* Formatter Strings */
 char	*f_inet, *f_inet6, *f_ether, *f_addr;
 
 static	bool group_member(const char *ifname, const char *match,
 		const char *nomatch);
 static	int ifconfig(int argc, char *const *argv, int iscreate,
 		const struct afswtch *afp);
 static	void status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
 		struct ifaddrs *ifa);
 static	void tunnel_status(int s);
 static _Noreturn void usage(void);
 
 static int getifflags(const char *ifname, int us);
 
 static struct afswtch *af_getbyname(const char *name);
 static struct afswtch *af_getbyfamily(int af);
 static void af_other_status(int);
 
 void printifnamemaybe(void);
 
 static struct option *opts = NULL;
 
 struct ifa_order_elt {
 	int if_order;
 	int af_orders[255];
 	struct ifaddrs *ifa;
 	TAILQ_ENTRY(ifa_order_elt) link;
 };
 
 TAILQ_HEAD(ifa_queue, ifa_order_elt);
 
 static struct module_map_entry {
 	const char *ifname;
 	const char *kldname;
 } module_map[] = {
 	{
 		.ifname = "tun",
 		.kldname = "if_tuntap",
 	},
 	{
 		.ifname = "tap",
 		.kldname = "if_tuntap",
 	},
 	{
 		.ifname = "vmnet",
 		.kldname = "if_tuntap",
 	},
 	{
 		.ifname = "ipsec",
 		.kldname = "ipsec",
 	},
 	{
 		/*
 		 * This mapping exists because there is a conflicting enc module
 		 * in CAM.  ifconfig's guessing behavior will attempt to match
 		 * the ifname to a module as well as if_${ifname} and clash with
 		 * CAM enc.  This is an assertion of the correct module to load.
 		 */
 		.ifname = "enc",
 		.kldname = "if_enc",
 	},
 };
 
 
 void
 opt_register(struct option *p)
 {
 	p->next = opts;
 	opts = p;
 }
 
 static void
 usage(void)
 {
 	char options[1024];
 	struct option *p;
 
 	/* XXX not right but close enough for now */
 	options[0] = '\0';
 	for (p = opts; p != NULL; p = p->next) {
 		strlcat(options, p->opt_usage, sizeof(options));
 		strlcat(options, " ", sizeof(options));
 	}
 
 	fprintf(stderr,
 	"usage: ifconfig [-f type:format] %sinterface address_family\n"
 	"                [address [dest_address]] [parameters]\n"
 	"       ifconfig interface create\n"
 	"       ifconfig -a %s[-d] [-m] [-u] [-v] [address_family]\n"
 	"       ifconfig -l [-d] [-u] [address_family]\n"
 	"       ifconfig %s[-d] [-m] [-u] [-v]\n",
 		options, options, options);
 	exit(1);
 }
 
 void
 ioctl_ifcreate(int s, struct ifreq *ifr)
 {
 	if (ioctl(s, SIOCIFCREATE2, ifr) < 0) {
 		switch (errno) {
 		case EEXIST:
 			errx(1, "interface %s already exists", ifr->ifr_name);
 		default:
 			err(1, "SIOCIFCREATE2");
 		}
 	}
 }
 
 #define ORDERS_SIZE(x) sizeof(x) / sizeof(x[0])
 
 static int
 calcorders(struct ifaddrs *ifa, struct ifa_queue *q)
 {
 	struct ifaddrs *prev;
 	struct ifa_order_elt *cur;
 	unsigned int ord, af, ifa_ord;
 
 	prev = NULL;
 	cur = NULL;
 	ord = 0;
 	ifa_ord = 0;
 
 	while (ifa != NULL) {
 		if (prev == NULL ||
 		    strcmp(ifa->ifa_name, prev->ifa_name) != 0) {
 			cur = calloc(1, sizeof(*cur));
 
 			if (cur == NULL)
 				return (-1);
 
 			TAILQ_INSERT_TAIL(q, cur, link);
 			cur->if_order = ifa_ord ++;
 			cur->ifa = ifa;
 			ord = 0;
 		}
 
 		if (ifa->ifa_addr) {
 			af = ifa->ifa_addr->sa_family;
 
 			if (af < ORDERS_SIZE(cur->af_orders) &&
 			    cur->af_orders[af] == 0)
 				cur->af_orders[af] = ++ord;
 		}
 		prev = ifa;
 		ifa = ifa->ifa_next;
 	}
 
 	return (0);
 }
 
 static int
 cmpifaddrs(struct ifaddrs *a, struct ifaddrs *b, struct ifa_queue *q)
 {
 	struct ifa_order_elt *cur, *e1, *e2;
 	unsigned int af1, af2;
 	int ret;
 
 	e1 = e2 = NULL;
 
 	ret = strcmp(a->ifa_name, b->ifa_name);
 	if (ret != 0) {
 		TAILQ_FOREACH(cur, q, link) {
 			if (e1 && e2)
 				break;
 
 			if (strcmp(cur->ifa->ifa_name, a->ifa_name) == 0)
 				e1 = cur;
 			else if (strcmp(cur->ifa->ifa_name, b->ifa_name) == 0)
 				e2 = cur;
 		}
 
 		if (!e1 || !e2)
 			return (0);
 		else
 			return (e1->if_order - e2->if_order);
 
 	} else if (a->ifa_addr != NULL && b->ifa_addr != NULL) {
 		TAILQ_FOREACH(cur, q, link) {
 			if (strcmp(cur->ifa->ifa_name, a->ifa_name) == 0) {
 				e1 = cur;
 				break;
 			}
 		}
 
 		if (!e1)
 			return (0);
 
 		af1 = a->ifa_addr->sa_family;
 		af2 = b->ifa_addr->sa_family;
 
 		if (af1 < ORDERS_SIZE(e1->af_orders) &&
 		    af2 < ORDERS_SIZE(e1->af_orders))
 			return (e1->af_orders[af1] - e1->af_orders[af2]);
 	}
 
 	return (0);
 }
 
 static void freeformat(void)
 {
 
 	if (f_inet != NULL)
 		free(f_inet);
 	if (f_inet6 != NULL)
 		free(f_inet6);
 	if (f_ether != NULL)
 		free(f_ether);
 	if (f_addr != NULL)
 		free(f_addr);
 }
 
 static void setformat(char *input)
 {
 	char	*formatstr, *category, *modifier; 
 
 	formatstr = strdup(input);
 	while ((category = strsep(&formatstr, ",")) != NULL) {
 		modifier = strchr(category, ':');
 		if (modifier == NULL || modifier[1] == '\0') {
 			warnx("Skipping invalid format specification: %s\n",
 			    category);
 			continue;
 		}
 
 		/* Split the string on the separator, then seek past it */
 		modifier[0] = '\0';
 		modifier++;
 
 		if (strcmp(category, "addr") == 0)
 			f_addr = strdup(modifier);
 		else if (strcmp(category, "ether") == 0)
 			f_ether = strdup(modifier);
 		else if (strcmp(category, "inet") == 0)
 			f_inet = strdup(modifier);
 		else if (strcmp(category, "inet6") == 0)
 			f_inet6 = strdup(modifier);
 	}
 	free(formatstr);
 }
 
 #undef ORDERS_SIZE
 
 static struct ifaddrs *
 sortifaddrs(struct ifaddrs *list,
     int (*compare)(struct ifaddrs *, struct ifaddrs *, struct ifa_queue *),
     struct ifa_queue *q)
 {
 	struct ifaddrs *right, *temp, *last, *result, *next, *tail;
 	
 	right = list;
 	temp = list;
 	last = list;
 	result = NULL;
 	next = NULL;
 	tail = NULL;
 
 	if (!list || !list->ifa_next)
 		return (list);
 
 	while (temp && temp->ifa_next) {
 		last = right;
 		right = right->ifa_next;
 		temp = temp->ifa_next->ifa_next;
 	}
 
 	last->ifa_next = NULL;
 
 	list = sortifaddrs(list, compare, q);
 	right = sortifaddrs(right, compare, q);
 
 	while (list || right) {
 
 		if (!right) {
 			next = list;
 			list = list->ifa_next;
 		} else if (!list) {
 			next = right;
 			right = right->ifa_next;
 		} else if (compare(list, right, q) <= 0) {
 			next = list;
 			list = list->ifa_next;
 		} else {
 			next = right;
 			right = right->ifa_next;
 		}
 
 		if (!result)
 			result = next;
 		else
 			tail->ifa_next = next;
 
 		tail = next;
 	}
 
 	return (result);
 }
 
 void printifnamemaybe()
 {
 	if (printifname)
 		printf("%s\n", name);
 }
 
 int
 main(int argc, char *argv[])
 {
 	int c, all, namesonly, downonly, uponly;
 	const struct afswtch *afp = NULL;
 	int ifindex;
 	struct ifaddrs *ifap, *sifap, *ifa;
 	struct ifreq paifr;
 	const struct sockaddr_dl *sdl;
 	char options[1024], *cp, *envformat, *namecp = NULL;
 	struct ifa_queue q = TAILQ_HEAD_INITIALIZER(q);
 	struct ifa_order_elt *cur, *tmp;
 	const char *ifname, *matchgroup, *nogroup;
 	struct option *p;
 	size_t iflen;
 	int flags;
 
 	all = downonly = uponly = namesonly = noload = verbose = 0;
 	f_inet = f_inet6 = f_ether = f_addr = NULL;
 	matchgroup = nogroup = NULL;
 
+	lifh = ifconfig_open();
+	if (lifh == NULL)
+		err(EXIT_FAILURE, "ifconfig_open");
+
 	envformat = getenv("IFCONFIG_FORMAT");
 	if (envformat != NULL)
 		setformat(envformat);
 
 	/*
 	 * Ensure we print interface name when expected to,
 	 * even if we terminate early due to error.
 	 */
 	atexit(printifnamemaybe);
 
 	/* Parse leading line options */
 	strlcpy(options, "G:adf:klmnuv", sizeof(options));
 	for (p = opts; p != NULL; p = p->next)
 		strlcat(options, p->opt, sizeof(options));
 	while ((c = getopt(argc, argv, options)) != -1) {
 		switch (c) {
 		case 'a':	/* scan all interfaces */
 			all++;
 			break;
 		case 'd':	/* restrict scan to "down" interfaces */
 			downonly++;
 			break;
 		case 'f':
 			if (optarg == NULL)
 				usage();
 			setformat(optarg);
 			break;
 		case 'G':
 			if (optarg == NULL || all == 0)
 				usage();
 			nogroup = optarg;
 			break;
 		case 'k':
 			printkeys++;
 			break;
 		case 'l':	/* scan interface names only */
 			namesonly++;
 			break;
 		case 'm':	/* show media choices in status */
 			supmedia = 1;
 			break;
 		case 'n':	/* suppress module loading */
 			noload++;
 			break;
 		case 'u':	/* restrict scan to "up" interfaces */
 			uponly++;
 			break;
 		case 'v':
 			verbose++;
 			break;
 		case 'g':
 			if (all) {
 				if (optarg == NULL)
 					usage();
 				matchgroup = optarg;
 				break;
 			}
 			/* FALLTHROUGH */
 		default:
 			for (p = opts; p != NULL; p = p->next)
 				if (p->opt[0] == c) {
 					p->cb(optarg);
 					break;
 				}
 			if (p == NULL)
 				usage();
 			break;
 		}
 	}
 	argc -= optind;
 	argv += optind;
 
 	/* -l cannot be used with -a or -m */
 	if (namesonly && (all || supmedia))
 		usage();
 
 	/* nonsense.. */
 	if (uponly && downonly)
 		usage();
 
 	/* no arguments is equivalent to '-a' */
 	if (!namesonly && argc < 1)
 		all = 1;
 
 	/* -a and -l allow an address family arg to limit the output */
 	if (all || namesonly) {
 		if (argc > 1)
 			usage();
 
 		ifname = NULL;
 		ifindex = 0;
 		if (argc == 1) {
 			afp = af_getbyname(*argv);
 			if (afp == NULL) {
 				warnx("Address family '%s' unknown.", *argv);
 				usage();
 			}
 			if (afp->af_name != NULL)
 				argc--, argv++;
 			/* leave with afp non-zero */
 		}
 	} else {
 		/* not listing, need an argument */
 		if (argc < 1)
 			usage();
 
 		ifname = *argv;
 		argc--, argv++;
 
 		/* check and maybe load support for this interface */
 		ifmaybeload(ifname);
 
 		ifindex = if_nametoindex(ifname);
 		if (ifindex == 0) {
 			/*
 			 * NOTE:  We must special-case the `create' command
 			 * right here as we would otherwise fail when trying
 			 * to find the interface.
 			 */
 			if (argc > 0 && (strcmp(argv[0], "create") == 0 ||
 			    strcmp(argv[0], "plumb") == 0)) {
 				iflen = strlcpy(name, ifname, sizeof(name));
 				if (iflen >= sizeof(name))
 					errx(1, "%s: cloning name too long",
 					    ifname);
 				ifconfig(argc, argv, 1, NULL);
 				exit(exit_code);
 			}
 #ifdef JAIL
 			/*
 			 * NOTE:  We have to special-case the `-vnet' command
 			 * right here as we would otherwise fail when trying
 			 * to find the interface as it lives in another vnet.
 			 */
 			if (argc > 0 && (strcmp(argv[0], "-vnet") == 0)) {
 				iflen = strlcpy(name, ifname, sizeof(name));
 				if (iflen >= sizeof(name))
 					errx(1, "%s: interface name too long",
 					    ifname);
 				ifconfig(argc, argv, 0, NULL);
 				exit(exit_code);
 			}
 #endif
 			errx(1, "interface %s does not exist", ifname);
 		} else {
 			/*
 			 * Do not allow use `create` command as hostname if
 			 * address family is not specified.
 			 */
 			if (argc > 0 && (strcmp(argv[0], "create") == 0 ||
 			    strcmp(argv[0], "plumb") == 0)) {
 				if (argc == 1)
 					errx(1, "interface %s already exists",
 					    ifname);
 				argc--, argv++;
 			}
 		}
 	}
 
 	/* Check for address family */
 	if (argc > 0) {
 		afp = af_getbyname(*argv);
 		if (afp != NULL)
 			argc--, argv++;
 	}
 
 	/*
 	 * Check for a requested configuration action on a single interface,
 	 * which doesn't require building, sorting, and searching the entire
 	 * system address list
 	 */
 	if ((argc > 0) && (ifname != NULL)) {
 		iflen = strlcpy(name, ifname, sizeof(name));
 		if (iflen >= sizeof(name)) {
 			warnx("%s: interface name too long, skipping", ifname);
 		} else {
 			flags = getifflags(name, -1);
 			if (!(((flags & IFF_CANTCONFIG) != 0) ||
 				(downonly && (flags & IFF_UP) != 0) ||
 				(uponly && (flags & IFF_UP) == 0)))
 				ifconfig(argc, argv, 0, afp);
 		}
 		goto done;
 	}
 
 	if (getifaddrs(&ifap) != 0)
 		err(EXIT_FAILURE, "getifaddrs");
 
 	cp = NULL;
 	
 	if (calcorders(ifap, &q) != 0)
 		err(EXIT_FAILURE, "calcorders");
 		
 	sifap = sortifaddrs(ifap, cmpifaddrs, &q);
 
 	TAILQ_FOREACH_SAFE(cur, &q, link, tmp)
 		free(cur);
 
 	ifindex = 0;
 	for (ifa = sifap; ifa; ifa = ifa->ifa_next) {
 		memset(&paifr, 0, sizeof(paifr));
 		strlcpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name));
 		if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) {
 			memcpy(&paifr.ifr_addr, ifa->ifa_addr,
 			    ifa->ifa_addr->sa_len);
 		}
 
 		if (ifname != NULL && strcmp(ifname, ifa->ifa_name) != 0)
 			continue;
 		if (ifa->ifa_addr->sa_family == AF_LINK)
 			sdl = (const struct sockaddr_dl *) ifa->ifa_addr;
 		else
 			sdl = NULL;
 		if (cp != NULL && strcmp(cp, ifa->ifa_name) == 0 && !namesonly)
 			continue;
 		iflen = strlcpy(name, ifa->ifa_name, sizeof(name));
 		if (iflen >= sizeof(name)) {
 			warnx("%s: interface name too long, skipping",
 			    ifa->ifa_name);
 			continue;
 		}
 		cp = ifa->ifa_name;
 
 		if ((ifa->ifa_flags & IFF_CANTCONFIG) != 0)
 			continue;
 		if (downonly && (ifa->ifa_flags & IFF_UP) != 0)
 			continue;
 		if (uponly && (ifa->ifa_flags & IFF_UP) == 0)
 			continue;
 		if (!group_member(ifa->ifa_name, matchgroup, nogroup))
 			continue;
 		/*
 		 * Are we just listing the interfaces?
 		 */
 		if (namesonly) {
 			if (namecp == cp)
 				continue;
 			if (afp != NULL) {
 				/* special case for "ether" address family */
 				if (!strcmp(afp->af_name, "ether")) {
 					if (sdl == NULL ||
 					    (sdl->sdl_type != IFT_ETHER &&
 					    sdl->sdl_type != IFT_L2VLAN &&
 					    sdl->sdl_type != IFT_BRIDGE) ||
 					    sdl->sdl_alen != ETHER_ADDR_LEN)
 						continue;
 				} else {
 					if (ifa->ifa_addr->sa_family 
 					    != afp->af_af)
 						continue;
 				}
 			}
 			namecp = cp;
 			ifindex++;
 			if (ifindex > 1)
 				printf(" ");
 			fputs(name, stdout);
 			continue;
 		}
 		ifindex++;
 
 		if (argc > 0)
 			ifconfig(argc, argv, 0, afp);
 		else
 			status(afp, sdl, ifa);
 	}
 	if (namesonly)
 		printf("\n");
 	freeifaddrs(ifap);
 
 done:
 	freeformat();
+	ifconfig_close(lifh);
 	exit(exit_code);
 }
 
 /*
  * Returns true if an interface should be listed because any its groups
  * matches shell pattern "match" and none of groups matches pattern "nomatch".
  * If any pattern is NULL, corresponding condition is skipped.
  */
 static bool
 group_member(const char *ifname, const char *match, const char *nomatch)
 {
 	static int		 sock = -1;
 
 	struct ifgroupreq	 ifgr;
 	struct ifg_req		*ifg;
 	int			 len;
 	bool			 matched, nomatched;
 
 	/* Sanity checks. */
 	if (match == NULL && nomatch == NULL)
 		return (true);
 	if (ifname == NULL)
 		return (false);
 
 	memset(&ifgr, 0, sizeof(ifgr));
 	strlcpy(ifgr.ifgr_name, ifname, IFNAMSIZ);
 
 	/* The socket is opened once. Let _exit() close it. */
 	if (sock == -1) {
 		sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
     		if (sock == -1)
             	    errx(1, "%s: socket(AF_LOCAL,SOCK_DGRAM)", __func__);
 	}
 
 	/* Determine amount of memory for the list of groups. */
 	if (ioctl(sock, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) {
 		if (errno == EINVAL || errno == ENOTTY)
 			return (false);
 		else
 			errx(1, "%s: SIOCGIFGROUP", __func__);
 	}
 
 	/* Obtain the list of groups. */
 	len = ifgr.ifgr_len;
 	ifgr.ifgr_groups =
 	    (struct ifg_req *)calloc(len / sizeof(*ifg), sizeof(*ifg));
 
 	if (ifgr.ifgr_groups == NULL)
 		errx(1, "%s: no memory", __func__);
 	if (ioctl(sock, SIOCGIFGROUP, (caddr_t)&ifgr) == -1)
 		errx(1, "%s: SIOCGIFGROUP", __func__);
 
 	/* Perform matching. */
 	matched = false;
 	nomatched = true;
 	for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(*ifg); ifg++) {
 		len -= sizeof(struct ifg_req);
 		if (match)
 			matched |= !fnmatch(match, ifg->ifgrq_group, 0);
 		if (nomatch)
 			nomatched &= fnmatch(nomatch, ifg->ifgrq_group, 0);
 	}
 	free(ifgr.ifgr_groups);
 
 	if (match && !nomatch)
 		return (matched);
 	if (!match && nomatch)
 		return (nomatched);
 	return (matched && nomatched);
 }
 
 static struct afswtch *afs = NULL;
 
 void
 af_register(struct afswtch *p)
 {
 	p->af_next = afs;
 	afs = p;
 }
 
 static struct afswtch *
 af_getbyname(const char *name)
 {
 	struct afswtch *afp;
 
 	for (afp = afs; afp !=  NULL; afp = afp->af_next)
 		if (strcmp(afp->af_name, name) == 0)
 			return afp;
 	return NULL;
 }
 
 static struct afswtch *
 af_getbyfamily(int af)
 {
 	struct afswtch *afp;
 
 	for (afp = afs; afp != NULL; afp = afp->af_next)
 		if (afp->af_af == af)
 			return afp;
 	return NULL;
 }
 
 static void
 af_other_status(int s)
 {
 	struct afswtch *afp;
 	uint8_t afmask[howmany(AF_MAX, NBBY)];
 
 	memset(afmask, 0, sizeof(afmask));
 	for (afp = afs; afp != NULL; afp = afp->af_next) {
 		if (afp->af_other_status == NULL)
 			continue;
 		if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af))
 			continue;
 		afp->af_other_status(s);
 		setbit(afmask, afp->af_af);
 	}
 }
 
 static void
 af_all_tunnel_status(int s)
 {
 	struct afswtch *afp;
 	uint8_t afmask[howmany(AF_MAX, NBBY)];
 
 	memset(afmask, 0, sizeof(afmask));
 	for (afp = afs; afp != NULL; afp = afp->af_next) {
 		if (afp->af_status_tunnel == NULL)
 			continue;
 		if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af))
 			continue;
 		afp->af_status_tunnel(s);
 		setbit(afmask, afp->af_af);
 	}
 }
 
 static struct cmd *cmds = NULL;
 
 void
 cmd_register(struct cmd *p)
 {
 	p->c_next = cmds;
 	cmds = p;
 }
 
 static const struct cmd *
 cmd_lookup(const char *name, int iscreate)
 {
 	const struct cmd *p;
 
 	for (p = cmds; p != NULL; p = p->c_next)
 		if (strcmp(name, p->c_name) == 0) {
 			if (iscreate) {
 				if (p->c_iscloneop)
 					return p;
 			} else {
 				if (!p->c_iscloneop)
 					return p;
 			}
 		}
 	return NULL;
 }
 
 struct callback {
 	callback_func *cb_func;
 	void	*cb_arg;
 	struct callback *cb_next;
 };
 static struct callback *callbacks = NULL;
 
 void
 callback_register(callback_func *func, void *arg)
 {
 	struct callback *cb;
 
 	cb = malloc(sizeof(struct callback));
 	if (cb == NULL)
 		errx(1, "unable to allocate memory for callback");
 	cb->cb_func = func;
 	cb->cb_arg = arg;
 	cb->cb_next = callbacks;
 	callbacks = cb;
 }
 
 /* specially-handled commands */
 static void setifaddr(const char *, int, int, const struct afswtch *);
 static const struct cmd setifaddr_cmd = DEF_CMD("ifaddr", 0, setifaddr);
 
 static void setifdstaddr(const char *, int, int, const struct afswtch *);
 static const struct cmd setifdstaddr_cmd =
 	DEF_CMD("ifdstaddr", 0, setifdstaddr);
 
 static int
 ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *uafp)
 {
 	const struct afswtch *afp, *nafp;
 	const struct cmd *p;
 	struct callback *cb;
 	int s;
 
 	strlcpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
 	afp = NULL;
 	if (uafp != NULL)
 		afp = uafp;
 	/*
 	 * This is the historical "accident" allowing users to configure IPv4
 	 * addresses without the "inet" keyword which while a nice feature has
 	 * proven to complicate other things.  We cannot remove this but only
 	 * make sure we will never have a similar implicit default for IPv6 or
 	 * any other address familiy.  We need a fallback though for
 	 * ifconfig IF up/down etc. to work without INET support as people
 	 * never used ifconfig IF link up/down, etc. either.
 	 */
 #ifndef RESCUE
 #ifdef INET
 	if (afp == NULL && feature_present("inet"))
 		afp = af_getbyname("inet");
 #endif
 #endif
 	if (afp == NULL)
 		afp = af_getbyname("link");
 	if (afp == NULL) {
 		warnx("Please specify an address_family.");
 		usage();
 	}
 top:
 	ifr.ifr_addr.sa_family =
 		afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ?
 		AF_LOCAL : afp->af_af;
 
 	if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0 &&
 	    (uafp != NULL || errno != EAFNOSUPPORT ||
 	     (s = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0))
 		err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family);
 
 	while (argc > 0) {
 		p = cmd_lookup(*argv, iscreate);
 		if (iscreate && p == NULL) {
 			/*
 			 * Push the clone create callback so the new
 			 * device is created and can be used for any
 			 * remaining arguments.
 			 */
 			cb = callbacks;
 			if (cb == NULL)
 				errx(1, "internal error, no callback");
 			callbacks = cb->cb_next;
 			cb->cb_func(s, cb->cb_arg);
 			iscreate = 0;
 			/*
 			 * Handle any address family spec that
 			 * immediately follows and potentially
 			 * recreate the socket.
 			 */
 			nafp = af_getbyname(*argv);
 			if (nafp != NULL) {
 				argc--, argv++;
 				if (nafp != afp) {
 					close(s);
 					afp = nafp;
 					goto top;
 				}
 			}
 			/*
 			 * Look for a normal parameter.
 			 */
 			continue;
 		}
 		if (p == NULL) {
 			/*
 			 * Not a recognized command, choose between setting
 			 * the interface address and the dst address.
 			 */
 			p = (setaddr ? &setifdstaddr_cmd : &setifaddr_cmd);
 		}
 		if (p->c_parameter == NEXTARG && p->c_u.c_func) {
 			if (argv[1] == NULL)
 				errx(1, "'%s' requires argument",
 				    p->c_name);
 			p->c_u.c_func(argv[1], 0, s, afp);
 			argc--, argv++;
 		} else if (p->c_parameter == OPTARG && p->c_u.c_func) {
 			p->c_u.c_func(argv[1], 0, s, afp);
 			if (argv[1] != NULL)
 				argc--, argv++;
 		} else if (p->c_parameter == NEXTARG2 && p->c_u.c_func2) {
 			if (argc < 3)
 				errx(1, "'%s' requires 2 arguments",
 				    p->c_name);
 			p->c_u.c_func2(argv[1], argv[2], s, afp);
 			argc -= 2, argv += 2;
 		} else if (p->c_u.c_func)
 			p->c_u.c_func(*argv, p->c_parameter, s, afp);
 		argc--, argv++;
 	}
 
 	/*
 	 * Do any post argument processing required by the address family.
 	 */
 	if (afp->af_postproc != NULL)
 		afp->af_postproc(s, afp);
 	/*
 	 * Do deferred callbacks registered while processing
 	 * command-line arguments.
 	 */
 	for (cb = callbacks; cb != NULL; cb = cb->cb_next)
 		cb->cb_func(s, cb->cb_arg);
 	/*
 	 * Do deferred operations.
 	 */
 	if (clearaddr) {
 		if (afp->af_ridreq == NULL || afp->af_difaddr == 0) {
 			warnx("interface %s cannot change %s addresses!",
 			      name, afp->af_name);
 			clearaddr = 0;
 		}
 	}
 	if (clearaddr) {
 		int ret;
 		strlcpy(((struct ifreq *)afp->af_ridreq)->ifr_name, name,
 			sizeof ifr.ifr_name);
 		ret = ioctl(s, afp->af_difaddr, afp->af_ridreq);
 		if (ret < 0) {
 			if (errno == EADDRNOTAVAIL && (doalias >= 0)) {
 				/* means no previous address for interface */
 			} else
 				Perror("ioctl (SIOCDIFADDR)");
 		}
 	}
 	if (newaddr) {
 		if (afp->af_addreq == NULL || afp->af_aifaddr == 0) {
 			warnx("interface %s cannot change %s addresses!",
 			      name, afp->af_name);
 			newaddr = 0;
 		}
 	}
 	if (newaddr && (setaddr || setmask)) {
 		strlcpy(((struct ifreq *)afp->af_addreq)->ifr_name, name,
 			sizeof ifr.ifr_name);
 		if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0)
 			Perror("ioctl (SIOCAIFADDR)");
 	}
 
 	close(s);
 	return(0);
 }
 
 /*ARGSUSED*/
 static void
 setifaddr(const char *addr, int param, int s, const struct afswtch *afp)
 {
 	if (afp->af_getaddr == NULL)
 		return;
 	/*
 	 * Delay the ioctl to set the interface addr until flags are all set.
 	 * The address interpretation may depend on the flags,
 	 * and the flags may change when the address is set.
 	 */
 	setaddr++;
 	if (doalias == 0 && afp->af_af != AF_LINK)
 		clearaddr = 1;
 	afp->af_getaddr(addr, (doalias >= 0 ? ADDR : RIDADDR));
 }
 
 static void
 settunnel(const char *src, const char *dst, int s, const struct afswtch *afp)
 {
 	struct addrinfo *srcres, *dstres;
 	int ecode;
 
 	if (afp->af_settunnel == NULL) {
 		warn("address family %s does not support tunnel setup",
 			afp->af_name);
 		return;
 	}
 
 	if ((ecode = getaddrinfo(src, NULL, NULL, &srcres)) != 0)
 		errx(1, "error in parsing address string: %s",
 		    gai_strerror(ecode));
 
 	if ((ecode = getaddrinfo(dst, NULL, NULL, &dstres)) != 0)
 		errx(1, "error in parsing address string: %s",
 		    gai_strerror(ecode));
 
 	if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family)
 		errx(1,
 		    "source and destination address families do not match");
 
 	afp->af_settunnel(s, srcres, dstres);
 
 	freeaddrinfo(srcres);
 	freeaddrinfo(dstres);
 }
 
 /* ARGSUSED */
 static void
 deletetunnel(const char *vname, int param, int s, const struct afswtch *afp)
 {
 
 	if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0)
 		err(1, "SIOCDIFPHYADDR");
 }
 
 #ifdef JAIL
 static void
 setifvnet(const char *jname, int dummy __unused, int s,
     const struct afswtch *afp)
 {
 	struct ifreq my_ifr;
 
 	memcpy(&my_ifr, &ifr, sizeof(my_ifr));
 	my_ifr.ifr_jid = jail_getid(jname);
 	if (my_ifr.ifr_jid < 0)
 		errx(1, "%s", jail_errmsg);
 	if (ioctl(s, SIOCSIFVNET, &my_ifr) < 0)
 		err(1, "SIOCSIFVNET");
 }
 
 static void
 setifrvnet(const char *jname, int dummy __unused, int s,
     const struct afswtch *afp)
 {
 	struct ifreq my_ifr;
 
 	memcpy(&my_ifr, &ifr, sizeof(my_ifr));
 	my_ifr.ifr_jid = jail_getid(jname);
 	if (my_ifr.ifr_jid < 0)
 		errx(1, "%s", jail_errmsg);
 	if (ioctl(s, SIOCSIFRVNET, &my_ifr) < 0)
 		err(1, "SIOCSIFRVNET(%d, %s)", my_ifr.ifr_jid, my_ifr.ifr_name);
 }
 #endif
 
 static void
 setifnetmask(const char *addr, int dummy __unused, int s,
     const struct afswtch *afp)
 {
 	if (afp->af_getaddr != NULL) {
 		setmask++;
 		afp->af_getaddr(addr, MASK);
 	}
 }
 
 static void
 setifbroadaddr(const char *addr, int dummy __unused, int s,
     const struct afswtch *afp)
 {
 	if (afp->af_getaddr != NULL)
 		afp->af_getaddr(addr, DSTADDR);
 }
 
 static void
 notealias(const char *addr, int param, int s, const struct afswtch *afp)
 {
 #define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
 	if (setaddr && doalias == 0 && param < 0)
 		if (afp->af_addreq != NULL && afp->af_ridreq != NULL)
 			bcopy((caddr_t)rqtosa(af_addreq),
 			      (caddr_t)rqtosa(af_ridreq),
 			      rqtosa(af_addreq)->sa_len);
 	doalias = param;
 	if (param < 0) {
 		clearaddr = 1;
 		newaddr = 0;
 	} else
 		clearaddr = 0;
 #undef rqtosa
 }
 
 /*ARGSUSED*/
 static void
 setifdstaddr(const char *addr, int param __unused, int s, 
     const struct afswtch *afp)
 {
 	if (afp->af_getaddr != NULL)
 		afp->af_getaddr(addr, DSTADDR);
 }
 
 static int
 getifflags(const char *ifname, int us)
 {
 	struct ifreq my_ifr;
 	int s;
 	
 	memset(&my_ifr, 0, sizeof(my_ifr));
 	(void) strlcpy(my_ifr.ifr_name, ifname, sizeof(my_ifr.ifr_name));
 	if (us < 0) {
 		if ((s = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0)
 			err(1, "socket(family AF_LOCAL,SOCK_DGRAM");
 	} else
 		s = us;
  	if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) {
  		Perror("ioctl (SIOCGIFFLAGS)");
  		exit(1);
  	}
 	if (us < 0)
 		close(s);
 	return ((my_ifr.ifr_flags & 0xffff) | (my_ifr.ifr_flagshigh << 16));
 }
 
 /*
  * Note: doing an SIOCIGIFFLAGS scribbles on the union portion
  * of the ifreq structure, which may confuse other parts of ifconfig.
  * Make a private copy so we can avoid that.
  */
 static void
 setifflags(const char *vname, int value, int s, const struct afswtch *afp)
 {
 	struct ifreq		my_ifr;
 	int flags;
 
 	flags = getifflags(name, s);
 	if (value < 0) {
 		value = -value;
 		flags &= ~value;
 	} else
 		flags |= value;
 	memset(&my_ifr, 0, sizeof(my_ifr));
 	(void) strlcpy(my_ifr.ifr_name, name, sizeof(my_ifr.ifr_name));
 	my_ifr.ifr_flags = flags & 0xffff;
 	my_ifr.ifr_flagshigh = flags >> 16;
 	if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0)
 		Perror(vname);
 }
 
 void
 setifcap(const char *vname, int value, int s, const struct afswtch *afp)
 {
 	int flags;
 
  	if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) {
  		Perror("ioctl (SIOCGIFCAP)");
  		exit(1);
  	}
 	flags = ifr.ifr_curcap;
 	if (value < 0) {
 		value = -value;
 		flags &= ~value;
 	} else
 		flags |= value;
 	flags &= ifr.ifr_reqcap;
 	ifr.ifr_reqcap = flags;
 	if (ioctl(s, SIOCSIFCAP, (caddr_t)&ifr) < 0)
 		Perror(vname);
 }
 
 static void
 setifmetric(const char *val, int dummy __unused, int s, 
     const struct afswtch *afp)
 {
 	strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
 	ifr.ifr_metric = atoi(val);
 	if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
 		err(1, "ioctl SIOCSIFMETRIC (set metric)");
 }
 
 static void
 setifmtu(const char *val, int dummy __unused, int s, 
     const struct afswtch *afp)
 {
 	strlcpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
 	ifr.ifr_mtu = atoi(val);
 	if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0)
 		err(1, "ioctl SIOCSIFMTU (set mtu)");
 }
 
 static void
 setifpcp(const char *val, int arg __unused, int s, const struct afswtch *afp)
 {
 	u_long ul;
 	char *endp;
 
 	ul = strtoul(val, &endp, 0);
 	if (*endp != '\0')
 		errx(1, "invalid value for pcp");
 	if (ul > 7)
 		errx(1, "value for pcp out of range");
 	ifr.ifr_lan_pcp = ul;
 	if (ioctl(s, SIOCSLANPCP, (caddr_t)&ifr) == -1)
 		err(1, "SIOCSLANPCP");
 }
 
 static void
 disableifpcp(const char *val, int arg __unused, int s,
     const struct afswtch *afp)
 {
 
 	ifr.ifr_lan_pcp = IFNET_PCP_NONE;
 	if (ioctl(s, SIOCSLANPCP, (caddr_t)&ifr) == -1)
 		err(1, "SIOCSLANPCP");
 }
 
 static void
 setifname(const char *val, int dummy __unused, int s, 
     const struct afswtch *afp)
 {
 	char *newname;
 	
 	strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
 
 	newname = strdup(val);
 	if (newname == NULL)
 		err(1, "no memory to set ifname");
 	ifr.ifr_data = newname;
 	if (ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) {
 		free(newname);
 		err(1, "ioctl SIOCSIFNAME (set name)");
 	}
 	printifname = 1;
 	strlcpy(name, newname, sizeof(name));
 	free(newname);
 }
 
 /* ARGSUSED */
 static void
 setifdescr(const char *val, int dummy __unused, int s, 
     const struct afswtch *afp)
 {
 	char *newdescr;
 
 	strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
 	
 	ifr.ifr_buffer.length = strlen(val) + 1;
 	if (ifr.ifr_buffer.length == 1) {
 		ifr.ifr_buffer.buffer = newdescr = NULL;
 		ifr.ifr_buffer.length = 0;
 	} else {
 		newdescr = strdup(val);
 		ifr.ifr_buffer.buffer = newdescr;
 		if (newdescr == NULL) {
 			warn("no memory to set ifdescr");
 			return;
 		}
 	}
 
 	if (ioctl(s, SIOCSIFDESCR, (caddr_t)&ifr) < 0)
 		err(1, "ioctl SIOCSIFDESCR (set descr)");
 
 	free(newdescr);
 }
 
 /* ARGSUSED */
 static void
 unsetifdescr(const char *val, int value, int s, const struct afswtch *afp)
 {
 
 	setifdescr("", 0, s, 0);
 }
 
 #define	IFFBITS \
 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\7RUNNING" \
 "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
 "\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP"
 
 #define	IFCAPBITS \
 "\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \
 "\10VLAN_HWCSUM\11TSO4\12TSO6\13LRO\14WOL_UCAST\15WOL_MCAST\16WOL_MAGIC" \
 "\17TOE4\20TOE6\21VLAN_HWFILTER\23VLAN_HWTSO\24LINKSTATE\25NETMAP" \
 "\26RXCSUM_IPV6\27TXCSUM_IPV6\31TXRTLMT\32HWRXTSTMP\33NOMAP\34TXTLS4\35TXTLS6" \
 "\36VXLAN_HWCSUM\37VXLAN_HWTSO\40TXTLS_RTLMT"
 
 /*
  * Print the status of the interface.  If an address family was
  * specified, show only it; otherwise, show them all.
  */
 static void
 status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
 	struct ifaddrs *ifa)
 {
 	struct ifaddrs *ift;
 	int allfamilies, s;
 	struct ifstat ifs;
 
 	if (afp == NULL) {
 		allfamilies = 1;
 		ifr.ifr_addr.sa_family = AF_LOCAL;
 	} else {
 		allfamilies = 0;
 		ifr.ifr_addr.sa_family =
 		    afp->af_af == AF_LINK ? AF_LOCAL : afp->af_af;
 	}
 	strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
 
 	s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0);
 	if (s < 0)
 		err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family);
 
 	printf("%s: ", name);
 	printb("flags", ifa->ifa_flags, IFFBITS);
 	if (ioctl(s, SIOCGIFMETRIC, &ifr) != -1)
 		printf(" metric %d", ifr.ifr_metric);
 	if (ioctl(s, SIOCGIFMTU, &ifr) != -1)
 		printf(" mtu %d", ifr.ifr_mtu);
 	putchar('\n');
 
 	for (;;) {
 		if ((descr = reallocf(descr, descrlen)) != NULL) {
 			ifr.ifr_buffer.buffer = descr;
 			ifr.ifr_buffer.length = descrlen;
 			if (ioctl(s, SIOCGIFDESCR, &ifr) == 0) {
 				if (ifr.ifr_buffer.buffer == descr) {
 					if (strlen(descr) > 0)
 						printf("\tdescription: %s\n",
 						    descr);
 				} else if (ifr.ifr_buffer.length > descrlen) {
 					descrlen = ifr.ifr_buffer.length;
 					continue;
 				}
 			}
 		} else
 			warn("unable to allocate memory for interface"
 			    "description");
 		break;
 	}
 
 	if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) {
 		if (ifr.ifr_curcap != 0) {
 			printb("\toptions", ifr.ifr_curcap, IFCAPBITS);
 			putchar('\n');
 		}
 		if (supmedia && ifr.ifr_reqcap != 0) {
 			printb("\tcapabilities", ifr.ifr_reqcap, IFCAPBITS);
 			putchar('\n');
 		}
 	}
 
 	tunnel_status(s);
 
 	for (ift = ifa; ift != NULL; ift = ift->ifa_next) {
 		if (ift->ifa_addr == NULL)
 			continue;
 		if (strcmp(ifa->ifa_name, ift->ifa_name) != 0)
 			continue;
 		if (allfamilies) {
 			const struct afswtch *p;
 			p = af_getbyfamily(ift->ifa_addr->sa_family);
 			if (p != NULL && p->af_status != NULL)
 				p->af_status(s, ift);
 		} else if (afp->af_af == ift->ifa_addr->sa_family)
 			afp->af_status(s, ift);
 	}
 #if 0
 	if (allfamilies || afp->af_af == AF_LINK) {
 		const struct afswtch *lafp;
 
 		/*
 		 * Hack; the link level address is received separately
 		 * from the routing information so any address is not
 		 * handled above.  Cobble together an entry and invoke
 		 * the status method specially.
 		 */
 		lafp = af_getbyname("lladdr");
 		if (lafp != NULL) {
 			info.rti_info[RTAX_IFA] = (struct sockaddr *)sdl;
 			lafp->af_status(s, &info);
 		}
 	}
 #endif
 	if (allfamilies)
 		af_other_status(s);
 	else if (afp->af_other_status != NULL)
 		afp->af_other_status(s);
 
 	strlcpy(ifs.ifs_name, name, sizeof ifs.ifs_name);
 	if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0) 
 		printf("%s", ifs.ascii);
 
 	if (verbose > 0)
 		sfp_status(s, &ifr, verbose);
 
 	close(s);
 	return;
 }
 
 static void
 tunnel_status(int s)
 {
 	af_all_tunnel_status(s);
 }
 
 void
 Perror(const char *cmd)
 {
 	switch (errno) {
 
 	case ENXIO:
 		errx(1, "%s: no such interface", cmd);
 		break;
 
 	case EPERM:
 		errx(1, "%s: permission denied", cmd);
 		break;
 
 	default:
 		err(1, "%s", cmd);
 	}
 }
 
 /*
  * Print a value a la the %b format of the kernel's printf
  */
 void
 printb(const char *s, unsigned v, const char *bits)
 {
 	int i, any = 0;
 	char c;
 
 	if (bits && *bits == 8)
 		printf("%s=%o", s, v);
 	else
 		printf("%s=%x", s, v);
 	if (bits) {
 		bits++;
 		putchar('<');
 		while ((i = *bits++) != '\0') {
 			if (v & (1u << (i-1))) {
 				if (any)
 					putchar(',');
 				any = 1;
 				for (; (c = *bits) > 32; bits++)
 					putchar(c);
 			} else
 				for (; *bits > 32; bits++)
 					;
 		}
 		putchar('>');
 	}
 }
 
 void
 print_vhid(const struct ifaddrs *ifa, const char *s)
 {
 	struct if_data *ifd;
 
 	if (ifa->ifa_data == NULL)
 		return;
 
 	ifd = ifa->ifa_data;
 	if (ifd->ifi_vhid == 0)
 		return;
 	
 	printf(" vhid %d", ifd->ifi_vhid);
 }
 
 void
 ifmaybeload(const char *name)
 {
 #define MOD_PREFIX_LEN		3	/* "if_" */
 	struct module_stat mstat;
 	int i, fileid, modid;
 	char ifkind[IFNAMSIZ + MOD_PREFIX_LEN], ifname[IFNAMSIZ], *dp;
 	const char *cp;
 	struct module_map_entry *mme;
 	bool found;
 
 	/* loading suppressed by the user */
 	if (noload)
 		return;
 
 	/* trim the interface number off the end */
 	strlcpy(ifname, name, sizeof(ifname));
 	for (dp = ifname; *dp != 0; dp++)
 		if (isdigit(*dp)) {
 			*dp = 0;
 			break;
 		}
 
 	/* Either derive it from the map or guess otherwise */
 	*ifkind = '\0';
 	found = false;
 	for (i = 0; i < nitems(module_map); ++i) {
 		mme = &module_map[i];
 		if (strcmp(mme->ifname, ifname) == 0) {
 			strlcpy(ifkind, mme->kldname, sizeof(ifkind));
 			found = true;
 			break;
 		}
 	}
 
 	/* We didn't have an alias for it... we'll guess. */
 	if (!found) {
 	    /* turn interface and unit into module name */
 	    strlcpy(ifkind, "if_", sizeof(ifkind));
 	    strlcat(ifkind, ifname, sizeof(ifkind));
 	}
 
 	/* scan files in kernel */
 	mstat.version = sizeof(struct module_stat);
 	for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) {
 		/* scan modules in file */
 		for (modid = kldfirstmod(fileid); modid > 0;
 		     modid = modfnext(modid)) {
 			if (modstat(modid, &mstat) < 0)
 				continue;
 			/* strip bus name if present */
 			if ((cp = strchr(mstat.name, '/')) != NULL) {
 				cp++;
 			} else {
 				cp = mstat.name;
 			}
 			/*
 			 * Is it already loaded?  Don't compare with ifname if
 			 * we were specifically told which kld to use.  Doing
 			 * so could lead to conflicts not trivially solved.
 			 */
 			if ((!found && strcmp(ifname, cp) == 0) ||
 			    strcmp(ifkind, cp) == 0)
 				return;
 		}
 	}
 
 	/*
 	 * Try to load the module.  But ignore failures, because ifconfig can't
 	 * infer the names of all drivers (eg mlx4en(4)).
 	 */
 	(void) kldload(ifkind);
 }
 
 static struct cmd basic_cmds[] = {
 	DEF_CMD("up",		IFF_UP,		setifflags),
 	DEF_CMD("down",		-IFF_UP,	setifflags),
 	DEF_CMD("arp",		-IFF_NOARP,	setifflags),
 	DEF_CMD("-arp",		IFF_NOARP,	setifflags),
 	DEF_CMD("debug",	IFF_DEBUG,	setifflags),
 	DEF_CMD("-debug",	-IFF_DEBUG,	setifflags),
 	DEF_CMD_ARG("description",		setifdescr),
 	DEF_CMD_ARG("descr",			setifdescr),
 	DEF_CMD("-description",	0,		unsetifdescr),
 	DEF_CMD("-descr",	0,		unsetifdescr),
 	DEF_CMD("promisc",	IFF_PPROMISC,	setifflags),
 	DEF_CMD("-promisc",	-IFF_PPROMISC,	setifflags),
 	DEF_CMD("add",		IFF_UP,		notealias),
 	DEF_CMD("alias",	IFF_UP,		notealias),
 	DEF_CMD("-alias",	-IFF_UP,	notealias),
 	DEF_CMD("delete",	-IFF_UP,	notealias),
 	DEF_CMD("remove",	-IFF_UP,	notealias),
 #ifdef notdef
 #define	EN_SWABIPS	0x1000
 	DEF_CMD("swabips",	EN_SWABIPS,	setifflags),
 	DEF_CMD("-swabips",	-EN_SWABIPS,	setifflags),
 #endif
 	DEF_CMD_ARG("netmask",			setifnetmask),
 	DEF_CMD_ARG("metric",			setifmetric),
 	DEF_CMD_ARG("broadcast",		setifbroadaddr),
 	DEF_CMD_ARG2("tunnel",			settunnel),
 	DEF_CMD("-tunnel", 0,			deletetunnel),
 	DEF_CMD("deletetunnel", 0,		deletetunnel),
 #ifdef JAIL
 	DEF_CMD_ARG("vnet",			setifvnet),
 	DEF_CMD_ARG("-vnet",			setifrvnet),
 #endif
 	DEF_CMD("link0",	IFF_LINK0,	setifflags),
 	DEF_CMD("-link0",	-IFF_LINK0,	setifflags),
 	DEF_CMD("link1",	IFF_LINK1,	setifflags),
 	DEF_CMD("-link1",	-IFF_LINK1,	setifflags),
 	DEF_CMD("link2",	IFF_LINK2,	setifflags),
 	DEF_CMD("-link2",	-IFF_LINK2,	setifflags),
 	DEF_CMD("monitor",	IFF_MONITOR,	setifflags),
 	DEF_CMD("-monitor",	-IFF_MONITOR,	setifflags),
 	DEF_CMD("mextpg",	IFCAP_MEXTPG,	setifcap),
 	DEF_CMD("-mextpg",	-IFCAP_MEXTPG,	setifcap),
 	DEF_CMD("staticarp",	IFF_STATICARP,	setifflags),
 	DEF_CMD("-staticarp",	-IFF_STATICARP,	setifflags),
 	DEF_CMD("rxcsum6",	IFCAP_RXCSUM_IPV6,	setifcap),
 	DEF_CMD("-rxcsum6",	-IFCAP_RXCSUM_IPV6,	setifcap),
 	DEF_CMD("txcsum6",	IFCAP_TXCSUM_IPV6,	setifcap),
 	DEF_CMD("-txcsum6",	-IFCAP_TXCSUM_IPV6,	setifcap),
 	DEF_CMD("rxcsum",	IFCAP_RXCSUM,	setifcap),
 	DEF_CMD("-rxcsum",	-IFCAP_RXCSUM,	setifcap),
 	DEF_CMD("txcsum",	IFCAP_TXCSUM,	setifcap),
 	DEF_CMD("-txcsum",	-IFCAP_TXCSUM,	setifcap),
 	DEF_CMD("netcons",	IFCAP_NETCONS,	setifcap),
 	DEF_CMD("-netcons",	-IFCAP_NETCONS,	setifcap),
 	DEF_CMD_ARG("pcp",			setifpcp),
 	DEF_CMD("-pcp", 0,			disableifpcp),
 	DEF_CMD("polling",	IFCAP_POLLING,	setifcap),
 	DEF_CMD("-polling",	-IFCAP_POLLING,	setifcap),
 	DEF_CMD("tso6",		IFCAP_TSO6,	setifcap),
 	DEF_CMD("-tso6",	-IFCAP_TSO6,	setifcap),
 	DEF_CMD("tso4",		IFCAP_TSO4,	setifcap),
 	DEF_CMD("-tso4",	-IFCAP_TSO4,	setifcap),
 	DEF_CMD("tso",		IFCAP_TSO,	setifcap),
 	DEF_CMD("-tso",		-IFCAP_TSO,	setifcap),
 	DEF_CMD("toe",		IFCAP_TOE,	setifcap),
 	DEF_CMD("-toe",		-IFCAP_TOE,	setifcap),
 	DEF_CMD("lro",		IFCAP_LRO,	setifcap),
 	DEF_CMD("-lro",		-IFCAP_LRO,	setifcap),
 	DEF_CMD("txtls",	IFCAP_TXTLS,	setifcap),
 	DEF_CMD("-txtls",	-IFCAP_TXTLS,	setifcap),
 	DEF_CMD("wol",		IFCAP_WOL,	setifcap),
 	DEF_CMD("-wol",		-IFCAP_WOL,	setifcap),
 	DEF_CMD("wol_ucast",	IFCAP_WOL_UCAST,	setifcap),
 	DEF_CMD("-wol_ucast",	-IFCAP_WOL_UCAST,	setifcap),
 	DEF_CMD("wol_mcast",	IFCAP_WOL_MCAST,	setifcap),
 	DEF_CMD("-wol_mcast",	-IFCAP_WOL_MCAST,	setifcap),
 	DEF_CMD("wol_magic",	IFCAP_WOL_MAGIC,	setifcap),
 	DEF_CMD("-wol_magic",	-IFCAP_WOL_MAGIC,	setifcap),
 	DEF_CMD("txrtlmt",	IFCAP_TXRTLMT,	setifcap),
 	DEF_CMD("-txrtlmt",	-IFCAP_TXRTLMT,	setifcap),
 	DEF_CMD("txtlsrtlmt",	IFCAP_TXTLS_RTLMT,	setifcap),
 	DEF_CMD("-txtlsrtlmt",	-IFCAP_TXTLS_RTLMT,	setifcap),
 	DEF_CMD("hwrxtstmp",	IFCAP_HWRXTSTMP,	setifcap),
 	DEF_CMD("-hwrxtstmp",	-IFCAP_HWRXTSTMP,	setifcap),
 	DEF_CMD("normal",	-IFF_LINK0,	setifflags),
 	DEF_CMD("compress",	IFF_LINK0,	setifflags),
 	DEF_CMD("noicmp",	IFF_LINK1,	setifflags),
 	DEF_CMD_ARG("mtu",			setifmtu),
 	DEF_CMD_ARG("name",			setifname),
 };
 
 static __constructor void
 ifconfig_ctor(void)
 {
 	size_t i;
 
 	for (i = 0; i < nitems(basic_cmds);  i++)
 		cmd_register(&basic_cmds[i]);
 }
diff --git a/sbin/ifconfig/ifconfig.h b/sbin/ifconfig/ifconfig.h
index 67c25f5921d6..61b1137b47ba 100644
--- a/sbin/ifconfig/ifconfig.h
+++ b/sbin/ifconfig/ifconfig.h
@@ -1,163 +1,168 @@
 /*-
  * SPDX-License-Identifier: BSD-4-Clause
  *
  * Copyright (c) 1997 Peter Wemm.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. 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.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
  *      This product includes software developed for the FreeBSD Project
  *	by Peter Wemm.
  * 4. The name of the author may not be used to endorse or promote products
  *    derived from this software without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
  *
  * so there!
  *
  * $FreeBSD$
  */
 
+#pragma once
+
+#include <libifconfig.h>
+
 #define	__constructor	__attribute__((constructor))
 
 struct afswtch;
 struct cmd;
 
 typedef	void c_func(const char *cmd, int arg, int s, const struct afswtch *afp);
 typedef	void c_func2(const char *arg1, const char *arg2, int s, const struct afswtch *afp);
 
 struct cmd {
 	const char *c_name;
 	int	c_parameter;
 #define	NEXTARG		0xffffff	/* has following arg */
 #define	NEXTARG2	0xfffffe	/* has 2 following args */
 #define	OPTARG		0xfffffd	/* has optional following arg */
 	union {
 		c_func	*c_func;
 		c_func2	*c_func2;
 	} c_u;
 	int	c_iscloneop;
 	struct cmd *c_next;
 };
 void	cmd_register(struct cmd *);
 
 typedef	void callback_func(int s, void *);
 void	callback_register(callback_func *, void *);
 
 /*
  * Macros for declaring command functions and initializing entries.
  */
 #define	DECL_CMD_FUNC(name, cmd, arg) \
 	void name(const char *cmd, int arg, int s, const struct afswtch *afp)
 #define	DECL_CMD_FUNC2(name, arg1, arg2) \
 	void name(const char *arg1, const char *arg2, int s, const struct afswtch *afp)
 
 #define	DEF_CMD(name, param, func)	{ name, param, { .c_func = func }, 0, NULL }
 #define	DEF_CMD_ARG(name, func)		{ name, NEXTARG, { .c_func = func }, 0, NULL }
 #define	DEF_CMD_OPTARG(name, func)	{ name, OPTARG, { .c_func = func }, 0, NULL }
 #define	DEF_CMD_ARG2(name, func)	{ name, NEXTARG2, { .c_func2 = func }, 0, NULL }
 #define	DEF_CLONE_CMD(name, param, func) { name, param, { .c_func = func }, 1, NULL }
 #define	DEF_CLONE_CMD_ARG(name, func)	{ name, NEXTARG, { .c_func = func }, 1, NULL }
 #define	DEF_CLONE_CMD_ARG2(name, func)	{ name, NEXTARG2, { .c_func2 = func }, 1, NULL }
 
 struct ifaddrs;
 struct addrinfo;
 
 enum {
 	RIDADDR,
 	ADDR,
 	MASK,
 	DSTADDR,
 };
 
 struct afswtch {
 	const char	*af_name;	/* as given on cmd line, e.g. "inet" */
 	short		af_af;		/* AF_* */
 	/*
 	 * Status is handled one of two ways; if there is an
 	 * address associated with the interface then the
 	 * associated address family af_status method is invoked
 	 * with the appropriate addressin info.  Otherwise, if
 	 * all possible info is to be displayed and af_other_status
 	 * is defined then it is invoked after all address status
 	 * is presented.
 	 */
 	void		(*af_status)(int, const struct ifaddrs *);
 	void		(*af_other_status)(int);
 					/* parse address method */
 	void		(*af_getaddr)(const char *, int);
 					/* parse prefix method (IPv6) */
 	void		(*af_getprefix)(const char *, int);
 	void		(*af_postproc)(int s, const struct afswtch *);
 	u_long		af_difaddr;	/* set dst if address ioctl */
 	u_long		af_aifaddr;	/* set if address ioctl */
 	void		*af_ridreq;	/* */
 	void		*af_addreq;	/* */
 	struct afswtch	*af_next;
 
 	/* XXX doesn't fit model */
 	void		(*af_status_tunnel)(int);
 	void		(*af_settunnel)(int s, struct addrinfo *srcres,
 				struct addrinfo *dstres);
 };
 void	af_register(struct afswtch *);
 
 struct option {
 	const char *opt;
 	const char *opt_usage;
 	void	(*cb)(const char *arg);
 	struct option *next;
 };
 void	opt_register(struct option *);
 
+extern	ifconfig_handle_t *lifh;
 extern	struct ifreq ifr;
 extern	char name[IFNAMSIZ];	/* name of interface */
 extern	int allmedia;
 extern	int supmedia;
 extern	int printkeys;
 extern	int newaddr;
 extern	int verbose;
 extern	int printifname;
 extern	int exit_code;
 
 void	setifcap(const char *, int value, int s, const struct afswtch *);
 
 void	Perror(const char *cmd);
 void	printb(const char *s, unsigned value, const char *bits);
 
 void	ifmaybeload(const char *name);
 
 typedef int  clone_match_func(const char *);
 typedef void clone_callback_func(int, struct ifreq *);
 void	clone_setdefcallback_prefix(const char *, clone_callback_func *);
 void	clone_setdefcallback_filter(clone_match_func *, clone_callback_func *);
 
 void	sfp_status(int s, struct ifreq *ifr, int verbose);
 
 /*
  * XXX expose this so modules that neeed to know of any pending
  * operations on ifmedia can avoid cmd line ordering confusion.
  */
 struct ifmediareq *ifmedia_getstate(int s);
 
 void print_vhid(const struct ifaddrs *, const char *);
 
 void ioctl_ifcreate(int s, struct ifreq *);
diff --git a/sbin/ifconfig/ifgroup.c b/sbin/ifconfig/ifgroup.c
index 2b13227af4f3..7f1173c316d7 100644
--- a/sbin/ifconfig/ifgroup.c
+++ b/sbin/ifconfig/ifgroup.c
@@ -1,177 +1,170 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  *
  * Copyright (c) 2006 Max Laier. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. 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 AUTHOR 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 AUTHOR 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.
  */
 
 #ifndef lint
 static const char rcsid[] =
   "$FreeBSD$";
 #endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <net/if.h>
 
 #include <ctype.h>
 #include <err.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include <libifconfig.h>
 
 #include "ifconfig.h"
 
 /* ARGSUSED */
 static void
 setifgroup(const char *group_name, int d, int s, const struct afswtch *rafp)
 {
 	struct ifgroupreq ifgr;
 
 	memset(&ifgr, 0, sizeof(ifgr));
 	strlcpy(ifgr.ifgr_name, name, IFNAMSIZ);
 
 	if (group_name[0] && isdigit(group_name[strlen(group_name) - 1]))
 		errx(1, "setifgroup: group names may not end in a digit");
 
 	if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ)
 		errx(1, "setifgroup: group name too long");
 	if (ioctl(s, SIOCAIFGROUP, (caddr_t)&ifgr) == -1 && errno != EEXIST)
 		err(1," SIOCAIFGROUP");
 }
 
 /* ARGSUSED */
 static void
 unsetifgroup(const char *group_name, int d, int s, const struct afswtch *rafp)
 {
 	struct ifgroupreq ifgr;
 
 	memset(&ifgr, 0, sizeof(ifgr));
 	strlcpy(ifgr.ifgr_name, name, IFNAMSIZ);
 
 	if (group_name[0] && isdigit(group_name[strlen(group_name) - 1]))
 		errx(1, "unsetifgroup: group names may not end in a digit");
 
 	if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ)
 		errx(1, "unsetifgroup: group name too long");
 	if (ioctl(s, SIOCDIFGROUP, (caddr_t)&ifgr) == -1 && errno != ENOENT)
 		err(1, "SIOCDIFGROUP");
 }
 
 static void
 getifgroups(int s)
 {
-	ifconfig_handle_t *lifh;
 	struct ifgroupreq ifgr;
 	size_t cnt;
 
-	lifh = ifconfig_open();
-	if (lifh == NULL)
-		return;
-
 	if (ifconfig_get_groups(lifh, name, &ifgr) == -1)
-		goto close;
+		return;
 
 	cnt = 0;
 	for (size_t i = 0; i < ifgr.ifgr_len / sizeof(struct ifg_req); ++i) {
 		struct ifg_req *ifg = &ifgr.ifgr_groups[i];
 
 		if (strcmp(ifg->ifgrq_group, "all")) {
 			if (cnt == 0)
 				printf("\tgroups:");
 			cnt++;
 			printf(" %s", ifg->ifgrq_group);
 		}
 	}
 	if (cnt)
 		printf("\n");
 
 	free(ifgr.ifgr_groups);
-close:
-	ifconfig_close(lifh);
 }
 
 static void
 printgroup(const char *groupname)
 {
 	struct ifgroupreq	 ifgr;
 	struct ifg_req		*ifg;
 	int			 len, cnt = 0;
 	int			 s;
 
 	s = socket(AF_LOCAL, SOCK_DGRAM, 0);
 	if (s == -1)
 		err(1, "socket(AF_LOCAL,SOCK_DGRAM)");
 	bzero(&ifgr, sizeof(ifgr));
 	strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name));
 	if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) {
 		if (errno == EINVAL || errno == ENOTTY ||
 		    errno == ENOENT)
 			exit(exit_code);
 		else
 			err(1, "SIOCGIFGMEMB");
 	}
 
 	len = ifgr.ifgr_len;
 	if ((ifgr.ifgr_groups = calloc(1, len)) == NULL)
 		err(1, "printgroup");
 	if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1)
 		err(1, "SIOCGIFGMEMB");
 
 	for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req);
 	    ifg++) {
 		len -= sizeof(struct ifg_req);
 		printf("%s\n", ifg->ifgrq_member);
 		cnt++;
 	}
 	free(ifgr.ifgr_groups);
 
 	exit(exit_code);
 }
 
 static struct cmd group_cmds[] = {
 	DEF_CMD_ARG("group",	setifgroup),
 	DEF_CMD_ARG("-group",	unsetifgroup),
 };
 static struct afswtch af_group = {
 	.af_name	= "af_group",
 	.af_af		= AF_UNSPEC,
 	.af_other_status = getifgroups,
 };
 static struct option group_gopt = { "g:", "[-g groupname]", printgroup };
 
 static __constructor void
 group_ctor(void)
 {
 	int i;
 
 	for (i = 0; i < nitems(group_cmds);  i++)
 		cmd_register(&group_cmds[i]);
 	af_register(&af_group);
 	opt_register(&group_gopt);
 }
diff --git a/sbin/ifconfig/iflagg.c b/sbin/ifconfig/iflagg.c
index 5e726115662a..48d7450076a9 100644
--- a/sbin/ifconfig/iflagg.c
+++ b/sbin/ifconfig/iflagg.c
@@ -1,362 +1,355 @@
 /*-
  */
 
 #ifndef lint
 static const char rcsid[] =
   "$FreeBSD$";
 #endif /* not lint */
 
 #include <sys/param.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/sockio.h>
 
 #include <stdlib.h>
 #include <unistd.h>
 
 #include <net/ethernet.h>
 #include <net/if.h>
 #include <net/if_lagg.h>
 #include <net/ieee8023ad_lacp.h>
 #include <net/route.h>
 
 #include <ctype.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <err.h>
 #include <errno.h>
 
 #include <libifconfig.h>
 
 #include "ifconfig.h"
 
 static struct iflaggparam params = {
 	.lagg_type = LAGG_TYPE_DEFAULT,
 };
 
 static char lacpbuf[120];	/* LACP peer '[(a,a,a),(p,p,p)]' */
 
 static void
 setlaggport(const char *val, int d, int s, const struct afswtch *afp)
 {
 	struct lagg_reqport rp;
 
 	bzero(&rp, sizeof(rp));
 	strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
 	strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname));
 
 	/*
 	 * Do not exit with an error here.  Doing so permits a
 	 * failed NIC to take down an entire lagg.
 	 *
 	 * Don't error at all if the port is already in the lagg.
 	 */
 	if (ioctl(s, SIOCSLAGGPORT, &rp) && errno != EEXIST) {
 		warnx("%s %s: SIOCSLAGGPORT: %s",
 		    name, val, strerror(errno));
 		exit_code = 1;
 	}
 }
 
 static void
 unsetlaggport(const char *val, int d, int s, const struct afswtch *afp)
 {
 	struct lagg_reqport rp;
 
 	bzero(&rp, sizeof(rp));
 	strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
 	strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname));
 
 	if (ioctl(s, SIOCSLAGGDELPORT, &rp))
 		err(1, "SIOCSLAGGDELPORT");
 }
 
 static void
 setlaggproto(const char *val, int d, int s, const struct afswtch *afp)
 {
 	struct lagg_protos lpr[] = LAGG_PROTOS;
 	struct lagg_reqall ra;
 	int i;
 
 	bzero(&ra, sizeof(ra));
 	ra.ra_proto = LAGG_PROTO_MAX;
 
 	for (i = 0; i < nitems(lpr); i++) {
 		if (strcmp(val, lpr[i].lpr_name) == 0) {
 			ra.ra_proto = lpr[i].lpr_proto;
 			break;
 		}
 	}
 	if (ra.ra_proto == LAGG_PROTO_MAX)
 		errx(1, "Invalid aggregation protocol: %s", val);
 
 	strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname));
 	if (ioctl(s, SIOCSLAGG, &ra) != 0)
 		err(1, "SIOCSLAGG");
 }
 
 static void
 setlaggflowidshift(const char *val, int d, int s, const struct afswtch *afp)
 {
 	struct lagg_reqopts ro;
 
 	bzero(&ro, sizeof(ro));
 	ro.ro_opts = LAGG_OPT_FLOWIDSHIFT;
 	strlcpy(ro.ro_ifname, name, sizeof(ro.ro_ifname));
 	ro.ro_flowid_shift = (int)strtol(val, NULL, 10);
 	if (ro.ro_flowid_shift & ~LAGG_OPT_FLOWIDSHIFT_MASK)
 		errx(1, "Invalid flowid_shift option: %s", val);
 	
 	if (ioctl(s, SIOCSLAGGOPTS, &ro) != 0)
 		err(1, "SIOCSLAGGOPTS");
 }
 
 static void
 setlaggrr_limit(const char *val, int d, int s, const struct afswtch *afp)
 {
 	struct lagg_reqopts ro;
 	
 	bzero(&ro, sizeof(ro));
 	strlcpy(ro.ro_ifname, name, sizeof(ro.ro_ifname));
 	ro.ro_opts = LAGG_OPT_RR_LIMIT;
 	ro.ro_bkt = (uint32_t)strtoul(val, NULL, 10);
 	if (ro.ro_bkt == 0)
 		errx(1, "Invalid round-robin stride: %s", val);
 
 	if (ioctl(s, SIOCSLAGGOPTS, &ro) != 0)
 		err(1, "SIOCSLAGGOPTS");
 }
 
 static void
 setlaggsetopt(const char *val, int d, int s, const struct afswtch *afp)
 {
 	struct lagg_reqopts ro;
 
 	bzero(&ro, sizeof(ro));
 	ro.ro_opts = d;
 	switch (ro.ro_opts) {
 	case LAGG_OPT_USE_FLOWID:
 	case -LAGG_OPT_USE_FLOWID:
 	case LAGG_OPT_USE_NUMA:
 	case -LAGG_OPT_USE_NUMA:
 	case LAGG_OPT_LACP_STRICT:
 	case -LAGG_OPT_LACP_STRICT:
 	case LAGG_OPT_LACP_TXTEST:
 	case -LAGG_OPT_LACP_TXTEST:
 	case LAGG_OPT_LACP_RXTEST:
 	case -LAGG_OPT_LACP_RXTEST:
 	case LAGG_OPT_LACP_FAST_TIMO:
 	case -LAGG_OPT_LACP_FAST_TIMO:
 		break;
 	default:
 		err(1, "Invalid lagg option");
 	}
 	strlcpy(ro.ro_ifname, name, sizeof(ro.ro_ifname));
 	
 	if (ioctl(s, SIOCSLAGGOPTS, &ro) != 0)
 		err(1, "SIOCSLAGGOPTS");
 }
 
 static void
 setlagghash(const char *val, int d, int s, const struct afswtch *afp)
 {
 	struct lagg_reqflags rf;
 	char *str, *tmp, *tok;
 
 
 	rf.rf_flags = 0;
 	str = tmp = strdup(val);
 	while ((tok = strsep(&tmp, ",")) != NULL) {
 		if (strcmp(tok, "l2") == 0)
 			rf.rf_flags |= LAGG_F_HASHL2;
 		else if (strcmp(tok, "l3") == 0)
 			rf.rf_flags |= LAGG_F_HASHL3;
 		else if (strcmp(tok, "l4") == 0)
 			rf.rf_flags |= LAGG_F_HASHL4;
 		else
 			errx(1, "Invalid lagghash option: %s", tok);
 	}
 	free(str);
 	if (rf.rf_flags == 0)
 		errx(1, "No lagghash options supplied");
 
 	strlcpy(rf.rf_ifname, name, sizeof(rf.rf_ifname));
 	if (ioctl(s, SIOCSLAGGHASH, &rf))
 		err(1, "SIOCSLAGGHASH");
 }
 
 static char *
 lacp_format_mac(const uint8_t *mac, char *buf, size_t buflen)
 {
 	snprintf(buf, buflen, "%02X-%02X-%02X-%02X-%02X-%02X",
 	    (int)mac[0], (int)mac[1], (int)mac[2], (int)mac[3],
 	    (int)mac[4], (int)mac[5]);
 
 	return (buf);
 }
 
 static char *
 lacp_format_peer(struct lacp_opreq *req, const char *sep)
 {
 	char macbuf1[20];
 	char macbuf2[20];
 
 	snprintf(lacpbuf, sizeof(lacpbuf),
 	    "[(%04X,%s,%04X,%04X,%04X),%s(%04X,%s,%04X,%04X,%04X)]",
 	    req->actor_prio,
 	    lacp_format_mac(req->actor_mac, macbuf1, sizeof(macbuf1)),
 	    req->actor_key, req->actor_portprio, req->actor_portno, sep,
 	    req->partner_prio,
 	    lacp_format_mac(req->partner_mac, macbuf2, sizeof(macbuf2)),
 	    req->partner_key, req->partner_portprio, req->partner_portno);
 
 	return(lacpbuf);
 }
 
 static void
 lagg_status(int s)
 {
 	struct lagg_protos protos[] = LAGG_PROTOS;
-	ifconfig_handle_t *lifh;
 	struct ifconfig_lagg_status *lagg;
 	struct lagg_reqall *ra;
 	struct lagg_reqflags *rf;
 	struct lagg_reqopts *ro;
 	struct lagg_reqport *ports;
 	struct lacp_opreq *lp;
 	const char *proto;
 
-	lifh = ifconfig_open();
-	if (lifh == NULL)
-		return;
-
 	if (ifconfig_lagg_get_lagg_status(lifh, name, &lagg) == -1)
-		goto close;
+		return;
 
 	ra = lagg->ra;
 	rf = lagg->rf;
 	ro = lagg->ro;
 	ports = ra->ra_port;
 
 	proto = "<unknown>";
 	for (size_t i = 0; i < nitems(protos); ++i) {
 		if (ra->ra_proto == protos[i].lpr_proto) {
 			proto = protos[i].lpr_name;
 			break;
 		}
 	}
 	printf("\tlaggproto %s", proto);
 
 	if (rf->rf_flags & LAGG_F_HASHMASK) {
 		const char *sep = "";
 
 		printf(" lagghash ");
 		if (rf->rf_flags & LAGG_F_HASHL2) {
 			printf("%sl2", sep);
 			sep = ",";
 		}
 		if (rf->rf_flags & LAGG_F_HASHL3) {
 			printf("%sl3", sep);
 			sep = ",";
 		}
 		if (rf->rf_flags & LAGG_F_HASHL4) {
 			printf("%sl4", sep);
 			sep = ",";
 		}
 	}
 	putchar('\n');
 	if (verbose) {
 		printf("\tlagg options:\n");
 		printb("\t\tflags", ro->ro_opts, LAGG_OPT_BITS);
 		putchar('\n');
 		printf("\t\tflowid_shift: %d\n", ro->ro_flowid_shift);
 		if (ra->ra_proto == LAGG_PROTO_ROUNDROBIN)
 			printf("\t\trr_limit: %d\n", ro->ro_bkt);
 		printf("\tlagg statistics:\n");
 		printf("\t\tactive ports: %d\n", ro->ro_active);
 		printf("\t\tflapping: %u\n", ro->ro_flapping);
 		if (ra->ra_proto == LAGG_PROTO_LACP) {
 			lp = &ra->ra_lacpreq;
 			printf("\tlag id: %s\n",
 			    lacp_format_peer(lp, "\n\t\t "));
 		}
 	}
 
 	for (size_t i = 0; i < ra->ra_ports; ++i) {
 		lp = &ports[i].rp_lacpreq;
 		printf("\tlaggport: %s ", ports[i].rp_portname);
 		printb("flags", ports[i].rp_flags, LAGG_PORT_BITS);
 		if (verbose && ra->ra_proto == LAGG_PROTO_LACP)
 			printb(" state", lp->actor_state, LACP_STATE_BITS);
 		putchar('\n');
 		if (verbose && ra->ra_proto == LAGG_PROTO_LACP)
 			printf("\t\t%s\n",
 			    lacp_format_peer(lp, "\n\t\t "));
 	}
 
 	ifconfig_lagg_free_lagg_status(lagg);
-close:
-	ifconfig_close(lifh);
 }
 
 static
 DECL_CMD_FUNC(setlaggtype, arg, d)
 {
 	static const struct lagg_types lt[] = LAGG_TYPES;
 	int i;
 
 	for (i = 0; i < nitems(lt); i++) {
 		if (strcmp(arg, lt[i].lt_name) == 0) {
 			params.lagg_type = lt[i].lt_value;
 			return;
 		}
 	}
 	errx(1, "invalid lagg type: %s", arg);
 }
 
 static void
 lagg_create(int s, struct ifreq *ifr)
 {
 	ifr->ifr_data = (caddr_t) &params;
 	ioctl_ifcreate(s, ifr);
 }
 
 static struct cmd lagg_cmds[] = {
 	DEF_CLONE_CMD_ARG("laggtype",   setlaggtype),
 	DEF_CMD_ARG("laggport",		setlaggport),
 	DEF_CMD_ARG("-laggport",	unsetlaggport),
 	DEF_CMD_ARG("laggproto",	setlaggproto),
 	DEF_CMD_ARG("lagghash",		setlagghash),
 	DEF_CMD("use_flowid",	LAGG_OPT_USE_FLOWID,	setlaggsetopt),
 	DEF_CMD("-use_flowid",	-LAGG_OPT_USE_FLOWID,	setlaggsetopt),
 	DEF_CMD("use_numa",	LAGG_OPT_USE_NUMA,	setlaggsetopt),
 	DEF_CMD("-use_numa",	-LAGG_OPT_USE_NUMA,	setlaggsetopt),
 	DEF_CMD("lacp_strict",	LAGG_OPT_LACP_STRICT,	setlaggsetopt),
 	DEF_CMD("-lacp_strict",	-LAGG_OPT_LACP_STRICT,	setlaggsetopt),
 	DEF_CMD("lacp_txtest",	LAGG_OPT_LACP_TXTEST,	setlaggsetopt),
 	DEF_CMD("-lacp_txtest",	-LAGG_OPT_LACP_TXTEST,	setlaggsetopt),
 	DEF_CMD("lacp_rxtest",	LAGG_OPT_LACP_RXTEST,	setlaggsetopt),
 	DEF_CMD("-lacp_rxtest",	-LAGG_OPT_LACP_RXTEST,	setlaggsetopt),
 	DEF_CMD("lacp_fast_timeout",	LAGG_OPT_LACP_FAST_TIMO,	setlaggsetopt),
 	DEF_CMD("-lacp_fast_timeout",	-LAGG_OPT_LACP_FAST_TIMO,	setlaggsetopt),
 	DEF_CMD_ARG("flowid_shift",	setlaggflowidshift),
 	DEF_CMD_ARG("rr_limit",		setlaggrr_limit),
 };
 static struct afswtch af_lagg = {
 	.af_name	= "af_lagg",
 	.af_af		= AF_UNSPEC,
 	.af_other_status = lagg_status,
 };
 
 static __constructor void
 lagg_ctor(void)
 {
 	int i;
 
 	for (i = 0; i < nitems(lagg_cmds);  i++)
 		cmd_register(&lagg_cmds[i]);
 	af_register(&af_lagg);
 	clone_setdefcallback_prefix("lagg", lagg_create);
 }
diff --git a/sbin/ifconfig/sfp.c b/sbin/ifconfig/sfp.c
index 15ff22639060..4900b18ff2c8 100644
--- a/sbin/ifconfig/sfp.c
+++ b/sbin/ifconfig/sfp.c
@@ -1,139 +1,131 @@
 /*-
  * Copyright (c) 2014 Alexander V. Chernikov. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. 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 AUTHOR 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 AUTHOR 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.
  */
 
 #ifndef lint
 static const char rcsid[] =
   "$FreeBSD$";
 #endif /* not lint */
 
 #include <sys/types.h>
 #include <sys/param.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 
 #include <net/if.h>
 #include <net/sff8436.h>
 #include <net/sff8472.h>
 
 #include <math.h>
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include <libutil.h>
 
 #include <libifconfig.h>
 #include <libifconfig_sfp.h>
 
 #include "ifconfig.h"
 
 void
 sfp_status(int s, struct ifreq *ifr, int verbose)
 {
 	struct ifconfig_sfp_info info;
 	struct ifconfig_sfp_info_strings strings;
 	struct ifconfig_sfp_vendor_info vendor_info;
 	struct ifconfig_sfp_status status;
-	ifconfig_handle_t *lifh;
 	size_t channel_count;
 
-	lifh = ifconfig_open();
-	if (lifh == NULL)
-		return;
-
 	if (ifconfig_sfp_get_sfp_info(lifh, name, &info) == -1)
-		goto close;
+		return;
 
 	ifconfig_sfp_get_sfp_info_strings(&info, &strings);
 
 	printf("\tplugged: %s %s (%s)\n",
 	    ifconfig_sfp_id_display(info.sfp_id),
 	    ifconfig_sfp_physical_spec(&info, &strings),
 	    strings.sfp_conn);
 
 	if (ifconfig_sfp_get_sfp_vendor_info(lifh, name, &vendor_info) == -1)
-		goto close;
+		return;
 
 	printf("\tvendor: %s PN: %s SN: %s DATE: %s\n",
 	    vendor_info.name, vendor_info.pn, vendor_info.sn, vendor_info.date);
 
 	if (ifconfig_sfp_id_is_qsfp(info.sfp_id)) {
 		if (verbose > 1)
 			printf("\tcompliance level: %s\n", strings.sfp_rev);
 	} else {
 		if (verbose > 5) {
 			printf("Class: %s\n",
 			    ifconfig_sfp_physical_spec(&info, &strings));
 			printf("Length: %s\n", strings.sfp_fc_len);
 			printf("Tech: %s\n", strings.sfp_cab_tech);
 			printf("Media: %s\n", strings.sfp_fc_media);
 			printf("Speed: %s\n", strings.sfp_fc_speed);
 		}
 	}
 
 	if (ifconfig_sfp_get_sfp_status(lifh, name, &status) == 0) {
 		if (ifconfig_sfp_id_is_qsfp(info.sfp_id) && verbose > 1)
 			printf("\tnominal bitrate: %u Mbps\n", status.bitrate);
 		printf("\tmodule temperature: %.2f C voltage: %.2f Volts\n",
 		    status.temp, status.voltage);
 		channel_count = ifconfig_sfp_channel_count(&info);
 		for (size_t chan = 0; chan < channel_count; ++chan) {
 			uint16_t rx = status.channel[chan].rx;
 			uint16_t tx = status.channel[chan].tx;
 			printf("\tlane %zu: "
 			    "RX power: %.2f mW (%.2f dBm) TX bias: %.2f mA\n",
 			    chan + 1, power_mW(rx), power_dBm(rx), bias_mA(tx));
 		}
 		ifconfig_sfp_free_sfp_status(&status);
 	}
 
 	if (verbose > 2) {
 		struct ifconfig_sfp_dump dump;
 
 		if (ifconfig_sfp_get_sfp_dump(lifh, name, &dump) == -1)
-			goto close;
+			return;
 
 		if (ifconfig_sfp_id_is_qsfp(info.sfp_id)) {
 			printf("\n\tSFF8436 DUMP (0xA0 128..255 range):\n");
 			hexdump(dump.data + QSFP_DUMP1_START, QSFP_DUMP1_SIZE,
 			    "\t", HD_OMIT_COUNT | HD_OMIT_CHARS);
 			printf("\n\tSFF8436 DUMP (0xA0 0..81 range):\n");
 			hexdump(dump.data + QSFP_DUMP0_START, QSFP_DUMP0_SIZE,
 			    "\t", HD_OMIT_COUNT | HD_OMIT_CHARS);
 		} else {
 			printf("\n\tSFF8472 DUMP (0xA0 0..127 range):\n");
 			hexdump(dump.data + SFP_DUMP_START, SFP_DUMP_SIZE,
 			    "\t", HD_OMIT_COUNT | HD_OMIT_CHARS);
 		}
 	}
-
-close:
-	ifconfig_close(lifh);
 }