Subject: fast_ipsec code review
To: None <tech-net@netbsd.org>
From: DEGROOTE Arnaud <degroote@enseirb.fr>
List: tech-net
Date: 11/14/2006 14:24:00
This message is in MIME format.

--=_6xgiauyepo0
Content-Type: text/plain;
	charset=ISO-8859-1;
	DelSp="Yes";
	format="flowed"
Content-Disposition: inline
Content-Transfer-Encoding: 7bit

Hi list

First news : I have add the support of extension header in fast_ipsec  
so fast_ipsec now can handle correctly any ipv6 packet.

Now, the support of ipv6 is quite complete. So it would be great if  
some people can review the current code. I have attached a diff  
against current, and you can retrieve all the code in the cvs / cvsweb  
associated with the project (  
http://netbsd-soc.cvs.sourceforge.net/netbsd-soc/ipsec6/ ).

It would be nice too if some people can test the code in more real  
cases and report success and failure. I can provide a  
GENERIC.FAST_IPSEC if someone needs it.

Take cares.

PS : Please CC me on reply

--
Arnaud Degroote



----------------------------------------------------------------
This message was sent using IMP, the Internet Messaging Program.


--=_6xgiauyepo0
Content-Type: text/plain;
	charset=UTF-8;
	name="fast_ipsec.txt"
Content-Disposition: attachment;
	filename="fast_ipsec.txt"
Content-Transfer-Encoding: quoted-printable

diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netinet/ip_output.c /home/zul=
/netbsd-dev/src/sys/netinet/ip_output.c
--- /home/zul/tmp/src/sys/netinet/ip_output.c=092006-11-13 06:13:42.00000000=
0 +0100
+++ /home/zul/netbsd-dev/src/sys/netinet/ip_output.c=092006-11-04 23:01:10.0=
00000000 +0100
@@ -1,4 +1,4 @@
-/*=09$NetBSD: ip_output.c,v 1.166 2006/11/13 05:13:42 dyoung Exp $=09*/
+/*=09$NetBSD: ip_output.c,v 1.165 2006/07/23 22:06:13 ad Exp $=09*/
=20
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -98,7 +98,7 @@
  */
=20
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.166 2006/11/13 05:13:42 dyoung =
Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.165 2006/07/23 22:06:13 ad Exp =
$");
=20
 #include "opt_pfil_hooks.h"
 #include "opt_inet.h"
@@ -176,6 +176,10 @@
 =09struct rtentry *rt;
 };
=20
+#ifdef FAST_IPSEC
+static int ip_output_cb(struct mbuf *, struct ip_callback *);
+#endif
+
 static int ip_tso_output_callback(void *, struct mbuf *);
 static int ip_tso_output(struct ifnet *, struct mbuf *, struct sockaddr *,
     struct rtentry *);
@@ -202,6 +206,22 @@
 =09return tcp4_segment(m, ip_tso_output_callback, &args);
 }
=20
+#ifdef FAST_IPSEC
+/*=20
+ * XXX Dummy implementation
+ * We need to split the stack in two and only process the second part=20
+ */
+int
+ip_output_cb(struct mbuf * m, struct ip_callback * ip_cb)
+{
+    int error;
+
+    error =3D ip_output(m, NULL, NULL,IP_RAWOUTPUT, NULL, NULL);
+    free(ip_cb,M_TEMP);
+    return error;
+}
+#endif /* FAST_IPSEC */
+
 /*
  * IP output.  The packet in mbuf chain m contains a skeletal IP
  * header (with len, off, ttl, proto, tos, src, dst).
@@ -219,7 +239,6 @@
 =09struct route iproute;
 =09struct sockaddr_in *dst;
 =09struct in_ifaddr *ia;
-=09struct ifaddr *xifa;
 =09struct mbuf *opt;
 =09struct route *ro;
 =09int flags, sw_csum;
@@ -238,6 +257,7 @@
 =09struct inpcb *inp;
 =09struct m_tag *mtag;
 =09struct secpolicy *sp =3D NULL;
+    struct ip_callback * ip_cb =3D NULL;
 =09struct tdb_ident *tdbi;
 =09int s;
 #endif
@@ -795,9 +806,17 @@
 =09=09ip->ip_len =3D htons(ip->ip_len);
 =09=09ip->ip_off =3D htons(ip->ip_off);
 #endif
+       =20
+        ip_cb =3D malloc(sizeof(struct ip_callback), M_TEMP, M_WAITOK);
+        if (ip_cb =3D=3D NULL){
+            error =3D ENOMEM;
+            goto bad;
+        }
+   =20
+        ip_cb->fn =3D ip_output_cb;
=20
 =09=09/* NB: callee frees mbuf */
-=09=09error =3D ipsec4_process_packet(m, sp->req, flags, 0);
+=09=09error =3D ipsec4_process_packet(m, sp->req, flags, 0, ip_cb);
 =09=09/*
 =09=09 * Preserve KAME behaviour: ENOENT can be returned
 =09=09 * when an SA acquire is in progress.  Don't propagate
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netinet/tcp_input.c /home/zul=
/netbsd-dev/src/sys/netinet/tcp_input.c
--- /home/zul/tmp/src/sys/netinet/tcp_input.c=092006-10-21 12:08:54.00000000=
0 +0200
+++ /home/zul/netbsd-dev/src/sys/netinet/tcp_input.c=092006-11-13 21:28:54.0=
00000000 +0100
@@ -1210,7 +1210,7 @@
 #ifdef INET6
 =09=09else if (in6p &&
 =09=09    (in6p->in6p_socket->so_options & SO_ACCEPTCONN) =3D=3D 0 &&
-=09=09    ipsec4_in_reject_so(m, in6p->in6p_socket)) {
+=09=09    ipsec6_in_reject_so(m, in6p->in6p_socket)) {
 =09=09=09ipsecstat.in_polvio++;
 =09=09=09goto drop;
 =09=09}
@@ -1518,7 +1518,7 @@
 =09=09=09=09}
 #endif
=20
-#ifdef IPSEC
+#if defined(IPSEC) || defined(FAST_IPSEC)
 =09=09=09=09switch (af) {
 #ifdef INET
 =09=09=09=09case AF_INET:
@@ -1539,7 +1539,7 @@
 =09=09=09=09=09break;
 #endif
 =09=09=09=09}
-#endif
+#endif /* IPSEC */
=20
 =09=09=09=09/*
 =09=09=09=09 * LISTEN socket received a SYN
@@ -2753,9 +2753,15 @@
 #ifdef FAST_IPSEC
 =09/* Extract the destination from the IP header in the mbuf. */
 =09bzero(&dst, sizeof(union sockaddr_union));
-=09dst.sa.sa_len =3D sizeof(struct sockaddr_in);
-=09dst.sa.sa_family =3D AF_INET;
-=09dst.sin.sin_addr =3D ip->ip_dst;
+    if (ip) {
+=09    dst.sa.sa_len =3D sizeof(struct sockaddr_in);
+=09    dst.sa.sa_family =3D AF_INET;
+=09    dst.sin.sin_addr =3D ip->ip_dst;
+    } else {
+        dst.sa.sa_len =3D sizeof(struct sockaddr_in6);
+        dst.sa.sa_family =3D AF_INET6;
+        dst.sin6.sin6_addr =3D ip6->ip6_dst;
+    }
=20
 =09/*
 =09 * Look up an SADB entry which matches the address of the peer.
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netinet/tcp_output.c /home/zu=
l/netbsd-dev/src/sys/netinet/tcp_output.c
--- /home/zul/tmp/src/sys/netinet/tcp_output.c=092006-10-17 13:11:40.0000000=
00 +0200
+++ /home/zul/netbsd-dev/src/sys/netinet/tcp_output.c=092006-11-13 21:28:54.=
000000000 +0100
@@ -185,6 +185,9 @@
 #ifdef FAST_IPSEC
 #include <netipsec/ipsec.h>
 #include <netipsec/key.h>
+#ifdef INET6
+#include <netipsec/ipsec6.h>
+#endif /* INET6 */
 #endif=09/* FAST_IPSEC*/
 #ifdef IPSEC
 #include <netinet6/ipsec.h>
@@ -369,7 +372,7 @@
 =09} else
 #endif
 =09if (in6p && tp->t_family =3D=3D AF_INET6) {
-#ifdef IPSEC
+#if defined(IPSEC) || defined(FAST_IPSEC)
 =09=09if (! IPSEC_PCB_SKIP_IPSEC(in6p->in6p_sp, IPSEC_DIR_OUTBOUND))
 =09=09=09optlen +=3D ipsec6_hdrsiz_tcp(tp);
 #endif
@@ -1134,9 +1137,6 @@
 =09TCP_REASS_UNLOCK(tp);
=20
 #ifdef TCP_SIGNATURE
-#if defined(INET6) && defined(FAST_IPSEC)
-=09if (tp->t_family =3D=3D AF_INET)
-#endif
 =09if (tp->t_flags & TF_SIGNATURE) {
 =09=09u_char *bp;
 =09=09/*
@@ -1352,9 +1352,6 @@
 =09=09tp->snd_up =3D tp->snd_una;=09=09/* drag it along */
=20
 #ifdef TCP_SIGNATURE
-#if defined(INET6) && defined(FAST_IPSEC)
-=09if (tp->t_family =3D=3D AF_INET) /* XXX */
-#endif
 =09if (sigoff && (tp->t_flags & TF_SIGNATURE)) {
 =09=09struct secasvar *sav;
 =09=09u_int8_t *sigp;
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netinet/tcp_subr.c /home/zul/=
netbsd-dev/src/sys/netinet/tcp_subr.c
--- /home/zul/tmp/src/sys/netinet/tcp_subr.c=092006-10-19 13:40:51.000000000=
 +0200
+++ /home/zul/netbsd-dev/src/sys/netinet/tcp_subr.c=092006-11-13 21:28:54.00=
0000000 +0100
@@ -2296,9 +2296,6 @@
 =09=09optlen +=3D TCPOLEN_TSTAMP_APPA;
=20
 #ifdef TCP_SIGNATURE
-#if defined(INET6) && defined(FAST_IPSEC)
-=09if (tp->t_family =3D=3D AF_INET)
-#endif
 =09if (tp->t_flags & TF_SIGNATURE)
 =09=09optlen +=3D TCPOLEN_SIGNATURE + 2;
 #endif /* TCP_SIGNATURE */
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netinet6/icmp6.c /home/zul/ne=
tbsd-dev/src/sys/netinet6/icmp6.c
--- /home/zul/tmp/src/sys/netinet6/icmp6.c=092006-10-12 03:32:38.000000000 +=
0200
+++ /home/zul/netbsd-dev/src/sys/netinet6/icmp6.c=092006-11-13 21:32:06.0000=
00000 +0100
@@ -102,6 +102,11 @@
 #include <netkey/key.h>
 #endif
=20
+#ifdef FAST_IPSEC
+#include <netipsec/ipsec.h>
+#include <netipsec/key.h>
+#endif
+
 #include "faith.h"
 #if defined(NFAITH) && 0 < NFAITH
 #include <net/if_faith.h>
@@ -615,8 +620,7 @@
 =09=09=09}
 =09=09=09m_freem(n0);
 =09=09}
-=09=09nip6 =3D mtod(n, struct ip6_hdr *);
-=09=09nicmp6 =3D (struct icmp6_hdr *)((caddr_t)nip6 + off);
+=09    IP6_EXTHDR_GET(nicmp6,struct icmp6_hdr *, n, off, sizeof(*nicmp6));
 =09=09nicmp6->icmp6_type =3D ICMP6_ECHO_REPLY;
 =09=09nicmp6->icmp6_code =3D 0;
 =09=09if (n) {
@@ -2332,7 +2336,7 @@
 =09=09sdst.sin6_len =3D sizeof(struct sockaddr_in6);
 =09=09bcopy(&reddst6, &sdst.sin6_addr, sizeof(struct in6_addr));
 =09=09pfctlinput(PRC_REDIRECT_HOST, (struct sockaddr *)&sdst);
-#ifdef IPSEC
+#if defined(IPSEC) || defined(FAST_IPSEC)
 =09=09key_sa_routechange((struct sockaddr *)&sdst);
 #endif
 =09}
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netinet6/in6_proto.c /home/zu=
l/netbsd-dev/src/sys/netinet6/in6_proto.c
--- /home/zul/tmp/src/sys/netinet6/in6_proto.c=092006-10-10 23:49:15.0000000=
00 +0200
+++ /home/zul/netbsd-dev/src/sys/netinet6/in6_proto.c=092006-11-13 21:32:06.=
000000000 +0100
@@ -115,6 +115,13 @@
 #include <netinet6/ipcomp.h>
 #endif /* IPSEC */
=20
+
+#ifdef FAST_IPSEC
+#include <netipsec/ipsec.h>
+#include <netipsec/ipsec6.h>
+#include <netipsec/key.h>
+#endif=09/* FAST_IPSEC */
+
 #include "carp.h"
 #if NCARP > 0
 #include <netinet/ip_carp.h>
@@ -198,6 +205,23 @@
   0,=09=090,=09=090,=09=090,
 },
 #endif /* IPSEC */
+#ifdef FAST_IPSEC
+{ SOCK_RAW,=09&inet6domain,=09IPPROTO_AH,=09PR_ATOMIC|PR_ADDR,
+  ipsec6_common_input,=090,=09 =09ah6_ctlinput,=090,
+  0,
+  0,=09=090,=09=090,=09=090,=09
+},
+{ SOCK_RAW,=09&inet6domain,=09IPPROTO_ESP,=09PR_ATOMIC|PR_ADDR,
+  ipsec6_common_input,    0,=09 =09esp6_ctlinput,=090,
+  0,
+  0,=09=090,=09=090,=09=090,=09=09
+},
+{ SOCK_RAW,=09&inet6domain,=09IPPROTO_IPCOMP,=09PR_ATOMIC|PR_ADDR,
+  ipsec6_common_input,    0,=09 =090,=09=090,
+  0,
+  0,=09=090,=09=090,=09=090,=09=09
+},
+#endif /* FAST_IPSEC */
 #ifdef INET
 { SOCK_RAW,=09&inet6domain,=09IPPROTO_IPV4,=09PR_ATOMIC|PR_ADDR|PR_LASTHDR,
   encap6_input,=09rip6_output, =09encap6_ctlinput, rip6_ctloutput,
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netinet6/ip6_forward.c /home/=
zul/netbsd-dev/src/sys/netinet6/ip6_forward.c
--- /home/zul/tmp/src/sys/netinet6/ip6_forward.c=092006-06-29 18:56:31.00000=
0000 +0200
+++ /home/zul/netbsd-dev/src/sys/netinet6/ip6_forward.c=092006-11-05 12:53:3=
1.000000000 +0100
@@ -65,6 +65,13 @@
 #include <netkey/key.h>
 #endif /* IPSEC */
=20
+#ifdef FAST_IPSEC
+#include <netipsec/ipsec.h>
+#include <netipsec/ipsec6.h>
+#include <netipsec/key.h>
+#include <netipsec/xform.h>
+#endif
+
 #ifdef PFIL_HOOKS
 #include <net/pfil.h>
 #endif
@@ -77,6 +84,20 @@
 extern struct pfil_head inet6_pfil_hook;=09/* XXX */
 #endif
=20
+#ifdef FAST_IPSEC
+static int ip6_forward_cb(struct mbuf *, struct ip_callback *);
+
+static int
+ip6_forward_cb(struct mbuf * m, struct ip_callback * ip_cb)
+{
+    int error;
+    error =3D ip6_output(m, NULL, NULL, IPV6_FORWARDING/*XXX*/, NULL, NULL,
+=09=09    NULL);
+    free(ip_cb,M_TEMP);
+    return error;
+}
+#endif /* FAST_IPSEC */
+
 /*
  * Forward a packet.  If some error occurs return the sender
  * an icmp packet.  Note we can't always generate a meaningful
@@ -107,6 +128,11 @@
 =09struct secpolicy *sp =3D NULL;
 =09int ipsecrt =3D 0;
 #endif
+#ifdef FAST_IPSEC
+    struct secpolicy *sp =3D NULL;
+    int needipsec =3D 0;
+    int s;
+#endif
=20
 #ifdef IPSEC
 =09/*
@@ -332,6 +358,24 @@
     }
     skip_ipsec:
 #endif /* IPSEC */
+#ifdef FAST_IPSEC
+=09 /* Check the security policy (SP) for the packet */
+
+    sp =3D ipsec6_check_policy(m,NULL,0,&needipsec,&error);
+    if ( error !=3D 0 ){
+         /*
+          * Hack: -EINVAL is used to signal that a packet
+          * should be silently discarded.  This is typically
+          * because we asked key management for an SA and
+          * it was delayed (e.g. kicked up to IKE).
+          */
+        if ( error =3D=3D -EINVAL )
+            error =3D 0;
+        goto freecopy;
+    }
+
+#endif /* FAST_IPSEC */
+
=20
 =09dst =3D &ip6_forward_rt.ro_dst;
 =09if (!srcrt) {
@@ -452,6 +496,36 @@
 =09=09return;
 =09}
=20
+#ifdef FAST_IPSEC
+    /*
+     * If we need to encapsulate the packet, do it here
+     * ipsec6_proces_packet will send the packet using ip6_output=20
+     */
+    if ( needipsec ) {
+       =20
+        struct ip_callback * ip_cb;
+        int skip, protoff;
+
+        ip_cb =3D malloc(sizeof(struct ip_callback),M_TEMP,M_WAITOK);
+        if (ip_cb =3D=3D NULL){
+            if (m)
+                m_freem(m);
+            goto freecopy;
+        }
+
+        ip_cb->fn =3D ip6_forward_cb;
+
+        skip =3D sizeof(struct ip6_hdr);
+        protoff =3D offsetof(struct ip6_hdr, ip6_nxt);
+
+        s =3D splsoftnet();
+        error =3D ipsec6_process_packet(m,sp->req,skip, protoff, ip_cb);
+        splx(s);
+        if (mcopy)
+            goto freecopy;
+    }
+#endif  =20
+
 =09if (m->m_pkthdr.len > IN6_LINKMTU(rt->rt_ifp)) {
 =09=09in6_ifstat_inc(rt->rt_ifp, ifs6_in_toobig);
 =09=09if (mcopy) {
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netinet6/ip6_input.c /home/zu=
l/netbsd-dev/src/sys/netinet6/ip6_input.c
--- /home/zul/tmp/src/sys/netinet6/ip6_input.c=092006-10-12 03:32:39.0000000=
00 +0200
+++ /home/zul/netbsd-dev/src/sys/netinet6/ip6_input.c=092006-11-13 21:32:06.=
000000000 +0100
@@ -112,6 +112,13 @@
 #include <netinet6/ipsec.h>
 #endif
=20
+#ifdef FAST_IPSEC
+#include <netipsec/ipsec.h>
+#include <netipsec/ipsec6.h>
+#include <netipsec/key.h>
+#endif /* FAST_IPSEC */
+
+
 #include <netinet6/ip6protosw.h>
=20
 #include "faith.h"
@@ -241,6 +248,13 @@
 =09int nxt, ours =3D 0;
 =09struct ifnet *deliverifp =3D NULL;
 =09int srcrt =3D 0;
+#ifdef FAST_IPSEC
+    struct m_tag *mtag;
+    struct tdb_ident *tdbi;
+    struct secpolicy *sp;
+    int s, error;
+#endif
+
=20
 #ifdef IPSEC
 =09/*
@@ -327,6 +341,8 @@
 =09 */
 #ifdef IPSEC
 =09if (!ipsec_getnhist(m))
+#elif defined(FAST_IPSEC)
+    if (!ipsec_indone(m))
 #else
 =09if (1)
 #endif
@@ -756,6 +772,45 @@
 =09=09=09goto bad;
 =09=09}
 #endif
+#ifdef FAST_IPSEC
+  /*
+     * enforce IPsec policy checking if we are seeing last header.
+     * note that we do not visit this with protocols with pcb layer
+     * code - like udp/tcp/raw ip.
+     */
+    if ((inet6sw[ip_protox[nxt]].pr_flags & PR_LASTHDR) !=3D 0) {
+        /*
+         * Check if the packet has already had IPsec processing
+         * done.  If so, then just pass it along.  This tag gets
+         * set during AH, ESP, etc. input handling, before the
+         * packet is returned to the ip input queue for delivery.
+         */
+        mtag =3D m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL);
+        s =3D splsoftnet();
+        if (mtag !=3D NULL) {
+            tdbi =3D (struct tdb_ident *)(mtag + 1);
+            sp =3D ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND);
+        } else {
+            sp =3D ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND,
+                           IP_FORWARDING, &error);
+        }
+        if (sp !=3D NULL) {
+            /*
+             * Check security policy against packet attributes.
+             */
+            error =3D ipsec_in_reject(sp, m);
+            KEY_FREESP(&sp);
+        } else {
+            /* XXX error stat??? */
+            error =3D EINVAL;
+            DPRINTF(("ip6_input: no SP, packet discarded\n"));/*XXX*/
+            goto bad;
+        }
+        splx(s);
+        if (error)
+            goto bad;
+    }
+#endif /* FAST_IPSEC */
=20
 =09=09nxt =3D (*inet6sw[ip6_protox[nxt]].pr_input)(&m, &off, nxt);
 =09}
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netinet6/ip6_output.c /home/z=
ul/netbsd-dev/src/sys/netinet6/ip6_output.c
--- /home/zul/tmp/src/sys/netinet6/ip6_output.c=092006-10-12 03:32:39.000000=
000 +0200
+++ /home/zul/netbsd-dev/src/sys/netinet6/ip6_output.c=092006-11-13 21:32:06=
.000000000 +0100
@@ -102,6 +102,13 @@
 #include <netkey/key.h>
 #endif /* IPSEC */
=20
+#ifdef FAST_IPSEC
+#include <netipsec/ipsec.h>
+#include <netipsec/ipsec6.h>
+#include <netipsec/key.h>
+#include <netipsec/xform.h>
+#endif
+
 #include <net/net_osdep.h>
=20
 #ifdef PFIL_HOOKS
@@ -137,11 +144,91 @@
 =09struct socket *));
 #endif
=20
+static int ip6_output2 (struct mbuf *, struct ip6_pktopts *,=20
+    struct route_in6 *, int, struct ip6_moptions*, struct socket *,=20
+    struct ifnet **, int, void *, struct ip6_exthdrs *, struct in6_addr *);
+
+#ifdef FAST_IPSEC
+struct ip6_output_cb_args {
+    struct ip6_pktopts * opt;
+    struct route_in6 * ro;
+    int flags;
+    struct ip6_moptions * im6o;
+    struct socket * so;
+    struct ifnet ** ifpp;
+    struct in6_addr finaldst;
+};
+
+static int ip6_output_cb(struct mbuf*, struct ip_callback *);
+static void get_exthdrs_from_mbuf(struct mbuf*, struct ip6_exthdrs*);=20
+#endif
+
 #define=09IN6_NEED_CHECKSUM(ifp, csum_flags) \
 =09(__predict_true(((ifp)->if_flags & IFF_LOOPBACK) =3D=3D 0 || \
 =09(((csum_flags) & M_CSUM_UDPv6) !=3D 0 && udp_do_loopback_cksum) || \
 =09(((csum_flags) & M_CSUM_TCPv6) !=3D 0 && tcp_do_loopback_cksum)))
=20
+
+#ifdef FAST_IPSEC
+static void
+get_exthdrs_from_mbuf(struct mbuf * m, struct ip6_exthdrs * exthdrs)
+{
+    struct ip6_hdr * ip6;
+    struct ip6_ext * ip6e;
+    struct mbuf * mnext;
+    u_int8_t nxt;
+
+    KASSERT(exthdrs !=3D NULL);
+    KASSERT(m !=3D NULL);
+
+    exthdrs->ip6e_ip6 =3D m;
+    ip6 =3D mtod(m, struct ip6_hdr *);
+    nxt =3D ip6->ip6_nxt;
+    mnext =3D m->m_next;
+   =20
+    while (nxt) {
+        switch(nxt){
+            case IPPROTO_HOPOPTS:=20
+                exthdrs->ip6e_hbh =3D mnext;
+                break;
+            case IPPROTO_ROUTING:
+                exthdrs->ip6e_rthdr =3D mnext;
+                break;
+            case IPPROTO_DSTOPTS:
+                exthdrs->ip6e_dest1 =3D mnext;
+                break;
+            default:
+                return;
+        }
+
+        ip6e =3D mtod(mnext,struct ip6_ext *);
+        nxt =3D ip6e->ip6e_nxt;
+        mnext =3D mnext->m_next;
+   }
+
+    return;=20
+}
+   =20
+
+static int=20
+ip6_output_cb(struct mbuf * m, struct ip_callback * ip_cb)
+{
+    struct ip6_exthdrs exthdrs;
+    struct ip6_output_cb_args * args;
+    int error;
+
+    memset(&exthdrs,0,sizeof(exthdrs));
+    get_exthdrs_from_mbuf(m,&exthdrs);
+    args =3D (struct ip6_output_cb_args *) & ip_cb->ip_callback_args[0];
+    error =3D ip6_output2(m, args->opt, args->ro, args->flags, args->im6o,
+                           args->so, args->ifpp, 1, NULL, &exthdrs,
+                           & args->finaldst);
+
+    free(ip_cb,M_TEMP);
+    return error;
+}
+#endif
+      =20
 /*
  * IP6 output. The packet in mbuf chain m contains a skeletal IP6
  * header (with pri, len, nxt, hlim, src, dst).
@@ -164,22 +251,12 @@
     struct ifnet **ifpp=09=09/* XXX: just for statistics */
 )
 {
-=09struct ip6_hdr *ip6, *mhip6;
-=09struct ifnet *ifp, *origifp;
+=09struct ip6_hdr *ip6;
 =09struct mbuf *m =3D m0;
-=09int hlen, tlen, len, off;
-=09struct route_in6 ip6route;
-=09struct rtentry *rt =3D NULL;
-=09struct sockaddr_in6 *dst, src_sa, dst_sa;
 =09int error =3D 0;
-=09struct in6_ifaddr *ia =3D NULL;
-=09u_long mtu;
-=09int alwaysfrag, dontfrag;
-=09u_int32_t optlen =3D 0, plen =3D 0, unfragpartlen =3D 0;
+=09u_int32_t optlen =3D 0, plen =3D 0;=20
 =09struct ip6_exthdrs exthdrs;
-=09struct in6_addr finaldst, src0, dst0;
-=09u_int32_t zone;
-=09struct route_in6 *ro_pmtu =3D NULL;
+    struct in6_addr finaldst;
 =09int hdrsplit =3D 0;
 =09int needipsec =3D 0;
 #ifdef IPSEC
@@ -188,6 +265,10 @@
=20
 =09ip6 =3D mtod(m, struct ip6_hdr *);
 #endif /* IPSEC */
+#ifdef FAST_IPSEC
+=09struct secpolicy *sp =3D NULL;
+    int s;
+#endif
=20
 #ifdef  DIAGNOSTIC
 =09if ((m->m_flags & M_PKTHDR) =3D=3D 0)
@@ -288,6 +369,24 @@
=20
   skippolicycheck:;
 #endif /* IPSEC */
+#ifdef FAST_IPSEC
+=09 /* Check the security policy (SP) for the packet */
+   =20
+    sp =3D ipsec6_check_policy(m,so,flags,&needipsec,&error);
+    if ( error !=3D 0 ){
+         /*
+          * Hack: -EINVAL is used to signal that a packet
+          * should be silently discarded.  This is typically
+          * because we asked key management for an SA and
+          * it was delayed (e.g. kicked up to IKE).
+          */
+        if ( error =3D=3D -EINVAL )=20
+            error =3D 0;
+        goto freehdrs;
+    }
+
+#endif /* FAST_IPSEC */
+
=20
 =09if (needipsec &&
 =09    (m->m_pkthdr.csum_flags & (M_CSUM_UDPv6|M_CSUM_TCPv6)) !=3D 0) {
@@ -303,9 +402,11 @@
 =09if (exthdrs.ip6e_hbh) optlen +=3D exthdrs.ip6e_hbh->m_len;
 =09if (exthdrs.ip6e_dest1) optlen +=3D exthdrs.ip6e_dest1->m_len;
 =09if (exthdrs.ip6e_rthdr) optlen +=3D exthdrs.ip6e_rthdr->m_len;
-=09unfragpartlen =3D optlen + sizeof(struct ip6_hdr);
 =09/* NOTE: we don't add AH/ESP length here. do that later. */
 =09if (exthdrs.ip6e_dest2) optlen +=3D exthdrs.ip6e_dest2->m_len;
=20
 =09/*
 =09 * If we need IPsec, or there is at least one extension header,
@@ -525,18 +626,6 @@
=20
 =09ip6stat.ip6s_localout++;
=20
-=09/*
-=09 * Route packet.
-=09 */
-=09/* initialize cached route */
-=09if (ro =3D=3D 0) {
-=09=09ro =3D &ip6route;
-=09=09bzero((caddr_t)ro, sizeof(*ro));
-=09}
-=09ro_pmtu =3D ro;
-=09if (opt && opt->ip6po_rthdr)
-=09=09ro =3D &opt->ip6po_route;
-=09dst =3D (struct sockaddr_in6 *)&ro->ro_dst;
=20
  =09/*
 =09 * if specified, try to fill in the traffic class field.
@@ -564,6 +653,156 @@
 =09=09=09ip6->ip6_hlim =3D ip6_defmcasthlim;
 =09}
=20
+#ifdef FAST_IPSEC
+    if ( needipsec ) {
+       =20
+        struct ip_callback * ip_cb;
+        struct ip6_output_cb_args * ip_cb_args;
+        int skip, protoff;
+
+        ip_cb =3D malloc(sizeof(struct ip_callback) +=20
+                  sizeof(struct ip6_output_cb_args), M_TEMP, M_WAITOK);
+       =20
+        if (ip_cb =3D=3D NULL){
+            error =3D ENOMEM;
+            goto bad;
+        }
+
+        ip_cb->fn =3D ip6_output_cb;
+        ip_cb_args =3D (struct ip6_output_cb_args*)&ip_cb->ip_callback_args=
;
+       =20
+        ip_cb_args->opt =3D opt;
+        ip_cb_args->ro =3D ro;
+        ip_cb_args->flags =3D flags;
+        ip_cb_args->im6o =3D im6o;
+        ip_cb_args->so =3D so;
+        ip_cb_args->ifpp =3D ifpp;
+        ip_cb_args->finaldst =3D finaldst;
+       =20
+        if (!optlen){ /* no extension header */
+            skip =3D sizeof(struct ip6_hdr);
+            protoff =3D offsetof(struct ip6_hdr, ip6_nxt);
+        } else {
+            skip =3D sizeof(struct ip6_hdr);
+            protoff =3D offsetof(struct ip6_hdr, ip6_nxt);
+
+            if (exthdrs.ip6e_hbh){
+                protoff =3D skip + offsetof(struct ip6_ext, ip6e_nxt);
+                skip +=3D exthdrs.ip6e_hbh->m_len;
+            }
+       =20
+            if (exthdrs.ip6e_dest1){
+                protoff =3D skip + offsetof(struct ip6_ext, ip6e_nxt);
+                skip +=3D exthdrs.ip6e_dest1->m_len;
+            }
+
+            if (exthdrs.ip6e_rthdr){
+                protoff =3D skip + offsetof(struct ip6_ext, ip6e_nxt);
+                skip +=3D exthdrs.ip6e_rthdr->m_len;
+            }
+        }
+
+=09    s =3D splsoftnet();
+        error =3D ipsec6_process_packet(m,sp->req,skip,protoff,ip_cb);
+
+        /*
+         * Preserve KAME behaviour: ENOENT can be returned
+         * when an SA acquire is in progress.  Don't propagate
+         * this to user-level; it confuses applications.
+         * XXX this will go away when the SADB is redone.
+         */
+        if (error =3D=3D ENOENT)
+            error =3D 0;
+        splx(s);
+        goto done;
+    }
+#endif /* FAST_IPSEC */   =20
+#ifdef IPSEC
+    if (needipsectun){
+        error =3D ip6_output2(m,opt,ro,flags,im6o,so,ifpp,needipsec,sp,=20
+                            &exthdrs,&finaldst);
+        goto done;
+    }
+   =20
+#endif /* IPSEC */
+    error =3D ip6_output2(m,opt,ro,flags,im6o,so,ifpp,needipsec,NULL,
+                        &exthdrs,&finaldst);
+   =20
+done:
+
+#ifdef IPSEC
+=09if (sp !=3D NULL)
+=09=09key_freesp(sp);
+#endif /* IPSEC */
+#ifdef FAST_IPSEC
+    if (sp !=3D NULL)
+        KEY_FREESP(&sp);
+#endif /* FAST_IPSEC */
+
+
+=09return (error);
+
+freehdrs:
+=09m_freem(exthdrs.ip6e_hbh);=09/* m_freem will check if mbuf is 0 */
+=09m_freem(exthdrs.ip6e_dest1);
+=09m_freem(exthdrs.ip6e_rthdr);
+=09m_freem(exthdrs.ip6e_dest2);
+=09/* FALLTHROUGH */
+bad:
+=09m_freem(m);
+=09goto done;
+}
+
+int
+ip6_output2(m0, opt, ro, flags, im6o, so, ifpp, needipsec, spp,
+            exthdrs,finaldst)
+=09struct mbuf *m0;
+=09struct ip6_pktopts *opt;
+=09struct route_in6 *ro;
+=09int flags;
+=09struct ip6_moptions *im6o;
+=09struct socket *so;
+=09struct ifnet **ifpp;=09=09/* XXX: just for statistics */
+    int needipsec;
+    void * spp;             =20
+    struct ip6_exthdrs * exthdrs;
+    struct in6_addr *  finaldst;
+{
+=09struct ip6_hdr *ip6, *mhip6;
+=09struct ifnet *ifp, *origifp;
+=09struct mbuf *m =3D m0;
+=09int hlen, tlen, len, off;
+=09struct route_in6 ip6route;
+=09struct rtentry *rt =3D NULL;
+=09struct sockaddr_in6 *dst, src_sa, dst_sa;
+=09int error =3D 0;
+=09struct in6_ifaddr *ia =3D NULL;
+=09u_long mtu;
+=09int alwaysfrag, dontfrag;
+=09u_int32_t unfragpartlen =3D 0;
+=09struct in6_addr  src0, dst0;
+=09u_int32_t zone;
+=09struct route_in6 *ro_pmtu =3D NULL;
+#ifdef IPSEC
+    int needipsectun =3D needipsec && ( spp !=3D NULL );
+    struct secpolicy * sp =3D spp;
+#endif
+   =20
+    KASSERT(exthdrs !=3D NULL);
+   =20
+=09/*
+=09 * Route packet.
+=09 */
+=09/* initialize cached route */
+=09if (ro =3D=3D NULL) {
+=09=09ro =3D &ip6route;
+=09=09bzero((caddr_t)ro, sizeof(*ro));
+=09}
+=09ro_pmtu =3D ro;
+=09if (opt && opt->ip6po_rthdr)
+=09=09ro =3D &opt->ip6po_route;
+=09dst =3D (struct sockaddr_in6 *)&ro->ro_dst;
+
 #ifdef IPSEC
 =09if (needipsec && needipsectun) {
 =09=09struct ipsec_output_state state;
@@ -576,8 +815,8 @@
 =09=09 *
 =09=09 * IPv6 [ESP|AH] IPv6 [extension headers] payload
 =09=09 */
-=09=09bzero(&exthdrs, sizeof(exthdrs));
-=09=09exthdrs.ip6e_ip6 =3D m;
+=09=09bzero(exthdrs, sizeof(*exthdrs));
+=09=09exthdrs->ip6e_ip6 =3D m;
=20
 =09=09bzero(&state, sizeof(state));
 =09=09state.m =3D m;
@@ -611,10 +850,9 @@
 =09=09=09goto bad;
 =09=09}
=20
-=09=09exthdrs.ip6e_ip6 =3D m;
+=09=09exthdrs->ip6e_ip6 =3D m;
 =09}
 #endif /* IPSEC */
-
 =09/* adjust pointer */
 =09ip6 =3D mtod(m, struct ip6_hdr *);
=20
@@ -784,7 +1022,7 @@
 =09=09*ifpp =3D ifp;
=20
 =09/* Determine path MTU. */
-=09if ((error =3D ip6_getpmtu(ro_pmtu, ro, ifp, &finaldst, &mtu,
+=09if ((error =3D ip6_getpmtu(ro_pmtu, ro, ifp, finaldst, &mtu,
 =09    &alwaysfrag)) !=3D 0)
 =09=09goto bad;
 #ifdef IPSEC
@@ -828,8 +1066,8 @@
 =09 * it must be examined and processed even by the source node.
 =09 * (RFC 2460, section 4.)
 =09 */
-=09if (exthdrs.ip6e_hbh) {
-=09=09struct ip6_hbh *hbh =3D mtod(exthdrs.ip6e_hbh, struct ip6_hbh *);
+=09if (exthdrs->ip6e_hbh) {
+=09=09struct ip6_hbh *hbh =3D mtod(exthdrs->ip6e_hbh, struct ip6_hbh *);
 =09=09u_int32_t dummy1; /* XXX unused */
 =09=09u_int32_t dummy2; /* XXX unused */
=20
@@ -974,6 +1212,14 @@
 =09=09 * fragment if possible.
 =09=09 * Must be able to put at least 8 bytes per fragment.
 =09=09 */
+       =20
+        unfragpartlen =3D sizeof(struct ip6_hdr);
+        if (exthdrs->ip6e_hbh) unfragpartlen +=3D exthdrs->ip6e_hbh->m_len;
+        if (exthdrs->ip6e_dest1) unfragpartlen +=3D
+                                             exthdrs->ip6e_dest1->m_len;
+        if (exthdrs->ip6e_rthdr) unfragpartlen +=3D
+                                              exthdrs->ip6e_rthdr->m_len;
+
 =09=09hlen =3D unfragpartlen;
 =09=09if (mtu > IPV6_MAXPACKET)
 =09=09=09mtu =3D IPV6_MAXPACKET;
@@ -1010,15 +1256,15 @@
 =09=09 * Change the next header field of the last header in the
 =09=09 * unfragmentable part.
 =09=09 */
-=09=09if (exthdrs.ip6e_rthdr) {
-=09=09=09nextproto =3D *mtod(exthdrs.ip6e_rthdr, u_char *);
-=09=09=09*mtod(exthdrs.ip6e_rthdr, u_char *) =3D IPPROTO_FRAGMENT;
-=09=09} else if (exthdrs.ip6e_dest1) {
-=09=09=09nextproto =3D *mtod(exthdrs.ip6e_dest1, u_char *);
-=09=09=09*mtod(exthdrs.ip6e_dest1, u_char *) =3D IPPROTO_FRAGMENT;
-=09=09} else if (exthdrs.ip6e_hbh) {
-=09=09=09nextproto =3D *mtod(exthdrs.ip6e_hbh, u_char *);
-=09=09=09*mtod(exthdrs.ip6e_hbh, u_char *) =3D IPPROTO_FRAGMENT;
+=09=09if (exthdrs->ip6e_rthdr) {
+=09=09=09nextproto =3D *mtod(exthdrs->ip6e_rthdr, u_char *);
+=09=09=09*mtod(exthdrs->ip6e_rthdr, u_char *) =3D IPPROTO_FRAGMENT;
+=09=09} else if (exthdrs->ip6e_dest1) {
+=09=09=09nextproto =3D *mtod(exthdrs->ip6e_dest1, u_char *);
+=09=09=09*mtod(exthdrs->ip6e_dest1, u_char *) =3D IPPROTO_FRAGMENT;
+=09=09} else if (exthdrs->ip6e_hbh) {
+=09=09=09nextproto =3D *mtod(exthdrs->ip6e_hbh, u_char *);
+=09=09=09*mtod(exthdrs->ip6e_hbh, u_char *) =3D IPPROTO_FRAGMENT;
 =09=09} else {
 =09=09=09nextproto =3D ip6->ip6_nxt;
 =09=09=09ip6->ip6_nxt =3D IPPROTO_FRAGMENT;
@@ -1129,25 +1375,13 @@
 =09} else if (ro_pmtu =3D=3D &ip6route && ro_pmtu->ro_rt) {
 =09=09RTFREE(ro_pmtu->ro_rt);
 =09}
+   =20
+    return (error);
=20
-#ifdef IPSEC
-=09if (sp !=3D NULL)
-=09=09key_freesp(sp);
-#endif /* IPSEC */
-
-=09return (error);
-
-freehdrs:
-=09m_freem(exthdrs.ip6e_hbh);=09/* m_freem will check if mbuf is 0 */
-=09m_freem(exthdrs.ip6e_dest1);
-=09m_freem(exthdrs.ip6e_rthdr);
-=09m_freem(exthdrs.ip6e_dest2);
-=09/* FALLTHROUGH */
 bad:
-=09m_freem(m);
-=09goto done;
+    m_freem(m);
+    goto done;
 }
-
 static int
 ip6_copyexthdr(mp, hdr, hlen)
 =09struct mbuf **mp;
@@ -1809,7 +2043,7 @@
 =09=09=09=09}
 =09=09=09=09break;
=20
-#ifdef IPSEC
+#if defined(IPSEC) || defined(FAST_IPSEC)
 =09=09=09case IPV6_IPSEC_POLICY:
 =09=09=09{
 =09=09=09=09caddr_t req =3D NULL;
@@ -2015,7 +2249,7 @@
 =09=09=09=09    in6p->in6p_moptions, mp);
 =09=09=09=09break;
=20
-#ifdef IPSEC
+#if defined(IPSEC) || defined(FAST_IPSEC)
 =09=09=09case IPV6_IPSEC_POLICY:
 =09=09=09    {
 =09=09=09=09caddr_t req =3D NULL;
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netinet6/raw_ip6.c /home/zul/=
netbsd-dev/src/sys/netinet6/raw_ip6.c
--- /home/zul/tmp/src/sys/netinet6/raw_ip6.c=092006-07-24 00:06:13.000000000=
 +0200
+++ /home/zul/netbsd-dev/src/sys/netinet6/raw_ip6.c=092006-10-01 00:53:36.00=
0000000 +0200
@@ -98,6 +98,12 @@
 #include <netinet6/ipsec.h>
 #endif /* IPSEC */
=20
+#ifdef FAST_IPSEC
+#include <netipsec/ipsec.h>
+#include <netipsec/ipsec_var.h> /* XXX ipsecstat namespace */
+#include <netipsec/ipsec6.h>
+#endif
+
 #include <machine/stdarg.h>
=20
 #include "faith.h"
@@ -204,6 +210,12 @@
 =09=09=09=09/* do not inject data into pcb */
 =09=09=09} else
 #endif /* IPSEC */
+#ifdef FAST_IPSEC
+            /*
+             * Check AH/ESP integrity
+             */
+            if ( !ipsec6_in_reject(m,last))=20
+#endif /* FAST_IPSEC */
 =09=09=09if ((n =3D m_copy(m, 0, (int)M_COPYALL)) !=3D NULL) {
 =09=09=09=09if (last->in6p_flags & IN6P_CONTROLOPTS)
 =09=09=09=09=09ip6_savecontrol(last, &opts, ip6, n);
@@ -234,6 +246,20 @@
 =09=09/* do not inject data into pcb */
 =09} else
 #endif /* IPSEC */
+#ifdef FAST_IPSEC
+=09if (last && ipsec6_in_reject(m, last)) {
+=09=09m_freem(m);
+        /*
+         * XXX ipsec6_in_reject update stat if there is an error
+         * so we just need to update stats by hand in the case of last is
+         * NULL
+         */
+        if ( !last )
+=09=09    ipsec6stat.in_polvio++;
+=09=09ip6stat.ip6s_delivered--;
+=09=09/* do not inject data into pcb */
+=09} else
+#endif /* FAST_IPSEC */
 =09if (last) {
 =09=09if (last->in6p_flags & IN6P_CONTROLOPTS)
 =09=09=09ip6_savecontrol(last, &opts, ip6, m);
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netipsec/ipcomp_var.h /home/z=
ul/netbsd-dev/src/sys/netipsec/ipcomp_var.h
--- /home/zul/tmp/src/sys/netipsec/ipcomp_var.h=092005-12-11 00:44:08.000000=
000 +0100
+++ /home/zul/netbsd-dev/src/sys/netipsec/ipcomp_var.h=092006-07-19 17:44:43=
.000000000 +0200
@@ -56,6 +56,7 @@
 =09u_int64_t=09ipcomps_ibytes;=09/* Input bytes */
 =09u_int64_t=09ipcomps_obytes;=09/* Output bytes */
 =09u_int64_t=09ipcomps_toobig;=09/* Packet got > IP_MAXPACKET */
+    u_int64_t   ipcomps_minlen; /* Packet too short for compress */
 =09u_int64_t=09ipcomps_pdrops;=09/* Packet blocked due to policy */
 =09u_int64_t=09ipcomps_crypto;=09/* "Crypto" processing failure */
 =09u_int64_t=09ipcomps_hist[IPCOMP_ALG_MAX];/* Per-algorithm op count */
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netipsec/ipsec.c /home/zul/ne=
tbsd-dev/src/sys/netipsec/ipsec.c
--- /home/zul/tmp/src/sys/netipsec/ipsec.c=092006-10-13 22:53:59.000000000 +=
0200
+++ /home/zul/netbsd-dev/src/sys/netipsec/ipsec.c=092006-11-13 21:35:22.0000=
00000 +0100
@@ -722,6 +722,60 @@
 =09return sp;
 }
=20
+#ifdef INET6
+struct secpolicy *
+ipsec6_checkpolicy(m, dir, flag, error, in6p)
+    struct mbuf *m;
+    u_int dir, flag;
+    int *error;
+    struct in6pcb *in6p;
+{
+    struct secpolicy *sp;
+
+    *error =3D 0;
+
+
+    /* XXX KAME IPv6 calls us with non-null inp but bogus inp_socket? */
+    if (in6p =3D=3D NULL || in6p->in6p_socket =3D=3D NULL) {
+        sp =3D ipsec_getpolicybyaddr(m, dir, flag, error);
+    } else
+        sp =3D ipsec_getpolicybysock(m, dir, IN6PCB_TO_PCB(in6p), error);
+    if (sp =3D=3D NULL) {
+        IPSEC_ASSERT(*error !=3D 0,
+            ("ipsec6_checkpolicy: getpolicy failed w/o error"));
+        newipsecstat.ips_out_inval++;
+        return NULL;
+    }
+    IPSEC_ASSERT(*error =3D=3D 0,
+        ("ipsec6_checkpolicy: sp w/ error set to %u", *error));
+    switch (sp->policy) {
+    case IPSEC_POLICY_ENTRUST:
+    default:
+        printf("ipsec6_checkpolicy: invalid policy %u\n", sp->policy);
+        /* fall thru... */
+    case IPSEC_POLICY_DISCARD:
+        newipsecstat.ips_out_polvio++;
+        *error =3D -EINVAL;   /* packet is discarded by caller */
+        break;
+    case IPSEC_POLICY_BYPASS:
+    case IPSEC_POLICY_NONE:
+        KEY_FREESP(&sp);
+        sp =3D NULL;      /* NB: force NULL result */
+        break;
+    case IPSEC_POLICY_IPSEC:
+        if (sp->req =3D=3D NULL)    /* acquire an SA */
+            *error =3D key_spdacquire(sp);
+        break;
+    }
+    if (*error !=3D 0) {
+        KEY_FREESP(&sp);
+        sp =3D NULL;
+    }
+    DPRINTF(("ipsecpol: done, sp %p error %d, \n", sp, *error));
+    return sp;
+}
+#endif /* INET6 */
+
 static int
 ipsec4_setspidx_inpcb(m, pcb)
 =09struct mbuf *m;
@@ -2165,6 +2219,106 @@
 =09printf("---\n");
 }
=20
+#ifdef INET6
+struct secpolicy *=20
+ipsec6_check_policy(m,so,flags,needipsecp,errorp)
+    struct mbuf * m;
+    const struct socket * so;
+    int flags;
+    int * needipsecp;
+    int * errorp;
+{
+    struct in6pcb *in6p =3D NULL;
+    struct m_tag *mtag;
+    struct secpolicy *sp =3D NULL;
+    struct tdb_ident *tdbi;
+    int s;
+    int error =3D 0;
+    int needipsec =3D 0;
+
+    if (so !=3D NULL && so->so_proto->pr_domain->dom_family =3D=3D AF_INET6=
)
+            in6p =3D sotoin6pcb(so);
+
+    mtag =3D m_tag_find(m, PACKET_TAG_IPSEC_PENDING_TDB, NULL);
+    s =3D splsoftnet();
+    if (mtag !=3D NULL) {
+        tdbi =3D (struct tdb_ident *)(mtag + 1);
+        sp =3D ipsec_getpolicy(tdbi, IPSEC_DIR_OUTBOUND);
+        if (sp =3D=3D NULL)
+            error =3D -EINVAL;    /* force silent drop */
+        m_tag_delete(m, mtag);
+    } else {
+        if ( in6p !=3D NULL &&
+             IPSEC_PCB_SKIP_IPSEC(in6p->in6p_sp, IPSEC_DIR_OUTBOUND))
+            goto skippolicycheck;
+       sp =3D ipsec6_checkpolicy(m, IPSEC_DIR_OUTBOUND, flags, &error, in6p=
);
+    }
+
+        /*
+     * There are four return cases:
+     *    sp !=3D NULL            apply IPsec policy
+     *    sp =3D=3D NULL, error =3D=3D 0        no IPsec handling needed
+     *    sp =3D=3D NULL, error =3D=3D -EINVAL  discard packet w/o error
+     *    sp =3D=3D NULL, error !=3D 0        discard packet, report error
+     */
+    if (sp =3D=3D NULL) {
+        splx(s);
+
+        if (error !=3D 0) {
+            needipsec =3D 0;
+        } else {
+            /* No IPsec processing for this packet. */
+            needipsec =3D 0;
+        }
+    } else {
+        /* Loop detection, check if ipsec processing already done */
+        IPSEC_ASSERT(sp->req !=3D NULL, ("ip6_output: no ipsec request"));
+        for (mtag =3D m_tag_first(m); mtag !=3D NULL;
+             mtag =3D m_tag_next(m, mtag)) {
+#ifdef MTAG_ABI_COMPAT
+            if (mtag->m_tag_cookie !=3D MTAG_ABI_COMPAT)
+                continue;
+#endif
+            if (mtag->m_tag_id !=3D PACKET_TAG_IPSEC_OUT_DONE &&
+                mtag->m_tag_id !=3D PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED)
+                continue;
+            /*
+             * Check if policy has an SA associated with it.
+             * This can happen when an SP has yet to acquire
+             * an SA; e.g. on first reference.  If it occurs,
+             * then we let ipsec4_process_packet do its thing.
+             */
+            if (sp->req->sav =3D=3D NULL)
+                break;
+            tdbi =3D (struct tdb_ident *)(mtag + 1);
+            if (tdbi->spi =3D=3D sp->req->sav->spi &&
+                tdbi->proto =3D=3D sp->req->sav->sah->saidx.proto &&
+                bcmp(&tdbi->dst, &sp->req->sav->sah->saidx.dst,
+                 sizeof (union sockaddr_union)) =3D=3D 0) {
+                /*
+                 * No IPsec processing is needed, free
+                 * reference to SP.
+                 *
+                 * NB: null pointer to avoid free at
+                 *     done: below.
+                 */
+                KEY_FREESP(&sp), sp =3D NULL;
+                needipsec =3D 0;
+                splx(s);
+                goto skippolicycheck;
+            }
+        }
+        splx(s);
+        needipsec =3D 1;
+    }
+skippolicycheck:;
+
+    *errorp =3D error;
+    *needipsecp =3D needipsec;
+    return sp;
+}
+#endif
+
 /* XXX this stuff doesn't belong here... */
=20
 static=09struct xformsw* xforms =3D NULL;
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netipsec/ipsec.h /home/zul/ne=
tbsd-dev/src/sys/netipsec/ipsec.h
--- /home/zul/tmp/src/sys/netipsec/ipsec.h=092006-10-13 22:53:59.000000000 +=
0200
+++ /home/zul/netbsd-dev/src/sys/netipsec/ipsec.h=092006-11-13 21:35:22.0000=
00000 +0100
@@ -150,6 +150,18 @@
 =09int count;=09=09/* for lifetime */
 =09/* XXX: here is mbuf place holder to be sent ? */
 };
+
+
+/*=20
+ * structure used to callback into the ip stack when ipsec processing was
+ * done
+ * arg is an opaque type which must not be accessed by ipsec processing
+ */
+struct ip_callback {
+    int (*fn)(struct mbuf *, struct ip_callback *);
+    char ip_callback_args[1];
+};
+
 #endif /* _KERNEL */
=20
 /* according to IANA assignment, port 0x0000 and proto 0xff are reserved. *=
/
@@ -328,8 +340,9 @@
 extern int ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
 =09=09=09int skip, int protoff, struct m_tag *mt);
 extern int ipsec4_process_packet __P((struct mbuf *, struct ipsecrequest *,
-=09=09=09int, int));
-extern int ipsec_process_done __P((struct mbuf *, struct ipsecrequest *));
+=09=09=09int, int, struct ip_callback *));
+extern int ipsec_process_done __P((struct mbuf *, struct ipsecrequest *,
+                                  int, int, struct ip_callback *));
 #define ipsec_indone(m)=09\
 =09(m_tag_find((m), PACKET_TAG_IPSEC_IN_DONE, NULL) !=3D NULL)
=20
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netipsec/ipsec6.h /home/zul/n=
etbsd-dev/src/sys/netipsec/ipsec6.h
--- /home/zul/tmp/src/sys/netipsec/ipsec6.h=092005-12-11 00:44:08.000000000 =
+0100
+++ /home/zul/netbsd-dev/src/sys/netipsec/ipsec6.h=092006-11-05 12:41:53.000=
000000 +0100
@@ -70,6 +70,13 @@
 =09caddr_t request, size_t len, int priv));
 extern int ipsec6_get_policy
 =09__P((struct in6pcb *inp, caddr_t request, size_t len, struct mbuf **mp))=
;
+
+extern struct secpolicy *ipsec6_checkpolicy __P((struct mbuf *, u_int,=20
+    u_int, int *, struct in6pcb *));
+
+struct secpolicy * ipsec6_check_policy(struct mbuf *,=20
+     const struct socket *, int, int*,int*);
+
 extern int ipsec6_in_reject __P((struct mbuf *, struct in6pcb *));
 /*
  * KAME ipsec6_in_reject_so(struct mbuf*, struct so)  compatibility shim
@@ -102,6 +109,9 @@
 =09struct mbuf *, struct secpolicy *, int, int *));
 extern int ipsec6_output_tunnel __P((struct ipsec_output_state *,
 =09struct secpolicy *, int));
+
+int ipsec6_process_packet __P((struct mbuf*,struct ipsecrequest *,=20
+                              int, int, struct ip_callback *));
 #endif /*_KERNEL*/
=20
 #endif /* !_NETIPSEC_IPSEC6_H_ */
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netipsec/ipsec_input.c /home/=
zul/netbsd-dev/src/sys/netipsec/ipsec_input.c
--- /home/zul/tmp/src/sys/netipsec/ipsec_input.c=092006-10-13 22:53:59.00000=
0000 +0200
+++ /home/zul/netbsd-dev/src/sys/netipsec/ipsec_input.c=092006-11-13 21:35:2=
2.000000000 +0100
@@ -413,8 +413,9 @@
=20
 =09=09m_tag_prepend(m, mtag);
 =09} else {
-=09=09mt->m_tag_id =3D PACKET_TAG_IPSEC_IN_DONE;
-=09=09/* XXX do we need to mark m_flags??? */
+        if ( mt !=3D NULL )
+=09=09    mt->m_tag_id =3D PACKET_TAG_IPSEC_IN_DONE;
+=09=09    /* XXX do we need to mark m_flags??? */
 =09}
=20
 =09key_sa_recordxfer(sav, m);=09=09/* record data transfer */
@@ -603,7 +604,7 @@
=20
 =09/* Sanity check */
 =09if (m =3D=3D NULL) {
-=09=09DPRINTF(("ipsec4_common_input_cb: null mbuf"));
+=09=09DPRINTF(("ipsec6_common_input_cb: null mbuf"));
 =09=09IPSEC_ISTAT(sproto, espstat.esps_badkcr, ahstat.ahs_badkcr,
 =09=09    ipcompstat.ipcomps_badkcr);
 =09=09error =3D EINVAL;
@@ -614,7 +615,7 @@
 =09if (m->m_len < sizeof(struct ip6_hdr) &&
 =09    (m =3D m_pullup(m, sizeof(struct ip6_hdr))) =3D=3D NULL) {
=20
-=09=09DPRINTF(("ipsec_common_input_cb: processing failed "
+=09=09DPRINTF(("ipsec6_common_input_cb: processing failed "
 =09=09    "for SA %s/%08lx\n", ipsec_address(&sav->sah->saidx.dst),
 =09=09    (u_long) ntohl(sav->spi)));
=20
@@ -649,7 +650,7 @@
 =09=09    (saidx->proxy.sa.sa_family !=3D AF_INET &&
 =09=09=09saidx->proxy.sa.sa_family !=3D 0)) {
=20
-=09=09=09DPRINTF(("ipsec_common_input_cb: inner "
+=09=09=09DPRINTF(("ipsec6_common_input_cb: inner "
 =09=09=09    "source address %s doesn't correspond to "
 =09=09=09    "expected proxy source %s, SA %s/%08lx\n",
 =09=09=09    inet_ntoa4(ipn.ip_src),
@@ -686,7 +687,7 @@
 =09=09    (saidx->proxy.sa.sa_family !=3D AF_INET6 &&
 =09=09=09saidx->proxy.sa.sa_family !=3D 0)) {
=20
-=09=09=09DPRINTF(("ipsec_common_input_cb: inner "
+=09=09=09DPRINTF(("ipsec6_common_input_cb: inner "
 =09=09=09    "source address %s doesn't correspond to "
 =09=09=09    "expected proxy source %s, SA %s/%08lx\n",
 =09=09=09    ip6_sprintf(&ip6n.ip6_src),
@@ -714,7 +715,7 @@
 =09=09mtag =3D m_tag_get(PACKET_TAG_IPSEC_IN_DONE,
 =09=09    sizeof(struct tdb_ident), M_NOWAIT);
 =09=09if (mtag =3D=3D NULL) {
-=09=09=09DPRINTF(("ipsec_common_input_cb: failed to "
+=09=09=09DPRINTF(("ipsec6_common_input_cb: failed to "
 =09=09=09    "get tag\n"));
 =09=09=09IPSEC_ISTAT(sproto, espstat.esps_hdrops,
 =09=09=09    ahstat.ahs_hdrops, ipcompstat.ipcomps_hdrops);
@@ -729,8 +730,9 @@
=20
 =09=09m_tag_prepend(m, mtag);
 =09} else {
-=09=09mt->m_tag_id =3D PACKET_TAG_IPSEC_IN_DONE;
-=09=09/* XXX do we need to mark m_flags??? */
+        if ( mt !=3D NULL )
+=09=09    mt->m_tag_id =3D PACKET_TAG_IPSEC_IN_DONE;
+=09=09    /* XXX do we need to mark m_flags??? */
 =09}
=20
 =09key_sa_recordxfer(sav, m);
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netipsec/ipsec_netbsd.c /home=
/zul/netbsd-dev/src/sys/netipsec/ipsec_netbsd.c
--- /home/zul/tmp/src/sys/netipsec/ipsec_netbsd.c=092006-05-14 23:19:34.0000=
00000 +0200
+++ /home/zul/netbsd-dev/src/sys/netipsec/ipsec_netbsd.c=092006-06-08 11:13:=
33.000000000 +0200
@@ -68,6 +68,7 @@
 #include <netipsec/key.h>
 #include <netipsec/keydb.h>
 #include <netipsec/key_debug.h>
+#include <netipsec/ah.h>
 #include <netipsec/ah_var.h>
 #include <netipsec/esp.h>
 #include <netipsec/esp_var.h>
@@ -206,6 +207,93 @@
=20
 #ifdef INET6
 void
+ah6_ctlinput(cmd, sa, d)
+=09int cmd;
+=09struct sockaddr *sa;
+=09void *d;
+{
+=09const struct newah *ahp;
+=09struct newah ah;
+=09struct secasvar *sav;
+=09struct ip6_hdr *ip6;
+=09struct mbuf *m;
+=09struct ip6ctlparam *ip6cp =3D NULL;
+=09int off;
+
+=09if (sa->sa_family !=3D AF_INET6 ||
+=09    sa->sa_len !=3D sizeof(struct sockaddr_in6))
+=09=09return;
+=09if ((unsigned)cmd >=3D PRC_NCMDS)
+=09=09return;
+
+=09/* if the parameter is from icmp6, decode it. */
+=09if (d !=3D NULL) {
+=09=09ip6cp =3D (struct ip6ctlparam *)d;
+=09=09m =3D ip6cp->ip6c_m;
+=09=09ip6 =3D ip6cp->ip6c_ip6;
+=09=09off =3D ip6cp->ip6c_off;
+=09} else {
+=09=09m =3D NULL;
+=09=09ip6 =3D NULL;
+=09=09off =3D 0;
+=09}
+
+=09if (ip6) {
+=09=09/*
+=09=09 * XXX: We assume that when ip6 is non NULL,
+=09=09 * M and OFF are valid.
+=09=09 */
+
+=09=09/* check if we can safely examine src and dst ports */
+=09=09if (m->m_pkthdr.len < off + sizeof(ah))
+=09=09=09return;
+
+=09=09if (m->m_len < off + sizeof(ah)) {
+=09=09=09/*
+=09=09=09 * this should be rare case,
+=09=09=09 * so we compromise on this copy...
+=09=09=09 */
+=09=09=09m_copydata(m, off, sizeof(ah), (caddr_t)&ah);
+=09=09=09ahp =3D &ah;
+=09=09} else
+=09=09=09ahp =3D (struct newah *)(mtod(m, caddr_t) + off);
+
+=09=09if (cmd =3D=3D PRC_MSGSIZE) {
+=09=09=09int valid =3D 0;
+
+=09=09=09/*
+=09=09=09 * Check to see if we have a valid SA corresponding to
+=09=09=09 * the address in the ICMP message payload.
+=09=09=09 */
+=09=09=09sav =3D KEY_ALLOCSA((union sockaddr_union*)sa,
+=09=09=09=09=09  IPPROTO_AH, ahp->ah_spi);
+
+=09=09=09if (sav) {
+=09=09=09=09if (sav->state =3D=3D SADB_SASTATE_MATURE ||
+=09=09=09=09    sav->state =3D=3D SADB_SASTATE_DYING)
+=09=09=09=09=09valid++;
+=09=09=09=09KEY_FREESAV(&sav);
+=09=09=09}
+
+=09=09=09/* XXX Further validation? */
+
+=09=09=09/*
+=09=09=09 * Depending on the value of "valid" and routing table
+=09=09=09 * size (mtudisc_{hi,lo}wat), we will:
+=09=09=09 * - recalcurate the new MTU and create the
+=09=09=09 *   corresponding routing entry, or
+=09=09=09 * - ignore the MTU change notification.
+=09=09=09 */
+=09=09=09icmp6_mtudisc_update((struct ip6ctlparam *)d, valid);
+=09=09}
+
+=09=09/* we normally notify single pcb here */
+=09} else {
+=09=09/* we normally notify any pcb here */
+=09}
+}
+
+void
 esp6_ctlinput(cmd, sa, d)
 =09int cmd;
 =09struct sockaddr *sa;
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netipsec/ipsec_output.c /home=
/zul/netbsd-dev/src/sys/netipsec/ipsec_output.c
--- /home/zul/tmp/src/sys/netipsec/ipsec_output.c=092006-10-13 22:53:59.0000=
00000 +0200
+++ /home/zul/netbsd-dev/src/sys/netipsec/ipsec_output.c=092006-11-13 21:36:=
10.000000000 +0100
@@ -92,7 +92,8 @@
 #include <net/net_osdep.h>=09=09/* ovbcopy() in ipsec6_encapsulate() */
=20
 int
-ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
+ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr,
+                   int skip, int protoff, struct ip_callback * ip_cb)
 {
 =09struct tdb_ident *tdbi;
 =09struct m_tag *mtag;
@@ -166,7 +167,22 @@
 =09 */
 =09if (isr->next) {
 =09=09newipsecstat.ips_out_bundlesa++;
-=09=09return ipsec4_process_packet(m, isr->next, 0, 0);
+        switch ( saidx->dst.sa.sa_family ) {
+#ifdef INET
+            case AF_INET:
+=09=09        return ipsec4_process_packet(m, isr->next, 0, 0,ip_cb);
+#endif /* INET */
+#ifdef INET6
+            case AF_INET6:
+                return ipsec6_process_packet(m,isr->next,skip,protoff,
+                                             ip_cb);
+#endif /* INET6 */
+            default :
+=09=09        DPRINTF(("ipsec_process_done: unknown protocol family %u\n",
+=09=09                saidx->dst.sa.sa_family));
+=09=09        error =3D ENXIO;
+=09=09        goto bad;
+        }
 =09}
=20
 =09/*
@@ -184,22 +200,21 @@
 =09=09ip->ip_len =3D ntohs(ip->ip_len);
 =09=09ip->ip_off =3D ntohs(ip->ip_off);
 #endif /* __FreeBSD_ */
-=09=09return ip_output(m, NULL, NULL, IP_RAWOUTPUT,
-=09=09    (struct ip_moptions *)NULL, (struct socket *)NULL);
-
-#endif /* INET */
+        return ip_cb->fn(m, ip_cb);
+#endif /* INET */=20
 #ifdef INET6
 =09case AF_INET6:
 =09=09/*
 =09=09 * We don't need massage, IPv6 header fields are always in
 =09=09 * net endian.
 =09=09 */
-=09=09return ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
+        return ip_cb->fn(m, ip_cb);
 #endif /* INET6 */
 =09}
 =09panic("ipsec_process_done");
 bad:
 =09m_freem(m);
+    free(ip_cb,M_TEMP);
 =09KEY_FREESAV(&sav);
 =09return (error);
 }
@@ -347,11 +362,11 @@
  */
 int
 ipsec4_process_packet(
-    struct mbuf *m,
-    struct ipsecrequest *isr,
-    int flags __unused,
-    int tunalready
-)
+=09struct mbuf *m,
+=09struct ipsecrequest *isr,
+=09int flags __unused,
+=09int tunalready,
+    struct ip_callback * ip_cb)
 {
 =09struct secasindex saidx;
 =09struct secasvar *sav;
@@ -433,7 +448,7 @@
 #endif
=20
 =09=09=09/* Encapsulate the packet */
-=09=09=09error =3D ipip_output(m, isr, &mp, 0, 0);
+=09=09=09error =3D ipip_output(m, isr, &mp, 0, 0, ip_cb);
 =09=09=09if (mp =3D=3D NULL && !error) {
 =09=09=09=09/* Should never happen. */
 =09=09=09=09DPRINTF(("ipsec4_process_packet: ipip_output "
@@ -484,9 +499,10 @@
 =09=09ip =3D mtod(m, struct ip *);
 =09=09i =3D ip->ip_hl << 2;
 =09=09off =3D offsetof(struct ip, ip_p);
-=09=09error =3D (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off);
+=09=09error =3D (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off,ip_cb);
 =09} else {
-=09=09error =3D ipsec_process_done(m, isr);
+        /* skip and protoff are unused for v4 case */
+=09=09error =3D ipsec_process_done(m, isr, 0, 0, ip_cb);=20
 =09}
 =09splx(s);
 =09return error;
@@ -494,11 +510,113 @@
 =09splx(s);
 =09if (m)
 =09=09m_freem(m);
+    if (ip_cb)
+        free(ip_cb,M_TEMP);
 =09return error;
 }
 #endif
=20
 #ifdef INET6
+int
+ipsec6_process_packet(
+=09struct mbuf *m,
+=09struct ipsecrequest *isr,
+    int skip,
+    int protoff,
+    struct ip_callback * ip_cb
+    )
+{
+=09struct secasindex saidx;
+=09struct secasvar *sav;
+    struct ip6_hdr *ip6;
+=09int s, error;=20
+
+=09IPSEC_ASSERT(m !=3D NULL, ("ipsec6_process_packet: null mbuf"));
+=09IPSEC_ASSERT(isr !=3D NULL, ("ipsec6_process_packet: null isr"));
+
+=09s =3D splsoftnet();=09=09=09/* insure SA contents don't change */
+
+=09isr =3D ipsec_nextisr(m, isr, AF_INET6, &saidx, &error);
+=09if (isr =3D=3D NULL) {
+        // XXX Should we send a notification ?
+=09=09goto bad;
+    }
+
+=09sav =3D isr->sav;
+=09if (sav->tdb_xform->xf_type !=3D XF_IP4) {
+=09=09error =3D (*sav->tdb_xform->xf_output)(m, isr, NULL, skip,=20
+                                             protoff, ip_cb);
+=09} else {
+=09=09union sockaddr_union *dst =3D &sav->sah->saidx.dst;
+
+        ip6 =3D mtod(m, struct ip6_hdr *);
+
+=09=09/* Do the appropriate encapsulation, if necessary */
+=09=09if (isr->saidx.mode =3D=3D IPSEC_MODE_TUNNEL || /* Tunnel requ'd */
+=09=09    dst->sa.sa_family !=3D AF_INET6 ||=09    /* PF mismatch */
+  =20
+            ((dst->sa.sa_family =3D=3D AF_INET6) &&
+                (!IN6_IS_ADDR_UNSPECIFIED(&dst->sin6.sin6_addr)) &&
+                (!IN6_ARE_ADDR_EQUAL(&dst->sin6.sin6_addr,
+                &ip6->ip6_dst)))=20
+            )
+        {
+=09=09=09struct mbuf *mp;
+
+            /* Fix IPv6 header payload length. */
+            if (m->m_len < sizeof(struct ip6_hdr))
+                if ((m =3D m_pullup(m,sizeof(struct ip6_hdr))) =3D=3D NULL)
+                    return ENOBUFS;
+
+            if (m->m_pkthdr.len - sizeof(*ip6) > IPV6_MAXPACKET) {
+                /* No jumbogram support. */
+                m_freem(m);
+                return ENXIO;   /*XXX*/
+            }
+            ip6 =3D mtod(m, struct ip6_hdr *);
+            ip6->ip6_plen =3D htons(m->m_pkthdr.len - sizeof(*ip6));
+
+=09=09    /* Encapsulate the packet */
+=09=09    error =3D ipip_output(m, isr, &mp, 0, 0, ip_cb);
+=09=09    if (mp =3D=3D NULL && !error) {
+=09=09=09    /* Should never happen. */
+=09=09=09    DPRINTF(("ipsec6_process_packet: ipip_output "
+=09=09=09=09    "returns no mbuf and no error!"));
+=09=09=09    error =3D EFAULT;
+=09=09    }
+=09=09    if (error) {
+=09=09=09    if (mp) {
+=09=09=09=09    /* XXX: Should never happen! */
+=09=09=09=09    m_freem(mp);
+=09=09=09    }
+=09=09=09    m =3D NULL; /* ipip_output() already freed it */
+=09=09=09    goto bad;
+=09=09    }
+=09=09
+            m =3D mp;
+            mp =3D NULL;
+           =20
+            /*=20
+             * here paquet is tunnelled. Compute the new values of skip and
+             * protoff
+             */
+           =20
+            skip =3D sizeof(struct ip6_hdr);
+            protoff =3D offsetof(struct ip6_hdr, ip6_nxt);
+        }
+=09=09error =3D ipsec_process_done(m, isr,skip,protoff,ip_cb);
+=09}
+=09splx(s);
+=09return error;
+bad:
+=09splx(s);
+=09if (m)
+=09=09m_freem(m);
+    if ( ip_cb )
+        free(ip_cb,M_TEMP);
+=09return error;
+}
+#if 0
 /*
  * Chop IP6 header from the payload.
  */
@@ -538,6 +656,7 @@
 /*
  * IPsec output logic for IPv6, transport mode.
  */
+
 int
 ipsec6_output_trans(
     struct ipsec_output_state *state,
@@ -784,4 +903,5 @@
 =09state->m =3D NULL;
 =09return error;
 }
+#endif
 #endif /*INET6*/
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netipsec/key.c /home/zul/netb=
sd-dev/src/sys/netipsec/key.c
--- /home/zul/tmp/src/sys/netipsec/key.c=092006-10-13 22:53:59.000000000 +02=
00
+++ /home/zul/netbsd-dev/src/sys/netipsec/key.c=092006-11-13 21:50:18.000000=
000 +0100
@@ -102,6 +102,7 @@
=20
 #include <netipsec/xform.h>
 #include <netipsec/ipsec_osdep.h>
+#include <netipsec/ipcomp.h>
=20
 #include <machine/stdarg.h>
=20
@@ -1047,12 +1048,35 @@
 =09struct secasvar *sav;
 =09u_int stateidx, state;
 =09int s;
+    int must_check_spi =3D 1;
+    int must_check_alg =3D 0;
+    u_int16_t cpi =3D 0;
+    u_int8_t algo =3D 0;
=20
 =09IPSEC_ASSERT(dst !=3D NULL, ("key_allocsa: null dst address"));
=20
 =09KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
 =09=09printf("DP key_allocsa from %s:%u\n", where, tag));
=20
+    /*
+     * XXX IPCOMP case=20
+     * We use cpi to define spi here. In the case where cpi <=3D
+     * IPCOMP_CPI_NEGOTIATE_MIN, cpi just define the algorithm used, not
+     * the real spi. In this case, don't check the spi but check the
+     * algorithm
+     */
+   =20
+    if ( proto =3D=3D IPPROTO_IPCOMP ){
+        u_int32_t tmp;
+        tmp =3D ntohl(spi);
+        cpi =3D (u_int16_t) tmp;
+        if ( cpi < IPCOMP_CPI_NEGOTIATE_MIN ) {
+            algo =3D (u_int8_t) cpi;
+            must_check_spi =3D 0;
+            must_check_alg =3D 1;
+        }
+    }
+
 =09/*
 =09 * searching SAD.
 =09 * XXX: to be checked internal IP header somewhere.  Also when
@@ -1075,8 +1099,12 @@
 =09=09=09=09=09continue;
 =09=09=09=09if (proto !=3D sav->sah->saidx.proto)
 =09=09=09=09=09continue;
-=09=09=09=09if (spi !=3D sav->spi)
+=09=09=09=09if (must_check_spi && spi !=3D sav->spi)
 =09=09=09=09=09continue;
+
+                /* XXX only on the ipcomp case */
+                if (must_check_alg && algo !=3D sav->alg_comp )
+                    continue;
 #if 0=09/* don't check src */
 =09=09=09=09/* check src address */
 =09=09=09=09if (key_sockaddrcmp(&src->sa, &sav->sah->saidx.src.sa, 0) !=3D =
0)
@@ -1767,32 +1795,6 @@
 =09dst0 =3D (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST];
 =09xpl0 =3D (struct sadb_x_policy *)mhp->ext[SADB_X_EXT_POLICY];
=20
-#if defined(__NetBSD__) && defined(INET6)
-=09/*
-=09 * On NetBSD, FAST_IPSEC and INET6 can be configured together,
-=09 * but FAST_IPSEC does not protect IPv6 traffic.
-=09 * Rather than silently leaking IPv6 traffic for which IPsec
-=09 * is configured, forbid  specifying IPsec for IPv6 traffic.
-=09 *
-=09 * (On FreeBSD, both FAST_IPSEC and INET6 gives a compile-time error.)
-=09 */
-=09if (((const struct sockaddr *)(src0 + 1))->sa_family =3D=3D AF_INET6 ||
-=09    ((const struct sockaddr *)(dst0 + 1))->sa_family =3D=3D AF_INET6) {
-=09=09static int v6_warned =3D 0;
-
-=09=09if (v6_warned =3D=3D 0) {
-=09=09=09printf("key_spdadd: FAST_IPSEC does not support IPv6.");
-=09=09=09printf("Check syslog for more per-SPD warnings.\n");
-=09=09=09v6_warned++;
-=09=09}
-=09=09log(LOG_WARNING,
-=09=09    "FAST_IPSEC does not support PF_INET6 SPDs. "
-=09=09    "Request refused.\n");
-
-=09=09return EOPNOTSUPP;=09/* EPROTOTYPE?  EAFNOSUPPORT? */
-=09}
-#endif /* __NetBSD__ && INET6 */
-
 =09/* make secindex */
 =09/* XXX boundary check against sa_len */
 =09KEY_SETSECSPIDX(xpl0->sadb_x_policy_dir,
@@ -2404,9 +2406,10 @@
 =09return key_sendup_mbuf(so, m, KEY_SENDUP_ALL);
 }
=20
+
 static struct sockaddr key_src =3D {=20
-=09.sa_len =3D 2,=20
-=09.sa_family =3D PF_KEY,
+       .sa_len =3D 2,=20
+       .sa_family =3D PF_KEY,
 };
=20
 static struct mbuf *
@@ -3371,7 +3374,7 @@
 =09switch (sav->sah->saidx.proto) {
 =09case IPPROTO_ESP:
 =09case IPPROTO_AH:
-=09=09if (ntohl(sav->spi) <=3D 255) {
+=09=09if (ntohl(sav->spi) <=3D 255) { /* spi is always positive */
 =09=09=09ipseclog((LOG_DEBUG,
 =09=09=09    "key_mature: illegal range of SPI %u.\n",
 =09=09=09    (u_int32_t)ntohl(sav->spi)));
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netipsec/keysock.c /home/zul/=
netbsd-dev/src/sys/netipsec/keysock.c
--- /home/zul/tmp/src/sys/netipsec/keysock.c=092006-10-13 22:53:59.000000000=
 +0200
+++ /home/zul/netbsd-dev/src/sys/netipsec/keysock.c=092006-11-13 21:40:12.00=
0000000 +0100
@@ -72,6 +72,7 @@
 };
 static struct key_cb key_cb;
=20
+
 static struct sockaddr key_dst =3D {
     .sa_len =3D 2,
     .sa_family =3D PF_KEY,
@@ -81,7 +82,6 @@
     .sa_family =3D PF_KEY,
 };
=20
-
 static int key_sendup0 __P((struct rawcb *, struct mbuf *, int, int));
=20
 struct pfkeystat pfkeystat;
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netipsec/xform.h /home/zul/ne=
tbsd-dev/src/sys/netipsec/xform.h
--- /home/zul/tmp/src/sys/netipsec/xform.h=092005-12-11 00:44:08.000000000 +=
0100
+++ /home/zul/netbsd-dev/src/sys/netipsec/xform.h=092006-10-23 00:58:14.0000=
00000 +0200
@@ -94,7 +94,8 @@
 =09int=09(*xf_input)(struct mbuf*, struct secasvar*,=09/* input */
 =09=09=09int, int);
 =09int=09(*xf_output)(struct mbuf*,=09       =09=09/* output */
-=09=09=09struct ipsecrequest *, struct mbuf **, int, int);
+=09=09=09struct ipsecrequest *, struct mbuf **, int, int,=20
+            struct ip_callback *);
 =09struct xformsw *xf_next;=09=09/* list of registered xforms */
 };
=20
@@ -108,7 +109,7 @@
 extern=09int ip4_input6(struct mbuf **m, int *offp, int proto);
 extern=09void ip4_input(struct mbuf *m, ...);
 extern=09int ipip_output(struct mbuf *, struct ipsecrequest *,
-=09=09=09struct mbuf **, int, int);
+=09=09=09struct mbuf **, int, int, struct ip_callback*);
=20
 /* XF_AH */
 extern int ah_init0(struct secasvar *, struct xformsw *, struct cryptoini *=
);
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netipsec/xform_ah.c /home/zul=
/netbsd-dev/src/sys/netipsec/xform_ah.c
--- /home/zul/tmp/src/sys/netipsec/xform_ah.c=092006-10-13 22:53:59.00000000=
0 +0200
+++ /home/zul/netbsd-dev/src/sys/netipsec/xform_ah.c=092006-11-13 21:41:00.0=
00000000 +0100
@@ -955,12 +955,12 @@
  */
 static int
 ah_output(
-    struct mbuf *m,
-    struct ipsecrequest *isr,
-    struct mbuf **mp __unused,
-    int skip,
-    int protoff
-)
+=09struct mbuf *m,
+=09struct ipsecrequest *isr,
+=09struct mbuf **mp __unused,
+=09int skip,
+=09int protoff,
+    struct ip_callback * ip_cb)
 {
 =09struct secasvar *sav;
 =09struct auth_hash *ahx;
@@ -1175,11 +1175,14 @@
 =09tc->tc_proto =3D sav->sah->saidx.proto;
 =09tc->tc_skip =3D skip;
 =09tc->tc_protoff =3D protoff;
+    tc->tc_ptr =3D (caddr_t) ip_cb;
=20
 =09return crypto_dispatch(crp);
 bad:
 =09if (m)
 =09=09m_freem(m);
+    if (ip_cb)
+        free(ip_cb,M_TEMP);
 =09return (error);
 }
=20
@@ -1193,6 +1196,7 @@
 =09struct tdb_crypto *tc;
 =09struct ipsecrequest *isr;
 =09struct secasvar *sav;
+    struct ip_callback * ip_cb;
 =09struct mbuf *m;
 =09caddr_t ptr;
 =09int s, err;
@@ -1201,6 +1205,7 @@
 =09IPSEC_ASSERT(tc !=3D NULL, ("ah_output_cb: null opaque data area!"));
 =09skip =3D tc->tc_skip;
 =09protoff =3D tc->tc_protoff;
+    ip_cb =3D (struct ip_callback *) tc->tc_ptr;
 =09ptr =3D (caddr_t) (tc + 1);
 =09m =3D (struct mbuf *) crp->crp_buf;
=20
@@ -1267,7 +1272,7 @@
 #endif
=20
 =09/* NB: m is reclaimed by ipsec_process_done. */
-=09err =3D ipsec_process_done(m, isr);
+=09err =3D ipsec_process_done(m, isr, skip, protoff,ip_cb);
 =09KEY_FREESAV(&sav);
 =09splx(s);
 =09return err;
@@ -1277,6 +1282,8 @@
 =09splx(s);
 =09if (m)
 =09=09m_freem(m);
+    if (ip_cb)
+        free(ip_cb,M_TEMP);
 =09free(tc, M_XDATA);
 =09crypto_freereq(crp);
 =09return error;
@@ -1284,8 +1291,8 @@
=20
 static struct xformsw ah_xformsw =3D {
 =09XF_AH,=09=09XFT_AUTH,=09"IPsec AH",
-=09ah_init,=09ah_zeroize,=09ah_input,=09ah_output,
-=09NULL,
+=09ah_init,=09ah_zeroize,=09ah_input,=09ah_output,=20
+    NULL,
 };
=20
 INITFN void
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netipsec/xform_esp.c /home/zu=
l/netbsd-dev/src/sys/netipsec/xform_esp.c
--- /home/zul/tmp/src/sys/netipsec/xform_esp.c=092006-10-13 22:53:59.0000000=
00 +0200
+++ /home/zul/netbsd-dev/src/sys/netipsec/xform_esp.c=092006-11-13 21:41:38.=
000000000 +0100
@@ -667,11 +667,12 @@
  */
 static int
 esp_output(
-    struct mbuf *m,
-    struct ipsecrequest *isr,
-    struct mbuf **mp __unused,
-    int skip,
-    int protoff
+=09struct mbuf *m,
+=09struct ipsecrequest *isr,
+=09struct mbuf **mp __unused,
+=09int skip,
+=09int protoff,
+    struct ip_callback * ip_cb
 )
 {
 =09struct enc_xform *espx;
@@ -873,6 +874,9 @@
 =09tc->tc_spi =3D sav->spi;
 =09tc->tc_dst =3D saidx->dst;
 =09tc->tc_proto =3D saidx->proto;
+    tc->tc_skip =3D skip;
+    tc->tc_protoff =3D protoff;
+    tc->tc_ptr =3D (caddr_t) ip_cb;
=20
 =09/* Crypto operation descriptor. */
 =09crp->crp_ilen =3D m->m_pkthdr.len; /* Total input length. */
@@ -898,6 +902,8 @@
 bad:
 =09if (m)
 =09=09m_freem(m);
+    if (ip_cb)
+        free(ip_cb,M_TEMP);
 =09return (error);
 }
=20
@@ -910,8 +916,9 @@
 =09struct tdb_crypto *tc;
 =09struct ipsecrequest *isr;
 =09struct secasvar *sav;
+    struct ip_callback * ip_cb;
 =09struct mbuf *m;
-=09int s, err, error;
+=09int s, err, error , skip, protoff;
=20
 =09tc =3D (struct tdb_crypto *) crp->crp_opaque;
 =09IPSEC_ASSERT(tc !=3D NULL, ("esp_output_cb: null opaque data area!"));
@@ -920,6 +927,9 @@
 =09s =3D splsoftnet();
=20
 =09isr =3D tc->tc_isr;
+    ip_cb =3D (struct ip_callback *) tc->tc_ptr;
+    skip =3D tc->tc_skip;
+    protoff =3D tc->tc_protoff;
 =09sav =3D KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
 =09if (sav =3D=3D NULL) {
 =09=09espstat.esps_notdb++;
@@ -984,7 +994,7 @@
 #endif
=20
 =09/* NB: m is reclaimed by ipsec_process_done. */
-=09err =3D ipsec_process_done(m, isr);
+=09err =3D ipsec_process_done(m, isr, skip, protoff, ip_cb);
 =09KEY_FREESAV(&sav);
 =09splx(s);
 =09return err;
@@ -994,6 +1004,8 @@
 =09splx(s);
 =09if (m)
 =09=09m_freem(m);
+    if (ip_cb)
+        free(ip_cb,M_TEMP);
 =09free(tc, M_XDATA);
 =09crypto_freereq(crp);
 =09return error;
@@ -1002,8 +1014,8 @@
 static struct xformsw esp_xformsw =3D {
 =09XF_ESP,=09=09XFT_CONF|XFT_AUTH,=09"IPsec ESP",
 =09esp_init,=09esp_zeroize,=09=09esp_input,
-=09esp_output,
-=09NULL,
+=09esp_output,=20
+    NULL,
 };
=20
 INITFN void
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netipsec/xform_ipcomp.c /home=
/zul/netbsd-dev/src/sys/netipsec/xform_ipcomp.c
--- /home/zul/tmp/src/sys/netipsec/xform_ipcomp.c=092006-10-13 22:53:59.0000=
00000 +0200
+++ /home/zul/netbsd-dev/src/sys/netipsec/xform_ipcomp.c=092006-11-13 21:42:=
15.000000000 +0100
@@ -72,7 +72,7 @@
 #include <opencrypto/deflate.h>
 #include <opencrypto/xform.h>
=20
-int=09ipcomp_enable =3D 0;
+int=09ipcomp_enable =3D 1;
 struct=09ipcompstat ipcompstat;
=20
 #ifdef __FreeBSD__
@@ -334,22 +334,20 @@
  */
 static int
 ipcomp_output(
-    struct mbuf *m,
-    struct ipsecrequest *isr,
-    struct mbuf **mp __unused,
-    int skip,
-    int protoff
+=09struct mbuf *m,
+=09struct ipsecrequest *isr,
+=09struct mbuf **mp __unused,
+=09int skip,
+=09int protoff,
+    struct ip_callback * ip_cb
 )
 {
 =09struct secasvar *sav;
 =09struct comp_algo *ipcompx;
-=09int error, ralen, hlen, maxpacketsize, roff;
-=09u_int8_t prot;
+=09int error, ralen, hlen, maxpacketsize;
 =09struct cryptodesc *crdc;
 =09struct cryptop *crp;
 =09struct tdb_crypto *tc;
-=09struct mbuf *mo;
-=09struct ipcomp *ipcomp;
=20
 =09IPSEC_SPLASSERT_SOFTNET("ipcomp_output");
 =09sav =3D isr->sav;
@@ -358,6 +356,13 @@
 =09IPSEC_ASSERT(ipcompx !=3D NULL, ("ipcomp_output: null compression xform"=
));
=20
 =09ralen =3D m->m_pkthdr.len - skip;=09/* Raw payload length before comp. *=
/
+   =20
+    /* Don't process the packet if it is too short */
+    if ( ralen < ipcompx->minlen ){
+        ipcompstat.ipcomps_minlen++;
+        return ipsec_process_done(m,isr,skip, protoff, ip_cb);
+    }
+
 =09hlen =3D IPCOMP_HLENGTH;
=20
 =09ipcompstat.ipcomps_output++;
@@ -408,40 +413,6 @@
 =09=09goto bad;
 =09}
=20
-=09/* Inject IPCOMP header */
-=09mo =3D m_makespace(m, skip, hlen, &roff);
-=09if (mo =3D=3D NULL) {
-=09=09ipcompstat.ipcomps_wrap++;
-=09=09DPRINTF(("ipcomp_output: failed to inject IPCOMP header for "
-=09=09    "IPCA %s/%08lx\n",
-=09=09    ipsec_address(&sav->sah->saidx.dst),
-=09=09    (u_long) ntohl(sav->spi)));
-=09=09error =3D ENOBUFS;
-=09=09goto bad;
-=09}
-=09ipcomp =3D (struct ipcomp *)(mtod(mo, caddr_t) + roff);
-
-=09/* Initialize the IPCOMP header */
-=09/* XXX alignment always correct? */
-=09switch (sav->sah->saidx.dst.sa.sa_family) {
-#ifdef INET
-=09case AF_INET:
-=09=09ipcomp->comp_nxt =3D mtod(m, struct ip *)->ip_p;
-=09=09break;
-#endif /* INET */
-#ifdef INET6
-=09case AF_INET6:
-=09=09ipcomp->comp_nxt =3D mtod(m, struct ip6_hdr *)->ip6_nxt;
-=09=09break;
-#endif
-=09}
-=09ipcomp->comp_flags =3D 0;
-=09ipcomp->comp_cpi =3D htons((u_int16_t) ntohl(sav->spi));
-
-=09/* Fix Next Protocol in IPv4/IPv6 header */
-=09prot =3D IPPROTO_IPCOMP;
-=09m_copyback(m, protoff, sizeof(u_int8_t), (u_char *) &prot);
-
 =09/* Ok now, we can pass to the crypto processing */
=20
 =09/* Get crypto descriptors */
@@ -455,10 +426,10 @@
 =09crdc =3D crp->crp_desc;
=20
 =09/* Compression descriptor */
-=09crdc->crd_skip =3D skip + hlen;
-=09crdc->crd_len =3D m->m_pkthdr.len - (skip + hlen);
+=09crdc->crd_skip =3D skip;
+=09crdc->crd_len =3D m->m_pkthdr.len - skip;
 =09crdc->crd_flags =3D CRD_F_COMP;
-=09crdc->crd_inject =3D skip + hlen;
+=09crdc->crd_inject =3D skip;
=20
 =09/* Compression operation */
 =09crdc->crd_alg =3D ipcompx->type;
@@ -478,7 +449,9 @@
 =09tc->tc_spi =3D sav->spi;
 =09tc->tc_dst =3D sav->sah->saidx.dst;
 =09tc->tc_proto =3D sav->sah->saidx.proto;
-=09tc->tc_skip =3D skip + hlen;
+    tc->tc_protoff =3D protoff;
+=09tc->tc_skip =3D skip;
+    tc->tc_ptr =3D (caddr_t) ip_cb;
=20
 =09/* Crypto operation descriptor */
 =09crp->crp_ilen =3D m->m_pkthdr.len;=09/* Total input length */
@@ -492,6 +465,8 @@
 bad:
 =09if (m)
 =09=09m_freem(m);
+    if (ip_cb)
+        free(ip_cb,M_TEMP);
 =09return (error);
 }
=20
@@ -504,13 +479,19 @@
 =09struct tdb_crypto *tc;
 =09struct ipsecrequest *isr;
 =09struct secasvar *sav;
-=09struct mbuf *m;
-=09int s, error, skip, rlen;
+    struct ip_callback * ip_cb;
+=09struct mbuf *m, *mo;
+=09int s, error, skip, rlen, roff, protoff;
+    u_int8_t prot;
+    u_int16_t cpi;
+    struct ipcomp * ipcomp;
=20
 =09tc =3D (struct tdb_crypto *) crp->crp_opaque;
 =09IPSEC_ASSERT(tc !=3D NULL, ("ipcomp_output_cb: null opaque data area!"))=
;
 =09m =3D (struct mbuf *) crp->crp_buf;
 =09skip =3D tc->tc_skip;
+    protoff =3D tc->tc_protoff;
+    ip_cb =3D (struct ip_callback *) tc->tc_ptr;
 =09rlen =3D crp->crp_ilen - skip;
=20
 =09s =3D splsoftnet();
@@ -551,6 +532,45 @@
 =09ipcompstat.ipcomps_hist[sav->alg_comp]++;
=20
 =09if (rlen > crp->crp_olen) {
+=09    /* Inject IPCOMP header */
+=09    mo =3D m_makespace(m, skip, IPCOMP_HLENGTH, &roff);
+=09    if (mo =3D=3D NULL) {
+=09=09    ipcompstat.ipcomps_wrap++;
+=09=09    DPRINTF(("ipcomp_output: failed to inject IPCOMP header for "
+=09=09        "IPCA %s/%08lx\n",
+=09=09        ipsec_address(&sav->sah->saidx.dst),
+=09=09        (u_long) ntohl(sav->spi)));
+=09=09    error =3D ENOBUFS;
+=09=09    goto bad;
+=09    }
+=09    ipcomp =3D (struct ipcomp *)(mtod(mo, caddr_t) + roff);
+
+=09    /* Initialize the IPCOMP header */
+=09    /* XXX alignment always correct? */
+=09    switch (sav->sah->saidx.dst.sa.sa_family) {
+    #ifdef INET
+=09    case AF_INET:
+=09=09    ipcomp->comp_nxt =3D mtod(m, struct ip *)->ip_p;
+=09=09    break;
+    #endif /* INET */
+    #ifdef INET6
+=09    case AF_INET6:
+=09=09    ipcomp->comp_nxt =3D mtod(m, struct ip6_hdr *)->ip6_nxt;
+=09=09    break;
+    #endif
+=09    }
+=09    ipcomp->comp_flags =3D 0;
+
+        if ((sav->flags & SADB_X_EXT_RAWCPI) =3D=3D 0)
+            cpi =3D sav->alg_enc;
+        else
+            cpi =3D ntohl(sav->spi) & 0xffff;
+=09    ipcomp->comp_cpi =3D htons(cpi);
+
+=09    /* Fix Next Protocol in IPv4/IPv6 header */
+=09    prot =3D IPPROTO_IPCOMP;
+=09    m_copyback(m, tc->tc_protoff, sizeof(u_int8_t), (u_char *) &prot);
+
 =09=09/* Adjust the length in the IP header */
 =09=09switch (sav->sah->saidx.dst.sa.sa_family) {
 #ifdef INET
@@ -584,7 +604,7 @@
 =09crypto_freereq(crp);
=20
 =09/* NB: m is reclaimed by ipsec_process_done. */
-=09error =3D ipsec_process_done(m, isr);
+=09error =3D ipsec_process_done(m, isr, skip, protoff, ip_cb);
 =09KEY_FREESAV(&sav);
 =09splx(s);
 =09return error;
@@ -594,6 +614,8 @@
 =09splx(s);
 =09if (m)
 =09=09m_freem(m);
+    if (ip_cb)
+        free(ip_cb, M_TEMP);
 =09free(tc, M_XDATA);
 =09crypto_freereq(crp);
 =09return error;
@@ -602,8 +624,8 @@
 static struct xformsw ipcomp_xformsw =3D {
 =09XF_IPCOMP,=09=09XFT_COMP,=09=09"IPcomp",
 =09ipcomp_init,=09=09ipcomp_zeroize,=09=09ipcomp_input,
-=09ipcomp_output,
-=09NULL,
+=09ipcomp_output,=20
+    NULL,
 };
=20
 INITFN void
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netipsec/xform_ipip.c /home/z=
ul/netbsd-dev/src/sys/netipsec/xform_ipip.c
--- /home/zul/tmp/src/sys/netipsec/xform_ipip.c=092006-10-13 22:53:59.000000=
000 +0200
+++ /home/zul/netbsd-dev/src/sys/netipsec/xform_ipip.c=092006-11-13 21:43:04=
.000000000 +0100
@@ -422,11 +422,12 @@
=20
 int
 ipip_output(
-    struct mbuf *m,
-    struct ipsecrequest *isr,
-    struct mbuf **mp,
-    int skip __unused,
-    int protoff __unused
+=09struct mbuf *m,
+=09struct ipsecrequest *isr,
+=09struct mbuf **mp,
+=09int skip __unused,
+=09int protoff __unused,
+    struct ip_callback * ip_cb __unused
 )
 {
 =09struct secasvar *sav;
@@ -682,25 +683,30 @@
=20
 static struct xformsw ipe4_xformsw =3D {
 =09XF_IP4,=09=090,=09=09"IPv4 Simple Encapsulation",
-=09ipe4_init,=09ipe4_zeroize,=09ipe4_input,=09ipip_output,
-=09NULL,
+=09ipe4_init,=09ipe4_zeroize,=09ipe4_input,=09ipip_output,=20
+    NULL,
 };
=20
+
+#ifdef INET
 extern struct domain inetdomain;
-static struct ipprotosw ipe4_protosw[] =3D {
-{ SOCK_RAW,=09&inetdomain,=09IPPROTO_IPV4,=09PR_ATOMIC|PR_ADDR|PR_LASTHDR,
+static struct ipprotosw ipe4_protosw =3D {
+  SOCK_RAW,=09&inetdomain,=09IPPROTO_IPV4,=09PR_ATOMIC|PR_ADDR|PR_LASTHDR,
   ip4_input,=090, =09=090,=09=09rip_ctloutput,
   rip_usrreq,
   0,=09=090,=09=090,=09=090,
-},
+};
+#endif
+
 #ifdef INET6
-{ SOCK_RAW,=09&inetdomain,=09IPPROTO_IPV6,=09PR_ATOMIC|PR_ADDR|PR_LASTHDR,
-  ip4_input,=090,=09 =090,=09=09rip_ctloutput,
-  rip_usrreq,
+extern struct domain inet6domain;
+static struct ip6protosw ipe4_protosw6 =3D {
+ SOCK_RAW,=09&inet6domain,=09IPPROTO_IPV6,=09PR_ATOMIC|PR_ADDR|PR_LASTHDR,
+  ip4_input6,=090,=09 =090,=09=09rip6_ctloutput,
+  rip6_usrreq,
   0,=09=090,=09=090,=09=090,
-},
-#endif
 };
+#endif
=20
 /*
  * Check the encapsulated packet to see if we want it
@@ -727,11 +733,13 @@
 =09xform_register(&ipe4_xformsw);
 =09/* attach to encapsulation framework */
 =09/* XXX save return cookie for detach on module remove */
+#ifdef INET
 =09(void) encap_attach_func(AF_INET, -1,
-=09=09ipe4_encapcheck, (struct protosw*) &ipe4_protosw[0], NULL);
+=09=09ipe4_encapcheck, (struct protosw*) &ipe4_protosw, NULL);
+#endif
 #ifdef INET6
 =09(void) encap_attach_func(AF_INET6, -1,
-=09=09ipe4_encapcheck, (struct protosw*) &ipe4_protosw[1], NULL);
+=09=09ipe4_encapcheck, (struct protosw*)(void*) &ipe4_protosw6, NULL);
 #endif
 }
=20
diff -ur --exclude=3DCVS /home/zul/tmp/src/sys/netipsec/xform_tcp.c /home/zu=
l/netbsd-dev/src/sys/netipsec/xform_tcp.c
--- /home/zul/tmp/src/sys/netipsec/xform_tcp.c=092005-12-11 13:25:06.0000000=
00 +0100
+++ /home/zul/netbsd-dev/src/sys/netipsec/xform_tcp.c=092006-11-04 22:22:36.=
000000000 +0100
@@ -147,7 +147,7 @@
  */
 static int
 tcpsignature_output(struct mbuf *m, struct ipsecrequest *isr,
-    struct mbuf **mp, int skip, int protoff)
+    struct mbuf **mp, int skip, int protoff, struct ip_callback*)
 {
=20
 =09return (EINVAL);
@@ -156,7 +156,7 @@
 static struct xformsw tcpsignature_xformsw =3D {
 =09XF_TCPSIGNATURE,=09XFT_AUTH,=09=09"TCPMD5",
 =09tcpsignature_init,=09tcpsignature_zeroize,
-=09tcpsignature_input,=09tcpsignature_output
+=09tcpsignature_input,=09tcpsignature_output, NULL
 };
=20
 INITFN void

--=_6xgiauyepo0--