mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-12-03 14:48:57 +00:00
MFC r318160, 318176: Persistently store NIC's hardware MAC address, and add
a way to retrive it NOTE: Due to restructuring, the merges didn't apply cleanly; the resulting change is almost identical to what went into stable/11, but in some cases in different locations. The MAC address reported by `ifconfig ${nic} ether' does not always match the address in the hardware, as reported by the driver during attach. In particular, NICs which are components of a lagg(4) interface all report the same MAC. When attaching, the NIC driver passes the MAC address it read from the hardware as an argument to ether_ifattach(). Keep a second copy of it, and create ioctl(SIOCGHWADDR) to return it. Teach `ifconfig' to report it along with the active MAC address. PR: 194386
This commit is contained in:
parent
ba5c57c9ba
commit
c7f17f47e7
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/stable/10/; revision=318430
@ -42,6 +42,7 @@ static const char rcsid[] =
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <net/if_dl.h>
|
#include <net/if_dl.h>
|
||||||
#include <net/if_types.h>
|
#include <net/if_types.h>
|
||||||
@ -69,6 +70,41 @@ link_status(int s __unused, const struct ifaddrs *ifa)
|
|||||||
|
|
||||||
printf("\tlladdr %s\n", link_ntoa(sdl) + n);
|
printf("\tlladdr %s\n", link_ntoa(sdl) + n);
|
||||||
}
|
}
|
||||||
|
/* Best-effort (i.e. failures are silent) to get original
|
||||||
|
* hardware address, as read by NIC driver at attach time. Only
|
||||||
|
* applies to Ethernet NICs (IFT_ETHER). However, laggX
|
||||||
|
* interfaces claim to be IFT_ETHER, and re-type their component
|
||||||
|
* Ethernet NICs as IFT_IEEE8023ADLAG. So, check for both. If
|
||||||
|
* the MAC is zeroed, then it's actually a lagg.
|
||||||
|
*/
|
||||||
|
if ((sdl->sdl_type == IFT_ETHER ||
|
||||||
|
sdl->sdl_type == IFT_IEEE8023ADLAG) &&
|
||||||
|
sdl->sdl_alen == ETHER_ADDR_LEN) {
|
||||||
|
struct ifreq ifr;
|
||||||
|
int sock_hw;
|
||||||
|
int rc;
|
||||||
|
static const u_char laggaddr[6] = {0};
|
||||||
|
|
||||||
|
strncpy(ifr.ifr_name, ifa->ifa_name,
|
||||||
|
sizeof(ifr.ifr_name));
|
||||||
|
memcpy(&ifr.ifr_addr, ifa->ifa_addr,
|
||||||
|
sizeof(ifa->ifa_addr->sa_len));
|
||||||
|
ifr.ifr_addr.sa_family = AF_LOCAL;
|
||||||
|
if ((sock_hw = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0) {
|
||||||
|
warn("socket(AF_LOCAL,SOCK_DGRAM)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rc = ioctl(sock_hw, SIOCGHWADDR, &ifr);
|
||||||
|
close(sock_hw);
|
||||||
|
if (rc != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (memcmp(ifr.ifr_addr.sa_data, laggaddr, sdl->sdl_alen) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("\thwaddr %s\n", ether_ntoa((const struct ether_addr *)
|
||||||
|
&ifr.ifr_addr.sa_data));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
34
sys/net/if.c
34
sys/net/if.c
@ -732,6 +732,11 @@ if_attach_internal(struct ifnet *ifp, int vmove, struct if_clone *ifc)
|
|||||||
/* Reliably crash if used uninitialized. */
|
/* Reliably crash if used uninitialized. */
|
||||||
ifp->if_broadcastaddr = NULL;
|
ifp->if_broadcastaddr = NULL;
|
||||||
|
|
||||||
|
if (ifp->if_type == IFT_ETHER) {
|
||||||
|
ifp->if_hw_addr = malloc(ifp->if_addrlen, M_IFADDR,
|
||||||
|
M_WAITOK | M_ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(INET) || defined(INET6)
|
#if defined(INET) || defined(INET6)
|
||||||
/* Use defaults for TSO, if nothing is set */
|
/* Use defaults for TSO, if nothing is set */
|
||||||
if (ifp->if_hw_tsomax == 0 &&
|
if (ifp->if_hw_tsomax == 0 &&
|
||||||
@ -988,6 +993,8 @@ if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp)
|
|||||||
* Remove link ifaddr pointer and maybe decrement if_index.
|
* Remove link ifaddr pointer and maybe decrement if_index.
|
||||||
* Clean up all addresses.
|
* Clean up all addresses.
|
||||||
*/
|
*/
|
||||||
|
free(ifp->if_hw_addr, M_IFADDR);
|
||||||
|
ifp->if_hw_addr = NULL;
|
||||||
ifp->if_addr = NULL;
|
ifp->if_addr = NULL;
|
||||||
|
|
||||||
/* We can now free link ifaddr. */
|
/* We can now free link ifaddr. */
|
||||||
@ -2639,6 +2646,10 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
|
|||||||
EVENTHANDLER_INVOKE(iflladdr_event, ifp);
|
EVENTHANDLER_INVOKE(iflladdr_event, ifp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SIOCGHWADDR:
|
||||||
|
error = if_gethwaddr(ifp, ifr);
|
||||||
|
break;
|
||||||
|
|
||||||
case SIOCAIFGROUP:
|
case SIOCAIFGROUP:
|
||||||
{
|
{
|
||||||
struct ifgroupreq *ifgr = (struct ifgroupreq *)ifr;
|
struct ifgroupreq *ifgr = (struct ifgroupreq *)ifr;
|
||||||
@ -3577,6 +3588,29 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the link layer address that was read from the hardware at attach.
|
||||||
|
*
|
||||||
|
* This is only set by Ethernet NICs (IFT_ETHER), but laggX interfaces re-type
|
||||||
|
* their component interfaces as IFT_IEEE8023ADLAG.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
if_gethwaddr(struct ifnet *ifp, struct ifreq *ifr)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (ifp->if_hw_addr == NULL)
|
||||||
|
return (ENODEV);
|
||||||
|
|
||||||
|
switch (ifp->if_type) {
|
||||||
|
case IFT_ETHER:
|
||||||
|
case IFT_IEEE8023ADLAG:
|
||||||
|
bcopy(ifp->if_hw_addr, ifr->ifr_addr.sa_data, ifp->if_addrlen);
|
||||||
|
return (0);
|
||||||
|
default:
|
||||||
|
return (ENODEV);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The name argument must be a pointer to storage which will last as
|
* The name argument must be a pointer to storage which will last as
|
||||||
* long as the interface does. For physical devices, the result of
|
* long as the interface does. For physical devices, the result of
|
||||||
|
@ -918,6 +918,9 @@ ether_ifattach(struct ifnet *ifp, const u_int8_t *lla)
|
|||||||
sdl->sdl_alen = ifp->if_addrlen;
|
sdl->sdl_alen = ifp->if_addrlen;
|
||||||
bcopy(lla, LLADDR(sdl), ifp->if_addrlen);
|
bcopy(lla, LLADDR(sdl), ifp->if_addrlen);
|
||||||
|
|
||||||
|
if (ifp->if_hw_addr != NULL)
|
||||||
|
bcopy(lla, ifp->if_hw_addr, ifp->if_addrlen);
|
||||||
|
|
||||||
bpfattach(ifp, DLT_EN10MB, ETHER_HDR_LEN);
|
bpfattach(ifp, DLT_EN10MB, ETHER_HDR_LEN);
|
||||||
if (ng_ether_attach_p != NULL)
|
if (ng_ether_attach_p != NULL)
|
||||||
(*ng_ether_attach_p)(ifp);
|
(*ng_ether_attach_p)(ifp);
|
||||||
|
@ -200,6 +200,7 @@ struct ifnet {
|
|||||||
(struct ifnet *, struct vnet *, char *);
|
(struct ifnet *, struct vnet *, char *);
|
||||||
struct vnet *if_home_vnet; /* where this ifnet originates from */
|
struct vnet *if_home_vnet; /* where this ifnet originates from */
|
||||||
struct ifaddr *if_addr; /* pointer to link-level address */
|
struct ifaddr *if_addr; /* pointer to link-level address */
|
||||||
|
void *if_hw_addr; /* hardware link-level address */
|
||||||
void *if_llsoftc; /* link layer softc */
|
void *if_llsoftc; /* link layer softc */
|
||||||
int if_drv_flags; /* driver-managed status flags */
|
int if_drv_flags; /* driver-managed status flags */
|
||||||
struct ifaltq if_snd; /* output queue (includes altq) */
|
struct ifaltq if_snd; /* output queue (includes altq) */
|
||||||
@ -973,6 +974,7 @@ void if_qflush(struct ifnet *);
|
|||||||
void if_ref(struct ifnet *);
|
void if_ref(struct ifnet *);
|
||||||
void if_rele(struct ifnet *);
|
void if_rele(struct ifnet *);
|
||||||
int if_setlladdr(struct ifnet *, const u_char *, int);
|
int if_setlladdr(struct ifnet *, const u_char *, int);
|
||||||
|
int if_gethwaddr(struct ifnet *, struct ifreq *);
|
||||||
void if_up(struct ifnet *);
|
void if_up(struct ifnet *);
|
||||||
int ifioctl(struct socket *, u_long, caddr_t, struct thread *);
|
int ifioctl(struct socket *, u_long, caddr_t, struct thread *);
|
||||||
int ifpromisc(struct ifnet *, int);
|
int ifpromisc(struct ifnet *, int);
|
||||||
|
@ -97,6 +97,7 @@
|
|||||||
#define SIOCGIFSTATUS _IOWR('i', 59, struct ifstat) /* get IF status */
|
#define SIOCGIFSTATUS _IOWR('i', 59, struct ifstat) /* get IF status */
|
||||||
#define SIOCSIFLLADDR _IOW('i', 60, struct ifreq) /* set linklevel addr */
|
#define SIOCSIFLLADDR _IOW('i', 60, struct ifreq) /* set linklevel addr */
|
||||||
#define SIOCGI2C _IOWR('i', 61, struct ifreq) /* get I2C data */
|
#define SIOCGI2C _IOWR('i', 61, struct ifreq) /* get I2C data */
|
||||||
|
#define SIOCGHWADDR _IOWR('i', 62, struct ifreq) /* get hardware lladdr */
|
||||||
|
|
||||||
#define SIOCSIFPHYADDR _IOW('i', 70, struct ifaliasreq) /* set gif address */
|
#define SIOCSIFPHYADDR _IOW('i', 70, struct ifaliasreq) /* set gif address */
|
||||||
#define SIOCGIFPSRCADDR _IOWR('i', 71, struct ifreq) /* get gif psrc addr */
|
#define SIOCGIFPSRCADDR _IOWR('i', 71, struct ifreq) /* get gif psrc addr */
|
||||||
|
Loading…
Reference in New Issue
Block a user