git: 6e3a9d7f2c8d - main - ifconfig: introduce `ifconfig_context` to store current global state.

From: Alexander V. Chernikov <melifaro_at_FreeBSD.org>
Date: Wed, 24 May 2023 10:40:43 UTC
The branch main has been updated by melifaro:

URL: https://cgit.FreeBSD.org/src/commit/?id=6e3a9d7f2c8dc18dc901d4f860a65028c0a82a64

commit 6e3a9d7f2c8dc18dc901d4f860a65028c0a82a64
Author:     Alexander V. Chernikov <melifaro@FreeBSD.org>
AuthorDate: 2023-05-23 17:02:12 +0000
Commit:     Alexander V. Chernikov <melifaro@FreeBSD.org>
CommitDate: 2023-05-24 10:40:34 +0000

    ifconfig: introduce `ifconfig_context` to store current global state.
    
    The structure consists of all current context - arguments,
    open sockets, current family and so on.
    
    Pass this structure as a first argument to most of the af_ menthods.
    This allows to propagate and update shared data without using
     global variables.
    
    The diff is pretty large, but de-facto mechanical. All changes
     except the structure setup in ifconfig[_netlink].c are one-line
     mechanical changes.
    
    Reviewed by:    kp
    Differential Revision: https://reviews.freebsd.org/D40239
    MFC after:      2 weeks
---
 sbin/ifconfig/af_inet.c          |   9 +-
 sbin/ifconfig/af_inet6.c         |  45 ++--
 sbin/ifconfig/af_link.c          |  15 +-
 sbin/ifconfig/af_nd6.c           |  24 +-
 sbin/ifconfig/carp.c             |  30 +--
 sbin/ifconfig/ifbridge.c         | 158 ++++++-----
 sbin/ifconfig/ifclone.c          |  12 +-
 sbin/ifconfig/ifconfig.c         | 199 +++++++-------
 sbin/ifconfig/ifconfig.h         |  61 ++---
 sbin/ifconfig/ifconfig_netlink.c |  40 +--
 sbin/ifconfig/iffib.c            |  16 +-
 sbin/ifconfig/ifgif.c            |  12 +-
 sbin/ifconfig/ifgre.c            |  26 +-
 sbin/ifconfig/ifgroup.c          |  12 +-
 sbin/ifconfig/ifieee80211.c      | 547 ++++++++++++++++++++-------------------
 sbin/ifconfig/ifipsec.c          |  10 +-
 sbin/ifconfig/iflagg.c           |  34 +--
 sbin/ifconfig/ifmac.c            |   8 +-
 sbin/ifconfig/ifmedia.c          |  18 +-
 sbin/ifconfig/ifpfsync.c         |  68 ++---
 sbin/ifconfig/ifstf.c            |  16 +-
 sbin/ifconfig/ifvlan.c           |  44 ++--
 sbin/ifconfig/ifvxlan.c          | 112 ++++----
 23 files changed, 755 insertions(+), 761 deletions(-)

diff --git a/sbin/ifconfig/af_inet.c b/sbin/ifconfig/af_inet.c
index 8d302b260bd1..fdde3bd23595 100644
--- a/sbin/ifconfig/af_inet.c
+++ b/sbin/ifconfig/af_inet.c
@@ -83,7 +83,7 @@ print_addr(struct sockaddr_in *sin)
 
 #ifdef WITHOUT_NETLINK
 static void
-in_status(int s __unused, const struct ifaddrs *ifa)
+in_status(if_ctx *ctx __unused, const struct ifaddrs *ifa)
 {
 	struct sockaddr_in *sin, null_sin = {};
 
@@ -143,8 +143,7 @@ get_mask(int plen)
 }
 
 static void
-in_status_nl(struct ifconfig_args *args __unused, struct io_handler *h,
-    if_link_t *link, if_addr_t *ifa)
+in_status_nl(if_ctx *ctx __unused, if_link_t *link, if_addr_t *ifa)
 {
 	struct sockaddr_in *sin = satosin(ifa->ifa_local);
 	int plen = ifa->ifa_prefixlen;
@@ -228,7 +227,7 @@ in_getaddr(const char *s, int which)
 }
 
 static void
-in_postproc(int s, const struct afswtch *afp, int newaddr, int ifflags)
+in_postproc(if_ctx *ctx __unused, int newaddr, int ifflags)
 {
 	if (sintab[ADDR]->sin_len != 0 && sintab[MASK]->sin_len == 0 &&
 	    newaddr && (ifflags & (IFF_POINTOPOINT | IFF_LOOPBACK)) == 0) {
@@ -292,7 +291,7 @@ static struct afswtch af_inet = {
 #ifdef WITHOUT_NETLINK
 	.af_status	= in_status,
 #else
-	.af_status_nl	= in_status_nl,
+	.af_status	= in_status_nl,
 #endif
 	.af_getaddr	= in_getaddr,
 	.af_postproc	= in_postproc,
diff --git a/sbin/ifconfig/af_inet6.c b/sbin/ifconfig/af_inet6.c
index af4cecf057da..8e2c4946e962 100644
--- a/sbin/ifconfig/af_inet6.c
+++ b/sbin/ifconfig/af_inet6.c
@@ -72,25 +72,27 @@ static	char *sec2str(time_t);
 static	int explicit_prefix = 0;
 extern	char *f_inet6, *f_addr;
 
-extern void setnd6flags(const char *, int, int, const struct afswtch *);
-extern void setnd6defif(const char *, int, int, const struct afswtch *);
-extern void nd6_status(int);
+extern void setnd6flags(if_ctx *, const char *, int);
+extern void setnd6defif(if_ctx *,const char *, int);
+extern void nd6_status(if_ctx *);
 
 static	char addr_buf[NI_MAXHOST];	/*for getnameinfo()*/
 
 static void
-setifprefixlen(const char *addr, int dummy __unused, int s,
-    const struct afswtch *afp)
+setifprefixlen(if_ctx *ctx, const char *addr, int dummy __unused)
 {
+	const struct afswtch *afp = ctx->afp;
+
         if (afp->af_getprefix != NULL)
                 afp->af_getprefix(addr, MASK);
 	explicit_prefix = 1;
 }
 
 static void
-setip6flags(const char *dummyaddr __unused, int flag, int dummysoc __unused,
-    const struct afswtch *afp)
+setip6flags(if_ctx *ctx, const char *dummyaddr __unused, int flag)
 {
+	const struct afswtch *afp = ctx->afp;
+
 	if (afp->af_af != AF_INET6)
 		err(1, "address flags can be set only for inet6 addresses");
 
@@ -101,9 +103,9 @@ setip6flags(const char *dummyaddr __unused, int flag, int dummysoc __unused,
 }
 
 static void
-setip6lifetime(const char *cmd, const char *val, int s, 
-    const struct afswtch *afp)
+setip6lifetime(if_ctx *ctx, const char *cmd, const char *val)
 {
+	const struct afswtch *afp = ctx->afp;
 	struct timespec now;
 	time_t newval;
 	char *ep;
@@ -124,23 +126,21 @@ setip6lifetime(const char *cmd, const char *val, int s,
 }
 
 static void
-setip6pltime(const char *seconds, int dummy __unused, int s, 
-    const struct afswtch *afp)
+setip6pltime(if_ctx *ctx, const char *seconds, int dummy __unused)
 {
-	setip6lifetime("pltime", seconds, s, afp);
+	setip6lifetime(ctx, "pltime", seconds);
 }
 
 static void
-setip6vltime(const char *seconds, int dummy __unused, int s, 
-    const struct afswtch *afp)
+setip6vltime(if_ctx *ctx, const char *seconds, int dummy __unused)
 {
-	setip6lifetime("vltime", seconds, s, afp);
+	setip6lifetime(ctx, "vltime", seconds);
 }
 
 static void
-setip6eui64(const char *cmd, int dummy __unused, int s,
-    const struct afswtch *afp)
+setip6eui64(if_ctx *ctx, const char *cmd, int dummy __unused)
 {
+	const struct afswtch *afp = ctx->afp;
 	struct ifaddrs *ifap, *ifa;
 	const struct sockaddr_in6 *sin6 = NULL;
 	const struct in6_addr *lladdr = NULL;
@@ -247,7 +247,7 @@ print_lifetime(const char *prepend, time_t px_time, struct timespec *now)
 
 #ifdef WITHOUT_NETLINK
 static void
-in6_status(int s __unused, const struct ifaddrs *ifa)
+in6_status(if_ctx *ctx __unused, const struct ifaddrs *ifa)
 {
 	struct sockaddr_in6 *sin, null_sin = {};
 	struct in6_ifreq ifr6;
@@ -341,8 +341,7 @@ show_lifetime(struct ifa_cacheinfo *ci)
 }
 
 static void
-in6_status_nl(struct ifconfig_args *args __unused, struct io_handler *h,
-    if_link_t *link, if_addr_t *ifa)
+in6_status_nl(if_ctx *ctx __unused, if_link_t *link, if_addr_t *ifa)
 {
 	int plen = ifa->ifa_prefixlen;
 	uint32_t scopeid;
@@ -495,14 +494,14 @@ sec2str(time_t total)
 }
 
 static void
-in6_postproc(int s, const struct afswtch *afp, int newaddr __unused,
+in6_postproc(if_ctx *ctx, int newaddr __unused,
     int ifflags __unused)
 {
 	if (explicit_prefix == 0) {
 		/* Aggregatable address architecture defines all prefixes
 		   are 64. So, it is convenient to set prefixlen to 64 if
 		   it is not specified. */
-		setifprefixlen("64", 0, s, afp);
+		setifprefixlen(ctx, "64", 0);
 		/* in6_getprefix("64", MASK) if MASK is available here... */
 	}
 }
@@ -600,7 +599,7 @@ static struct afswtch af_inet6 = {
 #ifdef WITHOUT_NETLINK
 	.af_status	= in6_status,
 #else
-	.af_status_nl	= in6_status_nl,
+	.af_status	= in6_status_nl,
 #endif
 	.af_getaddr	= in6_getaddr,
 	.af_getprefix	= in6_getprefix,
diff --git a/sbin/ifconfig/af_link.c b/sbin/ifconfig/af_link.c
index 52295453b4f0..978006c217de 100644
--- a/sbin/ifconfig/af_link.c
+++ b/sbin/ifconfig/af_link.c
@@ -93,7 +93,7 @@ print_pcp(int s)
 
 #ifdef WITHOUT_NETLINK
 static void
-link_status(int s __unused, const struct ifaddrs *ifa)
+link_status(if_ctx *ctx, const struct ifaddrs *ifa)
 {
 	/* XXX no const 'cuz LLADDR is defined wrong */
 	struct sockaddr_dl *sdl;
@@ -142,7 +142,7 @@ link_status(int s __unused, const struct ifaddrs *ifa)
 
 	print_ether((const struct ether_addr *)&ifr.ifr_addr.sa_data, "hwaddr");
 pcp:
-	print_pcp(s);
+	print_pcp(ctx->io_s);
 }
 
 #else
@@ -159,8 +159,7 @@ convert_iftype(uint8_t iftype)
 }
 
 static void
-link_status_nl(struct ifconfig_args *args __unused, struct io_handler *h,
-    if_link_t *link, if_addr_t *ifa __unused)
+link_status_nl(if_ctx *ctx, if_link_t *link, if_addr_t *ifa __unused)
 {
 	if (link->ifla_address != NULL) {
 		struct sockaddr_dl sdl = {
@@ -180,7 +179,7 @@ link_status_nl(struct ifconfig_args *args __unused, struct io_handler *h,
 		}
 	}
 	if (convert_iftype(link->ifi_type) == IFT_ETHER)
-		print_pcp(h->s);
+		print_pcp(ctx->io_s);
 }
 #endif
 
@@ -224,7 +223,7 @@ static struct afswtch af_link = {
 #ifdef WITHOUT_NETLINK
 	.af_status	= link_status,
 #else
-	.af_status_nl	= link_status_nl,
+	.af_status	= link_status_nl,
 #endif
 	.af_getaddr	= link_getaddr,
 	.af_aifaddr	= SIOCSIFLLADDR,
@@ -236,7 +235,7 @@ static struct afswtch af_ether = {
 #ifdef WITHOUT_NETLINK
 	.af_status	= link_status,
 #else
-	.af_status_nl	= link_status_nl,
+	.af_status	= link_status_nl,
 #endif
 	.af_getaddr	= link_getaddr,
 	.af_aifaddr	= SIOCSIFLLADDR,
@@ -248,7 +247,7 @@ static struct afswtch af_lladdr = {
 #ifdef WITHOUT_NETLINK
 	.af_status	= link_status,
 #else
-	.af_status_nl	= link_status_nl,
+	.af_status	= link_status_nl,
 #endif
 	.af_getaddr	= link_getaddr,
 	.af_aifaddr	= SIOCSIFLLADDR,
diff --git a/sbin/ifconfig/af_nd6.c b/sbin/ifconfig/af_nd6.c
index d1be5a4dc00f..ef46f5694cc0 100644
--- a/sbin/ifconfig/af_nd6.c
+++ b/sbin/ifconfig/af_nd6.c
@@ -70,21 +70,19 @@ static const char rcsid[] =
 #endif
 
 static int isnd6defif(int);
-void setnd6flags(const char *, int, int, const struct afswtch *);
-void setnd6defif(const char *, int, int, const struct afswtch *);
-void nd6_status(int);
+void setnd6flags(if_ctx *, const char *, int);
+void setnd6defif(if_ctx *,const char *, int);
+void nd6_status(if_ctx *);
 
 void
-setnd6flags(const char *dummyaddr __unused,
-	int d, int s,
-	const struct afswtch *afp)
+setnd6flags(if_ctx *ctx, const char *dummyaddr __unused, int d)
 {
 	struct in6_ndireq nd;
 	int error;
 
 	memset(&nd, 0, sizeof(nd));
 	strlcpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname));
-	error = ioctl(s, SIOCGIFINFO_IN6, &nd);
+	error = ioctl_ctx(ctx, SIOCGIFINFO_IN6, &nd);
 	if (error) {
 		warn("ioctl(SIOCGIFINFO_IN6)");
 		return;
@@ -93,15 +91,13 @@ setnd6flags(const char *dummyaddr __unused,
 		nd.ndi.flags &= ~(-d);
 	else
 		nd.ndi.flags |= d;
-	error = ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd);
+	error = ioctl_ctx(ctx, SIOCSIFINFO_IN6, (caddr_t)&nd);
 	if (error)
 		warn("ioctl(SIOCSIFINFO_IN6)");
 }
 
 void
-setnd6defif(const char *dummyaddr __unused,
-	int d, int s,
-	const struct afswtch *afp)
+setnd6defif(if_ctx *ctx, const char *dummyaddr __unused, int d)
 {
 	struct in6_ndifreq ndifreq;
 	int ifindex;
@@ -111,7 +107,7 @@ setnd6defif(const char *dummyaddr __unused,
 	strlcpy(ndifreq.ifname, ifr.ifr_name, sizeof(ndifreq.ifname));
 
 	if (d < 0) {
-		if (isnd6defif(s)) {
+		if (isnd6defif(ctx->io_s)) {
 			/* ifindex = 0 means to remove default if */
 			ifindex = 0;
 		} else
@@ -122,7 +118,7 @@ setnd6defif(const char *dummyaddr __unused,
 	}
 
 	ndifreq.ifindex = ifindex;
-	error = ioctl(s, SIOCSDEFIFACE_IN6, (caddr_t)&ndifreq);
+	error = ioctl_ctx(ctx, SIOCSDEFIFACE_IN6, (caddr_t)&ndifreq);
 	if (error)
 		warn("ioctl(SIOCSDEFIFACE_IN6)");
 }
@@ -147,7 +143,7 @@ isnd6defif(int s)
 }
 
 void
-nd6_status(int s)
+nd6_status(if_ctx *ctx __unused)
 {
 	struct in6_ndireq nd;
 	int s6;
diff --git a/sbin/ifconfig/carp.c b/sbin/ifconfig/carp.c
index 2d6c581582b1..d4978d53f083 100644
--- a/sbin/ifconfig/carp.c
+++ b/sbin/ifconfig/carp.c
@@ -60,12 +60,7 @@
 
 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;
@@ -76,7 +71,7 @@ static struct in6_addr carp_addr6;
 static unsigned char const *carpr_key;
 
 static void
-carp_status(int s)
+carp_status(if_ctx *ctx __unused)
 {
 	struct ifconfig_carp carpr[CARP_MAXVHID];
 	char addr_buf[NI_MAXHOST];
@@ -102,8 +97,9 @@ carp_status(int s)
 }
 
 static void
-setcarp_vhid(const char *val, int d, int s, const struct afswtch *afp)
+setcarp_vhid(if_ctx *ctx, const char *val, int dummy __unused)
 {
+	const struct afswtch *afp = ctx->afp;
 
 	carpr_vhid = atoi(val);
 
@@ -148,7 +144,7 @@ setcarp_callback(int s, void *arg __unused)
 }
 
 static void
-setcarp_passwd(const char *val, int d, int s, const struct afswtch *afp)
+setcarp_passwd(if_ctx *ctx __unused, const char *val, int dummy __unused)
 {
 
 	if (carpr_vhid == -1)
@@ -158,7 +154,7 @@ setcarp_passwd(const char *val, int d, int s, const struct afswtch *afp)
 }
 
 static void
-setcarp_advskew(const char *val, int d, int s, const struct afswtch *afp)
+setcarp_advskew(if_ctx *ctx __unused, const char *val, int dummy __unused)
 {
 
 	if (carpr_vhid == -1)
@@ -168,7 +164,7 @@ setcarp_advskew(const char *val, int d, int s, const struct afswtch *afp)
 }
 
 static void
-setcarp_advbase(const char *val, int d, int s, const struct afswtch *afp)
+setcarp_advbase(if_ctx *ctx __unused, const char *val, int dummy __unused)
 {
 
 	if (carpr_vhid == -1)
@@ -178,7 +174,7 @@ setcarp_advbase(const char *val, int d, int s, const struct afswtch *afp)
 }
 
 static void
-setcarp_state(const char *val, int d, int s, const struct afswtch *afp)
+setcarp_state(if_ctx *ctx __unused, const char *val, int dummy __unused)
 {
 	int i;
 
@@ -195,19 +191,19 @@ setcarp_state(const char *val, int d, int s, const struct afswtch *afp)
 }
 
 static void
-setcarp_peer(const char *val, int d, int s, const struct afswtch *afp)
+setcarp_peer(if_ctx *ctx __unused, const char *val, int dummy __unused)
 {
 	carp_addr.s_addr = inet_addr(val);
 }
 
 static void
-setcarp_mcast(const char *val, int d, int s, const struct afswtch *afp)
+setcarp_mcast(if_ctx *ctx __unused, const char *val __unused, int dummy __unused)
 {
 	carp_addr.s_addr = htonl(INADDR_CARP_GROUP);
 }
 
 static void
-setcarp_peer6(const char *val, int d, int s, const struct afswtch *afp)
+setcarp_peer6(if_ctx *ctx __unused, const char *val, int dummy __unused)
 {
 	struct addrinfo hints, *res;
 
@@ -224,7 +220,7 @@ setcarp_peer6(const char *val, int d, int s, const struct afswtch *afp)
 }
 
 static void
-setcarp_mcast6(const char *val, int d, int s, const struct afswtch *afp)
+setcarp_mcast6(if_ctx *ctx __unused, const char *val __unused, int dummy __unused)
 {
 	bzero(&carp_addr6, sizeof(carp_addr6));
 	carp_addr6.s6_addr[0] = 0xff;
@@ -253,8 +249,8 @@ static __constructor void
 carp_ctor(void)
 {
 	/* Default to multicast. */
-	setcarp_mcast(NULL, 0, 0, NULL);
-	setcarp_mcast6(NULL, 0, 0, NULL);
+	setcarp_mcast(NULL, NULL, 0);
+	setcarp_mcast6(NULL, NULL, 0);
 
 	for (size_t i = 0; i < nitems(carp_cmds);  i++)
 		cmd_register(&carp_cmds[i]);
diff --git a/sbin/ifconfig/ifbridge.c b/sbin/ifconfig/ifbridge.c
index 6bbc63ac9779..9d3c64a184b4 100644
--- a/sbin/ifconfig/ifbridge.c
+++ b/sbin/ifconfig/ifbridge.c
@@ -154,7 +154,7 @@ bridge_addresses(int s, const char *prefix)
 }
 
 static void
-bridge_status(int s)
+bridge_status(if_ctx *ctx __unused)
 {
 	struct ifconfig_bridge_status *bridge;
 	struct ifbropreq *params;
@@ -225,178 +225,177 @@ bridge_status(int s)
 }
 
 static void
-setbridge_add(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_add(if_ctx *ctx, const char *val, int dummy __unused)
 {
 	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)
+	if (do_cmd(ctx->io_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)
+setbridge_delete(if_ctx *ctx, const char *val, int dummy __unused)
 {
 	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)
+	if (do_cmd(ctx->io_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)
+setbridge_discover(if_ctx *ctx, const char *val, int dummy __unused)
 {
 
-	do_bridgeflag(s, val, IFBIF_DISCOVER, 1);
+	do_bridgeflag(ctx->io_s, val, IFBIF_DISCOVER, 1);
 }
 
 static void
-unsetbridge_discover(const char *val, int d, int s, const struct afswtch *afp)
+unsetbridge_discover(if_ctx *ctx, const char *val, int dummy __unused)
 {
 
-	do_bridgeflag(s, val, IFBIF_DISCOVER, 0);
+	do_bridgeflag(ctx->io_s, val, IFBIF_DISCOVER, 0);
 }
 
 static void
-setbridge_learn(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_learn(if_ctx *ctx, const char *val, int dummy __unused)
 {
 
-	do_bridgeflag(s, val, IFBIF_LEARNING,  1);
+	do_bridgeflag(ctx->io_s, val, IFBIF_LEARNING,  1);
 }
 
 static void
-unsetbridge_learn(const char *val, int d, int s, const struct afswtch *afp)
+unsetbridge_learn(if_ctx *ctx, const char *val, int dummy __unused)
 {
 
-	do_bridgeflag(s, val, IFBIF_LEARNING,  0);
+	do_bridgeflag(ctx->io_s, val, IFBIF_LEARNING,  0);
 }
 
 static void
-setbridge_sticky(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_sticky(if_ctx *ctx, const char *val, int dummy __unused)
 {
 
-	do_bridgeflag(s, val, IFBIF_STICKY,  1);
+	do_bridgeflag(ctx->io_s, val, IFBIF_STICKY,  1);
 }
 
 static void
-unsetbridge_sticky(const char *val, int d, int s, const struct afswtch *afp)
+unsetbridge_sticky(if_ctx *ctx, const char *val, int dummy __unused)
 {
 
-	do_bridgeflag(s, val, IFBIF_STICKY,  0);
+	do_bridgeflag(ctx->io_s, val, IFBIF_STICKY,  0);
 }
 
 static void
-setbridge_span(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_span(if_ctx *ctx, const char *val, int dummy __unused)
 {
 	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)
+	if (do_cmd(ctx->io_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)
+unsetbridge_span(if_ctx *ctx, const char *val, int dummy __unused)
 {
 	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)
+	if (do_cmd(ctx->io_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)
+setbridge_stp(if_ctx *ctx, const char *val, int dummy __unused)
 {
 
-	do_bridgeflag(s, val, IFBIF_STP, 1);
+	do_bridgeflag(ctx->io_s, val, IFBIF_STP, 1);
 }
 
 static void
-unsetbridge_stp(const char *val, int d, int s, const struct afswtch *afp)
+unsetbridge_stp(if_ctx *ctx, const char *val, int dummy __unused)
 {
 
-	do_bridgeflag(s, val, IFBIF_STP, 0);
+	do_bridgeflag(ctx->io_s, val, IFBIF_STP, 0);
 }
 
 static void
-setbridge_edge(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_edge(if_ctx *ctx, const char *val, int dummy __unused)
 {
-	do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 1);
+	do_bridgeflag(ctx->io_s, val, IFBIF_BSTP_EDGE, 1);
 }
 
 static void
-unsetbridge_edge(const char *val, int d, int s, const struct afswtch *afp)
+unsetbridge_edge(if_ctx *ctx, const char *val, int dummy __unused)
 {
-	do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 0);
+	do_bridgeflag(ctx->io_s, val, IFBIF_BSTP_EDGE, 0);
 }
 
 static void
-setbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_autoedge(if_ctx *ctx, const char *val, int dummy __unused)
 {
-	do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 1);
+	do_bridgeflag(ctx->io_s, val, IFBIF_BSTP_AUTOEDGE, 1);
 }
 
 static void
-unsetbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp)
+unsetbridge_autoedge(if_ctx *ctx, const char *val, int dummy __unused)
 {
-	do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 0);
+	do_bridgeflag(ctx->io_s, val, IFBIF_BSTP_AUTOEDGE, 0);
 }
 
 static void
-setbridge_ptp(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_ptp(if_ctx *ctx, const char *val, int dummy __unused)
 {
-	do_bridgeflag(s, val, IFBIF_BSTP_PTP, 1);
+	do_bridgeflag(ctx->io_s, val, IFBIF_BSTP_PTP, 1);
 }
 
 static void
-unsetbridge_ptp(const char *val, int d, int s, const struct afswtch *afp)
+unsetbridge_ptp(if_ctx *ctx, const char *val, int dummy __unused)
 {
-	do_bridgeflag(s, val, IFBIF_BSTP_PTP, 0);
+	do_bridgeflag(ctx->io_s, val, IFBIF_BSTP_PTP, 0);
 }
 
 static void
-setbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_autoptp(if_ctx *ctx, const char *val, int dummy __unused)
 {
-	do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 1);
+	do_bridgeflag(ctx->io_s, val, IFBIF_BSTP_AUTOPTP, 1);
 }
 
 static void
-unsetbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp)
+unsetbridge_autoptp(if_ctx *ctx, const char *val, int dummy __unused)
 {
-	do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 0);
+	do_bridgeflag(ctx->io_s, val, IFBIF_BSTP_AUTOPTP, 0);
 }
 
 static void
-setbridge_flush(const char *val, int d, int s, const struct afswtch *afp)
+setbridge_flush(if_ctx *ctx, const char *val, int dummy __unused)
 {
 	struct ifbreq req;
 
 	memset(&req, 0, sizeof(req));
 	req.ifbr_ifsflags = IFBF_FLUSHDYN;
-	if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0)
+	if (do_cmd(ctx->io_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)
+setbridge_flushall(if_ctx *ctx, const char *val, int dummy __unused)
 {
 	struct ifbreq req;
 
 	memset(&req, 0, sizeof(req));
 	req.ifbr_ifsflags = IFBF_FLUSHALL;
-	if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0)
+	if (do_cmd(ctx->io_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)
+setbridge_static(if_ctx *ctx, const char *val, const char *mac)
 {
 	struct ifbareq req;
 	struct ether_addr *ea;
@@ -412,12 +411,12 @@ setbridge_static(const char *val, const char *mac, int s,
 	req.ifba_flags = IFBAF_STATIC;
 	req.ifba_vlan = 1; /* XXX allow user to specify */
 
-	if (do_cmd(s, BRDGSADDR, &req, sizeof(req), 1) < 0)
+	if (do_cmd(ctx->io_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)
+setbridge_deladdr(if_ctx *ctx, const char *val, int dummy __unused)
 {
 	struct ifbareq req;
 	struct ether_addr *ea;
@@ -430,19 +429,19 @@ setbridge_deladdr(const char *val, int d, int s, const struct afswtch *afp)
 
 	memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst));
 
-	if (do_cmd(s, BRDGDADDR, &req, sizeof(req), 1) < 0)
+	if (do_cmd(ctx->io_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)
+setbridge_addr(if_ctx *ctx, const char *val, int dummy __unused)
 {
 
-	bridge_addresses(s, "");
+	bridge_addresses(ctx->io_s, "");
 }
 
 static void
-setbridge_maxaddr(const char *arg, int d, int s, const struct afswtch *afp)
+setbridge_maxaddr(if_ctx *ctx, const char *arg, int dummy __unused)
 {
 	struct ifbrparam param;
 	u_long val;
@@ -452,12 +451,12 @@ setbridge_maxaddr(const char *arg, int d, int s, const struct afswtch *afp)
 
 	param.ifbrp_csize = val & 0xffffffff;
 
-	if (do_cmd(s, BRDGSCACHE, &param, sizeof(param), 1) < 0)
+	if (do_cmd(ctx->io_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)
+setbridge_hellotime(if_ctx *ctx, const char *arg, int dummy __unused)
 {
 	struct ifbrparam param;
 	u_long val;
@@ -467,12 +466,12 @@ setbridge_hellotime(const char *arg, int d, int s, const struct afswtch *afp)
 
 	param.ifbrp_hellotime = val & 0xff;
 
-	if (do_cmd(s, BRDGSHT, &param, sizeof(param), 1) < 0)
+	if (do_cmd(ctx->io_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)
+setbridge_fwddelay(if_ctx *ctx, const char *arg, int dummy __unused)
 {
 	struct ifbrparam param;
 	u_long val;
@@ -482,12 +481,12 @@ setbridge_fwddelay(const char *arg, int d, int s, const struct afswtch *afp)
 
 	param.ifbrp_fwddelay = val & 0xff;
 
-	if (do_cmd(s, BRDGSFD, &param, sizeof(param), 1) < 0)
+	if (do_cmd(ctx->io_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)
+setbridge_maxage(if_ctx *ctx, const char *arg, int dummy __unused)
 {
 	struct ifbrparam param;
 	u_long val;
@@ -497,12 +496,12 @@ setbridge_maxage(const char *arg, int d, int s, const struct afswtch *afp)
 
 	param.ifbrp_maxage = val & 0xff;
 
-	if (do_cmd(s, BRDGSMA, &param, sizeof(param), 1) < 0)
+	if (do_cmd(ctx->io_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)
+setbridge_priority(if_ctx *ctx, const char *arg, int dummy __unused)
 {
 	struct ifbrparam param;
 	u_long val;
@@ -512,12 +511,12 @@ setbridge_priority(const char *arg, int d, int s, const struct afswtch *afp)
 
 	param.ifbrp_prio = val & 0xffff;
 
-	if (do_cmd(s, BRDGSPRI, &param, sizeof(param), 1) < 0)
+	if (do_cmd(ctx->io_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)
+setbridge_protocol(if_ctx *ctx, const char *arg, int dummy __unused)
 {
 	struct ifbrparam param;
 
@@ -529,12 +528,12 @@ setbridge_protocol(const char *arg, int d, int s, const struct afswtch *afp)
 		errx(1, "unknown stp protocol");
 	}
 
-	if (do_cmd(s, BRDGSPROTO, &param, sizeof(param), 1) < 0)
+	if (do_cmd(ctx->io_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)
+setbridge_holdcount(if_ctx *ctx, const char *arg, int dummy __unused)
 {
 	struct ifbrparam param;
 	u_long val;
@@ -544,13 +543,12 @@ setbridge_holdcount(const char *arg, int d, int s, const struct afswtch *afp)
 
 	param.ifbrp_txhc = val & 0xff;
 
-	if (do_cmd(s, BRDGSTXHC, &param, sizeof(param), 1) < 0)
+	if (do_cmd(ctx->io_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)
+setbridge_ifpriority(if_ctx *ctx, const char *ifn, const char *pri)
 {
 	struct ifbreq req;
 	u_long val;
@@ -563,13 +561,12 @@ setbridge_ifpriority(const char *ifn, const char *pri, int s,
 	strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
 	req.ifbr_priority = val & 0xff;
 
-	if (do_cmd(s, BRDGSIFPRIO, &req, sizeof(req), 1) < 0)
+	if (do_cmd(ctx->io_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)
+setbridge_ifpathcost(if_ctx *ctx, const char *ifn, const char *cost)
 {
 	struct ifbreq req;
 	u_long val;
@@ -582,13 +579,12 @@ setbridge_ifpathcost(const char *ifn, const char *cost, int s,
 	strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
 	req.ifbr_path_cost = val;
 
-	if (do_cmd(s, BRDGSIFCOST, &req, sizeof(req), 1) < 0)
+	if (do_cmd(ctx->io_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)
+setbridge_ifmaxaddr(if_ctx *ctx, const char *ifn, const char *arg)
 {
 	struct ifbreq req;
 	u_long val;
@@ -601,12 +597,12 @@ setbridge_ifmaxaddr(const char *ifn, const char *arg, int s,
 	strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
 	req.ifbr_addrmax = val & 0xffffffff;
 
-	if (do_cmd(s, BRDGSIFAMAX, &req, sizeof(req), 1) < 0)
+	if (do_cmd(ctx->io_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)
+setbridge_timeout(if_ctx *ctx, const char *arg, int dummy __unused)
 {
 	struct ifbrparam param;
 	u_long val;
@@ -616,22 +612,22 @@ setbridge_timeout(const char *arg, int d, int s, const struct afswtch *afp)
 
 	param.ifbrp_ctime = val & 0xffffffff;
 
-	if (do_cmd(s, BRDGSTO, &param, sizeof(param), 1) < 0)
+	if (do_cmd(ctx->io_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)
+setbridge_private(if_ctx *ctx, const char *val, int dummy __unused)
 {
 
-	do_bridgeflag(s, val, IFBIF_PRIVATE, 1);
+	do_bridgeflag(ctx->io_s, val, IFBIF_PRIVATE, 1);
 }
 
 static void
-unsetbridge_private(const char *val, int d, int s, const struct afswtch *afp)
+unsetbridge_private(if_ctx *ctx, const char *val, int dummy __unused)
 {
 
-	do_bridgeflag(s, val, IFBIF_PRIVATE, 0);
+	do_bridgeflag(ctx->io_s, val, IFBIF_PRIVATE, 0);
 }
 
 static struct cmd bridge_cmds[] = {
diff --git a/sbin/ifconfig/ifclone.c b/sbin/ifconfig/ifclone.c
index 9cacff239967..0894366bb185 100644
--- a/sbin/ifconfig/ifclone.c
+++ b/sbin/ifconfig/ifclone.c
@@ -160,17 +160,17 @@ ifclonecreate(int s, void *arg)
 	}
 }
 
-static
-DECL_CMD_FUNC(clone_create, arg, d)
+static void
+clone_create(if_ctx *ctx __unused, const char *cmd __unused, int d __unused)
 {
 	callback_register(ifclonecreate, NULL);
 }
 
-static
-DECL_CMD_FUNC(clone_destroy, arg, d)
+static void
+clone_destroy(if_ctx *ctx, const char *cmd __unused, int d __unused)
 {
-	(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
-	if (ioctl(s, SIOCIFDESTROY, &ifr) < 0)
+	strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+	if (ioctl(ctx->io_s, SIOCIFDESTROY, &ifr) < 0)
 		err(1, "SIOCIFDESTROY");
 }
 
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index db275d877c00..ba14f84f7e7e 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -105,7 +105,7 @@ int	newaddr = 1;
 int	verbose;
 int	printifname = 0;
 
-struct ifconfig_args args;
+struct ifconfig_args global_args;
 
 int	printkeys = 0;		/* Print keying material for interfaces. */
 int	exit_code = 0;
@@ -569,6 +569,8 @@ main(int ac, char *av[])
 #ifdef JAIL
 	int jid;
 #endif
+	struct ifconfig_args *args = &global_args;
+
 	f_inet = f_inet6 = f_ether = f_addr = NULL;
 
 	lifh = ifconfig_open();
@@ -585,11 +587,11 @@ main(int ac, char *av[])
*** 3308 LINES SKIPPED ***