diff options
author | rwatson <rwatson@FreeBSD.org> | 2009-06-24 10:36:48 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2009-06-24 10:36:48 +0000 |
commit | d5bc5239c3664794a0e4b2683aece3f495495e69 (patch) | |
tree | 4da2b4cee74b1df01748e8e28218a50441dc660d /sys/net/if.c | |
parent | 4bbf479ced91674e3eea5636ffc8e776fa1d741c (diff) | |
download | FreeBSD-src-d5bc5239c3664794a0e4b2683aece3f495495e69.zip FreeBSD-src-d5bc5239c3664794a0e4b2683aece3f495495e69.tar.gz |
In if_setlladdr(), use IF_ADDR_LOCK() and ifaddr references to improve
the safety of link layer address manipulation.
MFC after: 6 weeks
Diffstat (limited to 'sys/net/if.c')
-rw-r--r-- | sys/net/if.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index 46a2ca7..58ab679 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -3145,14 +3145,23 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len) struct ifaddr *ifa; struct ifreq ifr; + IF_ADDR_LOCK(ifp); ifa = ifp->if_addr; - if (ifa == NULL) + if (ifa == NULL) { + IF_ADDR_UNLOCK(ifp); return (EINVAL); + } + ifa_ref(ifa); + IF_ADDR_UNLOCK(ifp); sdl = (struct sockaddr_dl *)ifa->ifa_addr; - if (sdl == NULL) + if (sdl == NULL) { + ifa_free(ifa); return (EINVAL); - if (len != sdl->sdl_alen) /* don't allow length to change */ + } + if (len != sdl->sdl_alen) { /* don't allow length to change */ + ifa_free(ifa); return (EINVAL); + } switch (ifp->if_type) { case IFT_ETHER: case IFT_FDDI: @@ -3164,10 +3173,13 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len) case IFT_IEEE8023ADLAG: case IFT_IEEE80211: bcopy(lladdr, LLADDR(sdl), len); + ifa_free(ifa); break; default: + ifa_free(ifa); return (ENODEV); } + /* * If the interface is already up, we need * to re-init it in order to reprogram its |