diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-10-27 12:06:38 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-10-27 12:06:38 +0000 |
commit | 6584c4f1e7c5c1d4db003396d988218bf0a3e4ac (patch) | |
tree | 176a6b9815874518dc2dbd340cf493012e624995 /sys/netinet | |
parent | 7d23b196fe9c13424843352dd86abd202e1e0762 (diff) |
Rewrite in_ouraddr() to not use ``rt_ifa'' since it is not obvious that
the lifetime of an ``ifa'' is tied to a route entry, so it might no
longer be valid after calling rtfree(9).
While here put a KERNEL_LOCK() around the per-ifp address list iteration.
ok bluhm@
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/ip_input.c | 50 |
1 files changed, 26 insertions, 24 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 632c1eac8c4..4c426549d84 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_input.c,v 1.259 2015/10/26 15:49:13 mpi Exp $ */ +/* $OpenBSD: ip_input.c,v 1.260 2015/10/27 12:06:37 mpi Exp $ */ /* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ /* @@ -646,9 +646,9 @@ bad: int in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct in_addr ina) { - struct in_ifaddr *ia = NULL; struct rtentry *rt; struct sockaddr_in sin; + int match = 0; #if NPF > 0 struct pf_state_key *key; @@ -671,11 +671,25 @@ in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct in_addr ina) sin.sin_family = AF_INET; sin.sin_addr = ina; rt = rtalloc(sintosa(&sin), 0, m->m_pkthdr.ph_rtableid); - if (rtisvalid(rt) && ISSET(rt->rt_flags, RTF_LOCAL|RTF_BROADCAST)) - ia = ifatoia(rt->rt_ifa); + if (rtisvalid(rt)) { + if (ISSET(rt->rt_flags, RTF_LOCAL)) + match = 1; + + /* + * If directedbcast is enabled we only consider it local + * if it is received on the interface with that address. + */ + if (ISSET(rt->rt_flags, RTF_BROADCAST) && + (!ip_directedbcast || rt->rt_ifidx == ifp->if_index)) { + match = 1; + + /* Make sure M_BCAST is set */ + m->m_flags |= M_BCAST; + } + } rtfree(rt); - if (ia == NULL) { + if (!match) { struct ifaddr *ifa; /* @@ -695,33 +709,21 @@ in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct in_addr ina) * interface, and that M_BCAST will only be set on a BROADCAST * interface. */ + KERNEL_LOCK(); TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { if (ifa->ifa_addr->sa_family != AF_INET) continue; if (IN_CLASSFULBROADCAST(ina.s_addr, - ifatoia(ifa)->ia_addr.sin_addr.s_addr)) - return (1); + ifatoia(ifa)->ia_addr.sin_addr.s_addr)) { + match = 1; + break; + } } - - return (0); + KERNEL_UNLOCK(); } - if (ina.s_addr != ia->ia_addr.sin_addr.s_addr) { - /* - * This matches a broadcast address on one of our interfaces. - * If directedbcast is enabled we only consider it local if it - * is received on the interface with that address. - */ - if (ip_directedbcast && ia->ia_ifp != ifp) - return (0); - - /* Make sure M_BCAST is set */ - if (m) - m->m_flags |= M_BCAST; - } - - return (1); + return (match); } /* |