add SIOCGIFDATA ioctl

For interfaces that do not support SIOCGIFMEDIA (for which there are
quite a few) the only fallback is to query the interface for
if_data->ifi_link_state.  While it's possible to get at if_data for an
interface via getifaddrs(3) or sysctl, both are heavy weight mechanisms.

SIOCGIFDATA is a simple ioctl to retrieve this fast with very little
resource use in comparison.  This implementation mirrors that of other
similar ioctls in FreeBSD.

Submitted by:	Roy Marples <roy@marples.name>
Reviewed by:	markj
MFC after:	1 month
Differential Revision:	https://reviews.freebsd.org/D26538
This commit is contained in:
emaste 2020-09-28 16:54:39 +00:00
parent 49f341315a
commit 61213163ca
3 changed files with 16 additions and 2 deletions

View File

@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd November 14, 2018
.Dd September 28, 2020
.Dt IFNET 9
.Os
.Sh NAME
@ -1310,12 +1310,13 @@ list.
Caller must have appropriate privilege.
(No call-down to driver.)
.It Dv SIOCGIFCAP
.It Dv SIOCGIFDATA
.It Dv SIOCGIFFIB
.It Dv SIOCGIFFLAGS
.It Dv SIOCGIFMETRIC
.It Dv SIOCGIFMTU
.It Dv SIOCGIFPHYS
Get interface capabilities, FIB, flags, metric, MTU, medium selection.
Get interface capabilities, data, FIB, flags, metric, MTU, medium selection.
(No call-down to driver.)
.Pp
.It Dv SIOCSIFCAP

View File

@ -2518,6 +2518,18 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
ifr->ifr_curcap = ifp->if_capenable;
break;
case SIOCGIFDATA:
{
struct if_data ifd;
/* Ensure uninitialised padding is not leaked. */
memset(&ifd, 0, sizeof(ifd));
if_data_copy(ifp, &ifd);
error = copyout(&ifd, ifr_data_get_ptr(ifr), sizeof(ifd));
break;
}
#ifdef MAC
case SIOCGIFMAC:
error = mac_ifnet_ioctl_get(td->td_ucred, ifr, ifp);

View File

@ -83,6 +83,7 @@
#define SIOCSIFDESCR _IOW('i', 41, struct ifreq) /* set ifnet descr */
#define SIOCGIFDESCR _IOWR('i', 42, struct ifreq) /* get ifnet descr */
#define SIOCAIFADDR _IOW('i', 43, struct ifaliasreq)/* add/chg IF alias */
#define SIOCGIFDATA _IOW('i', 44, struct ifreq) /* get if_data */
#define SIOCADDMULTI _IOW('i', 49, struct ifreq) /* add m'cast addr */
#define SIOCDELMULTI _IOW('i', 50, struct ifreq) /* del m'cast addr */