git: 7fa282e616c3 - main - ifconfig: remove (most of) the usages of global 'struct ifreq ifr'.

From: Alexander V. Chernikov <melifaro_at_FreeBSD.org>
Date: Fri, 16 Jun 2023 07:19:43 UTC
The branch main has been updated by melifaro:

URL: https://cgit.FreeBSD.org/src/commit/?id=7fa282e616c303261904cb6158959d5a784dc3ee

commit 7fa282e616c303261904cb6158959d5a784dc3ee
Author:     Alexander V. Chernikov <melifaro@FreeBSD.org>
AuthorDate: 2023-06-14 13:00:49 +0000
Commit:     Alexander V. Chernikov <melifaro@FreeBSD.org>
CommitDate: 2023-06-16 07:19:21 +0000

    ifconfig: remove (most of) the usages of global 'struct ifreq ifr'.
    
    It is hard to reason about the contents of 'ifr' at any given time
    as nearly every function sets random fields or pointers in this
    structure.
    Use local on-stack clean 'struct ifreq' for each function instead.
    
    Reviewed by: kp
    Differential Revision: https://reviews.freebsd.org/D40534
    MFC after:      2 weeks
---
 sbin/ifconfig/af_inet6.c         |   4 +-
 sbin/ifconfig/af_link.c          |  10 +--
 sbin/ifconfig/af_nd6.c           |  30 ++++-----
 sbin/ifconfig/ifclone.c          |   5 +-
 sbin/ifconfig/ifconfig.c         | 128 +++++++++++++++++++++++----------------
 sbin/ifconfig/ifconfig.h         |   5 +-
 sbin/ifconfig/ifconfig_netlink.c |   5 +-
 sbin/ifconfig/iffib.c            |   8 +--
 sbin/ifconfig/ifgif.c            |   8 +--
 sbin/ifconfig/ifgre.c            |  22 +++----
 sbin/ifconfig/ifipsec.c          |   9 ++-
 sbin/ifconfig/ifpfsync.c         |  35 +++++------
 sbin/ifconfig/ifstf.c            |   6 +-
 sbin/ifconfig/ifvlan.c           |  44 ++++++--------
 sbin/ifconfig/ifvxlan.c          |   8 +--
 15 files changed, 170 insertions(+), 157 deletions(-)

diff --git a/sbin/ifconfig/af_inet6.c b/sbin/ifconfig/af_inet6.c
index b8a5cb3012ed..1acfc28cad94 100644
--- a/sbin/ifconfig/af_inet6.c
+++ b/sbin/ifconfig/af_inet6.c
@@ -291,7 +291,7 @@ print_lifetime(const char *prepend, time_t px_time, struct timespec *now)
 
 #ifdef WITHOUT_NETLINK
 static void
-in6_status(if_ctx *ctx __unused, const struct ifaddrs *ifa)
+in6_status(if_ctx *ctx, const struct ifaddrs *ifa)
 {
 	struct sockaddr_in6 *sin, null_sin = {};
 	struct in6_ifreq ifr6;
@@ -303,7 +303,7 @@ in6_status(if_ctx *ctx __unused, const struct ifaddrs *ifa)
 	if (sin == NULL)
 		return;
 
-	strlcpy(ifr6.ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name));
+	strlcpy(ifr6.ifr_name, ctx->ifname, sizeof(ifr6.ifr_name));
 	if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
 		warn("socket(AF_INET6,SOCK_DGRAM)");
 		return;
diff --git a/sbin/ifconfig/af_link.c b/sbin/ifconfig/af_link.c
index 7b7c5259d6c9..e66266ece86b 100644
--- a/sbin/ifconfig/af_link.c
+++ b/sbin/ifconfig/af_link.c
@@ -101,9 +101,11 @@ print_lladdr(struct sockaddr_dl *sdl)
 }
 
 static void
-print_pcp(int s)
+print_pcp(if_ctx *ctx)
 {
-	if (ioctl(s, SIOCGLANPCP, (caddr_t)&ifr) == 0 &&
+	struct ifreq ifr = {};
+
+	if (ioctl_ctx_ifr(ctx, SIOCGLANPCP, &ifr) == 0 &&
 	    ifr.ifr_lan_pcp != IFNET_PCP_NONE)
 		printf("\tpcp %d\n", ifr.ifr_lan_pcp);
 }
@@ -159,7 +161,7 @@ link_status(if_ctx *ctx, const struct ifaddrs *ifa)
 
 	print_ether((const struct ether_addr *)&ifr.ifr_addr.sa_data, "hwaddr");
 pcp:
-	print_pcp(ctx->io_s);
+	print_pcp(ctx);
 }
 
 #else
@@ -196,7 +198,7 @@ link_status_nl(if_ctx *ctx, if_link_t *link, if_addr_t *ifa __unused)
 		}
 	}
 	if (convert_iftype(link->ifi_type) == IFT_ETHER)
-		print_pcp(ctx->io_s);
+		print_pcp(ctx);
 }
 #endif
 
diff --git a/sbin/ifconfig/af_nd6.c b/sbin/ifconfig/af_nd6.c
index ef46f5694cc0..7eeb86585197 100644
--- a/sbin/ifconfig/af_nd6.c
+++ b/sbin/ifconfig/af_nd6.c
@@ -69,7 +69,7 @@ static const char rcsid[] =
 		"\007NO_RADR\010NO_PREFER_IFACE\011NO_DAD\020DEFAULTIF"
 #endif
 
-static int isnd6defif(int);
+static int isnd6defif(if_ctx *ctx, int s);
 void setnd6flags(if_ctx *, const char *, int);
 void setnd6defif(if_ctx *,const char *, int);
 void nd6_status(if_ctx *);
@@ -77,11 +77,10 @@ void nd6_status(if_ctx *);
 void
 setnd6flags(if_ctx *ctx, const char *dummyaddr __unused, int d)
 {
-	struct in6_ndireq nd;
+	struct in6_ndireq nd = {};
 	int error;
 
-	memset(&nd, 0, sizeof(nd));
-	strlcpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname));
+	strlcpy(nd.ifname, ctx->ifname, sizeof(nd.ifname));
 	error = ioctl_ctx(ctx, SIOCGIFINFO_IN6, &nd);
 	if (error) {
 		warn("ioctl(SIOCGIFINFO_IN6)");
@@ -99,15 +98,14 @@ setnd6flags(if_ctx *ctx, const char *dummyaddr __unused, int d)
 void
 setnd6defif(if_ctx *ctx, const char *dummyaddr __unused, int d)
 {
-	struct in6_ndifreq ndifreq;
+	struct in6_ndifreq ndifreq = {};
 	int ifindex;
 	int error;
 
-	memset(&ndifreq, 0, sizeof(ndifreq));
-	strlcpy(ndifreq.ifname, ifr.ifr_name, sizeof(ndifreq.ifname));
+	strlcpy(ndifreq.ifname, ctx->ifname, sizeof(ndifreq.ifname));
 
 	if (d < 0) {
-		if (isnd6defif(ctx->io_s)) {
+		if (isnd6defif(ctx, ctx->io_s)) {
 			/* ifindex = 0 means to remove default if */
 			ifindex = 0;
 		} else
@@ -124,14 +122,13 @@ setnd6defif(if_ctx *ctx, const char *dummyaddr __unused, int d)
 }
 
 static int
-isnd6defif(int s)
+isnd6defif(if_ctx *ctx, int s)
 {
-	struct in6_ndifreq ndifreq;
+	struct in6_ndifreq ndifreq = {};
 	unsigned int ifindex;
 	int error;
 
-	memset(&ndifreq, 0, sizeof(ndifreq));
-	strlcpy(ndifreq.ifname, ifr.ifr_name, sizeof(ndifreq.ifname));
+	strlcpy(ndifreq.ifname, ctx->ifname, sizeof(ndifreq.ifname));
 
 	ifindex = if_nametoindex(ndifreq.ifname);
 	error = ioctl(s, SIOCGDEFIFACE_IN6, (caddr_t)&ndifreq);
@@ -143,15 +140,14 @@ isnd6defif(int s)
 }
 
 void
-nd6_status(if_ctx *ctx __unused)
+nd6_status(if_ctx *ctx)
 {
-	struct in6_ndireq nd;
+	struct in6_ndireq nd = {};
 	int s6;
 	int error;
 	int isdefif;
 
-	memset(&nd, 0, sizeof(nd));
-	strlcpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname));
+	strlcpy(nd.ifname, ctx->ifname, sizeof(nd.ifname));
 	if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
 		if (errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT)
 			warn("socket(AF_INET6, SOCK_DGRAM)");
@@ -164,7 +160,7 @@ nd6_status(if_ctx *ctx __unused)
 		close(s6);
 		return;
 	}
-	isdefif = isnd6defif(s6);
+	isdefif = isnd6defif(ctx, s6);
 	close(s6);
 	if (nd.ndi.flags == 0 && !isdefif)
 		return;
diff --git a/sbin/ifconfig/ifclone.c b/sbin/ifconfig/ifclone.c
index f0ae93ec792c..8b378cbe341f 100644
--- a/sbin/ifconfig/ifclone.c
+++ b/sbin/ifconfig/ifclone.c
@@ -159,8 +159,9 @@ clone_create(if_ctx *ctx __unused, const char *cmd __unused, int d __unused)
 static void
 clone_destroy(if_ctx *ctx, const char *cmd __unused, int d __unused)
 {
-	strlcpy(ifr.ifr_name, ctx->ifname, sizeof(ifr.ifr_name));
-	if (ioctl(ctx->io_s, SIOCIFDESTROY, &ifr) < 0)
+	struct ifreq ifr = {};
+
+	if (ioctl_ctx_ifr(ctx, SIOCIFDESTROY, &ifr) < 0)
 		err(1, "SIOCIFDESTROY");
 }
 
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index 6a80ad5763b2..5ac217858057 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -206,6 +206,19 @@ ifname_update(if_ctx *ctx, const char *name)
 	strlcpy(ifname_to_print, name, sizeof(ifname_to_print));
 }
 
+static void
+ifr_set_name(struct ifreq *ifr, const char *name)
+{
+	strlcpy(ifr->ifr_name, name, sizeof(ifr->ifr_name));
+}
+
+int
+ioctl_ctx_ifr(if_ctx *ctx, unsigned long cmd, struct ifreq *ifr)
+{
+	ifr_set_name(ifr, ctx->ifname);
+	return (ioctl_ctx(ctx, cmd, ifr));
+}
+
 void
 ifcreate_ioctl(if_ctx *ctx, struct ifreq *ifr)
 {
@@ -1105,6 +1118,7 @@ ifconfig_ioctl(if_ctx *orig_ctx, int iscreate, const struct afswtch *uafp)
 	};
 	struct ifconfig_context *ctx = &_ctx;
 
+	struct ifreq ifr = {};
 	strlcpy(ifr.ifr_name, ctx->ifname, sizeof ifr.ifr_name);
 	afp = NULL;
 	if (uafp != NULL)
@@ -1282,8 +1296,9 @@ settunnel(if_ctx *ctx, const char *src, const char *dst)
 static void
 deletetunnel(if_ctx *ctx, const char *vname __unused, int param __unused)
 {
+	struct ifreq ifr = {};
 
-	if (ioctl_ctx(ctx, SIOCDIFPHYADDR, &ifr) < 0)
+	if (ioctl_ctx_ifr(ctx, SIOCDIFPHYADDR, &ifr) < 0)
 		err(1, "SIOCDIFPHYADDR");
 }
 
@@ -1291,27 +1306,25 @@ deletetunnel(if_ctx *ctx, const char *vname __unused, int param __unused)
 static void
 setifvnet(if_ctx *ctx, const char *jname, int dummy __unused)
 {
-	struct ifreq my_ifr;
+	struct ifreq ifr = {};
 
-	memcpy(&my_ifr, &ifr, sizeof(my_ifr));
-	my_ifr.ifr_jid = jail_getid(jname);
-	if (my_ifr.ifr_jid < 0)
+	ifr.ifr_jid = jail_getid(jname);
+	if (ifr.ifr_jid < 0)
 		errx(1, "%s", jail_errmsg);
-	if (ioctl(ctx->io_s, SIOCSIFVNET, &my_ifr) < 0)
+	if (ioctl_ctx_ifr(ctx, SIOCSIFVNET, &ifr) < 0)
 		err(1, "SIOCSIFVNET");
 }
 
 static void
 setifrvnet(if_ctx *ctx, const char *jname, int dummy __unused)
 {
-	struct ifreq my_ifr;
+	struct ifreq ifr = {};
 
-	memcpy(&my_ifr, &ifr, sizeof(my_ifr));
-	my_ifr.ifr_jid = jail_getid(jname);
-	if (my_ifr.ifr_jid < 0)
+	ifr.ifr_jid = jail_getid(jname);
+	if (ifr.ifr_jid < 0)
 		errx(1, "%s", jail_errmsg);
-	if (ioctl(ctx->io_s, SIOCSIFRVNET, &my_ifr) < 0)
-		err(1, "SIOCSIFRVNET(%d, %s)", my_ifr.ifr_jid, my_ifr.ifr_name);
+	if (ioctl_ctx_ifr(ctx, SIOCSIFRVNET, &ifr) < 0)
+		err(1, "SIOCSIFRVNET(%d, %s)", ifr.ifr_jid, ifr.ifr_name);
 }
 #endif
 
@@ -1413,9 +1426,10 @@ setifflags(if_ctx *ctx, const char *vname, int value)
 void
 setifcap(if_ctx *ctx, const char *vname, int value)
 {
+	struct ifreq ifr = {};
 	int flags;
 
-	if (ioctl(ctx->io_s, SIOCGIFCAP, (caddr_t)&ifr) < 0) {
+	if (ioctl_ctx_ifr(ctx, SIOCGIFCAP, &ifr) < 0) {
  		Perror("ioctl (SIOCGIFCAP)");
  		exit(1);
  	}
@@ -1430,7 +1444,7 @@ setifcap(if_ctx *ctx, const char *vname, int value)
 	if (ifr.ifr_curcap == flags)
 		return;
 	ifr.ifr_reqcap = flags;
-	if (ioctl(ctx->io_s, SIOCSIFCAP, (caddr_t)&ifr) < 0)
+	if (ioctl_ctx(ctx, SIOCSIFCAP, &ifr) < 0)
 		Perror(vname);
 }
 
@@ -1442,8 +1456,9 @@ setifcapnv(if_ctx *ctx, const char *vname, const char *arg)
 	char *marg, *mopt;
 	size_t nvbuflen;
 	bool neg;
+	struct ifreq ifr = {};
 
-	if (ioctl(ctx->io_s, SIOCGIFCAP, (caddr_t)&ifr) < 0)
+	if (ioctl_ctx_ifr(ctx, SIOCGIFCAP, &ifr) < 0)
 		Perror("ioctl (SIOCGIFCAP)");
 	if ((ifr.ifr_curcap & IFCAP_NV) == 0) {
 		warnx("IFCAP_NV not supported");
@@ -1474,7 +1489,7 @@ setifcapnv(if_ctx *ctx, const char *vname, const char *arg)
 	}
 	ifr.ifr_cap_nv.buf_length = ifr.ifr_cap_nv.length = nvbuflen;
 	ifr.ifr_cap_nv.buffer = buf;
-	if (ioctl(ctx->io_s, SIOCSIFCAPNV, (caddr_t)&ifr) < 0)
+	if (ioctl_ctx(ctx, SIOCSIFCAPNV, (caddr_t)&ifr) < 0)
 		Perror(vname);
 	free(buf);
 	nvlist_destroy(nvcap);
@@ -1484,24 +1499,27 @@ setifcapnv(if_ctx *ctx, const char *vname, const char *arg)
 static void
 setifmetric(if_ctx *ctx, const char *val, int dummy __unused)
 {
-	strlcpy(ifr.ifr_name, ctx->ifname, sizeof (ifr.ifr_name));
+	struct ifreq ifr = {};
+
 	ifr.ifr_metric = atoi(val);
-	if (ioctl(ctx->io_s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
+	if (ioctl_ctx_ifr(ctx, SIOCSIFMETRIC, &ifr) < 0)
 		err(1, "ioctl SIOCSIFMETRIC (set metric)");
 }
 
 static void
 setifmtu(if_ctx *ctx, const char *val, int dummy __unused)
 {
-	strlcpy(ifr.ifr_name, ctx->ifname, sizeof (ifr.ifr_name));
+	struct ifreq ifr = {};
+
 	ifr.ifr_mtu = atoi(val);
-	if (ioctl(ctx->io_s, SIOCSIFMTU, (caddr_t)&ifr) < 0)
+	if (ioctl_ctx_ifr(ctx, SIOCSIFMTU, &ifr) < 0)
 		err(1, "ioctl SIOCSIFMTU (set mtu)");
 }
 
 static void
 setifpcp(if_ctx *ctx, const char *val, int arg __unused)
 {
+	struct ifreq ifr = {};
 	u_long ul;
 	char *endp;
 
@@ -1511,31 +1529,32 @@ setifpcp(if_ctx *ctx, const char *val, int arg __unused)
 	if (ul > 7)
 		errx(1, "value for pcp out of range");
 	ifr.ifr_lan_pcp = ul;
-	if (ioctl(ctx->io_s, SIOCSLANPCP, (caddr_t)&ifr) == -1)
+	if (ioctl_ctx_ifr(ctx, SIOCSLANPCP, &ifr) == -1)
 		err(1, "SIOCSLANPCP");
 }
 
 static void
 disableifpcp(if_ctx *ctx, const char *val __unused, int arg __unused)
 {
+	struct ifreq ifr = {};
 
 	ifr.ifr_lan_pcp = IFNET_PCP_NONE;
-	if (ioctl_ctx(ctx, SIOCSLANPCP, (caddr_t)&ifr) == -1)
+	if (ioctl_ctx_ifr(ctx, SIOCSLANPCP, &ifr) == -1)
 		err(1, "SIOCSLANPCP");
 }
 
 static void
 setifname(if_ctx *ctx, const char *val, int dummy __unused)
 {
+	struct ifreq ifr = {};
 	char *newname;
-	
-	strlcpy(ifr.ifr_name, ctx->ifname, sizeof(ifr.ifr_name));
 
+	ifr_set_name(&ifr, ctx->ifname);
 	newname = strdup(val);
 	if (newname == NULL)
 		err(1, "no memory to set ifname");
 	ifr.ifr_data = newname;
-	if (ioctl(ctx->io_s, SIOCSIFNAME, (caddr_t)&ifr) < 0) {
+	if (ioctl_ctx(ctx, SIOCSIFNAME, (caddr_t)&ifr) < 0) {
 		free(newname);
 		err(1, "ioctl SIOCSIFNAME (set name)");
 	}
@@ -1546,10 +1565,9 @@ setifname(if_ctx *ctx, const char *val, int dummy __unused)
 static void
 setifdescr(if_ctx *ctx, const char *val, int dummy __unused)
 {
+	struct ifreq ifr = {};
 	char *newdescr;
 
-	strlcpy(ifr.ifr_name, ctx->ifname, sizeof(ifr.ifr_name));
-	
 	ifr.ifr_buffer.length = strlen(val) + 1;
 	if (ifr.ifr_buffer.length == 1) {
 		ifr.ifr_buffer.buffer = newdescr = NULL;
@@ -1563,7 +1581,7 @@ setifdescr(if_ctx *ctx, const char *val, int dummy __unused)
 		}
 	}
 
-	if (ioctl(ctx->io_s, SIOCSIFDESCR, (caddr_t)&ifr) < 0)
+	if (ioctl_ctx_ifr(ctx, SIOCSIFDESCR, &ifr) < 0)
 		err(1, "ioctl SIOCSIFDESCR (set descr)");
 
 	free(newdescr);
@@ -1588,8 +1606,9 @@ unsetifdescr(if_ctx *ctx, const char *val __unused, int value __unused)
 "\36VXLAN_HWCSUM\37VXLAN_HWTSO\40TXTLS_RTLMT"
 
 static void
-print_ifcap_nv(struct ifconfig_args *args, int s)
+print_ifcap_nv(if_ctx *ctx)
 {
+	struct ifreq ifr = {};
 	nvlist_t *nvcap;
 	const char *nvname;
 	void *buf, *cookie;
@@ -1601,7 +1620,7 @@ print_ifcap_nv(struct ifconfig_args *args, int s)
 		Perror("malloc");
 	ifr.ifr_cap_nv.buffer = buf;
 	ifr.ifr_cap_nv.buf_length = IFR_CAP_NV_MAXBUFSIZE;
-	if (ioctl(s, SIOCGIFCAPNV, (caddr_t)&ifr) != 0)
+	if (ioctl_ctx_ifr(ctx, SIOCGIFCAPNV, &ifr) != 0)
 		Perror("ioctl (SIOCGIFCAPNV)");
 	nvcap = nvlist_unpack(ifr.ifr_cap_nv.buffer,
 	    ifr.ifr_cap_nv.length, 0);
@@ -1623,7 +1642,7 @@ print_ifcap_nv(struct ifconfig_args *args, int s)
 			}
 		}
 	}
-	if (args->supmedia) {
+	if (ctx->args->supmedia) {
 		printf("\tcapabilities");
 		cookie = NULL;
 		for (first = true;; first = false) {
@@ -1641,24 +1660,25 @@ print_ifcap_nv(struct ifconfig_args *args, int s)
 	nvlist_destroy(nvcap);
 	free(buf);
 
-	if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) != 0)
+	if (ioctl_ctx(ctx, SIOCGIFCAP, (caddr_t)&ifr) != 0)
 		Perror("ioctl (SIOCGIFCAP)");
 }
 
 void
-print_ifcap(struct ifconfig_args *args, int s)
+print_ifcap(if_ctx *ctx)
 {
-	if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) != 0)
+	struct ifreq ifr = {};
+
+	if (ioctl_ctx_ifr(ctx, SIOCGIFCAP, &ifr) != 0)
 		return;
 
 	if ((ifr.ifr_curcap & IFCAP_NV) != 0)
-		print_ifcap_nv(args, s);
+		print_ifcap_nv(ctx);
 	else {
 		printb("\toptions", ifr.ifr_curcap, IFCAPBITS);
 		putchar('\n');
-		if (args->supmedia && ifr.ifr_reqcap != 0) {
-			printb("\tcapabilities", ifr.ifr_reqcap,
-			    IFCAPBITS);
+		if (ctx->args->supmedia && ifr.ifr_reqcap != 0) {
+			printb("\tcapabilities", ifr.ifr_reqcap, IFCAPBITS);
 			putchar('\n');
 		}
 	}
@@ -1675,28 +1695,35 @@ print_ifstatus(if_ctx *ctx)
 }
 
 void
-print_metric(int s)
+print_metric(if_ctx *ctx)
 {
-	if (ioctl(s, SIOCGIFMETRIC, &ifr) != -1)
+	struct ifreq ifr = {};
+
+	if (ioctl_ctx_ifr(ctx, SIOCGIFMETRIC, &ifr) != -1)
 		printf(" metric %d", ifr.ifr_metric);
 }
 
 #ifdef WITHOUT_NETLINK
 static void
-print_mtu(int s)
+print_mtu(if_ctx *ctx)
 {
-	if (ioctl(s, SIOCGIFMTU, &ifr) != -1)
+	struct ifreq ifr = {};
+
+	if (ioctl_ctx_ifr(ctx, SIOCGIFMTU, &ifr) != -1)
 		printf(" mtu %d", ifr.ifr_mtu);
 }
 
 static void
-print_description(int s)
+print_description(if_ctx *ctx)
 {
+	struct ifreq ifr = {};
+
+	ifr_set_name(&ifr, ctx->ifname);
 	for (;;) {
 		if ((descr = reallocf(descr, descrlen)) != NULL) {
 			ifr.ifr_buffer.buffer = descr;
 			ifr.ifr_buffer.length = descrlen;
-			if (ioctl(s, SIOCGIFDESCR, &ifr) == 0) {
+			if (ioctl_ctx(ctx, SIOCGIFDESCR, &ifr) == 0) {
 				if (ifr.ifr_buffer.buffer == descr) {
 					if (strlen(descr) > 0)
 						printf("\tdescription: %s\n",
@@ -1725,14 +1752,13 @@ status(if_ctx *ctx, const struct sockaddr_dl *sdl,
 	int s, old_s;
 	struct ifconfig_args *args = ctx->args;
 	bool allfamilies = args->afp == NULL;
-	char *ifname = ifa->ifa_name;
+	struct ifreq ifr = {};
 
 	if (args->afp == NULL)
 		ifr.ifr_addr.sa_family = AF_LOCAL;
 	else
 		ifr.ifr_addr.sa_family =
 		   args->afp->af_af == AF_LINK ? AF_LOCAL : args->afp->af_af;
-	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
 
 	s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0);
 	if (s < 0)
@@ -1740,15 +1766,15 @@ status(if_ctx *ctx, const struct sockaddr_dl *sdl,
 	old_s = ctx->io_s;
 	ctx->io_s = s;
 
-	printf("%s: ", ifname);
+	printf("%s: ", ctx->ifname);
 	printb("flags", ifa->ifa_flags, IFFBITS);
-	print_metric(s);
-	print_mtu(s);
+	print_metric(ctx);
+	print_mtu(ctx);
 	putchar('\n');
 
-	print_description(s);
+	print_description(ctx);
 
-	print_ifcap(args, s);
+	print_ifcap(ctx);
 
 	tunnel_status(ctx);
 
diff --git a/sbin/ifconfig/ifconfig.h b/sbin/ifconfig/ifconfig.h
index 7001725543d8..334027c36d89 100644
--- a/sbin/ifconfig/ifconfig.h
+++ b/sbin/ifconfig/ifconfig.h
@@ -153,6 +153,7 @@ void	callback_register(callback_func *, void *);
 }
 
 #define	ioctl_ctx(ctx, _req, ...)	ioctl((ctx)->io_s, _req, ## __VA_ARGS__)
+int ioctl_ctx_ifr(if_ctx *ctx, unsigned long cmd, struct ifreq *ifr);
 
 struct ifaddrs;
 struct addrinfo;
@@ -275,12 +276,12 @@ bool	match_ether(const struct sockaddr_dl *sdl);
 bool	match_if_flags(struct ifconfig_args *args, int if_flags);
 int	ifconfig_ioctl(if_ctx *ctx, int iscreate, const struct afswtch *uafp);
 bool	group_member(const char *ifname, const char *match, const char *nomatch);
-void	print_ifcap(struct ifconfig_args *args, int s);
+void	print_ifcap(if_ctx *ctx);
 void	tunnel_status(if_ctx *ctx);
 struct afswtch	*af_getbyfamily(int af);
 void	af_other_status(if_ctx *ctx);
 void	print_ifstatus(if_ctx *ctx);
-void	print_metric(int s);
+void	print_metric(if_ctx *ctx);
 
 /* Netlink-related functions */
 void	list_interfaces_nl(struct ifconfig_args *args);
diff --git a/sbin/ifconfig/ifconfig_netlink.c b/sbin/ifconfig/ifconfig_netlink.c
index a7d3cfe6f300..2460d8c60109 100644
--- a/sbin/ifconfig/ifconfig_netlink.c
+++ b/sbin/ifconfig/ifconfig_netlink.c
@@ -354,15 +354,14 @@ status_nl(if_ctx *ctx, struct iface *iface)
 	printf("flags=%x", link->ifi_flags);
 	print_bits("IFF", &link->ifi_flags, 1, IFFBITS, nitems(IFFBITS));
 
-	print_metric(ctx->io_s);
+	print_metric(ctx);
 	printf(" mtu %d\n", link->ifla_mtu);
 
 	if (link->ifla_ifalias != NULL)
 		printf("\tdescription: %s\n", link->ifla_ifalias);
 
 	/* TODO: convert to netlink */
-	strlcpy(ifr.ifr_name, link->ifla_ifname, sizeof(ifr.ifr_name));
-	print_ifcap(args, ctx->io_s);
+	print_ifcap(ctx);
 	tunnel_status(ctx);
 
 	if (args->allfamilies | (args->afp != NULL && args->afp->af_af == AF_LINK)) {
diff --git a/sbin/ifconfig/iffib.c b/sbin/ifconfig/iffib.c
index 684c57c88f64..0f44168fe7dc 100644
--- a/sbin/ifconfig/iffib.c
+++ b/sbin/ifconfig/iffib.c
@@ -66,6 +66,7 @@ fib_status(if_ctx *ctx)
 static void
 setiffib(if_ctx *ctx, const char *val, int dummy __unused)
 {
+	struct ifreq ifr = {};
 	unsigned long fib;
 	char *ep;
 
@@ -75,15 +76,15 @@ setiffib(if_ctx *ctx, const char *val, int dummy __unused)
 		return;
 	}
 
-	strlcpy(ifr.ifr_name, ctx->ifname, sizeof (ifr.ifr_name));
 	ifr.ifr_fib = fib;
-	if (ioctl(ctx->io_s, SIOCSIFFIB, (caddr_t)&ifr) < 0)
+	if (ioctl_ctx_ifr(ctx, SIOCSIFFIB, &ifr) < 0)
 		warn("ioctl (SIOCSIFFIB)");
 }
 
 static void
 settunfib(if_ctx *ctx, const char *val, int dummy __unused)
 {
+	struct ifreq ifr = {};
 	unsigned long fib;
 	char *ep;
 
@@ -93,9 +94,8 @@ settunfib(if_ctx *ctx, const char *val, int dummy __unused)
 		return;
 	}
 
-	strlcpy(ifr.ifr_name, ctx->ifname, sizeof (ifr.ifr_name));
 	ifr.ifr_fib = fib;
-	if (ioctl(ctx->io_s, SIOCSTUNFIB, (caddr_t)&ifr) < 0)
+	if (ioctl_ctx_ifr(ctx, SIOCSTUNFIB, &ifr) < 0)
 		warn("ioctl (SIOCSTUNFIB)");
 }
 
diff --git a/sbin/ifconfig/ifgif.c b/sbin/ifconfig/ifgif.c
index 759360bf2f00..3a41ef63d1d3 100644
--- a/sbin/ifconfig/ifgif.c
+++ b/sbin/ifconfig/ifgif.c
@@ -59,9 +59,9 @@ static void
 gif_status(if_ctx *ctx)
 {
 	int opts;
+	struct ifreq ifr = { .ifr_data = (caddr_t)&opts };
 
-	ifr.ifr_data = (caddr_t)&opts;
-	if (ioctl_ctx(ctx, GIFGOPTS, &ifr) == -1)
+	if (ioctl_ctx_ifr(ctx, GIFGOPTS, &ifr) == -1)
 		return;
 	if (opts == 0)
 		return;
@@ -73,9 +73,9 @@ static void
 setgifopts(if_ctx *ctx, const char *val __unused, int d)
 {
 	int opts;
+	struct ifreq ifr = { .ifr_data = (caddr_t)&opts };
 
-	ifr.ifr_data = (caddr_t)&opts;
-	if (ioctl_ctx(ctx, GIFGOPTS, &ifr) == -1) {
+	if (ioctl_ctx_ifr(ctx, GIFGOPTS, &ifr) == -1) {
 		warn("ioctl(GIFGOPTS)");
 		return;
 	}
diff --git a/sbin/ifconfig/ifgre.c b/sbin/ifconfig/ifgre.c
index 67732981228e..018167a32046 100644
--- a/sbin/ifconfig/ifgre.c
+++ b/sbin/ifconfig/ifgre.c
@@ -49,10 +49,9 @@ __FBSDID("$FreeBSD$");
 static void
 gre_status(if_ctx *ctx)
 {
-	uint32_t opts, port;
+	uint32_t opts = 0, port;
+	struct ifreq ifr = { .ifr_data = (caddr_t)&opts };
 
-	opts = 0;
-	ifr.ifr_data = (caddr_t)&opts;
 	if (ioctl_ctx(ctx, GREGKEY, &ifr) == 0)
 		if (opts != 0)
 			printf("\tgrekey: 0x%x (%u)\n", opts, opts);
@@ -62,7 +61,7 @@ gre_status(if_ctx *ctx)
 
 	port = 0;
 	ifr.ifr_data = (caddr_t)&port;
-	if (ioctl_ctx(ctx, GREGPORT, &ifr) == 0 && port != 0)
+	if (ioctl_ctx_ifr(ctx, GREGPORT, &ifr) == 0 && port != 0)
 		printf("\tudpport: %u\n", port);
 	printb("\toptions", opts, GREBITS);
 	putchar('\n');
@@ -72,10 +71,10 @@ static void
 setifgrekey(if_ctx *ctx, const char *val, int dummy __unused)
 {
 	uint32_t grekey = strtol(val, NULL, 0);
+	struct ifreq ifr = { .ifr_data = (caddr_t)&grekey };
 
-	strlcpy(ifr.ifr_name, ctx->ifname, sizeof (ifr.ifr_name));
 	ifr.ifr_data = (caddr_t)&grekey;
-	if (ioctl(ctx->io_s, GRESKEY, (caddr_t)&ifr) < 0)
+	if (ioctl_ctx_ifr(ctx, GRESKEY, &ifr) < 0)
 		warn("ioctl (set grekey)");
 }
 
@@ -83,10 +82,9 @@ static void
 setifgreport(if_ctx *ctx, const char *val, int dummy __unused)
 {
 	uint32_t udpport = strtol(val, NULL, 0);
+	struct ifreq ifr = { .ifr_data = (caddr_t)&udpport };
 
-	strlcpy(ifr.ifr_name, ctx->ifname, sizeof (ifr.ifr_name));
-	ifr.ifr_data = (caddr_t)&udpport;
-	if (ioctl(ctx->io_s, GRESPORT, (caddr_t)&ifr) < 0)
+	if (ioctl_ctx_ifr(ctx, GRESPORT, &ifr) < 0)
 		warn("ioctl (set udpport)");
 }
 
@@ -94,9 +92,9 @@ static void
 setifgreopts(if_ctx *ctx, const char *val __unused, int d)
 {
 	uint32_t opts;
+	struct ifreq ifr = { .ifr_data = (caddr_t)&opts };
 
-	ifr.ifr_data = (caddr_t)&opts;
-	if (ioctl(ctx->io_s, GREGOPTS, &ifr) == -1) {
+	if (ioctl_ctx_ifr(ctx, GREGOPTS, &ifr) == -1) {
 		warn("ioctl(GREGOPTS)");
 		return;
 	}
@@ -106,7 +104,7 @@ setifgreopts(if_ctx *ctx, const char *val __unused, int d)
 	else
 		opts |= d;
 
-	if (ioctl(ctx->io_s, GRESOPTS, &ifr) == -1) {
+	if (ioctl_ctx(ctx, GRESOPTS, &ifr) == -1) {
 		warn("ioctl(GIFSOPTS)");
 		return;
 	}
diff --git a/sbin/ifconfig/ifipsec.c b/sbin/ifconfig/ifipsec.c
index 929cc56bdcdf..2d9790208858 100644
--- a/sbin/ifconfig/ifipsec.c
+++ b/sbin/ifconfig/ifipsec.c
@@ -54,9 +54,9 @@ static void
 ipsec_status(if_ctx *ctx)
 {
 	uint32_t reqid;
+	struct ifreq ifr = { .ifr_data = (caddr_t)&reqid };
 
-	ifr.ifr_data = (caddr_t)&reqid;
-	if (ioctl_ctx(ctx, IPSECGREQID, &ifr) == -1)
+	if (ioctl_ctx_ifr(ctx, IPSECGREQID, &ifr) == -1)
 		return;
 	printf("\treqid: %u\n", reqid);
 }
@@ -66,15 +66,14 @@ setreqid(if_ctx *ctx, const char *val, int dummy __unused)
 {
 	char *ep;
 	uint32_t v;
+	struct ifreq ifr = { .ifr_data = (caddr_t)&v };
 
 	v = strtoul(val, &ep, 0);
 	if (*ep != '\0') {
 		warn("Invalid reqid value %s", val);
 		return;
 	}
-	strlcpy(ifr.ifr_name, ctx->ifname, sizeof(ifr.ifr_name));
-	ifr.ifr_data = (char *)&v;
-	if (ioctl_ctx(ctx, IPSECSREQID, &ifr) == -1) {
+	if (ioctl_ctx_ifr(ctx, IPSECSREQID, &ifr) == -1) {
 		warn("ioctl(IPSECSREQID)");
 		return;
 	}
diff --git a/sbin/ifconfig/ifpfsync.c b/sbin/ifconfig/ifpfsync.c
index 81bf463db117..b97b9925c644 100644
--- a/sbin/ifconfig/ifpfsync.c
+++ b/sbin/ifconfig/ifpfsync.c
@@ -51,10 +51,11 @@
 #include "ifconfig.h"
 
 static int
-pfsync_do_ioctl(int s, uint cmd, nvlist_t **nvl)
+pfsync_do_ioctl(if_ctx *ctx, uint cmd, nvlist_t **nvl)
 {
 	void *data;
 	size_t nvlen;
+	struct ifreq ifr = {};
 
 	data = nvlist_pack(*nvl, &nvlen);
 
@@ -64,7 +65,7 @@ pfsync_do_ioctl(int s, uint cmd, nvlist_t **nvl)
 	ifr.ifr_cap_nv.length = nvlen;
 	free(data);
 
-	if (ioctl(s, cmd, (caddr_t)&ifr) == -1) {
+	if (ioctl_ctx_ifr(ctx, cmd, &ifr) == -1) {
 		free(ifr.ifr_cap_nv.buffer);
 		return -1;
 	}
@@ -172,7 +173,7 @@ setpfsync_syncdev(if_ctx *ctx, const char *val, int dummy __unused)
 	if (strlen(val) > IFNAMSIZ)
 		errx(1, "interface name %s is too long", val);
 
-	if (pfsync_do_ioctl(ctx->io_s, SIOCGETPFSYNCNV, &nvl) == -1)
+	if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
 		err(1, "SIOCGETPFSYNCNV");
 
 	if (nvlist_exists_string(nvl, "syncdev"))
@@ -180,7 +181,7 @@ setpfsync_syncdev(if_ctx *ctx, const char *val, int dummy __unused)
 
 	nvlist_add_string(nvl, "syncdev", val);
 
-	if (pfsync_do_ioctl(ctx->io_s, SIOCSETPFSYNCNV, &nvl) == -1)
+	if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
 		err(1, "SIOCSETPFSYNCNV");
 }
 
@@ -189,7 +190,7 @@ unsetpfsync_syncdev(if_ctx *ctx, const char *val __unused, int dummy __unused)
 {
 	nvlist_t *nvl = nvlist_create(0);
 
-	if (pfsync_do_ioctl(ctx->io_s, SIOCGETPFSYNCNV, &nvl) == -1)
+	if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
 		err(1, "SIOCGETPFSYNCNV");
 
 	if (nvlist_exists_string(nvl, "syncdev"))
@@ -197,7 +198,7 @@ unsetpfsync_syncdev(if_ctx *ctx, const char *val __unused, int dummy __unused)
 
 	nvlist_add_string(nvl, "syncdev", "");
 
-	if (pfsync_do_ioctl(ctx->io_s, SIOCSETPFSYNCNV, &nvl) == -1)
+	if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
 		err(1, "SIOCSETPFSYNCNV");
 }
 
@@ -210,7 +211,7 @@ setpfsync_syncpeer(if_ctx *ctx, const char *val, int dummy __unused)
 
 	nvlist_t *nvl = nvlist_create(0);
 
-	if (pfsync_do_ioctl(ctx->io_s, SIOCGETPFSYNCNV, &nvl) == -1)
+	if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
 		err(1, "SIOCGETPFSYNCNV");
 
 	if ((ecode = getaddrinfo(val, NULL, NULL, &peerres)) != 0)
@@ -239,7 +240,7 @@ setpfsync_syncpeer(if_ctx *ctx, const char *val, int dummy __unused)
 	nvlist_add_nvlist(nvl, "syncpeer",
 	    pfsync_sockaddr_to_syncpeer_nvlist(&addr));
 
-	if (pfsync_do_ioctl(ctx->io_s, SIOCSETPFSYNCNV, &nvl) == -1)
+	if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
 		err(1, "SIOCSETPFSYNCNV");
 
 	nvlist_destroy(nvl);
@@ -254,7 +255,7 @@ unsetpfsync_syncpeer(if_ctx *ctx, const char *val __unused, int dummy __unused)
 
 	nvlist_t *nvl = nvlist_create(0);
 
-	if (pfsync_do_ioctl(ctx->io_s, SIOCGETPFSYNCNV, &nvl) == -1)
+	if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
 		err(1, "SIOCGETPFSYNCNV");
 
 	if (nvlist_exists_nvlist(nvl, "syncpeer"))
@@ -263,7 +264,7 @@ unsetpfsync_syncpeer(if_ctx *ctx, const char *val __unused, int dummy __unused)
 	nvlist_add_nvlist(nvl, "syncpeer",
 	    pfsync_sockaddr_to_syncpeer_nvlist(&addr));
 
-	if (pfsync_do_ioctl(ctx->io_s, SIOCSETPFSYNCNV, &nvl) == -1)
+	if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
 		err(1, "SIOCSETPFSYNCNV");
 
 	nvlist_destroy(nvl);
@@ -279,13 +280,13 @@ setpfsync_maxupd(if_ctx *ctx, const char *val, int dummy __unused)
 	if ((maxupdates < 0) || (maxupdates > 255))
 		errx(1, "maxupd %s: out of range", val);
 
-	if (pfsync_do_ioctl(ctx->io_s, SIOCGETPFSYNCNV, &nvl) == -1)
+	if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
 		err(1, "SIOCGETPFSYNCNV");
 
 	nvlist_free_number(nvl, "maxupdates");
 	nvlist_add_number(nvl, "maxupdates", maxupdates);
 
-	if (pfsync_do_ioctl(ctx->io_s, SIOCSETPFSYNCNV, &nvl) == -1)
+	if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
 		err(1, "SIOCSETPFSYNCNV");
 
 	nvlist_destroy(nvl);
@@ -296,13 +297,13 @@ setpfsync_defer(if_ctx *ctx, const char *val __unused, int d)
 {
 	nvlist_t *nvl = nvlist_create(0);
 
-	if (pfsync_do_ioctl(ctx->io_s, SIOCGETPFSYNCNV, &nvl) == -1)
+	if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
 		err(1, "SIOCGETPFSYNCNV");
 
 	nvlist_free_number(nvl, "flags");
 	nvlist_add_number(nvl, "flags", d ? PFSYNCF_DEFER : 0);
 
-	if (pfsync_do_ioctl(ctx->io_s, SIOCSETPFSYNCNV, &nvl) == -1)
+	if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
 		err(1, "SIOCSETPFSYNCNV");
 
 	nvlist_destroy(nvl);
@@ -317,13 +318,13 @@ setpfsync_version(if_ctx *ctx, const char *val, int dummy __unused)
 	/* Don't verify, kernel knows which versions are supported.*/
 	version = atoi(val);
 
-	if (pfsync_do_ioctl(ctx->io_s, SIOCGETPFSYNCNV, &nvl) == -1)
+	if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1)
 		err(1, "SIOCGETPFSYNCNV");
 
 	nvlist_free_number(nvl, "version");
 	nvlist_add_number(nvl, "version", version);
 
-	if (pfsync_do_ioctl(ctx->io_s, SIOCSETPFSYNCNV, &nvl) == -1)
+	if (pfsync_do_ioctl(ctx, SIOCSETPFSYNCNV, &nvl) == -1)
 		err(1, "SIOCSETPFSYNCNV");
 
 	nvlist_destroy(nvl);
@@ -343,7 +344,7 @@ pfsync_status(if_ctx *ctx)
 
 	nvl = nvlist_create(0);
 
-	if (pfsync_do_ioctl(ctx->io_s, SIOCGETPFSYNCNV, &nvl) == -1) {
+	if (pfsync_do_ioctl(ctx, SIOCGETPFSYNCNV, &nvl) == -1) {
 		nvlist_destroy(nvl);
 		return;
 	}
diff --git a/sbin/ifconfig/ifstf.c b/sbin/ifconfig/ifstf.c
index 0089cedf7a6b..a99592b4801f 100644
--- a/sbin/ifconfig/ifstf.c
+++ b/sbin/ifconfig/ifstf.c
@@ -54,11 +54,9 @@
 static int
 do_cmd(if_ctx *ctx, u_long op, void *arg, size_t argsize, int set)
 {
-	struct ifdrv ifd;
+	struct ifdrv ifd = {};
 
-	memset(&ifd, 0, sizeof(ifd));
-
-	strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name));
+	strlcpy(ifd.ifd_name, ctx->ifname, sizeof(ifd.ifd_name));
 	ifd.ifd_cmd = op;
 	ifd.ifd_len = argsize;
 	ifd.ifd_data = arg;
diff --git a/sbin/ifconfig/ifvlan.c b/sbin/ifconfig/ifvlan.c
index 2d0d15fdd828..b871e953c44a 100644
--- a/sbin/ifconfig/ifvlan.c
+++ b/sbin/ifconfig/ifvlan.c
@@ -75,21 +75,13 @@ static 	struct vlanreq params = {
 	.vlr_proto	= ETHERTYPE_VLAN,
 };
 
-static int
-getvlan(int s, struct ifreq *ifr, struct vlanreq *vreq)
-{
-	bzero((char *)vreq, sizeof(*vreq));
-	ifr->ifr_data = (caddr_t)vreq;
-
-	return ioctl(s, SIOCGETVLAN, (caddr_t)ifr);
-}
-
 static void
 vlan_status(if_ctx *ctx)
 {
-	struct vlanreq		vreq;
+	struct vlanreq vreq = {};
+	struct ifreq ifr = { .ifr_data = (caddr_t)&vreq };
 
-	if (getvlan(ctx->io_s, &ifr, &vreq) == -1)
+	if (ioctl_ctx_ifr(ctx, SIOCGETVLAN, &ifr) == -1)
 		return;
 	printf("\tvlan: %d", vreq.vlr_tag);
 	printf(" vlanproto: ");
@@ -103,7 +95,7 @@ vlan_status(if_ctx *ctx)
 		default:
 			printf("0x%04x", vreq.vlr_proto);
*** 121 LINES SKIPPED ***