Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 15 May 2023 13:38:00 GMT
From:      "Alexander V. Chernikov" <melifaro@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: d1cd0344f7b7 - main - ifconfig: split printing functions into smaller per-type chunks.
Message-ID:  <202305151338.34FDc0oc059455@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by melifaro:

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

commit d1cd0344f7b7d81beda04c3cb8cfee99351c3eb8
Author:     Alexander V. Chernikov <melifaro@FreeBSD.org>
AuthorDate: 2023-05-15 12:17:54 +0000
Commit:     Alexander V. Chernikov <melifaro@FreeBSD.org>
CommitDate: 2023-05-15 13:37:27 +0000

    ifconfig: split printing functions into smaller per-type chunks.
    
    This change is a prerequisite for netlink conversion.
    No functional changes intended.
    
    Reviewed by: kp
    Differential Revision: https://reviews.freebsd.org/D40033
    MFC after: 2 weeks
---
 sbin/ifconfig/af_inet.c  |  21 ++--
 sbin/ifconfig/af_inet6.c | 154 +++++++++++++++------------
 sbin/ifconfig/af_link.c  |  67 +++++++-----
 sbin/ifconfig/ifconfig.c | 271 +++++++++++++++++++++++++++++------------------
 sbin/ifconfig/ifconfig.h |   3 +
 5 files changed, 305 insertions(+), 211 deletions(-)

diff --git a/sbin/ifconfig/af_inet.c b/sbin/ifconfig/af_inet.c
index c5c40de155d6..6ce11fa2d673 100644
--- a/sbin/ifconfig/af_inet.c
+++ b/sbin/ifconfig/af_inet.c
@@ -60,16 +60,9 @@ static char addr_buf[NI_MAXHOST];	/*for getnameinfo()*/
 extern char *f_inet, *f_addr;
 
 static void
-in_status(int s __unused, const struct ifaddrs *ifa)
+print_addr(struct sockaddr_in *sin)
 {
-	struct sockaddr_in *sin, null_sin;
 	int error, n_flags;
-	
-	memset(&null_sin, 0, sizeof(null_sin));
-
-	sin = (struct sockaddr_in *)ifa->ifa_addr;
-	if (sin == NULL)
-		return;
 
 	if (f_addr != NULL && strcmp(f_addr, "fqdn") == 0)
 		n_flags = 0;
@@ -85,6 +78,18 @@ in_status(int s __unused, const struct ifaddrs *ifa)
 		inet_ntop(AF_INET, &sin->sin_addr, addr_buf, sizeof(addr_buf));
 	
 	printf("\tinet %s", addr_buf);
+}
+
+static void
+in_status(int s __unused, const struct ifaddrs *ifa)
+{
+	struct sockaddr_in *sin, null_sin = {};
+
+	sin = (struct sockaddr_in *)ifa->ifa_addr;
+	if (sin == NULL)
+		return;
+
+	print_addr(sin);
 
 	if (ifa->ifa_flags & IFF_POINTOPOINT) {
 		sin = (struct sockaddr_in *)ifa->ifa_dstaddr;
diff --git a/sbin/ifconfig/af_inet6.c b/sbin/ifconfig/af_inet6.c
index 08902b934ad8..49049ba2c376 100644
--- a/sbin/ifconfig/af_inet6.c
+++ b/sbin/ifconfig/af_inet6.c
@@ -168,20 +168,88 @@ setip6eui64(const char *cmd, int dummy __unused, int s,
 	freeifaddrs(ifap);
 }
 
+static void
+print_addr(struct sockaddr_in6 *sin)
+{
+	int error, n_flags;
+
+	if (f_addr != NULL && strcmp(f_addr, "fqdn") == 0)
+		n_flags = 0;
+	else if (f_addr != NULL && strcmp(f_addr, "host") == 0)
+		n_flags = NI_NOFQDN;
+	else
+		n_flags = NI_NUMERICHOST;
+	error = getnameinfo((struct sockaddr *)sin, sin->sin6_len,
+			    addr_buf, sizeof(addr_buf), NULL, 0,
+			    n_flags);
+	if (error != 0)
+		inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf,
+			  sizeof(addr_buf));
+	printf("\tinet6 %s", addr_buf);
+}
+
+static void
+print_p2p(struct sockaddr_in6 *sin)
+{
+	int error;
+
+	error = getnameinfo((struct sockaddr *)sin, sin->sin6_len, addr_buf,
+	    sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
+
+	if (error != 0)
+		inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf, sizeof(addr_buf));
+	printf(" --> %s", addr_buf);
+}
+
+static void
+print_mask(int plen)
+{
+	if (f_inet6 != NULL && strcmp(f_inet6, "cidr") == 0)
+		printf("/%d", plen);
+	else
+		printf(" prefixlen %d", plen);
+}
+
+static void
+print_flags(int flags6)
+{
+	if ((flags6 & IN6_IFF_ANYCAST) != 0)
+		printf(" anycast");
+	if ((flags6 & IN6_IFF_TENTATIVE) != 0)
+		printf(" tentative");
+	if ((flags6 & IN6_IFF_DUPLICATED) != 0)
+		printf(" duplicated");
+	if ((flags6 & IN6_IFF_DETACHED) != 0)
+		printf(" detached");
+	if ((flags6 & IN6_IFF_DEPRECATED) != 0)
+		printf(" deprecated");
+	if ((flags6 & IN6_IFF_AUTOCONF) != 0)
+		printf(" autoconf");
+	if ((flags6 & IN6_IFF_TEMPORARY) != 0)
+		printf(" temporary");
+	if ((flags6 & IN6_IFF_PREFER_SOURCE) != 0)
+		printf(" prefer_source");
+
+}
+
+static void
+print_lifetime(const char *prepend, time_t px_time, struct timespec *now)
+{
+	printf(" %s", prepend);
+	if (px_time == 0)
+		printf(" infty");
+
+	printf(" %s", px_time < now->tv_sec ? "0" : sec2str(px_time - now->tv_sec));
+}
+
 static void
 in6_status(int s __unused, const struct ifaddrs *ifa)
 {
-	struct sockaddr_in6 *sin, null_sin;
+	struct sockaddr_in6 *sin, null_sin = {};
 	struct in6_ifreq ifr6;
 	int s6;
 	u_int32_t flags6;
 	struct in6_addrlifetime lifetime;
-	struct timespec now;
-	int error, n_flags;
-
-	clock_gettime(CLOCK_MONOTONIC_FAST, &now);
-
-	memset(&null_sin, 0, sizeof(null_sin));
 
 	sin = (struct sockaddr_in6 *)ifa->ifa_addr;
 	if (sin == NULL)
@@ -209,19 +277,7 @@ in6_status(int s __unused, const struct ifaddrs *ifa)
 	lifetime = ifr6.ifr_ifru.ifru_lifetime;
 	close(s6);
 
-	if (f_addr != NULL && strcmp(f_addr, "fqdn") == 0)
-		n_flags = 0;
-	else if (f_addr != NULL && strcmp(f_addr, "host") == 0)
-		n_flags = NI_NOFQDN;
-	else
-		n_flags = NI_NUMERICHOST;
-	error = getnameinfo((struct sockaddr *)sin, sin->sin6_len,
-			    addr_buf, sizeof(addr_buf), NULL, 0,
-			    n_flags);
-	if (error != 0)
-		inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf,
-			  sizeof(addr_buf));
-	printf("\tinet6 %s", addr_buf);
+	print_addr(sin);
 
 	if (ifa->ifa_flags & IFF_POINTOPOINT) {
 		sin = (struct sockaddr_in6 *)ifa->ifa_dstaddr;
@@ -229,67 +285,27 @@ in6_status(int s __unused, const struct ifaddrs *ifa)
 		 * some of the interfaces do not have valid destination
 		 * address.
 		 */
-		if (sin != NULL && sin->sin6_family == AF_INET6) {
-			int error;
-
-			error = getnameinfo((struct sockaddr *)sin,
-					    sin->sin6_len, addr_buf,
-					    sizeof(addr_buf), NULL, 0,
-					    NI_NUMERICHOST);
-			if (error != 0)
-				inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf,
-					  sizeof(addr_buf));
-			printf(" --> %s", addr_buf);
-		}
+		if (sin != NULL && sin->sin6_family == AF_INET6)
+			print_p2p(sin);
 	}
 
 	sin = (struct sockaddr_in6 *)ifa->ifa_netmask;
 	if (sin == NULL)
 		sin = &null_sin;
-	if (f_inet6 != NULL && strcmp(f_inet6, "cidr") == 0)
-		printf("/%d", prefix(&sin->sin6_addr,
-			sizeof(struct in6_addr)));
-	else
-		printf(" prefixlen %d", prefix(&sin->sin6_addr,
-			sizeof(struct in6_addr)));
+	print_mask(prefix(&sin->sin6_addr, sizeof(struct in6_addr)));
 
-	if ((flags6 & IN6_IFF_ANYCAST) != 0)
-		printf(" anycast");
-	if ((flags6 & IN6_IFF_TENTATIVE) != 0)
-		printf(" tentative");
-	if ((flags6 & IN6_IFF_DUPLICATED) != 0)
-		printf(" duplicated");
-	if ((flags6 & IN6_IFF_DETACHED) != 0)
-		printf(" detached");
-	if ((flags6 & IN6_IFF_DEPRECATED) != 0)
-		printf(" deprecated");
-	if ((flags6 & IN6_IFF_AUTOCONF) != 0)
-		printf(" autoconf");
-	if ((flags6 & IN6_IFF_TEMPORARY) != 0)
-		printf(" temporary");
-	if ((flags6 & IN6_IFF_PREFER_SOURCE) != 0)
-		printf(" prefer_source");
+	print_flags(flags6);
 
 	if (((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_scope_id)
 		printf(" scopeid 0x%x",
 		    ((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_scope_id);
 
 	if (ip6lifetime && (lifetime.ia6t_preferred || lifetime.ia6t_expire)) {
-		printf(" pltime");
-		if (lifetime.ia6t_preferred) {
-			printf(" %s", lifetime.ia6t_preferred < now.tv_sec
-			    ? "0" :
-			    sec2str(lifetime.ia6t_preferred - now.tv_sec));
-		} else
-			printf(" infty");
-
-		printf(" vltime");
-		if (lifetime.ia6t_expire) {
-			printf(" %s", lifetime.ia6t_expire < now.tv_sec
-			    ? "0" :
-			    sec2str(lifetime.ia6t_expire - now.tv_sec));
-		} else
-			printf(" infty");
+		struct timespec now;
+
+		clock_gettime(CLOCK_MONOTONIC_FAST, &now);
+		print_lifetime("pltime", lifetime.ia6t_preferred, &now);
+		print_lifetime("vltime", lifetime.ia6t_expire, &now);
 	}
 
 	print_vhid(ifa, " ");
diff --git a/sbin/ifconfig/af_link.c b/sbin/ifconfig/af_link.c
index fb7a235b2f49..f651ddc51cb4 100644
--- a/sbin/ifconfig/af_link.c
+++ b/sbin/ifconfig/af_link.c
@@ -56,34 +56,54 @@ static struct ifreq link_ridreq;
 
 extern char *f_ether;
 
+static void
+print_ether(const struct ether_addr *addr, const char *prefix)
+{
+	char *ether_format = ether_ntoa(addr);
+
+	if (f_ether != NULL && strcmp(f_ether, "dash") == 0) {
+		char *format_char;
+
+		while ((format_char = strchr(ether_format, ':')) != NULL) {
+			*format_char = '-';
+		}
+	}
+	printf("\t%s %s\n", prefix, ether_format);
+}
+
+static void
+print_lladdr(struct sockaddr_dl *sdl)
+{
+	if (match_ether(sdl)) {
+		print_ether((struct ether_addr *)LLADDR(sdl), "ether");
+	} else {
+		int n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0;
+		printf("\tlladdr %s\n", link_ntoa(sdl) + n);
+	}
+}
+
+static void
+print_pcp(int s)
+{
+	if (ioctl(s, SIOCGLANPCP, (caddr_t)&ifr) == 0 &&
+	    ifr.ifr_lan_pcp != IFNET_PCP_NONE)
+		printf("\tpcp %d\n", ifr.ifr_lan_pcp);
+}
+
 static void
 link_status(int s __unused, const struct ifaddrs *ifa)
 {
 	/* XXX no const 'cuz LLADDR is defined wrong */
 	struct sockaddr_dl *sdl;
-	char *ether_format, *format_char;
 	struct ifreq ifr;
-	int n, rc, sock_hw;
+	int rc, sock_hw;
 	static const u_char laggaddr[6] = {0};
 
 	sdl = (struct sockaddr_dl *) ifa->ifa_addr;
 	if (sdl == NULL || sdl->sdl_alen == 0)
 		return;
 
-	if ((sdl->sdl_type == IFT_ETHER || sdl->sdl_type == IFT_L2VLAN ||
-	    sdl->sdl_type == IFT_BRIDGE) && sdl->sdl_alen == ETHER_ADDR_LEN) {
-		ether_format = ether_ntoa((struct ether_addr *)LLADDR(sdl));
-		if (f_ether != NULL && strcmp(f_ether, "dash") == 0) {
-			while ((format_char = strchr(ether_format, ':')) !=
-			    NULL) {
-				*format_char = '-';
-			}
-		}
-		printf("\tether %s\n", ether_format);
-	} else {
-		n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0;
-		printf("\tlladdr %s\n", link_ntoa(sdl) + n);
-	}
+	print_lladdr(sdl);
 
 	/*
 	 * Best-effort (i.e. failures are silent) to get original
@@ -118,20 +138,9 @@ link_status(int s __unused, const struct ifaddrs *ifa)
 	    memcmp(ifr.ifr_addr.sa_data, LLADDR(sdl), sdl->sdl_alen) == 0)
 		goto pcp;
 
-	ether_format = ether_ntoa((const struct ether_addr *)
-	    &ifr.ifr_addr.sa_data);
-	if (f_ether != NULL && strcmp(f_ether, "dash") == 0) {
-		for (format_char = strchr(ether_format, ':');
-		     format_char != NULL;
-		     format_char = strchr(ether_format, ':'))
-			*format_char = '-';
-	}
-	printf("\thwaddr %s\n", ether_format);
-
+	print_ether((const struct ether_addr *)&ifr.ifr_addr.sa_data, "hwaddr");
 pcp:
-	if (ioctl(s, SIOCGLANPCP, (caddr_t)&ifr) == 0 &&
-	    ifr.ifr_lan_pcp != IFNET_PCP_NONE)
-		printf("\tpcp %d\n", ifr.ifr_lan_pcp);
+	print_pcp(s);
 }
 
 static void
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index 957a8fd7fb98..15a40f1c5601 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -611,6 +611,7 @@ main(int argc, char *argv[])
 	}
 
 	args.afp = afp;
+	args.allfamilies = afp == NULL;
 	args.argc = argc;
 	args.argv = argv;
 
@@ -622,6 +623,46 @@ done:
 	exit(exit_code);
 }
 
+bool
+match_ether(const struct sockaddr_dl *sdl)
+{
+	switch (sdl->sdl_type) {
+		case IFT_ETHER:
+		case IFT_L2VLAN:
+		case IFT_BRIDGE:
+			if (sdl->sdl_alen == ETHER_ADDR_LEN)
+				return (true);
+		default:
+			return (false);
+	}
+}
+
+static bool
+match_afp(const struct afswtch *afp, int sa_family, const struct sockaddr_dl *sdl)
+{
+	if (afp == NULL)
+		return (true);
+	/* special case for "ether" address family */
+	if (!strcmp(afp->af_name, "ether")) {
+		if (sdl == NULL && !match_ether(sdl))
+			return (false);
+		return (true);
+	}
+	return (afp->af_af == sa_family);
+}
+
+static bool
+match_if_flags(struct ifconfig_args *args, int if_flags)
+{
+	if ((if_flags & IFF_CANTCONFIG) != 0)
+		return (false);
+	if (args->downonly && (if_flags & IFF_UP) != 0)
+		return (false);
+	if (args->uponly && (if_flags & IFF_UP) == 0)
+		return (false);
+	return (true);
+}
+
 static void
 list_interfaces(struct ifconfig_args *args)
 {
@@ -672,11 +713,7 @@ list_interfaces(struct ifconfig_args *args)
 		}
 		cp = ifa->ifa_name;
 
-		if ((ifa->ifa_flags & IFF_CANTCONFIG) != 0)
-			continue;
-		if (args->downonly && (ifa->ifa_flags & IFF_UP) != 0)
-			continue;
-		if (args->uponly && (ifa->ifa_flags & IFF_UP) == 0)
+		if (!match_if_flags(args, ifa->ifa_flags))
 			continue;
 		if (!group_member(ifa->ifa_name, args->matchgroup, args->nogroup))
 			continue;
@@ -686,21 +723,8 @@ list_interfaces(struct ifconfig_args *args)
 		if (args->namesonly) {
 			if (namecp == cp)
 				continue;
-			if (args->afp != NULL) {
-				/* special case for "ether" address family */
-				if (!strcmp(args->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 
-					    != args->afp->af_af)
-						continue;
-				}
-			}
+			if (!match_afp(args->afp, ifa->ifa_addr->sa_family, sdl))
+				continue;
 			namecp = cp;
 			ifindex++;
 			if (ifindex > 1)
@@ -1432,44 +1456,110 @@ unsetifdescr(const char *val, int value, int s, const struct afswtch *afp)
 "\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(struct ifconfig_args *args, const struct sockaddr_dl *sdl,
-	struct ifaddrs *ifa)
+print_ifcap_nv(struct ifconfig_args *args, int s)
 {
-	struct ifaddrs *ift;
-	struct ifstat ifs;
 	nvlist_t *nvcap;
 	const char *nvname;
 	void *buf, *cookie;
-	int allfamilies, s, type;
 	bool first, val;
+	int type;
 
-	if (args->afp == NULL) {
-		allfamilies = 1;
-		ifr.ifr_addr.sa_family = AF_LOCAL;
-	} else {
-		allfamilies = 0;
-		ifr.ifr_addr.sa_family =
-		   args->afp->af_af == AF_LINK ? AF_LOCAL : args->afp->af_af;
+	buf = malloc(IFR_CAP_NV_MAXBUFSIZE);
+	if (buf == NULL)
+		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)
+		Perror("ioctl (SIOCGIFCAPNV)");
+	nvcap = nvlist_unpack(ifr.ifr_cap_nv.buffer,
+	    ifr.ifr_cap_nv.length, 0);
+	if (nvcap == NULL)
+		Perror("nvlist_unpack");
+	printf("\toptions");
+	cookie = NULL;
+	for (first = true;; first = false) {
+		nvname = nvlist_next(nvcap, &type, &cookie);
+		if (nvname == NULL) {
+			printf("\n");
+			break;
+		}
+		if (type == NV_TYPE_BOOL) {
+			val = nvlist_get_bool(nvcap, nvname);
+			if (val) {
+				printf("%c%s",
+				    first ? ' ' : ',', nvname);
+			}
+		}
 	}
-	strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+	if (args->supmedia) {
+		printf("\tcapabilities");
+		cookie = NULL;
+		for (first = true;; first = false) {
+			nvname = nvlist_next(nvcap, &type,
+			    &cookie);
+			if (nvname == NULL) {
+				printf("\n");
+				break;
+			}
+			if (type == NV_TYPE_BOOL)
+				printf("%c%s", first ? ' ' :
+				    ',', nvname);
+		}
+	}
+	nvlist_destroy(nvcap);
+	free(buf);
 
-	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);
+	if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) != 0)
+		Perror("ioctl (SIOCGIFCAP)");
+}
 
-	printf("%s: ", name);
-	printb("flags", ifa->ifa_flags, IFFBITS);
+static void
+print_ifcap(struct ifconfig_args *args, int s)
+{
+	if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) != 0)
+		return;
+
+	if ((ifr.ifr_curcap & IFCAP_NV) != 0)
+		print_ifcap_nv(args, s);
+	else {
+		printb("\toptions", ifr.ifr_curcap, IFCAPBITS);
+		putchar('\n');
+		if (args->supmedia && ifr.ifr_reqcap != 0) {
+			printb("\tcapabilities", ifr.ifr_reqcap,
+			    IFCAPBITS);
+			putchar('\n');
+		}
+	}
+}
+
+static void
+print_ifstatus(int s)
+{
+	struct ifstat ifs;
+
+	strlcpy(ifs.ifs_name, name, sizeof ifs.ifs_name);
+	if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0)
+		printf("%s", ifs.ascii);
+}
+
+static void
+print_metric(int s)
+{
 	if (ioctl(s, SIOCGIFMETRIC, &ifr) != -1)
 		printf(" metric %d", ifr.ifr_metric);
+}
+
+static void
+print_mtu(int s)
+{
 	if (ioctl(s, SIOCGIFMTU, &ifr) != -1)
 		printf(" mtu %d", ifr.ifr_mtu);
-	putchar('\n');
+}
 
+static void
+print_description(int s)
+{
 	for (;;) {
 		if ((descr = reallocf(descr, descrlen)) != NULL) {
 			ifr.ifr_buffer.buffer = descr;
@@ -1489,66 +1579,40 @@ status(struct ifconfig_args *args, const struct sockaddr_dl *sdl,
 			    "description");
 		break;
 	}
+}
 
-	if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) {
-		if ((ifr.ifr_curcap & IFCAP_NV) != 0) {
-			buf = malloc(IFR_CAP_NV_MAXBUFSIZE);
-			if (buf == NULL)
-				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)
-				Perror("ioctl (SIOCGIFCAPNV)");
-			nvcap = nvlist_unpack(ifr.ifr_cap_nv.buffer,
-			    ifr.ifr_cap_nv.length, 0);
-			if (nvcap == NULL)
-				Perror("nvlist_unpack");
-			printf("\toptions");
-			cookie = NULL;
-			for (first = true;; first = false) {
-				nvname = nvlist_next(nvcap, &type, &cookie);
-				if (nvname == NULL) {
-					printf("\n");
-					break;
-				}
-				if (type == NV_TYPE_BOOL) {
-					val = nvlist_get_bool(nvcap, nvname);
-					if (val) {
-						printf("%c%s",
-						    first ? ' ' : ',', nvname);
-					}
-				}
-			}
-			if (args->supmedia) {
-				printf("\tcapabilities");
-				cookie = NULL;
-				for (first = true;; first = false) {
-					nvname = nvlist_next(nvcap, &type,
-					    &cookie);
-					if (nvname == NULL) {
-						printf("\n");
-						break;
-					}
-					if (type == NV_TYPE_BOOL)
-						printf("%c%s", first ? ' ' :
-						    ',', nvname);
-				}
-			}
-			nvlist_destroy(nvcap);
-			free(buf);
+/*
+ * Print the status of the interface.  If an address family was
+ * specified, show only it; otherwise, show them all.
+ */
+static void
+status(struct ifconfig_args *args, const struct sockaddr_dl *sdl,
+	struct ifaddrs *ifa)
+{
+	struct ifaddrs *ift;
+	int s;
+	bool allfamilies = args->afp == NULL;
 
-			if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) != 0)
-				Perror("ioctl (SIOCGIFCAP)");
-		} else if (ifr.ifr_curcap != 0) {
-			printb("\toptions", ifr.ifr_curcap, IFCAPBITS);
-			putchar('\n');
-			if (args->supmedia && ifr.ifr_reqcap != 0) {
-				printb("\tcapabilities", ifr.ifr_reqcap,
-				    IFCAPBITS);
-				putchar('\n');
-			}
-		}
-	}
+	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, 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);
+	print_metric(s);
+	print_mtu(s);
+	putchar('\n');
+
+	print_description(s);
+
+	print_ifcap(args, s);
 
 	tunnel_status(s);
 
@@ -1587,10 +1651,7 @@ status(struct ifconfig_args *args, const struct sockaddr_dl *sdl,
 	else if (args->afp->af_other_status != NULL)
 		args->afp->af_other_status(s);
 
-	strlcpy(ifs.ifs_name, name, sizeof ifs.ifs_name);
-	if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0) 
-		printf("%s", ifs.ascii);
-
+	print_ifstatus(s);
 	if (args->verbose > 0)
 		sfp_status(s, &ifr, args->verbose);
 
diff --git a/sbin/ifconfig/ifconfig.h b/sbin/ifconfig/ifconfig.h
index b58b577f4328..e65c26a031e6 100644
--- a/sbin/ifconfig/ifconfig.h
+++ b/sbin/ifconfig/ifconfig.h
@@ -191,6 +191,7 @@ struct ifconfig_args {
 	bool noload;		/* Do not load relevant kernel modules */
 	bool supmedia;		/* Supported media */
 	bool printkeys;		/* Print security keys */
+	bool allfamilies;	/* Print all families */
 	int verbose;		/* verbosity level */
 	int argc;
 	char **argv;
@@ -235,6 +236,8 @@ void	clone_setdefcallback_filter(clone_match_func *, clone_callback_func *);
 
 void	sfp_status(int s, struct ifreq *ifr, int verbose);
 
+struct sockaddr_dl;
+bool	match_ether(const struct sockaddr_dl *sdl);
 /*
  * XXX expose this so modules that neeed to know of any pending
  * operations on ifmedia can avoid cmd line ordering confusion.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202305151338.34FDc0oc059455>