Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 17 Nov 2009 18:39:23 -0800
From:      Xin LI <delphij@gmail.com>
To:        freebsd-net@FreeBSD.org
Cc:        rwatson@freebsd.org, jhb@FreeBSD.org, "M. Warner Losh" <imp@bsdimp.com>, Antoine Brodin <antoine.brodin@laposte.net>
Subject:   [PATCH FOR REVIEW] interface description (revised)
Message-ID:  <a78074950911171839u3e3fb4f1oae4aa3fc79f1b152@mail.gmail.com>

next in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
Hi,

Here is the revised implementation for the interface description
feature, based on feedback from src-all@.

Some limitations:
 * Not yet able to send announce through route socket.  I need to
figure out a proper way to do this, maybe a future feature;
 * 32-bit vs 64-bit API compatibility.  Since the kernel has to copy
in a string, is there a clean way to do this?  I think we will also
need to deal with similar issue with SIOCSIFNAME as well.

Cheers,
-- 
Xin LI <delphij@delphij.net> http://www.delphij.net

[-- Attachment #2 --]
Index: contrib/libpcap/inet.c
===================================================================
--- contrib/libpcap/inet.c	(revision 199463)
+++ contrib/libpcap/inet.c	(working copy)
@@ -403,22 +403,30 @@ add_addr_to_iflist(pcap_if_t **alldevs, const char
 	pcap_addr_t *curaddr, *prevaddr, *nextaddr;
 #ifdef SIOCGIFDESCR
 	struct ifreq ifrdesc;
+#ifndef IFDESCRSIZE
+#define _IFDESCRSIZE 64
+	char ifdescr[_IFDESCRSIZE];
+#else
 	char ifdescr[IFDESCRSIZE];
+#endif
 	int s;
-#endif
 
-#ifdef SIOCGIFDESCR
 	/*
 	 * Get the description for the interface.
 	 */
 	memset(&ifrdesc, 0, sizeof ifrdesc);
 	strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
+#ifdef __FreeBSD__
+	ifrdesc.ifr_buffer.buffer = ifdescr;
+	ifrdesc.ifr_buffer.length = sizeof(ifdescr);
+#else
 	ifrdesc.ifr_data = (caddr_t)&ifdescr;
+#endif
 	s = socket(AF_INET, SOCK_DGRAM, 0);
 	if (s >= 0) {
 		if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0 &&
-		    strlen(ifrdesc.ifr_data) != 0)
-			description = ifrdesc.ifr_data;
+		    strlen(ifdescr) != 0)
+			description = ifdescr;
 		close(s);
 	}
 #endif
Index: sbin/ifconfig/ifconfig.8
===================================================================
--- sbin/ifconfig/ifconfig.8	(revision 199463)
+++ sbin/ifconfig/ifconfig.8	(working copy)
@@ -28,7 +28,7 @@
 .\"     From: @(#)ifconfig.8	8.3 (Berkeley) 1/5/94
 .\" $FreeBSD$
 .\"
-.Dd September 23, 2009
+.Dd November 26, 2009
 .Dt IFCONFIG 8
 .Os
 .Sh NAME
@@ -258,6 +258,12 @@ Disable permanently promiscuous mode.
 Another name for the
 .Fl alias
 parameter.
+.It Cm description Ar value
+Specify a description of the interface.
+This can be used to label interfaces in situations where they may
+otherwise be difficult to distinguish.
+.It Cm -description
+Clear the interface description.
 .It Cm down
 Mark an interface
 .Dq down .
@@ -2512,6 +2518,10 @@ Configure the interface
 to use 100baseTX, full duplex Ethernet media options:
 .Dl # ifconfig xl0 media 100baseTX mediaopt full-duplex
 .Pp
+Label the em0 interface as an uplink:
+.Pp
+.Dl # ifconfig em0 description \&"Uplink to Gigabit Switch 2\&"
+.Pp
 Create the software network interface
 .Li gif1 :
 .Dl # ifconfig gif1 create
Index: sbin/ifconfig/ifconfig.c
===================================================================
--- sbin/ifconfig/ifconfig.c	(revision 199463)
+++ sbin/ifconfig/ifconfig.c	(working copy)
@@ -44,7 +44,6 @@ static const char rcsid[] =
 #include <sys/param.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
-#include <sys/sysctl.h>
 #include <sys/time.h>
 #include <sys/module.h>
 #include <sys/linker.h>
@@ -83,6 +82,8 @@ static const char rcsid[] =
 struct	ifreq ifr;
 
 char	name[IFNAMSIZ];
+char	*descr = NULL;
+size_t	descrlen = 64;
 int	setaddr;
 int	setmask;
 int	doalias;
@@ -822,6 +823,35 @@ setifname(const char *val, int dummy __unused, int
 	free(newname);
 }
 
+/* ARGSUSED */
+static void
+setifdescr(const char *val, int dummy __unused, int s, 
+    const struct afswtch *afp)
+{
+	char *newdescr;
+
+	newdescr = strdup(val);
+	if (newdescr == NULL) {
+		warn("no memory to set ifdescr");
+		return;
+	}
+
+	ifr.ifr_buffer.buffer = newdescr;
+	ifr.ifr_buffer.length = strlen(newdescr) + 1;
+	if (ioctl(s, SIOCSIFDESCR, (caddr_t)&ifr) < 0)
+		warn("ioctl (set descr)");
+
+	free(newdescr);
+}
+
+/* ARGSUSED */
+static void
+unsetifdescr(const char *val, int value, int s, const struct afswtch *afp)
+{
+
+	setifdescr("", 0, s, 0);
+}
+
 #define	IFFBITS \
 "\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \
 "\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
@@ -866,6 +896,23 @@ status(const struct afswtch *afp, const struct soc
 		printf(" mtu %d", ifr.ifr_mtu);
 	putchar('\n');
 
+	descr = reallocf(descr, descrlen);
+	if (descr != NULL) {
+		do {
+			ifr.ifr_buffer.buffer = descr;
+			ifr.ifr_buffer.length = descrlen;
+			if (ioctl(s, SIOCGIFDESCR, &ifr) == 0) {
+			    if (strlen(descr) > 0)
+				printf("\tdescription: %s\n", descr);
+			    break;
+			}
+			if (errno == ENAMETOOLONG) {
+				descrlen *= 2;
+				descr = reallocf(descr, descrlen);
+			}
+		} while ((errno == ENAMETOOLONG) && (descr != NULL));
+	}
+
 	if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) {
 		if (ifr.ifr_curcap != 0) {
 			printb("\toptions", ifr.ifr_curcap, IFCAPBITS);
@@ -1035,6 +1082,10 @@ static struct cmd basic_cmds[] = {
 	DEF_CMD("-arp",		IFF_NOARP,	setifflags),
 	DEF_CMD("debug",	IFF_DEBUG,	setifflags),
 	DEF_CMD("-debug",	-IFF_DEBUG,	setifflags),
+	DEF_CMD_ARG("description",		setifdescr),
+	DEF_CMD_ARG("descr",			setifdescr),
+	DEF_CMD("-description",	0,		unsetifdescr),
+	DEF_CMD("-descr",	0,		unsetifdescr),
 	DEF_CMD("promisc",	IFF_PPROMISC,	setifflags),
 	DEF_CMD("-promisc",	-IFF_PPROMISC,	setifflags),
 	DEF_CMD("add",		IFF_UP,		notealias),
Index: share/man/man4/netintro.4
===================================================================
--- share/man/man4/netintro.4	(revision 199463)
+++ share/man/man4/netintro.4	(working copy)
@@ -32,7 +32,7 @@
 .\"     @(#)netintro.4	8.2 (Berkeley) 11/30/93
 .\" $FreeBSD$
 .\"
-.Dd June 18, 2004
+.Dd November 26, 2009
 .Dt NETINTRO 4
 .Os
 .Sh NAME
@@ -204,6 +204,7 @@ struct	ifreq {
         struct    sockaddr ifru_addr;
         struct    sockaddr ifru_dstaddr;
         struct    sockaddr ifru_broadaddr;
+        struct { size_t length; caddr_t buffer; } ifru_buffer;
         short     ifru_flags[2];
         short     ifru_index;
         int       ifru_metric;
@@ -216,6 +217,7 @@ struct	ifreq {
 #define ifr_addr      ifr_ifru.ifru_addr      /* address */
 #define ifr_dstaddr   ifr_ifru.ifru_dstaddr   /* other end of p-to-p link */
 #define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
+#define ifr_buffer    ifr_ifru.ifru_buffer    /* user supplied buffer with its length */
 #define ifr_flags     ifr_ifru.ifru_flags[0]  /* flags (low 16 bits) */
 #define ifr_flagshigh ifr_ifru.ifru_flags[1]  /* flags (high 16 bits) */
 #define ifr_metric    ifr_ifru.ifru_metric    /* metric */
@@ -277,6 +279,25 @@ and
 fields of the
 .Vt ifreq
 structure, respectively.
+.It Dv SIOCGIFDESCR
+Get the interface description, returned in the
+.Va buffer
+field of
+.Va ifru_buffer
+struct.
+The user supplied buffer length should defined in the
+.Va length
+field of
+.Va ifru_buffer
+struct passed in as parameter.
+.It Dv SIOCSIFDESCR
+Set the interface description to the value of the
+.Va buffer
+field of
+.Va ifru_buffer
+struct, with
+.Va length
+field specifying its length.
 .It Dv SIOCSIFFLAGS
 Set interface flags field.
 If the interface is marked down,
Index: share/man/man4/netintro.4
===================================================================
--- share/man/man4/netintro.4	(revision 199463)
+++ share/man/man4/netintro.4	(working copy)
@@ -32,7 +32,7 @@
 .\"     @(#)netintro.4	8.2 (Berkeley) 11/30/93
 .\" $FreeBSD$
 .\"
-.Dd June 18, 2004
+.Dd November 26, 2009
 .Dt NETINTRO 4
 .Os
 .Sh NAME
@@ -204,6 +204,7 @@ struct	ifreq {
         struct    sockaddr ifru_addr;
         struct    sockaddr ifru_dstaddr;
         struct    sockaddr ifru_broadaddr;
+        struct { size_t length; caddr_t buffer; } ifru_buffer;
         short     ifru_flags[2];
         short     ifru_index;
         int       ifru_metric;
@@ -216,6 +217,7 @@ struct	ifreq {
 #define ifr_addr      ifr_ifru.ifru_addr      /* address */
 #define ifr_dstaddr   ifr_ifru.ifru_dstaddr   /* other end of p-to-p link */
 #define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
+#define ifr_buffer    ifr_ifru.ifru_buffer    /* user supplied buffer with its length */
 #define ifr_flags     ifr_ifru.ifru_flags[0]  /* flags (low 16 bits) */
 #define ifr_flagshigh ifr_ifru.ifru_flags[1]  /* flags (high 16 bits) */
 #define ifr_metric    ifr_ifru.ifru_metric    /* metric */
@@ -277,6 +279,25 @@ and
 fields of the
 .Vt ifreq
 structure, respectively.
+.It Dv SIOCGIFDESCR
+Get the interface description, returned in the
+.Va buffer
+field of
+.Va ifru_buffer
+struct.
+The user supplied buffer length should defined in the
+.Va length
+field of
+.Va ifru_buffer
+struct passed in as parameter.
+.It Dv SIOCSIFDESCR
+Set the interface description to the value of the
+.Va buffer
+field of
+.Va ifru_buffer
+struct, with
+.Va length
+field specifying its length.
 .It Dv SIOCSIFFLAGS
 Set interface flags field.
 If the interface is marked down,
Index: sys/kern/kern_jail.c
===================================================================
--- sys/kern/kern_jail.c	(revision 199463)
+++ sys/kern/kern_jail.c	(working copy)
@@ -3467,6 +3467,7 @@ prison_priv_check(struct ucred *cred, int priv)
 	case PRIV_NET_SETIFMTU:
 	case PRIV_NET_SETIFFLAGS:
 	case PRIV_NET_SETIFCAP:
+	case PRIV_NET_SETIFDESCR:
 	case PRIV_NET_SETIFNAME	:
 	case PRIV_NET_SETIFMETRIC:
 	case PRIV_NET_SETIFPHYS:
Index: sys/net/if.c
===================================================================
--- sys/net/if.c	(revision 199463)
+++ sys/net/if.c	(working copy)
@@ -108,6 +108,13 @@ SYSCTL_INT(_net_link, OID_AUTO, log_link_state_cha
 	&log_link_state_change, 0,
 	"log interface link state change events");
 
+/* Interface description */
+static int ifdescr_maxlen = 1024;
+
+SYSCTL_INT(_net, OID_AUTO, ifdescr_maxlen, CTLFLAG_RW,
+	&ifdescr_maxlen, 0,
+	"administrative maximum length for interface description");
+
 void	(*bstp_linkstate_p)(struct ifnet *ifp, int state);
 void	(*ng_ether_link_state_p)(struct ifnet *ifp, int state);
 void	(*lagg_linkstate_p)(struct ifnet *ifp, int state);
@@ -463,6 +470,8 @@ if_free_internal(struct ifnet *ifp)
 #ifdef MAC
 	mac_ifnet_destroy(ifp);
 #endif /* MAC */
+	if (ifp->if_description != NULL)
+		sbuf_delete(ifp->if_description);
 	IF_AFDATA_DESTROY(ifp);
 	IF_ADDR_LOCK_DESTROY(ifp);
 	ifq_delete(&ifp->if_snd);
@@ -2054,6 +2063,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t d
 	char new_name[IFNAMSIZ];
 	struct ifaddr *ifa;
 	struct sockaddr_dl *sdl;
+	struct sbuf *old, *new;
 
 	ifr = (struct ifreq *)data;
 	switch (cmd) {
@@ -2090,6 +2100,74 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t d
 		ifr->ifr_phys = ifp->if_physical;
 		break;
 
+	case SIOCGIFDESCR:
+		error = 0;
+		if (ifr->ifr_buffer.length > ifdescr_maxlen) {
+			error = ENOMEM;
+			break;
+		}
+		new = sbuf_new(NULL, NULL, ifr->ifr_buffer.length, SBUF_FIXEDLEN);
+		if (new == NULL) {
+			error = ENOMEM;
+			break;
+		}
+
+		IF_AFDATA_RLOCK(ifp);
+		if (ifp->if_description == NULL)
+			error = ENOMSG;
+		else {
+			if (ifr->ifr_buffer.length <= sbuf_len(ifp->if_description))
+				error = ENAMETOOLONG;
+			if (sbuf_cpy(new, sbuf_data(ifp->if_description)) != 0)
+				error = ENAMETOOLONG;
+		}
+		IF_AFDATA_RUNLOCK(ifp);
+
+		if (error == 0) {
+			sbuf_finish(new);
+			/*
+			 * Copy 1 more byte to make sure that the copyout is NUL
+			 * terminated.
+			 */
+			error = copyout(sbuf_data(new), ifr->ifr_buffer.buffer,
+					sbuf_len(new) + 1);
+		}
+
+		sbuf_delete(new);
+
+		break;
+
+	case SIOCSIFDESCR:
+		error = priv_check(td, PRIV_NET_SETIFDESCR);
+		if (error)
+			return (error);
+
+		if (ifr->ifr_buffer.length > ifdescr_maxlen)
+			return (ENAMETOOLONG);
+
+		new = sbuf_new(NULL, NULL, ifr->ifr_buffer.length, SBUF_FIXEDLEN);
+		if (new == NULL)
+			return (ENOMEM);
+
+		if (sbuf_copyin(new, ifr->ifr_buffer.buffer,
+				ifr->ifr_buffer.length) == -1) {
+			sbuf_delete(new);
+			return (EFAULT);
+		}
+
+		sbuf_finish(new);
+
+		IF_AFDATA_WLOCK(ifp);
+		old = ifp->if_description;
+		ifp->if_description = new;
+		getmicrotime(&ifp->if_lastchange);
+		IF_AFDATA_WUNLOCK(ifp);
+
+		if (old != NULL)
+			sbuf_delete(old);
+
+		break;
+
 	case SIOCSIFFLAGS:
 		error = priv_check(td, PRIV_NET_SETIFFLAGS);
 		if (error)
Index: sys/net/if.h
===================================================================
--- sys/net/if.h	(revision 199463)
+++ sys/net/if.h	(working copy)
@@ -294,6 +294,7 @@ struct	ifreq {
 		struct	sockaddr ifru_addr;
 		struct	sockaddr ifru_dstaddr;
 		struct	sockaddr ifru_broadaddr;
+		struct { size_t length; caddr_t	buffer; } ifru_buffer;
 		short	ifru_flags[2];
 		short	ifru_index;
 		int	ifru_jid;
@@ -307,6 +308,7 @@ struct	ifreq {
 #define	ifr_addr	ifr_ifru.ifru_addr	/* address */
 #define	ifr_dstaddr	ifr_ifru.ifru_dstaddr	/* other end of p-to-p link */
 #define	ifr_broadaddr	ifr_ifru.ifru_broadaddr	/* broadcast address */
+#define	ifr_buffer	ifr_ifru.ifru_buffer	/* user supplied buffer with its length */
 #define	ifr_flags	ifr_ifru.ifru_flags[0]	/* flags (low 16 bits) */
 #define	ifr_flagshigh	ifr_ifru.ifru_flags[1]	/* flags (high 16 bits) */
 #define	ifr_jid		ifr_ifru.ifru_jid	/* jail/vnet */
Index: sys/net/if_var.h
===================================================================
--- sys/net/if_var.h	(revision 199463)
+++ sys/net/if_var.h	(working copy)
@@ -205,7 +205,8 @@ struct ifnet {
 	 * be used with care where binary compatibility is required.
 	 */
 	char	 if_cspare[3];
-	void	*if_pspare[8];
+	void	*if_pspare[7];
+	struct sbuf *if_description;	/* interface description */
 	int	if_ispare[4];
 };
 
Index: sys/sys/priv.h
===================================================================
--- sys/sys/priv.h	(revision 199463)
+++ sys/sys/priv.h	(working copy)
@@ -335,6 +335,7 @@
 #define	PRIV_NET_LAGG		415	/* Administer lagg interface. */
 #define	PRIV_NET_GIF		416	/* Administer gif interface. */
 #define	PRIV_NET_SETIFVNET	417	/* Move interface to vnet. */
+#define	PRIV_NET_SETIFDESCR	418	/* Set interface description. */
 
 /*
  * 802.11-related privileges.
Index: sys/sys/sockio.h
===================================================================
--- sys/sys/sockio.h	(revision 199463)
+++ sys/sys/sockio.h	(working copy)
@@ -82,6 +82,8 @@
 #define	SIOCGIFMAC	_IOWR('i', 38, struct ifreq)	/* get IF MAC label */
 #define	SIOCSIFMAC	 _IOW('i', 39, struct ifreq)	/* set IF MAC label */
 #define	SIOCSIFNAME	 _IOW('i', 40, struct ifreq)	/* set IF name */
+#define	SIOCSIFDESCR	 _IOW('i', 41, struct ifreq)	/* set ifnet descr */ 
+#define	SIOCGIFDESCR	_IOWR('i', 42, struct ifreq)	/* get ifnet descr */ 
 
 #define	SIOCADDMULTI	 _IOW('i', 49, struct ifreq)	/* add m'cast addr */
 #define	SIOCDELMULTI	 _IOW('i', 50, struct ifreq)	/* del m'cast addr */

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?a78074950911171839u3e3fb4f1oae4aa3fc79f1b152>