diff options
-rw-r--r-- | sys/netinet/ip_divert.c | 9 | ||||
-rw-r--r-- | sys/netinet6/ip6_divert.c | 41 |
2 files changed, 25 insertions, 25 deletions
diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index 9f8821d3559..a6b57213d81 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_divert.c,v 1.51 2017/09/06 00:05:02 bluhm Exp $ */ +/* $OpenBSD: ip_divert.c,v 1.52 2017/09/06 11:43:04 bluhm Exp $ */ /* * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org> @@ -75,16 +75,13 @@ divert_output(struct inpcb *inp, struct mbuf *m, struct mbuf *nam, struct mbuf *control) { struct sockaddr_in *sin; - struct socket *so; - int error, min_hdrlen = 0, dir; + int error, min_hdrlen, off, dir; struct ip *ip; - u_int16_t off; m_freem(control); if ((error = in_nam2sin(nam, &sin))) goto fail; - so = inp->inp_socket; /* Do basic sanity checks. */ if (m->m_pkthdr.len < sizeof(struct ip)) @@ -118,7 +115,7 @@ divert_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) 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); } |