summaryrefslogtreecommitdiff
path: root/sys/netinet6/ip6_divert.c
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2017-09-06 11:43:05 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2017-09-06 11:43:05 +0000
commit771206b5d171aa8a9b5e87e0ab3578fea211bc57 (patch)
treeb41082a88a1cbbc0713ec9a492bb9616417064ea /sys/netinet6/ip6_divert.c
parent4c6f8cecf9d7b2030e5b06a1663b69bb510faa92 (diff)
Replace the call to ifa_ifwithaddr() in divert6_output() with a
route lookup to make it MP safe. Only set the mbuf header fields that are needed. Validate the name input. Also use the same variables in IPv4 and IPv6 functions and avoid unneccessary initialization. OK mpi@
Diffstat (limited to 'sys/netinet6/ip6_divert.c')
-rw-r--r--sys/netinet6/ip6_divert.c41
1 files changed, 22 insertions, 19 deletions
diff --git a/sys/netinet6/ip6_divert.c b/sys/netinet6/ip6_divert.c
index 0ab1305684e..b3ccd4ac69a 100644
--- a/sys/netinet6/ip6_divert.c
+++ b/sys/netinet6/ip6_divert.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip6_divert.c,v 1.50 2017/09/05 07:59:11 mpi Exp $ */
+/* $OpenBSD: ip6_divert.c,v 1.51 2017/09/06 11:43:04 bluhm Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -62,8 +62,6 @@ int *divert6ctl_vars[DIVERT6CTL_MAXID] = DIVERT6CTL_VARS;
int divb6hashsize = DIVERTHASHSIZE;
-static struct sockaddr_in6 ip6addr = { sizeof(ip6addr), AF_INET6 };
-
int divert6_output(struct inpcb *, struct mbuf *, struct mbuf *,
struct mbuf *);
@@ -79,17 +77,13 @@ divert6_output(struct inpcb *inp, struct mbuf *m, struct mbuf *nam,
struct mbuf *control)
{
struct sockaddr_in6 *sin6;
- struct ifaddr *ifa;
- int error = 0, min_hdrlen = 0, nxt = 0, off, dir;
+ int error, min_hdrlen, nxt, off, dir;
struct ip6_hdr *ip6;
- m->m_pkthdr.ph_ifidx = 0;
- m->m_nextpkt = NULL;
- m->m_pkthdr.ph_rtableid = inp->inp_rtableid;
-
m_freem(control);
- sin6 = mtod(nam, struct sockaddr_in6 *);
+ if ((error = in6_nam2sin6(nam, &sin6)))
+ goto fail;
/* Do basic sanity checks. */
if (m->m_pkthdr.len < sizeof(struct ip6_hdr))
@@ -129,7 +123,7 @@ divert6_output(struct inpcb *inp, struct mbuf *m, struct mbuf *nam,
m->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT;
break;
default:
- /* nothing */
+ min_hdrlen = 0;
break;
}
if (min_hdrlen && m->m_pkthdr.len < off + min_hdrlen)
@@ -138,15 +132,17 @@ divert6_output(struct inpcb *inp, struct mbuf *m, struct mbuf *nam,
m->m_pkthdr.pf.flags |= PF_TAG_DIVERTED_PACKET;
if (dir == PF_IN) {
- ip6addr.sin6_addr = sin6->sin6_addr;
- /* XXXSMP ``ifa'' is not reference counted. */
- ifa = ifa_ifwithaddr(sin6tosa(&ip6addr),
- m->m_pkthdr.ph_rtableid);
- if (ifa == NULL) {
+ struct rtentry *rt;
+ struct ifnet *ifp;
+
+ rt = rtalloc(sin6tosa(sin6), 0, inp->inp_rtableid);
+ if (!rtisvalid(rt) || !ISSET(rt->rt_flags, RTF_LOCAL)) {
+ rtfree(rt);
error = EADDRNOTAVAIL;
goto fail;
}
- m->m_pkthdr.ph_ifidx = ifa->ifa_ifp->if_index;
+ m->m_pkthdr.ph_ifidx = rt->rt_ifidx;
+ rtfree(rt);
/*
* Recalculate the protocol checksum for the inbound packet
@@ -155,9 +151,16 @@ divert6_output(struct inpcb *inp, struct mbuf *m, struct mbuf *nam,
*/
in6_proto_cksum_out(m, NULL);
- /* XXXSMP ``ifa'' is not reference counted. */
- ipv6_input(ifa->ifa_ifp, m);
+ ifp = if_get(m->m_pkthdr.ph_ifidx);
+ if (ifp == NULL) {
+ error = ENETDOWN;
+ goto fail;
+ }
+ ipv6_input(ifp, m);
+ if_put(ifp);
} else {
+ m->m_pkthdr.ph_rtableid = inp->inp_rtableid;
+
error = ip6_output(m, NULL, &inp->inp_route6,
IP_ALLOWBROADCAST | IP_RAWOUTPUT, NULL, NULL);
}