diff options
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/ip_input.c | 103 | ||||
-rw-r--r-- | sys/netinet/ip_var.h | 5 |
2 files changed, 67 insertions, 41 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index b24f37858c4..65b27842075 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_input.c,v 1.312 2017/06/19 17:58:49 bluhm Exp $ */ +/* $OpenBSD: ip_input.c,v 1.313 2017/06/26 19:06:12 bluhm Exp $ */ /* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ /* @@ -126,8 +126,8 @@ int ip_sysctl_ipstat(void *, size_t *, void *); static struct mbuf_queue ipsend_mq; -void ip_ours(struct mbuf *); -void ip_local(struct mbuf *); +int ip_ours(struct mbuf **, int *, int, int); +int ip_local(struct mbuf **, int *, int, int); int ip_dooptions(struct mbuf *, struct ifnet *); int in_ouraddr(struct mbuf *, struct ifnet *, struct rtentry **); @@ -213,10 +213,12 @@ ip_init(void) * between the network layer (input/forward path) running without * KERNEL_LOCK() and the transport layer still needing it. */ -void -ip_ours(struct mbuf *m) +int +ip_ours(struct mbuf **mp, int *offp, int nxt, int af) { - niq_enqueue(&ipintrq, m); + niq_enqueue(&ipintrq, *mp); + *mp = NULL; + return IPPROTO_DONE; } /* @@ -226,13 +228,16 @@ void ipintr(void) { struct mbuf *m; + int off, nxt; while ((m = niq_dequeue(&ipintrq)) != NULL) { #ifdef DIAGNOSTIC if ((m->m_flags & M_PKTHDR) == 0) panic("ipintr no HDR"); #endif - ip_local(m); + off = 0; + nxt = ip_local(&m, &off, IPPROTO_IPV4, AF_UNSPEC); + KASSERT(nxt == IPPROTO_DONE); } } @@ -244,16 +249,29 @@ ipintr(void) void ipv4_input(struct ifnet *ifp, struct mbuf *m) { + int off, nxt; + + off = 0; + nxt = ip_input_if(&m, &off, IPPROTO_IPV4, AF_UNSPEC, ifp); + KASSERT(nxt == IPPROTO_DONE); +} + +int +ip_input_if(struct mbuf **mp, int *offp, int nxt, int af, struct ifnet *ifp) +{ + struct mbuf *m = *mp; struct rtentry *rt = NULL; struct ip *ip; int hlen, len; in_addr_t pfrdr = 0; + KASSERT(*offp == 0); + ipstat_inc(ips_total); if (m->m_len < sizeof (struct ip) && - (m = m_pullup(m, sizeof (struct ip))) == NULL) { + (m = *mp = m_pullup(m, sizeof (struct ip))) == NULL) { ipstat_inc(ips_toosmall); - goto out; + goto bad; } ip = mtod(m, struct ip *); if (ip->ip_v != IPVERSION) { @@ -266,9 +284,9 @@ ipv4_input(struct ifnet *ifp, struct mbuf *m) goto bad; } if (hlen > m->m_len) { - if ((m = m_pullup(m, hlen)) == NULL) { + if ((m = *mp = m_pullup(m, hlen)) == NULL) { ipstat_inc(ips_badhlen); - goto out; + goto bad; } ip = mtod(m, struct ip *); } @@ -336,10 +354,11 @@ ipv4_input(struct ifnet *ifp, struct mbuf *m) * Packet filter */ pfrdr = ip->ip_dst.s_addr; - if (pf_test(AF_INET, PF_IN, ifp, &m) != PF_PASS) + if (pf_test(AF_INET, PF_IN, ifp, mp) != PF_PASS) goto bad; + m = *mp; if (m == NULL) - goto out; + goto bad; ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2; @@ -353,17 +372,18 @@ ipv4_input(struct ifnet *ifp, struct mbuf *m) * to be sent and the original packet to be freed). */ if (hlen > sizeof (struct ip) && ip_dooptions(m, ifp)) { - goto out; + m = *mp = NULL; + goto bad; } if (ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_dst.s_addr == INADDR_ANY) { - ip_ours(m); + nxt = ip_ours(mp, offp, nxt, af); goto out; } if (in_ouraddr(m, ifp, &rt)) { - ip_ours(m); + nxt = ip_ours(mp, offp, nxt, af); goto out; } @@ -380,9 +400,9 @@ ipv4_input(struct ifnet *ifp, struct mbuf *m) int error; if (m->m_flags & M_EXT) { - if ((m = m_pullup(m, hlen)) == NULL) { + if ((m = *mp = m_pullup(m, hlen)) == NULL) { ipstat_inc(ips_toosmall); - goto out; + goto bad; } ip = mtod(m, struct ip *); } @@ -412,7 +432,7 @@ ipv4_input(struct ifnet *ifp, struct mbuf *m) * host belongs to their destination groups. */ if (ip->ip_p == IPPROTO_IGMP) { - ip_ours(m); + nxt = ip_ours(mp, offp, nxt, af); goto out; } ipstat_inc(ips_forward); @@ -428,7 +448,7 @@ ipv4_input(struct ifnet *ifp, struct mbuf *m) ipstat_inc(ips_cantforward); goto bad; } - ip_ours(m); + nxt = ip_ours(mp, offp, nxt, af); goto out; } @@ -463,11 +483,14 @@ ipv4_input(struct ifnet *ifp, struct mbuf *m) #endif /* IPSEC */ ip_forward(m, ifp, rt, pfrdr); - return; -bad: - m_freem(m); -out: + *mp = NULL; + return IPPROTO_DONE; + bad: + nxt = IPPROTO_DONE; + m_freemp(mp); + out: rtfree(rt); + return nxt; } /* @@ -475,9 +498,10 @@ out: * * If fragmented try to reassemble. Pass to next level. */ -void -ip_local(struct mbuf *m) +int +ip_local(struct mbuf **mp, int *offp, int nxt, int af) { + struct mbuf *m = *mp; struct ip *ip = mtod(m, struct ip *); struct ipq *fp; struct ipqent *ipqe; @@ -496,9 +520,9 @@ ip_local(struct mbuf *m) */ if (ip->ip_off &~ htons(IP_DF | IP_RF)) { if (m->m_flags & M_EXT) { /* XXX */ - if ((m = m_pullup(m, hlen)) == NULL) { + if ((m = *mp = m_pullup(m, hlen)) == NULL) { ipstat_inc(ips_toosmall); - return; + goto bad; } ip = mtod(m, struct ip *); } @@ -558,10 +582,9 @@ found: ipqe->ipqe_mff = mff; ipqe->ipqe_m = m; ipqe->ipqe_ip = ip; - m = ip_reass(ipqe, fp); - if (m == NULL) { - return; - } + m = *mp = ip_reass(ipqe, fp); + if (m == NULL) + goto bad; ipstat_inc(ips_reassembled); ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2; @@ -571,13 +594,14 @@ found: ip_freef(fp); } - ip_deliver(&m, &hlen, ip->ip_p, AF_INET); - return; -bad: - m_freem(m); + *offp = hlen; + return ip_deliver(mp, offp, ip->ip_p, AF_INET); + bad: + m_freemp(mp); + return IPPROTO_DONE; } -void +int ip_deliver(struct mbuf **mp, int *offp, int nxt, int af) { KERNEL_ASSERT_LOCKED(); @@ -601,11 +625,12 @@ ip_deliver(struct mbuf **mp, int *offp, int nxt, int af) ipstat_inc(ips_delivered); nxt = (*inetsw[ip_protox[nxt]].pr_input)(mp, offp, nxt, af); KASSERT(nxt == IPPROTO_DONE); - return; + return nxt; #ifdef IPSEC bad: #endif m_freemp(mp); + return IPPROTO_DONE; } int @@ -873,7 +898,7 @@ dropfrag: m_freem(m); pool_put(&ipqent_pool, ipqe); ip_frags--; - return (0); + return (NULL); } /* diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 737e8e214b8..eefa2127262 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_var.h,v 1.78 2017/05/31 05:59:09 mpi Exp $ */ +/* $OpenBSD: ip_var.h,v 1.79 2017/06/26 19:06:12 bluhm Exp $ */ /* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */ /* @@ -248,7 +248,8 @@ int ip_sysctl(int *, u_int, void *, size_t *, void *, size_t); void ip_savecontrol(struct inpcb *, struct mbuf **, struct ip *, struct mbuf *); void ipintr(void); -void ip_deliver(struct mbuf **, int *, int, int); +int ip_input_if(struct mbuf **, int *, int, int, struct ifnet *); +int ip_deliver(struct mbuf **, int *, int, int); void ip_forward(struct mbuf *, struct ifnet *, struct rtentry *, int); int rip_ctloutput(int, struct socket *, int, int, struct mbuf *); void rip_init(void); |