aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorRavi Pokala <rpokala@FreeBSD.org>2017-05-10 22:13:47 +0000
committerRavi Pokala <rpokala@FreeBSD.org>2017-05-10 22:13:47 +0000
commitddae57504b797d05f42b01bb763deef9ec0217e8 (patch)
tree43c4f72759acfc3bf5c5c7e2166bc6fae50be60f /sys
parent1a356b8b9053a30a4b3cd52f88118d1558ada754 (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/net/if.c34
-rw-r--r--sys/net/if_ethersubr.c2
-rw-r--r--sys/net/if_var.h2
-rw-r--r--sys/sys/sockio.h1
4 files changed, 39 insertions, 0 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index a7e60eb35e312..3e018a61f28d3 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -744,6 +744,11 @@ if_attach_internal(struct ifnet *ifp, int vmove, struct if_clone *ifc)
/* 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 &&
@@ -1059,6 +1064,8 @@ if_detach_internal(struct ifnet *ifp, int vmove, struct if_clone **ifcp)
* 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. */
@@ -2667,6 +2674,10 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
ifr->ifr_addr.sa_data, ifr->ifr_addr.sa_len);
break;
+ case SIOCGHWADDR:
+ error = if_gethwaddr(ifp, ifr);
+ break;
+
case SIOCAIFGROUP:
{
struct ifgroupreq *ifgr = (struct ifgroupreq *)ifr;
@@ -3584,6 +3595,29 @@ if_requestencap_default(struct ifnet *ifp, struct if_encap_req *req)
}
/*
+ * 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
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index 7956fcfa28ed0..738406be86cf3 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -916,6 +916,8 @@ ether_ifattach(struct ifnet *ifp, const u_int8_t *lla)
sdl->sdl_alen = ifp->if_addrlen;
bcopy(lla, LLADDR(sdl), ifp->if_addrlen);
+ 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);
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index e5d5c76045859..d4d2ddceeff1b 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -281,6 +281,7 @@ struct ifnet {
struct ifmultihead if_multiaddrs; /* multicast addresses configured */
int if_amcount; /* number of all-multicast requests */
struct ifaddr *if_addr; /* pointer to link-level address */
+ void *if_hw_addr; /* hardware link-level address */
const u_int8_t *if_broadcastaddr; /* linklevel broadcast bytestring */
struct rwlock if_afdata_lock;
void *if_afdata[AF_MAX];
@@ -650,6 +651,7 @@ int if_gethwassist(if_t ifp);
int if_setsoftc(if_t ifp, void *softc);
void *if_getsoftc(if_t ifp);
int if_setflags(if_t ifp, int flags);
+int if_gethwaddr(if_t ifp, struct ifreq *);
int if_setmtu(if_t ifp, int mtu);
int if_getmtu(if_t ifp);
int if_getmtu_family(if_t ifp, int family);
diff --git a/sys/sys/sockio.h b/sys/sys/sockio.h
index 5a3b482af17af..193560f64df7f 100644
--- a/sys/sys/sockio.h
+++ b/sys/sys/sockio.h
@@ -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 */