summaryrefslogtreecommitdiff
path: root/sys/netinet/if_ether.c
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2015-09-28 08:26:59 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2015-09-28 08:26:59 +0000
commitcb20c46da86ff642b22b381154155f93025fc342 (patch)
treefdd09ec6752dd0c1f1a089c2e504b9b32807a7f6 /sys/netinet/if_ether.c
parentb68a1556a462a0c6b1b161a09f7e0474c9cdcf6e (diff)
Do not manually decrement rt's refcounter in arplookup() and let the
callers rtfree(9) it. ok bluhm@
Diffstat (limited to 'sys/netinet/if_ether.c')
-rw-r--r--sys/netinet/if_ether.c60
1 files changed, 35 insertions, 25 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index cca016dbb90..9edbda2f4e8 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ether.c,v 1.169 2015/09/16 06:58:08 claudio Exp $ */
+/* $OpenBSD: if_ether.c,v 1.170 2015/09/28 08:26:58 mpi Exp $ */
/* $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $ */
/*
@@ -328,12 +328,12 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
struct sockaddr *dst, u_char *desten)
{
struct arpcom *ac = (struct arpcom *)ifp;
- struct llinfo_arp *la;
+ struct llinfo_arp *la = NULL;
struct sockaddr_dl *sdl;
struct rtentry *rt = NULL;
struct mbuf *mh;
char addr[INET_ADDRSTRLEN];
- int error;
+ int error, created = 0;
if (m->m_flags & M_BCAST) { /* broadcast */
memcpy(desten, etherbroadcastaddr, sizeof(etherbroadcastaddr));
@@ -367,27 +367,26 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
"local address\n", __func__, inet_ntop(AF_INET,
&satosin(dst)->sin_addr, addr, sizeof(addr)));
} else {
- la = NULL;
- if ((rt = arplookup(satosin(dst)->sin_addr.s_addr, 1, 0,
- ifp->if_rdomain)) != NULL)
+ rt = arplookup(satosin(dst)->sin_addr.s_addr, 1, 0,
+ ifp->if_rdomain);
+ if (rt != NULL) {
+ created = 1;
la = ((struct llinfo_arp *)rt->rt_llinfo);
+ }
if (la == NULL)
log(LOG_DEBUG, "%s: %s: can't allocate llinfo\n",
__func__,
inet_ntop(AF_INET, &satosin(dst)->sin_addr,
addr, sizeof(addr)));
}
- if (la == NULL || rt == NULL) {
- m_freem(m);
- return (EINVAL);
- }
+ if (la == NULL || rt == NULL)
+ goto bad;
sdl = SDL(rt->rt_gateway);
if (sdl->sdl_alen > 0 && sdl->sdl_alen != ETHER_ADDR_LEN) {
log(LOG_DEBUG, "%s: %s: incorrect arp information\n", __func__,
inet_ntop(AF_INET, &satosin(dst)->sin_addr,
addr, sizeof(addr)));
- m_freem(m);
- return (EINVAL);
+ goto bad;
}
/*
* Check the address family and length is valid, the address
@@ -396,12 +395,12 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
if ((rt->rt_expire == 0 || rt->rt_expire > time_second) &&
sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) {
memcpy(desten, LLADDR(sdl), sdl->sdl_alen);
+ if (created)
+ rtfree(rt);
return (0);
}
- if (ifp->if_flags & IFF_NOARP) {
- m_freem(m);
- return (EINVAL);
- }
+ if (ifp->if_flags & IFF_NOARP)
+ goto bad;
/*
* There is an arptab entry, but no ethernet address
@@ -460,7 +459,15 @@ arpresolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m,
}
}
}
+ if (created)
+ rtfree(rt);
return (EAGAIN);
+
+bad:
+ m_freem(m);
+ if (created)
+ rtfree(rt);
+ return (EINVAL);
}
/*
@@ -529,7 +536,7 @@ in_arpinput(struct mbuf *m)
struct arpcom *ac;
struct ether_header *eh;
struct llinfo_arp *la = 0;
- struct rtentry *rt;
+ struct rtentry *rt = NULL;
struct ifaddr *ifa;
struct sockaddr_dl *sdl;
struct sockaddr sa;
@@ -725,10 +732,13 @@ in_arpinput(struct mbuf *m)
reply:
if (op != ARPOP_REQUEST) {
out:
+ rtfree(rt);
if_put(ifp);
m_freem(m);
return;
}
+
+ rtfree(rt);
if (itaddr.s_addr == myaddr.s_addr) {
/* I am the target */
memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha));
@@ -743,6 +753,7 @@ out:
memcpy(ea->arp_tha, ea->arp_sha, sizeof(ea->arp_sha));
sdl = SDL(rt->rt_gateway);
memcpy(ea->arp_sha, LLADDR(sdl), sizeof(ea->arp_sha));
+ rtfree(rt);
}
memcpy(ea->arp_tpa, ea->arp_spa, sizeof(ea->arp_spa));
@@ -811,15 +822,11 @@ arplookup(u_int32_t addr, int create, int proxy, u_int tableid)
rt = rtalloc((struct sockaddr *)&sin, flags, tableid);
if (rt == NULL)
return (NULL);
- rt->rt_refcnt--;
if ((rt->rt_flags & RTF_GATEWAY) || (rt->rt_flags & RTF_LLINFO) == 0 ||
rt->rt_gateway->sa_family != AF_LINK) {
- if (create) {
- if (rt->rt_refcnt <= 0 &&
- (rt->rt_flags & RTF_CLONED) != 0) {
- rtdeletemsg(rt, tableid);
- }
- }
+ if (create && (rt->rt_flags & RTF_CLONED))
+ rtdeletemsg(rt, tableid);
+ rtfree(rt);
return (NULL);
}
return (rt);
@@ -842,13 +849,16 @@ arpproxy(struct in_addr in, unsigned int rtableid)
/* Check that arp information are correct. */
sdl = (struct sockaddr_dl *)rt->rt_gateway;
- if (sdl->sdl_alen != ETHER_ADDR_LEN)
+ if (sdl->sdl_alen != ETHER_ADDR_LEN) {
+ rtfree(rt);
return (0);
+ }
ifp = rt->rt_ifp;
if (!memcmp(LLADDR(sdl), LLADDR(ifp->if_sadl), sdl->sdl_alen))
found = 1;
+ rtfree(rt);
return (found);
}