diff options
Diffstat (limited to 'sys/net/if.c')
-rw-r--r-- | sys/net/if.c | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index 288d944..ff114b7 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -723,6 +723,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 && @@ -979,6 +984,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. */ @@ -2619,6 +2626,10 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td) EVENTHANDLER_INVOKE(iflladdr_event, ifp); break; + case SIOCGHWADDR: + error = if_gethwaddr(ifp, ifr); + break; + case SIOCAIFGROUP: { struct ifgroupreq *ifgr = (struct ifgroupreq *)ifr; @@ -3557,6 +3568,29 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len) } /* + * 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 |