On Wed, 6 Sep 2006 09:01:35 +0200
VANHULLEBUS Yvan <[EMAIL PROTECTED]> wrote:
> > Yes it was a clean RELENG_6_1.
> > >I compiled this on i386 and am64 just a few days ago and everything
> > >was fine.
> > >Perhaps contact me off-list and we'll post a summary once we found the
> > >problem?
> > Maybe it is because I am including FAST_IPSEC?   I have attempted to
> > build and use a NAT-T kernel on atleast 7 attempts now.  Last of which
> > was a couple months ago.
> Actually, I did NOT make the FAST_IPSEC part of the patch.

        Hummmm.... :-)

> Here is probably the good location and the good time for a small
> summary of the patch's state:

        Oh!

> - The public patch (A) works for IPSEC, and should apply on both
>   RELENG_6 and RELENG_6_1 (some minor patching issues may need to be
>   solved by hand, but it's just some indentation changes in the source
>   code between the two versions).
> - This public patch does NOT provide support for multiple peers behind
>   the same NAT device.
> - I have a newer version of the patch (B), against RELENG_6_1, which
>   provides such support for multiples peers behind the same NAT
>   device. I was about to put it in public place when someone raised a
>   discutable implementation choice in the way ipsec-tools and kernel
>   exchange some datas specific to that NAT-T support (I ported it from
>   Manu's work on NetBSD).

        How to get the patch(B)?  I'm interesting new version of the patch.

> - I guessed I would have quickly the time to look at it and to clean
>   it up for both FreeBSD and NetBSD (and perhaps Linux), but I
>   drastically lacked free time those last months.
> - Some FreeBSD developpers already had a look at the patch, and are in
>   contact with me to include it in the kernel, but it has been
>   reported several times for various reasons.
> - FAST_IPSEC support will be quite easy to do when all the other
>   problems will be solved, and I guess Larry Baird will do it if I
>   don't have free time for that quickly.
> As I reported that work several time on the last months, I guess I'll
> publish the actual version of the patch (B) those days, which will
> already solve some problems for most people, then I'll start to do the
> rest of the stuff (FAST_IPSEC and solve kernel/ipsec-tools
> commnication design).

        I'm interesting FAST_IPSEC support:-).

> > The Kernel configuration file that I am trying to build is
> > http://pfsense.com/cgi-bin/cvsweb.cgi/tools/builder_scripts/conf/pfSense.6?rev=1.32
> > with the added options         IPSEC_NAT_T
> > option.
> > Maybe I am overlooking something simple?
> FAST_IPSEC....

        .....

        I made a patch for 6-stable, based on MD5 (freebsd6-natt.diff) =
        5e7bb5a3203c8959928bf910d5498140.  But I didn't compile, yet:-).
--- sys/conf/options.orig       Sat Sep  2 22:12:08 2006
+++ sys/conf/options    Sat Sep  9 19:44:12 2006
@@ -352,6 +352,7 @@
 INET6                  opt_inet6.h
 IPSEC                  opt_ipsec.h
 IPSEC_ESP              opt_ipsec.h
+IPSEC_NAT_T            opt_ipsec.h
 IPSEC_DEBUG            opt_ipsec.h
 IPSEC_FILTERGIF                opt_ipsec.h
 FAST_IPSEC             opt_ipsec.h
--- sys/net/pfkeyv2.h.orig      Fri Jan  7 10:45:35 2005
+++ sys/net/pfkeyv2.h   Sat Sep  9 19:46:21 2006
@@ -75,7 +75,8 @@
 #define SADB_X_SPDSETIDX  20
 #define SADB_X_SPDEXPIRE  21
 #define SADB_X_SPDDELETE2 22   /* by policy id */
-#define SADB_MAX          22
+#define SADB_X_NAT_T_NEW_MAPPING 23
+#define SADB_MAX          23
 
 struct sadb_msg {
   u_int8_t sadb_msg_version;
@@ -255,6 +256,25 @@
    */
 };
 
+/* NAT traversal type, see RFC 3948 */
+/* sizeof(struct sadb_x_nat_t_type) == 8 */
+struct sadb_x_nat_t_type {
+  u_int16_t sadb_x_nat_t_type_len;
+  u_int16_t sadb_x_nat_t_type_exttype;
+  u_int8_t sadb_x_nat_t_type_type;
+  u_int8_t sadb_x_nat_t_type_reserved[3];
+};
+
+/* NAT traversal source or destination port */
+/* sizeof(struct sadb_x_nat_t_port) == 8 */
+struct sadb_x_nat_t_port { 
+  u_int16_t sadb_x_nat_t_port_len;
+  u_int16_t sadb_x_nat_t_port_exttype;
+  u_int16_t sadb_x_nat_t_port_port;
+  u_int16_t sadb_x_nat_t_port_reserved;
+};
+
+
 #define SADB_EXT_RESERVED             0
 #define SADB_EXT_SA                   1
 #define SADB_EXT_LIFETIME_CURRENT     2
@@ -275,7 +295,11 @@
 #define SADB_X_EXT_KMPRIVATE          17
 #define SADB_X_EXT_POLICY             18
 #define SADB_X_EXT_SA2                19
-#define SADB_EXT_MAX                  19
+#define SADB_X_EXT_NAT_T_TYPE         20
+#define SADB_X_EXT_NAT_T_SPORT        21
+#define SADB_X_EXT_NAT_T_DPORT        22
+#define SADB_X_EXT_NAT_T_OA           23
+#define SADB_EXT_MAX                  23
 
 #define SADB_SATYPE_UNSPEC     0
 #define SADB_SATYPE_AH         2
--- sys/netinet/in_pcb.h.orig   Mon Aug 21 04:28:43 2006
+++ sys/netinet/in_pcb.h        Sat Sep  9 19:48:02 2006
@@ -298,6 +298,11 @@
 #define        IN6P_RFC2292            0x40000000 /* used RFC2292 API on the 
socket */
 #define        IN6P_MTU                0x80000000 /* receive path MTU */
 
+/* XXX should move to an UDP control block */
+#define INP_ESPINUDP           0x100   /* ESP over UDP for NAT-T */
+#define INP_ESPINUDP_NON_IKE   0x200   /* ESP over UDP for NAT-T */
+#define INP_ESPINUDP_ALL       (INP_ESPINUDP|INP_ESPINUDP_NON_IKE)
+
 #define        INP_CONTROLOPTS         
(INP_RECVOPTS|INP_RECVRETOPTS|INP_RECVDSTADDR|\
                                 INP_RECVIF|INP_RECVTTL|\
                                 IN6P_PKTINFO|IN6P_HOPLIMIT|IN6P_HOPOPTS|\
--- sys/netinet/in_proto.c.orig Tue Jan  3 17:15:32 2006
+++ sys/netinet/in_proto.c      Sat Sep  9 19:50:09 2006
@@ -122,7 +122,7 @@
        .pr_flags =             PR_ATOMIC|PR_ADDR,
        .pr_input =             udp_input,
        .pr_ctlinput =          udp_ctlinput,
-       .pr_ctloutput =         ip_ctloutput,
+       .pr_ctloutput =         udp_ctloutput,
        .pr_init =              udp_init,
        .pr_usrreqs =           &udp_usrreqs
 },
--- sys/netinet/udp.h.orig      Fri Jan  7 10:45:45 2005
+++ sys/netinet/udp.h   Sat Sep  9 19:56:15 2006
@@ -44,4 +44,17 @@
        u_short uh_sum;                 /* udp checksum */
 };
 
+/* socket options for UDP */
+#define UDP_ENCAP      100
+
+/* Encapsulation types */
+#define UDP_ENCAP_ESPINUDP_NON_IKE     1 /* draft-ietf-ipsec-nat-t-ike-00/01 */
+#define UDP_ENCAP_ESPINUDP             2 /* draft-ietf-ipsec-udp-encaps-02+ */
+
+/* Default encapsulation port */
+#define UDP_ENCAP_ESPINUDP_PORT                500
+
+/* Maximum UDP fragment size for ESP over UDP */
+#define UDP_ENCAP_ESPINUDP_MAXFRAGLEN  552
+
 #endif
--- sys/netinet/udp_usrreq.c.orig       Tue May 16 16:27:48 2006
+++ sys/netinet/udp_usrreq.c    Sat Sep  9 19:52:13 2006
@@ -86,6 +86,9 @@
 
 #include <machine/in_cksum.h>
 
+#include <netinet6/ipsec.h>
+#include <netinet6/esp.h>
+
 /*
  * UDP protocol implementation.
  * Per RFC 768, August, 1980.
@@ -128,6 +131,11 @@
 static int udp_detach(struct socket *so);
 static int udp_output(struct inpcb *, struct mbuf *, struct sockaddr *,
                struct mbuf *, struct thread *);
+#ifdef IPSEC
+#ifdef INET
+static int udp4_espinudp (struct mbuf *, int, struct sockaddr *, struct socket 
*);
+#endif
+#endif
 
 static void
 udp_zone_change(void *tag)
@@ -464,6 +472,41 @@
                return;
        }
 #endif /*IPSEC || FAST_IPSEC*/
+#ifdef IPSEC_NAT_T
+       /* Handle ESP over UDP */
+       if (last->inp_flags & INP_ESPINUDP_ALL) {
+               struct sockaddr_in src;
+               struct sockaddr *sa = (struct sockaddr *)(&src);
+               size_t minlen;
+
+               bzero(&src, sizeof(src));
+               src.sin_family = AF_INET;
+               src.sin_len = sizeof(struct sockaddr_in);
+               bcopy(&ip->ip_src, &src.sin_addr, sizeof(src.sin_addr));
+               src.sin_port = udp_in->sin_port;
+
+               /* 
+                * Collapse the mbuf chain if the first mbuf is too short
+                * The longest case is: UDP + non ESP marker + ESP
+                */
+               minlen = off + sizeof(struct udphdr) + sizeof(u_int64_t) + 
sizeof(struct esp);
+               if (minlen > n->m_pkthdr.len)
+                       minlen = n->m_pkthdr.len;
+
+               if ((n = m_pullup(n, minlen)) == NULL) {
+                       printf("udp_append: m_pullup failed\n");
+                       m_freem(n);
+                       return;
+               }
+
+               if (udp4_espinudp(n, off, sa, last->inp_socket) != 0) {
+                       m_freem(n);
+                       return;
+               }
+               
+               /* Normal UDP processing will take place */
+       }
+#endif
 #ifdef MAC
        if (mac_check_inpcb_deliver(last, n) != 0) {
                m_freem(n);
@@ -702,6 +745,80 @@
     CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_PRISON, 0, 0,
     udp_getcred, "S,xucred", "Get the xucred of a UDP connection");
 
+
+int
+udp_ctloutput(so, sopt)
+       struct socket *so;
+       struct sockopt *sopt;
+{
+       int error, optval, s;
+       struct inpcb *inp;
+       int family;
+
+       error = 0;
+       family = so->so_proto->pr_domain->dom_family;
+
+       s = splnet();
+       if (sopt->sopt_level != IPPROTO_UDP) {
+#ifdef INET6
+               if (INP_CHECK_SOCKAF(so, AF_INET6))
+                       error = ip6_ctloutput(so, sopt);
+               else
+#endif /* INET6 */
+               error = ip_ctloutput(so, sopt);
+               splx(s);
+               return (error);
+       }
+       inp = sotoinpcb(so);
+
+       switch (sopt->sopt_dir) {
+       case SOPT_SET:
+               switch (sopt->sopt_name) {
+                       case UDP_ENCAP:
+                       error = sooptcopyin(sopt, &optval, sizeof optval,
+                                           sizeof optval);
+                       if (error)
+                               break;
+
+                       switch(optval){
+                       case 0:
+                               inp->inp_flags &= ~INP_ESPINUDP_ALL;
+                               break;
+
+                       case UDP_ENCAP_ESPINUDP:
+                               inp->inp_flags |= INP_ESPINUDP;
+                               break;
+                               
+                       case UDP_ENCAP_ESPINUDP_NON_IKE:
+                               inp->inp_flags |= INP_ESPINUDP_NON_IKE;
+                               break;
+
+                       default:
+                               error = EINVAL;
+                               goto end;
+                               break;
+                       }
+                       break;
+
+                       default:
+                       error = ENOPROTOOPT;
+                       goto end;
+                       break;
+               }
+               break;
+
+       default:
+               error = EINVAL;
+               goto end;
+               break;
+       }       
+       
+end:
+       splx(s);
+       return error;
+}
+
+
 static int
 udp_output(inp, m, addr, control, td)
        register struct inpcb *inp;
@@ -922,6 +1039,115 @@
        m_freem(m);
        return (error);
 }
+
+#ifdef IPSEC
+#ifdef INET
+/*
+ * Returns:
+ * 1 if the packet was processed
+ * 0 if normal UDP processing should take place
+ */
+static int
+udp4_espinudp(m, off, src, so)
+       struct mbuf *m;
+       int off;
+       struct sockaddr *src;
+       struct socket *so;
+{
+       size_t len;
+       caddr_t data;
+       struct inpcb *inp;
+       size_t skip = 0;
+       size_t minlen;
+       size_t iphdrlen;
+       struct ip *ip;
+       struct mbuf *n;
+
+       /* 
+        * Cannot collapse the mbuf chain here, must have been done in
+        * calling function
+        * The longest case is: UDP + non ESP marker + ESP
+        */
+       minlen = off + sizeof(u_int64_t) + sizeof(struct esp);
+       if (minlen > m->m_pkthdr.len)
+               minlen = m->m_pkthdr.len;
+
+       if (m->m_len < minlen)
+               return 0;
+
+       len = m->m_len - off;   
+       data = mtod(m, caddr_t) + off;
+       inp = sotoinpcb(so);
+
+       /* Ignore keepalive packets */
+       if ((len == 1) && (data[0] == '\xff')) {
+               return 1;
+       }
+
+       /* 
+        * Check that the payload is long enough to hold 
+        * an ESP header and compute the length of encapsulation
+        * header to remove 
+        */
+       if (inp->inp_flags & INP_ESPINUDP) {
+               u_int32_t *st = (u_int32_t *)data;
+
+               if ((len <= sizeof(struct esp)) || (*st == 0))
+                       return 0; /* Normal UDP processing */
+
+               skip = sizeof(struct udphdr);
+       }
+
+       if (inp->inp_flags & INP_ESPINUDP_NON_IKE) {
+               u_int64_t *st = (u_int64_t *)data;
+
+               if ((len <= sizeof(u_int64_t) + sizeof(struct esp))
+                   || (*st != 0))
+                       return 0; /* Normal UDP processing */
+               
+               skip = sizeof(struct udphdr) + sizeof(u_int64_t);
+       }
+
+       /*
+        * Remove the UDP header (and possibly the non ESP marker)
+        * IP header lendth is iphdrlen
+        * Before:   
+        *   <--- off --->
+        *   +----+------+-----+
+        *   | IP |  UDP | ESP |
+        *   +----+------+-----+
+        *        <-skip->
+        * After:
+        *          +----+-----+
+        *          | IP | ESP |
+        *          +----+-----+
+        *   <-skip->
+        */
+       iphdrlen = off - sizeof(struct udphdr);
+       ovbcopy(mtod(m, caddr_t), mtod(m, caddr_t) + skip, iphdrlen);
+       m_adj(m, skip);
+
+       ip = mtod(m, struct ip *);
+       ip->ip_len = htons(ntohs(ip->ip_len) - skip);
+       ip->ip_p = IPPROTO_ESP;
+
+       /*
+        * Copy the mbuf to avoid multiple free, as both 
+        * esp4_input (which we call) and udp_input (which 
+        * called us) free the mbuf.
+        */
+       if ((n = m_dup(m, M_DONTWAIT)) == NULL) {
+               printf("udp4_espinudp: m_dup failed\n");
+               return 0;
+       }
+
+       esp4_input(n, iphdrlen);
+
+       /* We handled it, it shoudln't be handled by UDP */
+       return 1;
+}
+#endif
+#endif
 
 u_long udp_sendspace = 9216;           /* really max datagram size */
                                        /* 40 1K datagrams */
--- sys/netinet/udp_var.h.orig  Fri Jan  7 10:45:45 2005
+++ sys/netinet/udp_var.h       Sat Sep  9 19:54:50 2006
@@ -100,6 +100,7 @@
 extern int     log_in_vain;
 
 void   udp_ctlinput(int, struct sockaddr *, void *);
+int            udp_ctloutput(struct socket *, struct sockopt *sopt);
 void   udp_init(void);
 void   udp_input(struct mbuf *, int);
 
--- sys/netinet6/esp_output.c.orig      Fri Jan  7 11:30:34 2005
+++ sys/netinet6/esp_output.c   Sat Sep  9 19:57:55 2006
@@ -56,6 +56,8 @@
 #include <netinet/ip.h>
 #include <netinet/in_var.h>
 
+#include <netinet/udp.h>
+
 #ifdef INET6
 #include <netinet/ip6.h>
 #include <netinet6/ip6_var.h>
@@ -139,6 +141,17 @@
                hdrsiz = sizeof(struct newesp) + ivlen + 9 + authlen;
        }
 
+#ifdef IPSEC_NAT_T
+       /*
+        * If NAT-T is enabled, add the space for UDP encapsulation
+        */
+       if (sav->natt_type != 0) {
+               hdrsiz += sizeof(struct udphdr);
+               if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE)
+                       hdrsiz += sizeof(u_int64_t);
+       }
+#endif
+
        return hdrsiz;
 
    estimate:
@@ -149,8 +162,14 @@
         *      9 = (maximum padding length without random padding length)
         *         + (Pad Length field) + (Next Header field).
         *      16 = maximum ICV we support.
+        *  sizeof(struct udphdr) in case NAT traversal is used
         */
+#if defined (IPSEC_NAT_T)
+       return sizeof(struct newesp) + esp_max_ivlen() + 9 + 16 +
+           sizeof(u_int64_t) + sizeof(struct udphdr);
+#else
        return sizeof(struct newesp) + esp_max_ivlen() + 9 + 16;
+#endif
 }
 
 /*
@@ -196,6 +215,9 @@
        size_t extendsiz;
        int error = 0;
        struct ipsecstat *stat;
+#ifdef IPSEC_NAT_T
+       struct udphdr *udp = NULL;
+#endif
 
        switch (af) {
 #ifdef INET
@@ -334,10 +356,25 @@
 
        espoff = m->m_pkthdr.len - plen;
 
+#ifdef IPSEC_NAT_T
+       if (sav->natt_type != 0) {
+               esphlen += sizeof(struct udphdr);
+               espoff += sizeof(struct udphdr);
+               
+               if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE) {
+                       /* NON-IKE marker */
+                       esphlen += sizeof(u_int64_t);
+                       espoff += sizeof(u_int64_t);
+               }
+       }
+#endif
+
        /*
         * grow the mbuf to accomodate ESP header.
         * before: IP ... payload
-        * after:  IP ... ESP IV payload
+        * after (without NAT-T):  IP ... ESP IV payload
+        * after (with older NAT-T):  IP ... UDP non-IKE-marker ESP IV payload
+        * after (with newer NAT-T):  IP ... UDP ESP IV payload
         */
        if (M_LEADINGSPACE(md) < esphlen || (md->m_flags & M_EXT) != 0) {
                MGET(n, M_DONTWAIT, MT_DATA);
@@ -358,6 +395,21 @@
                esp = mtod(md, struct esp *);
        }
 
+#ifdef IPSEC_NAT_T
+       if (sav->natt_type != 0) {
+               udp = (struct udphdr *)esp;
+               esp = (struct esp *)(udp + 1);
+
+               if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE) {
+                       u_int64_t *data = (u_int64_t *)esp;
+
+                       *data = 0; /* NON-IKE marker */
+                       esp = (struct esp *)(data + 1);
+               }
+       }
+#endif
+
+
        nxt = *nexthdrp;
        *nexthdrp = IPPROTO_ESP;
        switch (af) {
@@ -523,6 +575,26 @@
                break;
        }
 
+#ifdef IPSEC_NAT_T
+       if (sav->natt_type != 0) {
+               *nexthdrp = IPPROTO_UDP;
+
+               /* 
+                * Create the UDP encapsulation header for NAT-T
+                * uh_len is set later, when the size is known.
+                */
+               if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE)
+                       udp->uh_sport = htons(UDP_ENCAP_ESPINUDP_PORT);
+               else
+                       udp->uh_sport = htons(sav->local_ike_port);
+
+               udp->uh_dport = htons(sav->remote_ike_port);
+               udp->uh_sum = 0;
+       } else {
+               *nexthdrp = IPPROTO_ESP;
+       }
+#endif
+
        /* initialize esp trailer. */
        esptail = (struct esptail *)
                (mtod(n, u_int8_t *) + n->m_len - sizeof(struct esptail));
@@ -665,6 +737,18 @@
 #endif
        }
     }
+
+#ifdef IPSEC_NAT_T
+       if (sav->natt_type != 0) {
+               struct ip *ip;
+               ip = mtod(m, struct ip *);
+#ifdef _IP_VHL
+               udp->uh_ulen = htons(ntohs(ip->ip_len) - (IP_VHL_HL(ip->ip_vhl) 
<< 2));
+#else
+               udp->uh_ulen = htons(ntohs(ip->ip_len) - (ip->ip_hl << 2));
+#endif
+       }
+#endif
 
 noantireplay:
        if (!m) {
--- sys/netkey/key.c.orig       Sat Nov  5 05:26:16 2005
+++ sys/netkey/key.c    Sat Sep  9 20:01:27 2006
@@ -194,6 +194,10 @@
        0,                              /* SADB_X_EXT_KMPRIVATE */
        sizeof(struct sadb_x_policy),   /* SADB_X_EXT_POLICY */
        sizeof(struct sadb_x_sa2),      /* SADB_X_SA2 */
+       sizeof(struct sadb_x_nat_t_type), /* SADB_X_EXT_NAT_T_TYPE */
+       sizeof(struct sadb_x_nat_t_port), /* SADB_X_EXT_NAT_T_SPORT */
+       sizeof(struct sadb_x_nat_t_port), /* SADB_X_EXT_NAT_T_DPORT */
+       sizeof(struct sadb_address),    /* SADB_X_EXT_NAT_T_OA */
 };
 static const int maxsize[] = {
        sizeof(struct sadb_msg),        /* SADB_EXT_RESERVED */
@@ -216,6 +220,10 @@
        0,                              /* SADB_X_EXT_KMPRIVATE */
        0,                              /* SADB_X_EXT_POLICY */
        sizeof(struct sadb_x_sa2),      /* SADB_X_SA2 */
+       sizeof(struct sadb_x_nat_t_type), /* SADB_X_EXT_NAT_T_TYPE */
+       sizeof(struct sadb_x_nat_t_port), /* SADB_X_EXT_NAT_T_SPORT */
+       sizeof(struct sadb_x_nat_t_port), /* SADB_X_EXT_NAT_T_DPORT */
+       0,                              /* SADB_X_EXT_NAT_T_OA */
 };
 
 static int ipsec_esp_keymin = 256;
@@ -384,6 +392,8 @@
        const struct sadb_msghdr *);
 static int key_spddump(struct socket *, struct mbuf *,
        const struct sadb_msghdr *);
+static int key_nat_map(struct socket *, struct mbuf *,
+       const struct sadb_msghdr *);
 static struct mbuf *key_setdumpsp(struct secpolicy *,
        u_int8_t, u_int32_t, u_int32_t);
 static u_int key_getspreqmsglen(struct secpolicy *);
@@ -2475,6 +2485,62 @@
        return 0;
 }
 
+/* 
+ * SADB_X_NAT_T_NEW_MAPPING 
+ */
+static int
+key_nat_map(so, m, mhp)
+       struct socket *so;
+       struct mbuf *m;
+       const struct sadb_msghdr *mhp;
+{
+       struct sadb_x_nat_t_type *type;
+       struct sadb_x_nat_t_port *sport;
+       struct sadb_x_nat_t_port *dport;
+       struct sadb_address *addr;
+
+       /* sanity check */
+       if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
+               panic("key_nat_map: NULL pointer is passed.");
+
+       if (mhp->ext[SADB_X_EXT_NAT_T_TYPE] == NULL ||
+           mhp->ext[SADB_X_EXT_NAT_T_SPORT] == NULL ||
+           mhp->ext[SADB_X_EXT_NAT_T_DPORT] == NULL) {
+               ipseclog((LOG_DEBUG, "key_nat_map: invalid message.\n"));
+               return key_senderror(so, m, EINVAL);
+       }
+       if ((mhp->extlen[SADB_X_EXT_NAT_T_TYPE] < sizeof(*type)) ||
+           (mhp->extlen[SADB_X_EXT_NAT_T_SPORT] < sizeof(*sport)) ||
+           (mhp->extlen[SADB_X_EXT_NAT_T_DPORT] < sizeof(*dport))) {
+               ipseclog((LOG_DEBUG, "key_nat_map: invalid message.\n"));
+               return key_senderror(so, m, EINVAL);
+       }
+
+       if ((mhp->ext[SADB_X_EXT_NAT_T_OA] != NULL) && 
+           (mhp->extlen[SADB_X_EXT_NAT_T_OA] < sizeof(*addr))) {
+               ipseclog((LOG_DEBUG, "key_nat_map: invalid message\n"));
+               return key_senderror(so, m, EINVAL);
+       }
+
+       type = (struct sadb_x_nat_t_type *)mhp->ext[SADB_X_EXT_NAT_T_TYPE];
+       sport = (struct sadb_x_nat_t_port *)mhp->ext[SADB_X_EXT_NAT_T_SPORT];
+       dport = (struct sadb_x_nat_t_port *)mhp->ext[SADB_X_EXT_NAT_T_DPORT];
+       addr = (struct sadb_address *)mhp->ext[SADB_X_EXT_NAT_T_OA];
+
+       printf("sadb_nat_map: type %d, sport = %d, dport = %d\n", 
+               type->sadb_x_nat_t_type_type,
+               sport->sadb_x_nat_t_port_port,
+               dport->sadb_x_nat_t_port_port);
+
+       /* 
+        * XXX handle that, it should also contain a SA, or anything 
+        * that enable to update the SA information.
+        */
+
+       return 0;
+}
+
+
 static struct mbuf *
 key_setdumpsp(sp, type, seq, pid)
        struct secpolicy *sp;
@@ -3025,6 +3091,9 @@
        sav->lft_c = NULL;
        sav->lft_h = NULL;
        sav->lft_s = NULL;
+       sav->natt_type = 0;
+       sav->remote_ike_port = 0;
+       sav->local_ike_port = 0;
 
        /* SA */
        if (mhp->ext[SADB_EXT_SA] != NULL) {
@@ -5223,6 +5292,50 @@
        }
 
        /*
+        * Handle NAT-T info if present
+        */
+       if (mhp->ext[SADB_X_EXT_NAT_T_OA] != NULL) {
+               printf("add: NAT-T OA present\n");
+       }
+       if ((mhp->ext[SADB_X_EXT_NAT_T_TYPE] != NULL) &&
+           (mhp->ext[SADB_X_EXT_NAT_T_SPORT] != NULL) &&
+           (mhp->ext[SADB_X_EXT_NAT_T_DPORT] != NULL)) { 
+               struct sadb_x_nat_t_type *type;
+               struct sadb_x_nat_t_port *sport;
+               struct sadb_x_nat_t_port *dport;
+               struct sadb_address *addr;
+
+               if ((mhp->extlen[SADB_X_EXT_NAT_T_TYPE] < sizeof(*type)) ||
+                   (mhp->extlen[SADB_X_EXT_NAT_T_SPORT] < sizeof(*sport)) ||
+                   (mhp->extlen[SADB_X_EXT_NAT_T_DPORT] < sizeof(*dport))) {
+                       ipseclog((LOG_DEBUG, "key_add: "
+                           "invalid message.\n"));
+                       return key_senderror(so, m, EINVAL);
+               }
+
+               if ((mhp->ext[SADB_X_EXT_NAT_T_OA] != NULL) && 
+                   (mhp->extlen[SADB_X_EXT_NAT_T_OA] < sizeof(*addr))) {
+                       ipseclog((LOG_DEBUG, "key_add: invalid message\n"));
+                       return key_senderror(so, m, EINVAL);
+               }
+
+               type = (struct sadb_x_nat_t_type *)
+                   mhp->ext[SADB_X_EXT_NAT_T_TYPE];
+               sport = (struct sadb_x_nat_t_port *)
+                   mhp->ext[SADB_X_EXT_NAT_T_SPORT];
+               dport = (struct sadb_x_nat_t_port *)
+                   mhp->ext[SADB_X_EXT_NAT_T_DPORT];
+               addr = (struct sadb_address *)
+                   mhp->ext[SADB_X_EXT_NAT_T_OA];
+       
+               newsav->natt_type = type->sadb_x_nat_t_type_type;
+               newsav->local_ike_port = ntohs(sport->sadb_x_nat_t_port_port);
+               newsav->remote_ike_port = ntohs(dport->sadb_x_nat_t_port_port);
+       }
+
+
+
+       /*
         * don't call key_freesav() here, as we would like to keep the SA
         * in the database on success.
         */
@@ -6875,6 +6988,7 @@
        key_spdadd,     /* SADB_X_SPDSETIDX */
        NULL,           /* SADB_X_SPDEXPIRE */
        key_spddelete2, /* SADB_X_SPDDELETE2 */
+       key_nat_map, /* SADB_X_NAT_T_NEW_MAPPING */
 };
 
 /*
@@ -7227,6 +7341,12 @@
                case SADB_EXT_SPIRANGE:
                case SADB_X_EXT_POLICY:
                case SADB_X_EXT_SA2:
+#ifdef IPSEC_NAT_T
+               case SADB_X_EXT_NAT_T_TYPE:
+               case SADB_X_EXT_NAT_T_SPORT:
+               case SADB_X_EXT_NAT_T_DPORT:
+               case SADB_X_EXT_NAT_T_OA:
+#endif
                        /* duplicate check */
                        /*
                         * XXX Are there duplication payloads of either
--- sys/netkey/keydb.h.orig     Fri Jan  7 10:45:48 2005
+++ sys/netkey/keydb.h  Sat Sep  9 20:05:00 2006
@@ -114,6 +114,11 @@
        pid_t pid;                      /* message's pid */
 
        struct secashead *sah;          /* back pointer to the secashead */
+  /* For NAT-Traversal 
+   */
+       u_int16_t       natt_type;
+       u_int16_t       remote_ike_port;
+       u_int16_t       local_ike_port; /* ??? */
 
        u_int32_t id;                   /* SA id */
 };

_______________________________________________
freebsd-net@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to