From d97064d770b5fe7f4ea2dc4cd031e829b1a1a0e3 Mon Sep 17 00:00:00 2001 From: rpokala Date: Wed, 17 May 2017 22:29:25 +0000 Subject: 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 (cherry picked from commit 2ce46e31d62424593e08c3853efe8c1e9283aba2) --- sbin/ifconfig/af_link.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'sbin') diff --git a/sbin/ifconfig/af_link.c b/sbin/ifconfig/af_link.c index 4a4b661..d3e8896 100644 --- a/sbin/ifconfig/af_link.c +++ b/sbin/ifconfig/af_link.c @@ -42,6 +42,7 @@ static const char rcsid[] = #include #include #include +#include #include #include @@ -69,6 +70,41 @@ link_status(int s __unused, const struct ifaddrs *ifa) 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)); + } } } -- cgit v1.1