summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2017-06-26 19:06:13 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2017-06-26 19:06:13 +0000
commita9809ed178dc74023a2b4fd700d8128ef3b3ed32 (patch)
tree8bc46f56e725eeece9e17755acb7ebda4af73b88 /sys
parent96e064c2d3e970f645b2f112541db8bd382fe04f (diff)
Convert ip_input() to a pr_input style function. Goal is to process
IPsec packets without additional enqueueing. OK mpi@
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/ip_input.c103
-rw-r--r--sys/netinet/ip_var.h5
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);