Revised revision 199201 (add interface description capability as inspired

by OpenBSD), based on comments from many, including rwatson, jhb, brooks
and others.

Sponsored by:	iXsystems, Inc.
MFC after:	1 month
This commit is contained in:
Xin LI 2010-01-27 00:30:07 +00:00
parent ac95ee294c
commit 215940b3fa
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=203052
11 changed files with 207 additions and 8 deletions

View File

@ -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

View File

@ -28,7 +28,7 @@
.\" From: @(#)ifconfig.8 8.3 (Berkeley) 1/5/94
.\" $FreeBSD$
.\"
.Dd September 23, 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 .
@ -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

View File

@ -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;
@ -838,6 +839,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" \
@ -882,6 +917,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);
@ -1051,6 +1105,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),

View File

@ -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 ,

View File

@ -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:

View File

@ -106,6 +106,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);
@ -442,6 +454,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);
@ -1979,6 +1993,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;
@ -2018,6 +2034,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)

View File

@ -283,6 +283,14 @@ struct if_announcemsghdr {
#define IFAN_ARRIVAL 0 /* interface arrival */
#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
@ -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 */

View File

@ -203,7 +203,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];
};

View File

@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
#define __FreeBSD_version 900008 /* Master, propagated to newvers */
#define __FreeBSD_version 900009 /* Master, propagated to newvers */
#ifndef LOCORE
#include <sys/types.h>

View File

@ -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.

View File

@ -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 */