Subject: Re: Heads-up, status update on FAST_IPSEC
To: None <tech-kern@netbsd.org>
From: Jun-ichiro itojun Hagino <itojun@iijlab.net>
List: tech-net
Date: 08/05/2003 09:46:07
>I have a NetBSD port of Sam Leffler's FAST_IPSEC which works well
>enough to start some work on integration -- enough that other
>developers/users can start testing, if they wish.  The current version
>is IPv4-only. The source code can co-exist with KAME IPsec, but only
>one or the other can be configured into a kernel at one time.

	before committing FAST_IPSEC code, please make sure transport-mode
	packet does not get injected into ip_input() again.  it has bad
	sideeffects such as:
	- stat counters being not accurate
	- ip options evaluated twice
	- ip header processed twice
	the attached diff should solve that for openbsd-current.

itojun


Index: ip_ipsp.h
===================================================================
RCS file: /cvs/src/sys/netinet/ip_ipsp.h,v
retrieving revision 1.123
diff -u -r1.123 ip_ipsp.h
--- ip_ipsp.h	24 Jul 2003 08:03:20 -0000	1.123
+++ ip_ipsp.h	5 Aug 2003 00:45:15 -0000
@@ -570,7 +570,7 @@
 
 #ifdef INET
 extern void ah4_input(struct mbuf *, ...);
-extern int ah4_input_cb(struct mbuf *, ...);
+extern int ah4_input_cb(struct mbuf *, int, int);
 extern void *ah4_ctlinput(int, struct sockaddr *, void *);
 #endif /* INET */
 
@@ -591,7 +591,7 @@
 
 #ifdef INET
 extern void esp4_input(struct mbuf *, ...);
-extern int esp4_input_cb(struct mbuf *, ...);
+extern int esp4_input_cb(struct mbuf *, int, int);
 extern void *esp4_ctlinput(int, struct sockaddr *, void *);
 #endif /* INET */
 
@@ -612,7 +612,7 @@
 
 #ifdef INET
 extern void ipcomp4_input(struct mbuf *, ...);
-extern int ipcomp4_input_cb(struct mbuf *, ...);
+extern int ipcomp4_input_cb(struct mbuf *, int, int);
 #endif /* INET */
 
 #ifdef INET6
Index: ipsec_input.c
===================================================================
RCS file: /cvs/src/sys/netinet/ipsec_input.c,v
retrieving revision 1.69
diff -u -r1.69 ipsec_input.c
--- ipsec_input.c	28 Jul 2003 10:10:16 -0000	1.69
+++ ipsec_input.c	5 Aug 2003 00:45:16 -0000
@@ -88,6 +88,8 @@
 int ah_enable = 1;
 int ipcomp_enable = 0;
 
+extern struct protosw inetsw[];
+extern u_char ip_protox[];
 #ifdef INET6
 extern struct ip6protosw inet6sw[];
 extern u_char ip6_protox[];
@@ -584,13 +586,13 @@
 		switch (sproto)
 		{
 		case IPPROTO_ESP:
-			return esp4_input_cb(m);
+			return esp4_input_cb(m, skip, protoff);
 
 		case IPPROTO_AH:
-			return ah4_input_cb(m);
+			return ah4_input_cb(m, skip, protoff);
 
 		case IPPROTO_IPCOMP:
-			return ipcomp4_input_cb(m);
+			return ipcomp4_input_cb(m, skip, protoff);
 
 		default:
 			DPRINTF(("ipsec_common_input_cb(): unknown/unsupported"
@@ -701,31 +703,29 @@
 
 /* IPv4 AH callback. */
 int
-ah4_input_cb(struct mbuf *m, ...)
+ah4_input_cb(struct mbuf *m, int off, int protoff)
 {
-	struct ifqueue *ifq = &ipintrq;
-	int s = splimp();
+	int nxt;
+	u_int8_t nxt8;
+
+	/* Retrieve new protocol */
+	m_copydata(m, protoff, sizeof(u_int8_t), (caddr_t) &nxt8);
+	nxt = nxt8;
 
 	/*
-	 * Interface pointer is already in first mbuf; chop off the
-	 * `outer' header and reschedule.
+	 * Protection against faulty packet - there should be
+	 * more sanity checks in header chain processing.
 	 */
-
-	if (IF_QFULL(ifq)) {
-		IF_DROP(ifq);
-		ahstat.ahs_qfull++;
-		splx(s);
-
-		m_freem(m);
-		DPRINTF(("ah4_input_cb(): dropped packet because of full "
-		    "IP queue\n"));
-		return ENOBUFS;
+	if (m->m_pkthdr.len < off) {
+		ipstat.ips_tooshort++;
+		goto bad;
 	}
-
-	IF_ENQUEUE(ifq, m);
-	schednetisr(NETISR_IP);
-	splx(s);
+	(*inetsw[ip_protox[nxt]].pr_input)(m, off, NULL, 0);
 	return 0;
+
+ bad:
+	m_freem(m);
+	return EINVAL;
 }
 
 
@@ -756,30 +756,9 @@
 
 /* IPv4 ESP callback. */
 int
-esp4_input_cb(struct mbuf *m, ...)
+esp4_input_cb(struct mbuf *m, int off, int protoff)
 {
-	struct ifqueue *ifq = &ipintrq;
-	int s = splimp();
-
-	/*
-	 * Interface pointer is already in first mbuf; chop off the
-	 * `outer' header and reschedule.
-	 */
-	if (IF_QFULL(ifq)) {
-		IF_DROP(ifq);
-		espstat.esps_qfull++;
-		splx(s);
-
-		m_freem(m);
-		DPRINTF(("esp4_input_cb(): dropped packet because of full "
-		    "IP queue\n"));
-		return ENOBUFS;
-	}
-
-	IF_ENQUEUE(ifq, m);
-	schednetisr(NETISR_IP);
-	splx(s);
-	return 0;
+	return ah4_input_cb(m, off, protoff);
 }
 
 /* IPv4 IPCOMP wrapper */
@@ -798,30 +777,9 @@
 
 /* IPv4 IPCOMP callback */
 int
-ipcomp4_input_cb(struct mbuf *m, ...)
+ipcomp4_input_cb(struct mbuf *m, int off, int protoff)
 {
-	struct ifqueue *ifq = &ipintrq;
-	int s = splimp();
-
-	/*
-	 * Interface pointer is already in first mbuf; chop off the
-	 * `outer' header and reschedule.
-	 */
-	if (IF_QFULL(ifq)) {
-		IF_DROP(ifq);
-		ipcompstat.ipcomps_qfull++;
-		splx(s);
-
-		m_freem(m);
-		DPRINTF(("ipcomp4_input_cb(): dropped packet because of full IP queue\n"));
-		return ENOBUFS;
-	}
-
-	IF_ENQUEUE(ifq, m);
-	schednetisr(NETISR_IP);
-	splx(s);
-
-	return 0;
+	return ah4_input_cb(m, off, protoff);
 }
 
 void *