Where is IPSec NAT-T support?
Norikatsu Shigemura
nork at FreeBSD.org
Sat Sep 9 04:32:03 PDT 2006
On Wed, 6 Sep 2006 09:01:35 +0200
VANHULLEBUS Yvan <vanhu_bsd at zeninc.net> 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:-).
-------------- next part --------------
--- 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 */
};
More information about the freebsd-net
mailing list