Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 17 May 2017 22:29:25 +0000 (UTC)
From:      Ravi Pokala <rpokala@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r318430 - in stable/10: sbin/ifconfig sys/net sys/sys
Message-ID:  <201705172229.v4HMTPHG065760@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rpokala
Date: Wed May 17 22:29:25 2017
New Revision: 318430
URL: https://svnweb.freebsd.org/changeset/base/318430

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

Modified:
  stable/10/sbin/ifconfig/af_link.c
  stable/10/sys/net/if.c
  stable/10/sys/net/if_ethersubr.c
  stable/10/sys/net/if_var.h
  stable/10/sys/sys/sockio.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sbin/ifconfig/af_link.c
==============================================================================
--- stable/10/sbin/ifconfig/af_link.c	Wed May 17 22:13:07 2017	(r318429)
+++ stable/10/sbin/ifconfig/af_link.c	Wed May 17 22:29:25 2017	(r318430)
@@ -42,6 +42,7 @@ static const char rcsid[] =
 #include <stdlib.h>
 #include <string.h>
 #include <ifaddrs.h>
+#include <unistd.h>
 
 #include <net/if_dl.h>
 #include <net/if_types.h>
@@ -69,6 +70,41 @@ link_status(int s __unused, const struct
 
 			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));
+		}
 	}
 }
 

Modified: stable/10/sys/net/if.c
==============================================================================
--- stable/10/sys/net/if.c	Wed May 17 22:13:07 2017	(r318429)
+++ stable/10/sys/net/if.c	Wed May 17 22:29:25 2017	(r318430)
@@ -732,6 +732,11 @@ if_attach_internal(struct ifnet *ifp, in
 		/* Reliably crash if used uninitialized. */
 		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)
 		/* Use defaults for TSO, if nothing is set */
 		if (ifp->if_hw_tsomax == 0 &&
@@ -988,6 +993,8 @@ if_detach_internal(struct ifnet *ifp, in
 		 * Remove link ifaddr pointer and maybe decrement if_index.
 		 * Clean up all addresses.
 		 */
+		free(ifp->if_hw_addr, M_IFADDR);
+		ifp->if_hw_addr = NULL;
 		ifp->if_addr = NULL;
 
 		/* We can now free link ifaddr. */
@@ -2639,6 +2646,10 @@ ifhwioctl(u_long cmd, struct ifnet *ifp,
 		EVENTHANDLER_INVOKE(iflladdr_event, ifp);
 		break;
 
+	case SIOCGHWADDR:
+		error = if_gethwaddr(ifp, ifr);
+		break;
+
 	case SIOCAIFGROUP:
 	{
 		struct ifgroupreq *ifgr = (struct ifgroupreq *)ifr;
@@ -3578,6 +3589,29 @@ if_setlladdr(struct ifnet *ifp, const u_
 }
 
 /*
+ * 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
  * long as the interface does.  For physical devices, the result of
  * device_get_name(dev) is a good choice and for pseudo-devices a

Modified: stable/10/sys/net/if_ethersubr.c
==============================================================================
--- stable/10/sys/net/if_ethersubr.c	Wed May 17 22:13:07 2017	(r318429)
+++ stable/10/sys/net/if_ethersubr.c	Wed May 17 22:29:25 2017	(r318430)
@@ -918,6 +918,9 @@ ether_ifattach(struct ifnet *ifp, const 
 	sdl->sdl_alen = 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);
 	if (ng_ether_attach_p != NULL)
 		(*ng_ether_attach_p)(ifp);

Modified: stable/10/sys/net/if_var.h
==============================================================================
--- stable/10/sys/net/if_var.h	Wed May 17 22:13:07 2017	(r318429)
+++ stable/10/sys/net/if_var.h	Wed May 17 22:29:25 2017	(r318430)
@@ -200,6 +200,7 @@ struct ifnet {
 		(struct ifnet *, struct vnet *, char *);
 	struct	vnet *if_home_vnet;	/* where this ifnet originates from */
 	struct	ifaddr	*if_addr;	/* pointer to link-level address */
+	void	*if_hw_addr;		/* hardware link-level address */
 	void	*if_llsoftc;		/* link layer softc */
 	int	if_drv_flags;		/* driver-managed status flags */
 	struct  ifaltq if_snd;		/* output queue (includes altq) */
@@ -973,6 +974,7 @@ void	if_qflush(struct ifnet *);
 void	if_ref(struct ifnet *);
 void	if_rele(struct ifnet *);
 int	if_setlladdr(struct ifnet *, const u_char *, int);
+int	if_gethwaddr(struct ifnet *, struct ifreq *);
 void	if_up(struct ifnet *);
 int	ifioctl(struct socket *, u_long, caddr_t, struct thread *);
 int	ifpromisc(struct ifnet *, int);

Modified: stable/10/sys/sys/sockio.h
==============================================================================
--- stable/10/sys/sys/sockio.h	Wed May 17 22:13:07 2017	(r318429)
+++ stable/10/sys/sys/sockio.h	Wed May 17 22:29:25 2017	(r318430)
@@ -97,6 +97,7 @@
 #define	SIOCGIFSTATUS	_IOWR('i', 59, struct ifstat)	/* get IF status */
 #define	SIOCSIFLLADDR	 _IOW('i', 60, struct ifreq)	/* set linklevel addr */
 #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	SIOCGIFPSRCADDR	_IOWR('i', 71, struct ifreq)	/* get gif psrc addr */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201705172229.v4HMTPHG065760>