summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2010-02-26 00:54:47 +0000
committerdelphij <delphij@FreeBSD.org>2010-02-26 00:54:47 +0000
commit2c255a85f1a94490d53a0d50a11a7292322fdebb (patch)
tree8c253d3e96cef0c433208d7c21a093ea7c8e1ccd
parentd6816492901c7ee5e4aeda381c2493e6d40b3d8d (diff)
downloadFreeBSD-src-2c255a85f1a94490d53a0d50a11a7292322fdebb.zip
FreeBSD-src-2c255a85f1a94490d53a0d50a11a7292322fdebb.tar.gz
MFC 203052:
Add interface description capability as inspired by OpenBSD. Thanks for rwatson@, jhb@, brooks@ and others for feedback to the old implementation! Sponsored by: iXsystems, Inc.
-rw-r--r--contrib/libpcap/inet.c16
-rw-r--r--sbin/ifconfig/ifconfig.812
-rw-r--r--sbin/ifconfig/ifconfig.c60
-rw-r--r--share/man/man4/netintro.438
-rw-r--r--sys/kern/kern_jail.c1
-rw-r--r--sys/net/if.c70
-rw-r--r--sys/net/if.h10
-rw-r--r--sys/net/if_var.h3
-rw-r--r--sys/sys/param.h2
-rw-r--r--sys/sys/priv.h1
-rw-r--r--sys/sys/sockio.h2
11 files changed, 207 insertions, 8 deletions
diff --git a/contrib/libpcap/inet.c b/contrib/libpcap/inet.c
index aad8796..5f081a6 100644
--- a/contrib/libpcap/inet.c
+++ b/contrib/libpcap/inet.c
@@ -401,10 +401,15 @@ add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
pcap_if_t *curdev;
char *description = NULL;
pcap_addr_t *curaddr, *prevaddr, *nextaddr;
+ int s;
#ifdef SIOCGIFDESCR
struct ifreq ifrdesc;
+#ifndef IFDESCRSIZE
+#define _IFDESCRSIZE 64
+ char ifdescr[_IFDESCRSIZE];
+#else
char ifdescr[IFDESCRSIZE];
- int s;
+#endif
#endif
#ifdef SIOCGIFDESCR
@@ -413,12 +418,17 @@ add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
*/
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
diff --git a/sbin/ifconfig/ifconfig.8 b/sbin/ifconfig/ifconfig.8
index c372a08..32e8fa3 100644
--- a/sbin/ifconfig/ifconfig.8
+++ b/sbin/ifconfig/ifconfig.8
@@ -28,7 +28,7 @@
.\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94
.\" $FreeBSD$
.\"
-.Dd December 7, 2009
+.Dd January 26, 2010
.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 , Cm descr 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 , Cm -descr
+Clear the interface description.
.It Cm down
Mark an interface
.Dq down .
@@ -2493,6 +2499,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
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index f05374c..ec5e403 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -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,40 @@ setifname(const char *val, int dummy __unused, int s,
free(newname);
}
+/* ARGSUSED */
+static void
+setifdescr(const char *val, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ char *newdescr;
+
+ ifr.ifr_buffer.length = strlen(val) + 1;
+ if (ifr.ifr_buffer.length == 1) {
+ ifr.ifr_buffer.buffer = newdescr = NULL;
+ ifr.ifr_buffer.length = 0;
+ } else {
+ newdescr = strdup(val);
+ ifr.ifr_buffer.buffer = newdescr;
+ if (newdescr == NULL) {
+ warn("no memory to set ifdescr");
+ return;
+ }
+ }
+
+ 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 +901,25 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
printf(" mtu %d", ifr.ifr_mtu);
putchar('\n');
+ for (;;) {
+ if ((descr = reallocf(descr, descrlen)) != NULL) {
+ 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;
+ } else if (errno == ENAMETOOLONG)
+ descrlen = ifr.ifr_buffer.length;
+ else
+ break;
+ } else {
+ warn("unable to allocate memory for interface"
+ "description");
+ break;
+ }
+ };
+
if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) {
if (ifr.ifr_curcap != 0) {
printb("\toptions", ifr.ifr_curcap, IFCAPBITS);
@@ -1035,6 +1089,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),
diff --git a/share/man/man4/netintro.4 b/share/man/man4/netintro.4
index f5d479b..348a13e 100644
--- a/share/man/man4/netintro.4
+++ b/share/man/man4/netintro.4
@@ -32,7 +32,7 @@
.\" @(#)netintro.4 8.2 (Berkeley) 11/30/93
.\" $FreeBSD$
.\"
-.Dd June 18, 2004
+.Dd January 26, 2010
.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 ifreq_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,33 @@ 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 be defined in the
+.Va length
+field of
+.Va ifru_buffer
+struct passed in as parameter, and the length would include
+the terminating nul character.
+If there is not enough space to hold the interface length,
+no copy would be done and an
+error would be returned.
+The kernel will store the buffer length in the
+.Va length
+field upon return, regardless whether the buffer itself is
+sufficient to hold the data.
+.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 (counting the terminating nul).
.It Dv SIOCSIFFLAGS
Set interface flags field.
If the interface is marked down,
@@ -404,6 +433,13 @@ struct if_clonereq {
char *ifcr_buffer; /* buffer for cloner names */
};
.Ed
+.Bd -literal
+/* Structure used in SIOCGIFDESCR and SIOCSIFDESCR requests */
+struct ifreq_buffer {
+ size_t length; /* length of the buffer */
+ void *buffer; /* pointer to userland space buffer */
+};
+.Ed
.Sh SEE ALSO
.Xr ioctl 2 ,
.Xr socket 2 ,
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index 7dcf479..f10522e 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -3592,6 +3592,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:
diff --git a/sys/net/if.c b/sys/net/if.c
index 1724061..64135ac 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -108,6 +108,18 @@ SYSCTL_INT(_net_link, OID_AUTO, log_link_state_change, CTLFLAG_RW,
&log_link_state_change, 0,
"log interface link state change events");
+/* Interface description */
+static unsigned int ifdescr_maxlen = 1024;
+SYSCTL_UINT(_net, OID_AUTO, ifdescr_maxlen, CTLFLAG_RW,
+ &ifdescr_maxlen, 0,
+ "administrative maximum length for interface description");
+
+MALLOC_DEFINE(M_IFDESCR, "ifdescr", "ifnet descriptions");
+
+/* global sx for non-critical path ifdescr */
+static struct sx ifdescr_sx;
+SX_SYSINIT(ifdescr_sx, &ifdescr_sx, "ifnet descr");
+
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 +475,8 @@ if_free_internal(struct ifnet *ifp)
#ifdef MAC
mac_ifnet_destroy(ifp);
#endif /* MAC */
+ if (ifp->if_description != NULL)
+ free(ifp->if_description, M_IFDESCR);
IF_AFDATA_DESTROY(ifp);
IF_ADDR_LOCK_DESTROY(ifp);
ifq_delete(&ifp->if_snd);
@@ -2045,6 +2059,8 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
int error = 0;
int new_flags, temp_flags;
size_t namelen, onamelen;
+ size_t descrlen;
+ char *descrbuf, *odescrbuf;
char new_name[IFNAMSIZ];
struct ifaddr *ifa;
struct sockaddr_dl *sdl;
@@ -2084,6 +2100,60 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
ifr->ifr_phys = ifp->if_physical;
break;
+ case SIOCGIFDESCR:
+ error = 0;
+ sx_slock(&ifdescr_sx);
+ if (ifp->if_description == NULL) {
+ ifr->ifr_buffer.length = 0;
+ error = ENOMSG;
+ } else {
+ /* space for terminating nul */
+ descrlen = strlen(ifp->if_description) + 1;
+ if (ifr->ifr_buffer.length < descrlen)
+ error = ENAMETOOLONG;
+ else
+ error = copyout(ifp->if_description,
+ ifr->ifr_buffer.buffer, descrlen);
+ ifr->ifr_buffer.length = descrlen;
+ }
+ sx_sunlock(&ifdescr_sx);
+ break;
+
+ case SIOCSIFDESCR:
+ error = priv_check(td, PRIV_NET_SETIFDESCR);
+ if (error)
+ return (error);
+
+ /*
+ * Copy only (length-1) bytes to make sure that
+ * if_description is always nul terminated. The
+ * length parameter is supposed to count the
+ * terminating nul in.
+ */
+ if (ifr->ifr_buffer.length > ifdescr_maxlen)
+ return (ENAMETOOLONG);
+ else if (ifr->ifr_buffer.length == 0)
+ descrbuf = NULL;
+ else {
+ descrbuf = malloc(ifr->ifr_buffer.length, M_IFDESCR,
+ M_WAITOK | M_ZERO);
+ error = copyin(ifr->ifr_buffer.buffer, descrbuf,
+ ifr->ifr_buffer.length - 1);
+ if (error) {
+ free(descrbuf, M_IFDESCR);
+ break;
+ }
+ }
+
+ sx_xlock(&ifdescr_sx);
+ odescrbuf = ifp->if_description;
+ ifp->if_description = descrbuf;
+ sx_xunlock(&ifdescr_sx);
+
+ getmicrotime(&ifp->if_lastchange);
+ free(odescrbuf, M_IFDESCR);
+ break;
+
case SIOCSIFFLAGS:
error = priv_check(td, PRIV_NET_SETIFFLAGS);
if (error)
diff --git a/sys/net/if.h b/sys/net/if.h
index f94b54a..aff0d76 100644
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -284,6 +284,14 @@ struct if_announcemsghdr {
#define IFAN_DEPARTURE 1 /* interface departure */
/*
+ * Buffer with length to be used in SIOCGIFDESCR/SIOCSIFDESCR requests
+ */
+struct ifreq_buffer {
+ size_t length;
+ void *buffer;
+};
+
+/*
* Interface request structure used for socket
* ioctl's. All interface ioctl's must have parameter
* definitions which begin with ifr_name. The
@@ -295,6 +303,7 @@ struct ifreq {
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
+ struct ifreq_buffer ifru_buffer;
short ifru_flags[2];
short ifru_index;
int ifru_jid;
@@ -308,6 +317,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 */
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index eac7dbf..5f9064b 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -205,7 +205,8 @@ struct ifnet {
* be used with care where binary compatibility is required.
*/
char if_cspare[3];
- void *if_pspare[8];
+ char *if_description; /* interface description */
+ void *if_pspare[7];
int if_ispare[4];
};
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 2776d06..6da5e60 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 800502 /* Master, propagated to newvers */
+#define __FreeBSD_version 800503 /* Master, propagated to newvers */
#ifndef LOCORE
#include <sys/types.h>
diff --git a/sys/sys/priv.h b/sys/sys/priv.h
index c8ccfa6..5738fca 100644
--- a/sys/sys/priv.h
+++ b/sys/sys/priv.h
@@ -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.
diff --git a/sys/sys/sockio.h b/sys/sys/sockio.h
index a5911b7..2af2467 100644
--- a/sys/sys/sockio.h
+++ b/sys/sys/sockio.h
@@ -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 */
OpenPOWER on IntegriCloud