svn commit: r301059 - head/sbin/ifconfig

Allan Jude allanjude at FreeBSD.org
Tue May 31 17:30:09 UTC 2016


Author: allanjude
Date: Tue May 31 17:30:08 2016
New Revision: 301059
URL: https://svnweb.freebsd.org/changeset/base/301059

Log:
  ifconfig(8) now supports some output formatting options
  
  specified by the -f flag or IFCONFIG_FORMAT environment variable, the user
  can request that inet4 subnet masks be printed in CIDR or dotted-quad
  notation, in addition to the traditional hex output.
  inet6 prefixes can be printed in CIDR as well.
  
  For more documentation see the ifconfig(8) man page.
  
  PR:		169072
  Requested by:	seanc, marcel, brd, many others
  Reviewed by:	gnn, jhb (earlier version)
  Relnotes:	yes
  Sponsored by:	ScaleEngine Inc.
  Differential Revision:	https://reviews.freebsd.org/D2856

Modified:
  head/sbin/ifconfig/af_inet.c
  head/sbin/ifconfig/af_inet6.c
  head/sbin/ifconfig/af_link.c
  head/sbin/ifconfig/ifconfig.8
  head/sbin/ifconfig/ifconfig.c

Modified: head/sbin/ifconfig/af_inet.c
==============================================================================
--- head/sbin/ifconfig/af_inet.c	Tue May 31 17:23:27 2016	(r301058)
+++ head/sbin/ifconfig/af_inet.c	Tue May 31 17:30:08 2016	(r301059)
@@ -54,11 +54,14 @@ static const char rcsid[] =
 
 static struct in_aliasreq in_addreq;
 static struct ifreq in_ridreq;
+static char addr_buf[MAXHOSTNAMELEN *2 + 1];	/*for getnameinfo()*/
+extern char *f_inet, *f_addr;
 
 static void
 in_status(int s __unused, const struct ifaddrs *ifa)
 {
 	struct sockaddr_in *sin, null_sin;
+	int error, n_flags;
 	
 	memset(&null_sin, 0, sizeof(null_sin));
 
@@ -66,19 +69,47 @@ in_status(int s __unused, const struct i
 	if (sin == NULL)
 		return;
 
-	printf("\tinet %s ", inet_ntoa(sin->sin_addr));
+	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->sin_len, addr_buf,
+			    sizeof(addr_buf), NULL, 0, n_flags);
+
+	if (error)
+		inet_ntop(AF_INET, &sin->sin_addr, addr_buf, sizeof(addr_buf));
+	
+	printf("\tinet %s", addr_buf);
 
 	if (ifa->ifa_flags & IFF_POINTOPOINT) {
 		sin = (struct sockaddr_in *)ifa->ifa_dstaddr;
 		if (sin == NULL)
 			sin = &null_sin;
-		printf("--> %s ", inet_ntoa(sin->sin_addr));
+		printf(" --> %s ", inet_ntoa(sin->sin_addr));
 	}
 
 	sin = (struct sockaddr_in *)ifa->ifa_netmask;
 	if (sin == NULL)
 		sin = &null_sin;
-	printf("netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr));
+	if (f_inet != NULL && strcmp(f_inet, "cidr") == 0) {
+		int cidr = 32;
+		unsigned long smask;
+
+		smask = ntohl(sin->sin_addr.s_addr);
+		while ((smask & 1) == 0) {
+			smask = smask >> 1;
+			cidr--;
+			if (cidr == 0)
+				break;
+		}
+		printf("/%d ", cidr);
+	} else if (f_inet != NULL && strcmp(f_inet, "dotted") == 0)
+		printf(" netmask %s ", inet_ntoa(sin->sin_addr));
+	else
+		printf(" netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr));
 
 	if (ifa->ifa_flags & IFF_BROADCAST) {
 		sin = (struct sockaddr_in *)ifa->ifa_broadaddr;

Modified: head/sbin/ifconfig/af_inet6.c
==============================================================================
--- head/sbin/ifconfig/af_inet6.c	Tue May 31 17:23:27 2016	(r301058)
+++ head/sbin/ifconfig/af_inet6.c	Tue May 31 17:30:08 2016	(r301059)
@@ -65,6 +65,7 @@ static	int ip6lifetime;
 static	int prefix(void *, int);
 static	char *sec2str(time_t);
 static	int explicit_prefix = 0;
+extern	char *f_inet6, *f_addr, *f_scope;
 
 extern void setnd6flags(const char *, int, int, const struct afswtch *);
 extern void setnd6defif(const char *, int, int, const struct afswtch *);
@@ -172,9 +173,10 @@ in6_status(int s __unused, const struct 
 	struct in6_ifreq ifr6;
 	int s6;
 	u_int32_t flags6;
+	const u_int16_t *a;
 	struct in6_addrlifetime lifetime;
 	struct timespec now;
-	int error;
+	int error, n_flags, i;
 
 	clock_gettime(CLOCK_MONOTONIC_FAST, &now);
 
@@ -206,12 +208,30 @@ in6_status(int s __unused, const struct 
 	lifetime = ifr6.ifr_ifru.ifru_lifetime;
 	close(s6);
 
-	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("\tinet6 %s ", addr_buf);
+	if (f_addr != NULL && strcmp(f_addr, "full") == 0) {
+		a = (const u_int16_t *)&sin->sin6_addr;
+		printf("\tinet6 ");
+		for (i = 0; i < 8; i++) {
+			printf("%04hx", ntohs(*(a + i)));
+			if (i < 7)
+				printf(":");
+		}
+	} else {
+		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 ||
+		    (f_scope != NULL && strcmp(f_scope, "none") == 0))
+			inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf,
+				  sizeof(addr_buf));
+		printf("\tinet6 %s", addr_buf);
+	}
 
 	if (ifa->ifa_flags & IFF_POINTOPOINT) {
 		sin = (struct sockaddr_in6 *)ifa->ifa_dstaddr;
@@ -229,15 +249,19 @@ in6_status(int s __unused, const struct 
 			if (error != 0)
 				inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf,
 					  sizeof(addr_buf));
-			printf("--> %s ", addr_buf);
+			printf(" --> %s ", addr_buf);
 		}
 	}
 
 	sin = (struct sockaddr_in6 *)ifa->ifa_netmask;
 	if (sin == NULL)
 		sin = &null_sin;
-	printf("prefixlen %d ", prefix(&sin->sin6_addr,
-		sizeof(struct in6_addr)));
+	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)));
 
 	if ((flags6 & IN6_IFF_ANYCAST) != 0)
 		printf("anycast ");
@@ -256,7 +280,8 @@ in6_status(int s __unused, const struct 
 	if ((flags6 & IN6_IFF_PREFER_SOURCE) != 0)
 		printf("prefer_source ");
 
-	if (((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_scope_id)
+	if ((f_scope == NULL || strcmp(f_scope, "none") != 0) &&
+	    ((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_scope_id)
 		printf("scopeid 0x%x ",
 		    ((struct sockaddr_in6 *)(ifa->ifa_addr))->sin6_scope_id);
 

Modified: head/sbin/ifconfig/af_link.c
==============================================================================
--- head/sbin/ifconfig/af_link.c	Tue May 31 17:23:27 2016	(r301058)
+++ head/sbin/ifconfig/af_link.c	Tue May 31 17:30:08 2016	(r301059)
@@ -51,19 +51,31 @@ static const char rcsid[] =
 
 static struct ifreq link_ridreq;
 
+extern char *f_ether;
+
 static void
 link_status(int s __unused, const struct ifaddrs *ifa)
 {
 	/* XXX no const 'cuz LLADDR is defined wrong */
 	struct sockaddr_dl *sdl = (struct sockaddr_dl *) ifa->ifa_addr;
+	char *ether_format;
+	int i;
 
 	if (sdl != NULL && sdl->sdl_alen > 0) {
 		if ((sdl->sdl_type == IFT_ETHER ||
 		    sdl->sdl_type == IFT_L2VLAN ||
 		    sdl->sdl_type == IFT_BRIDGE) &&
 		    sdl->sdl_alen == ETHER_ADDR_LEN)
-			printf("\tether %s\n",
-			    ether_ntoa((struct ether_addr *)LLADDR(sdl)));
+			if (f_ether != NULL && strcmp(f_ether, "dash") == 0) {
+				ether_format = ether_ntoa((struct ether_addr *)LLADDR(sdl));
+				for (i = 0; i < strlen(ether_format); i++) {
+					if (ether_format[i] == ':')
+						ether_format[i] = '-';
+				}
+				printf("\tether %s\n", ether_format);
+			} else
+				printf("\tether %s\n",
+				    ether_ntoa((struct ether_addr *)LLADDR(sdl)));
 		else {
 			int n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0;
 

Modified: head/sbin/ifconfig/ifconfig.8
==============================================================================
--- head/sbin/ifconfig/ifconfig.8	Tue May 31 17:23:27 2016	(r301058)
+++ head/sbin/ifconfig/ifconfig.8	Tue May 31 17:30:08 2016	(r301059)
@@ -28,7 +28,7 @@
 .\"     From: @(#)ifconfig.8	8.3 (Berkeley) 1/5/94
 .\" $FreeBSD$
 .\"
-.Dd November 6, 2015
+.Dd May 29, 2016
 .Dt IFCONFIG 8
 .Os
 .Sh NAME
@@ -36,6 +36,7 @@
 .Nd configure network interface parameters
 .Sh SYNOPSIS
 .Nm
+.Op Fl f Ar type:format Ns Op Ar ,type:format
 .Op Fl L
 .Op Fl k
 .Op Fl m
@@ -194,6 +195,102 @@ for example,
 List the interfaces in the given group.
 .El
 .Pp
+The output format of
+.Nm
+can be controlled using the
+.Fl f
+flag or the
+.Ev IFCONFIG_FORMAT
+environment variable.
+The format is specified as a comma separated list of
+.Sy type:format
+pairs.
+See the
+.Sx EXAMPLES
+section for more information.
+The
+.Sy types
+and their associated
+.Sy format
+strings are:
+.Bl -tag -width scope
+.It Sy addr
+Adjust the display of inet and inet6 addresses
+.Bl -tag -width default
+.It Sy default
+Display inet and inet6 addresses in the default format,
+.Sy numeric
+.It Sy fqdn
+Display inet and inet6 addresses as fully qualified domain names
+.Pq FQDN
+.It Sy full
+Display inet6 addresses without suppressing zeroes.
+Only applicable to inet6
+.It Sy host
+Display inet and inet6 addresses as unqualified hostnames
+.It Sy numeric
+Display inet and inet6 addresses in numeric format
+.El
+.It Sy ether
+Adjust the display of link-level ethernet (MAC) addresses
+.Bl -tag -width default
+.It Sy colon
+Separate address segments with a colon
+.It Sy dash
+Separate address segments with a dash
+.It Sy default
+Display ethernet addresses in the default format,
+.Sy colon
+.El
+.It Sy inet
+Adjust the display of inet address subnet masks:
+.Bl -tag -width default
+.It Sy cidr
+Display subnet masks in CIDR notation, for example:
+.br
+10.0.0.0/8 or 203.0.113.224/26
+.It Sy default
+Display subnet masks in the default format,
+.Sy hex
+.It Sy dotted
+Display subnet masks in dotted quad notation, for example:
+.br
+255.255.0.0 or 255.255.255.192
+.It Sy hex
+Display subnet masks in hexidecimal, for example:
+.br
+0xffff0000 or 0xffffffc0
+.El
+.It Sy inet6
+Adjust the display of inet6 address prefixes (subnet masks):
+.Bl -tag -width default
+.It Sy cidr
+Display subnet prefix in CIDR notation, for example:
+.br
+::1/128 or fe80::1%lo0/64
+.It Sy default
+Display subnet prefix in the default format
+.Sy numeric
+.It Sy numeric
+Display subnet prefix in integer format, for example:
+.br
+prefixlen 64
+.El
+.It Sy scope
+Controls the display of the interface scope as part of the address.
+Only applicable to inet6 addresses.
+.Bl -tag -width default
+.It Sy default
+The interface scope and scopeid are included in the address, for example:
+.br
+inet6 fe80::1%lo0 prefixlen 64 scopeid 0x7
+.It Sy none
+The interface scope and scopeid are not displayed, for example:
+.br
+inet6 fe80::1 prefixlen 64
+.El
+.El
+.Pp
 The following parameters may be set with
 .Nm :
 .Bl -tag -width indent
@@ -2855,6 +2952,9 @@ Destroy the software network interface
 Display available wireless networks using
 .Li wlan0 :
 .Dl # ifconfig wlan0 list scan
+.Pp
+Display inet and inet6 address subnet masks in CIDR notation
+.Dl # ifconfig -f inet:cidr,inet6:cidr
 .Sh DIAGNOSTICS
 Messages indicating the specified interface does not exist, the
 requested address is unknown, or the user is not privileged and

Modified: head/sbin/ifconfig/ifconfig.c
==============================================================================
--- head/sbin/ifconfig/ifconfig.c	Tue May 31 17:23:27 2016	(r301058)
+++ head/sbin/ifconfig/ifconfig.c	Tue May 31 17:30:08 2016	(r301059)
@@ -98,6 +98,9 @@ int	printifname = 0;
 int	supmedia = 0;
 int	printkeys = 0;		/* Print keying material for interfaces. */
 
+/* Formatter Strings */
+char	*f_inet, *f_inet6, *f_ether, *f_addr, *f_scope;
+
 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,
@@ -143,8 +146,8 @@ usage(void)
 	}
 
 	fprintf(stderr,
-	"usage: ifconfig %sinterface address_family [address [dest_address]]\n"
-	"                [parameters]\n"
+	"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"
@@ -243,6 +246,52 @@ cmpifaddrs(struct ifaddrs *a, struct ifa
 	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);
+	if (f_scope != NULL)
+		free(f_scope);
+}
+
+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);
+		else if (strcmp(category, "scope") == 0)
+			f_scope = strdup(modifier);
+	}
+	free(formatstr);
+}
+
 #undef ORDERS_SIZE
 
 static struct ifaddrs *
@@ -315,7 +364,7 @@ main(int argc, char *argv[])
 	struct ifaddrs *ifap, *sifap, *ifa;
 	struct ifreq paifr;
 	const struct sockaddr_dl *sdl;
-	char options[1024], *cp, *namecp = NULL;
+	char options[1024], *cp, *envformat, *namecp = NULL;
 	struct ifa_queue q = TAILQ_HEAD_INITIALIZER(q);
 	struct ifa_order_elt *cur, *tmp;
 	const char *ifname;
@@ -323,7 +372,12 @@ main(int argc, char *argv[])
 	size_t iflen;
 
 	all = downonly = uponly = namesonly = noload = verbose = 0;
-	
+	f_inet = f_inet6 = f_ether = f_addr = f_scope = NULL;
+
+	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.
@@ -331,7 +385,7 @@ main(int argc, char *argv[])
 	atexit(printifnamemaybe);
 
 	/* Parse leading line options */
-	strlcpy(options, "adklmnuv", sizeof(options));
+	strlcpy(options, "f:adklmnuv", sizeof(options));
 	for (p = opts; p != NULL; p = p->next)
 		strlcat(options, p->opt, sizeof(options));
 	while ((c = getopt(argc, argv, options)) != -1) {
@@ -342,6 +396,11 @@ main(int argc, char *argv[])
 		case 'd':	/* restrict scan to "down" interfaces */
 			downonly++;
 			break;
+		case 'f':
+			if (optarg == NULL)
+				usage();
+			setformat(optarg);
+			break;
 		case 'k':
 			printkeys++;
 			break;
@@ -539,6 +598,7 @@ main(int argc, char *argv[])
 		printf("\n");
 	freeifaddrs(ifap);
 
+	freeformat();
 	exit(0);
 }
 


More information about the svn-src-head mailing list