From owner-freebsd-net@FreeBSD.ORG Sat Sep 9 11:32:03 2006 Return-Path: X-Original-To: freebsd-net@FreeBSD.org Delivered-To: freebsd-net@FreeBSD.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 08FB216A417 for ; Sat, 9 Sep 2006 11:32:03 +0000 (UTC) (envelope-from nork@FreeBSD.org) Received: from sakura.ninth-nine.com (sakura.ninth-nine.com [219.127.74.120]) by mx1.FreeBSD.org (Postfix) with ESMTP id 4458F43D60 for ; Sat, 9 Sep 2006 11:31:48 +0000 (GMT) (envelope-from nork@FreeBSD.org) Received: from nadesico.ninth-nine.com (nadesico.ninth-nine.com [219.127.74.122]) by sakura.ninth-nine.com (8.13.6/8.13.6/NinthNine) with ESMTP id k89BVlDW093359; Sat, 9 Sep 2006 20:31:48 +0900 (JST) (envelope-from nork@FreeBSD.org) Date: Sat, 9 Sep 2006 20:31:47 +0900 From: Norikatsu Shigemura To: VANHULLEBUS Yvan Message-Id: <20060909203147.219ae160.nork@FreeBSD.org> In-Reply-To: <20060906070135.GA1003@jayce.zen.inc> References: <20060905022120.19c6d62d.nork@FreeBSD.org> <20060904172700.W44392@maildrop.int.zabbadoz.net> <20060904175127.F44392@maildrop.int.zabbadoz.net> <20060906070135.GA1003@jayce.zen.inc> X-Mailer: Sylpheed version 2.2.7 (GTK+ 2.8.20; i386-portbld-freebsd6.1) Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="Multipart=_Sat__9_Sep_2006_20_31_47_+0900_LsJNF2y__AcBQXgZ" X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-2.0.2 (sakura.ninth-nine.com [219.127.74.121]); Sat, 09 Sep 2006 20:31:48 +0900 (JST) Cc: freebsd-net@FreeBSD.org Subject: Re: Where is IPSec NAT-T support? X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 09 Sep 2006 11:32:03 -0000 This is a multi-part message in MIME format. --Multipart=_Sat__9_Sep_2006_20_31_47_+0900_LsJNF2y__AcBQXgZ Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit On Wed, 6 Sep 2006 09:01:35 +0200 VANHULLEBUS Yvan 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:-). --Multipart=_Sat__9_Sep_2006_20_31_47_+0900_LsJNF2y__AcBQXgZ Content-Type: text/plain; name="freebsd6s-natt.diff" Content-Disposition: attachment; filename="freebsd6s-natt.diff" Content-Transfer-Encoding: 7bit --- 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 +#include +#include + /* * 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 #include +#include + #ifdef INET6 #include #include @@ -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 */ }; --Multipart=_Sat__9_Sep_2006_20_31_47_+0900_LsJNF2y__AcBQXgZ--