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
This commit is contained in:
Alexander V. Chernikov 2023-05-15 12:17:54 +00:00
parent d91f8db5f1
commit d1cd0344f7
5 changed files with 304 additions and 210 deletions

View File

@ -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;

View File

@ -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");
struct timespec now;
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");
clock_gettime(CLOCK_MONOTONIC_FAST, &now);
print_lifetime("pltime", lifetime.ia6t_preferred, &now);
print_lifetime("vltime", lifetime.ia6t_expire, &now);
}
print_vhid(ifa, " ");

View File

@ -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

View File

@ -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 @@ main(int argc, char *argv[])
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);

View File

@ -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.