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
This commit is contained in:
parent
0393e22f73
commit
7c2aa74437
@ -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 ifaddrs *ifa)
|
||||
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;
|
||||
|
@ -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 ifaddrs *ifa)
|
||||
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 ifaddrs *ifa)
|
||||
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 ifaddrs *ifa)
|
||||
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 ifaddrs *ifa)
|
||||
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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 ifaddrs *b, struct ifa_queue *q)
|
||||
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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user