summaryrefslogtreecommitdiffstats
path: root/sys/net/if.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-06-24 10:36:48 +0000
committerrwatson <rwatson@FreeBSD.org>2009-06-24 10:36:48 +0000
commitd5bc5239c3664794a0e4b2683aece3f495495e69 (patch)
tree4da2b4cee74b1df01748e8e28218a50441dc660d /sys/net/if.c
parent4bbf479ced91674e3eea5636ffc8e776fa1d741c (diff)
downloadFreeBSD-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.c18
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
OpenPOWER on IntegriCloud