The branch main has been updated by melifaro:

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

commit d1cd0344f7b7d81beda04c3cb8cfee99351c3eb8
Author:     Alexander V. Chernikov <melif...@freebsd.org>
AuthorDate: 2023-05-15 12:17:54 +0000
Commit:     Alexander V. Chernikov <melif...@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.

Reply via email to