Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src ifconfig: Report link state even if media is not supported



details:   https://anonhg.NetBSD.org/src/rev/4803c953b882
branches:  trunk
changeset: 955167:4803c953b882
user:      roy <roy%NetBSD.org@localhost>
date:      Tue Sep 22 14:14:17 2020 +0000

description:
ifconfig: Report link state even if media is not supported

For AF_LINK addrs from getifaddrs(2), ifa_data is struct if_data.
This in turn holds ifi_link_state which we can use to report
link status if the interface does not support media where it's normally
reported.

Based on OpenBSD.

diffstat:

 sbin/ifconfig/ifconfig.c |  22 +++++-----
 sbin/ifconfig/media.c    |  89 ++++++++++++++++++++++++++++++-----------------
 sbin/ifconfig/media.h    |   4 +-
 sys/net/if.h             |  27 ++++++++++++++-
 4 files changed, 96 insertions(+), 46 deletions(-)

diffs (270 lines):

diff -r 9b1d6d6258a4 -r 4803c953b882 sbin/ifconfig/ifconfig.c
--- a/sbin/ifconfig/ifconfig.c  Tue Sep 22 12:21:11 2020 +0000
+++ b/sbin/ifconfig/ifconfig.c  Tue Sep 22 14:14:17 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ifconfig.c,v 1.242 2020/06/07 06:02:58 thorpej Exp $   */
+/*     $NetBSD: ifconfig.c,v 1.243 2020/09/22 14:14:17 roy Exp $       */
 
 /*-
  * Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc.
@@ -63,7 +63,7 @@
 #ifndef lint
 __COPYRIGHT("@(#) Copyright (c) 1983, 1993\
  The Regents of the University of California.  All rights reserved.");
-__RCSID("$NetBSD: ifconfig.c,v 1.242 2020/06/07 06:02:58 thorpej Exp $");
+__RCSID("$NetBSD: ifconfig.c,v 1.243 2020/09/22 14:14:17 roy Exp $");
 #endif /* not lint */
 
 #include <sys/param.h>
@@ -135,7 +135,7 @@
 static int unsetlinkstr(prop_dictionary_t, prop_dictionary_t);
 static int setifdescr(prop_dictionary_t, prop_dictionary_t);
 static int unsetifdescr(prop_dictionary_t, prop_dictionary_t);
-static void status(const struct sockaddr *, prop_dictionary_t,
+static void status(const struct sockaddr_dl *, prop_dictionary_t,
     prop_dictionary_t);
 __dead static void usage(void);
 
@@ -851,7 +851,7 @@
 {
        struct ifaddrs *ifap, *ifa;
        struct ifreq ifr;
-       const struct sockaddr *sdl = NULL;
+       const struct sockaddr_dl *sdl = NULL;
        prop_dictionary_t env, oenv;
        int idx;
        char *p;
@@ -881,7 +881,7 @@
                if (ifname != NULL && strcmp(ifname, ifa->ifa_name) != 0)
                        continue;
                if (ifa->ifa_addr->sa_family == AF_LINK)
-                       sdl = ifa->ifa_addr;
+                       sdl = (const struct sockaddr_dl *)ifa->ifa_addr;
                if (p && strcmp(p, ifa->ifa_name) == 0)
                        continue;
                if (!prop_dictionary_set_string(env, "if", ifa->ifa_name))
@@ -1265,7 +1265,7 @@
 #define MAX_PRINT_LEN 58       /* XXX need a better way to determine this! */
 
 void
-status(const struct sockaddr *sdl, prop_dictionary_t env,
+status(const struct sockaddr_dl *sdl, prop_dictionary_t env,
     prop_dictionary_t oenv)
 {
        const struct if_data *ifi;
@@ -1360,11 +1360,6 @@
                free(p);
        }
 
-       media_status(env, oenv);
-
-       if (!vflag && !zflag)
-               goto proto_status;
-
        estrlcpy(ifdr.ifdr_name, ifname, sizeof(ifdr.ifdr_name));
 
        if (prog_ioctl(s, zflag ? SIOCZIFDATA : SIOCGIFDATA, &ifdr) == -1)
@@ -1372,6 +1367,11 @@
 
        ifi = &ifdr.ifdr_data;
 
+       media_status(sdl->sdl_type, ifi->ifi_link_state, env, oenv);
+
+       if (!vflag && !zflag)
+               goto proto_status;
+
        print_plural("\tinput: ", ifi->ifi_ipackets, "packet");
        print_human_bytes(hflag, ifi->ifi_ibytes);
        if (ifi->ifi_imcasts)
diff -r 9b1d6d6258a4 -r 4803c953b882 sbin/ifconfig/media.c
--- a/sbin/ifconfig/media.c     Tue Sep 22 12:21:11 2020 +0000
+++ b/sbin/ifconfig/media.c     Tue Sep 22 14:14:17 2020 +0000
@@ -1,6 +1,6 @@
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: media.c,v 1.9 2020/06/07 06:02:58 thorpej Exp $");
+__RCSID("$NetBSD: media.c,v 1.10 2020/09/22 14:14:17 roy Exp $");
 #endif /* not lint */
 
 #include <assert.h>
@@ -16,6 +16,7 @@
 #include <net/if.h>
 #include <net/if_dl.h>
 #include <net/if_media.h>
+#include <net/if_types.h>
 
 #include <prop/proplib.h>
 
@@ -52,6 +53,9 @@
 static const struct ifmedia_status_description ifm_status_descriptions[] =
     IFM_STATUS_DESCRIPTIONS;
 
+const struct if_status_description if_status_descriptions[] =
+       LINK_STATE_DESCRIPTIONS;
+
 static struct pstr mediamode = PSTR_INITIALIZER1(&mediamode, "mediamode",
     setmediamode, "mediamode", false, &command_root.pb_parser);
 
@@ -344,8 +348,55 @@
                printf(" instance %d", IFM_INST(ifmw));
 }
 
+static void
+print_link_status(int media_type, int link_state)
+{
+       const struct if_status_description *p;
+
+       printf("\tstatus: ");
+       for (p = if_status_descriptions; p->ifs_string != NULL; p++) {
+               if (LINK_STATE_DESC_MATCH(p, media_type, link_state)) {
+                       printf("%s\n", p->ifs_string);
+                       return;
+               }
+       }
+       printf("[#%d]\n", link_state);
+}
+
+static void
+print_media_status(int media_type, int media_status)
+{
+       const struct ifmedia_status_description *ifms;
+       int bitno, found = 0;
+
+       printf("\tstatus: ");
+       for (bitno = 0; ifm_status_valid_list[bitno] != 0; bitno++) {
+               for (ifms = ifm_status_descriptions;
+                    ifms->ifms_valid != 0; ifms++) {
+                       if (ifms->ifms_type != media_type ||
+                           ifms->ifms_valid != ifm_status_valid_list[bitno])
+                               continue;
+                       printf("%s%s", found ? ", " : "",
+                           IFM_STATUS_DESC(ifms, media_status));
+                       found = 1;
+
+                       /*
+                        * For each valid indicator bit, there's
+                        * only one entry for each media type, so
+                        * terminate the inner loop now.
+                        */
+                       break;
+               }
+       }
+
+       if (found == 0)
+               printf("unknown");
+       printf("\n");
+}
+
 void
-media_status(prop_dictionary_t env, prop_dictionary_t oenv)
+media_status(int media_type, int link_state,
+    prop_dictionary_t env, prop_dictionary_t oenv)
 {
        struct ifmediareq ifmr;
        int af, i, s;
@@ -368,6 +419,8 @@
                /*
                 * Interface doesn't support SIOC{G,S}IFMEDIA.
                 */
+               if (link_state != LINK_STATE_UNKNOWN)
+                       print_link_status(media_type, link_state);
                return;
        }
 
@@ -393,36 +446,8 @@
        } else
                media_list = NULL;
 
-       if (ifmr.ifm_status & IFM_STATUS_VALID) {
-               const struct ifmedia_status_description *ifms;
-               int bitno, found = 0;
-
-               printf("\tstatus: ");
-               for (bitno = 0; ifm_status_valid_list[bitno] != 0; bitno++) {
-                       for (ifms = ifm_status_descriptions;
-                            ifms->ifms_valid != 0; ifms++) {
-                               if (ifms->ifms_type !=
-                                     IFM_TYPE(ifmr.ifm_current) ||
-                                   ifms->ifms_valid !=
-                                     ifm_status_valid_list[bitno])
-                                       continue;
-                               printf("%s%s", found ? ", " : "",
-                                   IFM_STATUS_DESC(ifms, ifmr.ifm_status));
-                               found = 1;
-
-                               /*
-                                * For each valid indicator bit, there's
-                                * only one entry for each media type, so
-                                * terminate the inner loop now.
-                                */
-                               break;
-                       }
-               }
-
-               if (found == 0)
-                       printf("unknown");
-               printf("\n");
-       }
+       if (ifmr.ifm_status & IFM_STATUS_VALID)
+               print_media_status(IFM_TYPE(ifmr.ifm_current), ifmr.ifm_status);
 
        if (get_flag('m')) {
                int type, printed_type;
diff -r 9b1d6d6258a4 -r 4803c953b882 sbin/ifconfig/media.h
--- a/sbin/ifconfig/media.h     Tue Sep 22 12:21:11 2020 +0000
+++ b/sbin/ifconfig/media.h     Tue Sep 22 14:14:17 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: media.h,v 1.1 2008/07/02 07:44:15 dyoung Exp $ */
+/*     $NetBSD: media.h,v 1.2 2020/09/22 14:14:17 roy Exp $    */
 
 #ifndef        _IFCONFIG_MEDIA_H
 #define        _IFCONFIG_MEDIA_H
@@ -11,6 +11,6 @@
 
 void   print_media_word(int, const char *);
 void   process_media_commands(prop_dictionary_t);
-void   media_status(prop_dictionary_t, prop_dictionary_t);
+void   media_status(int, int, prop_dictionary_t, prop_dictionary_t);
 
 #endif /* _IFCONFIG_MEDIA_H */
diff -r 9b1d6d6258a4 -r 4803c953b882 sys/net/if.h
--- a/sys/net/if.h      Tue Sep 22 12:21:11 2020 +0000
+++ b/sys/net/if.h      Tue Sep 22 14:14:17 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if.h,v 1.284 2020/08/28 06:23:42 ozaki-r Exp $ */
+/*     $NetBSD: if.h,v 1.285 2020/09/22 14:14:17 roy Exp $     */
 
 /*-
  * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -208,6 +208,31 @@
 #define        LINK_STATE_UP           2       /* link is up */
 
 /*
+ * Status bit descriptions for the various interface types.
+ */
+struct if_status_description {
+       unsigned char   ifs_type;
+       unsigned char   ifs_state;
+       const char      *ifs_string;
+};
+
+#define LINK_STATE_DESC_MATCH(_ifs, _t, _s)                            \
+       (((_ifs)->ifs_type == (_t) || (_ifs)->ifs_type == 0) &&         \
+           (_ifs)->ifs_state == (_s))
+
+#define LINK_STATE_DESCRIPTIONS {                                      \
+       { IFT_ETHER, LINK_STATE_DOWN, "no carrier" },                   \
+       { IFT_IEEE80211, LINK_STATE_DOWN, "no network" },               \
+       { IFT_PPP, LINK_STATE_DOWN, "no carrier" },                     \
+       { IFT_CARP, LINK_STATE_DOWN, "backup" },                        \
+       { IFT_CARP, LINK_STATE_UP, "master" },                          \
+       { 0, LINK_STATE_UP, "active" },                                 \
+       { 0, LINK_STATE_UNKNOWN, "unknown" },                           \
+       { 0, LINK_STATE_DOWN, "down" },                                 \
+       { 0, 0, NULL }                                                  \
+}
+
+/*
  * Structure defining a queue for a network interface.
  */
 struct ifqueue {



Home | Main Index | Thread Index | Old Index