Module Name:    src
Committed By:   roy
Date:           Tue Sep 22 14:14:17 UTC 2020

Modified Files:
        src/sbin/ifconfig: ifconfig.c media.c media.h
        src/sys/net: if.h

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.242 -r1.243 src/sbin/ifconfig/ifconfig.c
cvs rdiff -u -r1.9 -r1.10 src/sbin/ifconfig/media.c
cvs rdiff -u -r1.1 -r1.2 src/sbin/ifconfig/media.h
cvs rdiff -u -r1.284 -r1.285 src/sys/net/if.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sbin/ifconfig/ifconfig.c
diff -u src/sbin/ifconfig/ifconfig.c:1.242 src/sbin/ifconfig/ifconfig.c:1.243
--- src/sbin/ifconfig/ifconfig.c:1.242	Sun Jun  7 06:02:58 2020
+++ src/sbin/ifconfig/ifconfig.c	Tue Sep 22 14:14:17 2020
@@ -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 setlinkstr(prop_dictionary_t,
 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 @@ printall(const char *ifname, prop_dictio
 {
 	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 @@ printall(const char *ifname, prop_dictio
 		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 @@ print_human_bytes(bool humanize, uint64_
 #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 @@ status(const struct sockaddr *sdl, prop_
 		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 @@ status(const struct sockaddr *sdl, prop_
 
 	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)

Index: src/sbin/ifconfig/media.c
diff -u src/sbin/ifconfig/media.c:1.9 src/sbin/ifconfig/media.c:1.10
--- src/sbin/ifconfig/media.c:1.9	Sun Jun  7 06:02:58 2020
+++ src/sbin/ifconfig/media.c	Tue Sep 22 14:14:17 2020
@@ -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 @@ __RCSID("$NetBSD: media.c,v 1.9 2020/06/
 #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 int ifm_status_valid_list[]
 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 @@ print_media_word(int ifmw, const char *o
 		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 @@ media_status(prop_dictionary_t env, prop
 		/*
 		 * 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 @@ media_status(prop_dictionary_t env, prop
 	} 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;

Index: src/sbin/ifconfig/media.h
diff -u src/sbin/ifconfig/media.h:1.1 src/sbin/ifconfig/media.h:1.2
--- src/sbin/ifconfig/media.h:1.1	Wed Jul  2 07:44:15 2008
+++ src/sbin/ifconfig/media.h	Tue Sep 22 14:14:17 2020
@@ -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 @@ extern struct pkw kwmedia;
 
 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 */

Index: src/sys/net/if.h
diff -u src/sys/net/if.h:1.284 src/sys/net/if.h:1.285
--- src/sys/net/if.h:1.284	Fri Aug 28 06:23:42 2020
+++ src/sys/net/if.h	Tue Sep 22 14:14:17 2020
@@ -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 @@ struct if_data {
 #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 {

Reply via email to