summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordegroote <degroote@NetBSD.org>2007-06-27 20:38:32 +0000
committerdegroote <degroote@NetBSD.org>2007-06-27 20:38:32 +0000
commit4ddfe916ff26f11fe4a4e85f93b6fdf0937bdf83 (patch)
tree8bc2d1342852366985e53c63dcaac5821ba0e957
parentf4e11163b69206beed1725024d5fb5336ffa996b (diff)
Add support for options IPSEC_NAT_T (RFC 3947 and 3948) for fast_ipsec(4).
No objection on tech-net@
-rw-r--r--sys/netinet/udp_usrreq.c6
-rw-r--r--sys/netipsec/ipsec_input.c27
-rw-r--r--sys/netipsec/ipsec_netbsd.c12
-rw-r--r--sys/netipsec/ipsec_output.c76
-rw-r--r--sys/netipsec/key.c510
-rw-r--r--sys/netipsec/key.h16
-rw-r--r--sys/netipsec/keydb.h9
-rw-r--r--sys/netipsec/xform_ah.c22
-rw-r--r--sys/netipsec/xform_esp.c21
-rw-r--r--sys/netipsec/xform_ipcomp.c21
10 files changed, 619 insertions, 101 deletions
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 26095d92ed3..6e365e0279c 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -1,4 +1,4 @@
-/* $NetBSD: udp_usrreq.c,v 1.159 2007/05/12 02:03:15 dyoung Exp $ */
+/* $NetBSD: udp_usrreq.c,v 1.160 2007/06/27 20:38:32 degroote Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.159 2007/05/12 02:03:15 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.160 2007/06/27 20:38:32 degroote Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@@ -1528,7 +1528,7 @@ udp4_espinudp(struct mbuf **mp, int off, struct sockaddr *src,
m_tag_prepend(n, tag);
#ifdef FAST_IPSEC
- ipsec4_common_input(n, iphdrlen);
+ ipsec4_common_input(n, iphdrlen, IPPROTO_ESP);
#else
esp4_input(n, iphdrlen);
#endif
diff --git a/sys/netipsec/ipsec_input.c b/sys/netipsec/ipsec_input.c
index e815a23ed80..e454ad15ba4 100644
--- a/sys/netipsec/ipsec_input.c
+++ b/sys/netipsec/ipsec_input.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ipsec_input.c,v 1.16 2007/03/04 21:17:54 degroote Exp $ */
+/* $NetBSD: ipsec_input.c,v 1.17 2007/06/27 20:38:33 degroote Exp $ */
/* $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/netipsec/ipsec_input.c,v 1.2.4.2 2003/03/28 20:32:53 sam Exp $ */
/* $OpenBSD: ipsec_input.c,v 1.63 2003/02/20 18:35:43 deraadt Exp $ */
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ipsec_input.c,v 1.16 2007/03/04 21:17:54 degroote Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipsec_input.c,v 1.17 2007/06/27 20:38:33 degroote Exp $");
/*
* IPsec input processing.
@@ -116,7 +116,12 @@ ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
union sockaddr_union dst_address;
struct secasvar *sav;
u_int32_t spi;
+ u_int16_t sport = 0;
+ u_int16_t dport = 0;
int s, error;
+#ifdef IPSEC_NAT_T
+ struct m_tag * tag = NULL;
+#endif
IPSEC_ISTAT(sproto, espstat.esps_input, ahstat.ahs_input,
ipcompstat.ipcomps_input);
@@ -149,7 +154,19 @@ ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
u_int16_t cpi;
m_copydata(m, skip + sizeof(u_int16_t), sizeof(u_int16_t), &cpi);
spi = ntohl(htons(cpi));
+ } else {
+ panic("ipsec_common_input called with bad protocol number :"
+ "%d\n", sproto);
}
+
+
+#ifdef IPSEC_NAT_T
+ /* find the source port for NAT-T */
+ if ((tag = m_tag_find(m, PACKET_TAG_IPSEC_NAT_T_PORTS, NULL))) {
+ sport = ((u_int16_t *)(tag + 1))[0];
+ dport = ((u_int16_t *)(tag + 1))[1];
+ }
+#endif
/*
* Find the SA and (indirectly) call the appropriate
@@ -187,12 +204,12 @@ ipsec_common_input(struct mbuf *m, int skip, int protoff, int af, int sproto)
s = splsoftnet();
/* NB: only pass dst since key_allocsa follows RFC2401 */
- sav = KEY_ALLOCSA(&dst_address, sproto, spi);
+ sav = KEY_ALLOCSA(&dst_address, sproto, spi, sport, dport);
if (sav == NULL) {
DPRINTF(("ipsec_common_input: no key association found for"
- " SA %s/%08lx/%u\n",
+ " SA %s/%08lx/%u/%u\n",
ipsec_address(&dst_address),
- (u_long) ntohl(spi), sproto));
+ (u_long) ntohl(spi), sproto, ntohs(dport)));
IPSEC_ISTAT(sproto, espstat.esps_notdb, ahstat.ahs_notdb,
ipcompstat.ipcomps_notdb);
splx(s);
diff --git a/sys/netipsec/ipsec_netbsd.c b/sys/netipsec/ipsec_netbsd.c
index 7ef1ba26dbf..0b795d56ff4 100644
--- a/sys/netipsec/ipsec_netbsd.c
+++ b/sys/netipsec/ipsec_netbsd.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ipsec_netbsd.c,v 1.26 2007/04/11 22:21:41 degroote Exp $ */
+/* $NetBSD: ipsec_netbsd.c,v 1.27 2007/06/27 20:38:33 degroote Exp $ */
/* $KAME: esp_input.c,v 1.60 2001/09/04 08:43:19 itojun Exp $ */
/* $KAME: ah_input.c,v 1.64 2001/09/04 08:43:19 itojun Exp $ */
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ipsec_netbsd.c,v 1.26 2007/04/11 22:21:41 degroote Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipsec_netbsd.c,v 1.27 2007/06/27 20:38:33 degroote Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@@ -112,7 +112,7 @@ ah4_ctlinput(cmd, sa, v)
*/
ah = (struct ah *)((char *)ip + (ip->ip_hl << 2));
sav = KEY_ALLOCSA((const union sockaddr_union *)sa,
- IPPROTO_AH, ah->ah_spi);
+ IPPROTO_AH, ah->ah_spi, 0, 0);
if (sav) {
if (sav->state == SADB_SASTATE_MATURE ||
@@ -163,7 +163,7 @@ esp4_ctlinput(cmd, sa, v)
*/
esp = (struct esp *)((char *)ip + (ip->ip_hl << 2));
sav = KEY_ALLOCSA((const union sockaddr_union *)sa,
- IPPROTO_ESP, esp->esp_spi);
+ IPPROTO_ESP, esp->esp_spi, 0, 0);
if (sav) {
if (sav->state == SADB_SASTATE_MATURE ||
@@ -249,7 +249,7 @@ ah6_ctlinput(cmd, sa, d)
* to the address in the ICMP message payload.
*/
sav = KEY_ALLOCSA((const union sockaddr_union*)sa,
- IPPROTO_AH, ahp->ah_spi);
+ IPPROTO_AH, ahp->ah_spi, 0, 0);
if (sav) {
if (sav->state == SADB_SASTATE_MATURE ||
@@ -357,7 +357,7 @@ esp6_ctlinput(cmd, sa, d)
*/
sav = KEY_ALLOCSA((const union sockaddr_union*)sa,
- IPPROTO_ESP, espp->esp_spi);
+ IPPROTO_ESP, espp->esp_spi, 0, 0);
if (sav) {
if (sav->state == SADB_SASTATE_MATURE ||
diff --git a/sys/netipsec/ipsec_output.c b/sys/netipsec/ipsec_output.c
index 46f44a73c1e..21d24dfbe28 100644
--- a/sys/netipsec/ipsec_output.c
+++ b/sys/netipsec/ipsec_output.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ipsec_output.c,v 1.21 2007/02/10 09:43:05 degroote Exp $ */
+/* $NetBSD: ipsec_output.c,v 1.22 2007/06/27 20:38:33 degroote Exp $ */
/*-
* Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ipsec_output.c,v 1.21 2007/02/10 09:43:05 degroote Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipsec_output.c,v 1.22 2007/06/27 20:38:33 degroote Exp $");
/*
* IPsec output processing.
@@ -72,6 +72,9 @@ __KERNEL_RCSID(0, "$NetBSD: ipsec_output.c,v 1.21 2007/02/10 09:43:05 degroote E
#ifdef INET6
#include <netinet/icmp6.h>
#endif
+#ifdef IPSEC_NAT_T
+#include <netinet/udp.h>
+#endif
#include <netipsec/ipsec.h>
#include <netipsec/ipsec_var.h>
@@ -99,6 +102,18 @@ ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
struct secasvar *sav;
struct secasindex *saidx;
int error;
+#ifdef INET
+ struct ip * ip;
+#endif /* INET */
+#ifdef INET6
+ struct ip6_hdr * ip6;
+#endif /* INET6 */
+#ifdef IPSEC_NAT_T
+ struct mbuf * mo;
+ struct udphdr *udp = NULL;
+ uint64_t * data = NULL;
+ int hlen, roff;
+#endif /* IPSEC_NAT_T */
IPSEC_SPLASSERT_SOFTNET("ipsec_process_done");
@@ -109,11 +124,57 @@ ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
IPSEC_ASSERT(sav->sah != NULL, ("ipsec_process_done: null SAH"));
saidx = &sav->sah->saidx;
+
+#ifdef IPSEC_NAT_T
+ if(sav->natt_type != 0) {
+ ip = mtod(m, struct ip *);
+
+ hlen = sizeof(struct udphdr);
+ if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE)
+ hlen += sizeof(uint64_t);
+
+ mo = m_makespace(m, sizeof(struct ip), hlen, &roff);
+ if (mo == NULL) {
+ DPRINTF(("ipsec_process_done : failed to inject"
+ "%u byte UDP for SA %s/%08lx\n",
+ hlen, ipsec_address(&saidx->dst),
+ (u_long) ntohl(sav->spi)));
+ error = ENOBUFS;
+ goto bad;
+ }
+
+ udp = (struct udphdr*) (mtod(mo, char*) + roff);
+ data = (uint64_t*) (udp + 1);
+
+ if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE)
+ *data = 0; /* NON-IKE Marker */
+
+ if (sav->natt_type == UDP_ENCAP_ESPINUDP_NON_IKE)
+ udp->uh_sport = htons(UDP_ENCAP_ESPINUDP_PORT);
+ else
+ udp->uh_sport = key_portfromsaddr(&saidx->src);
+
+ udp->uh_dport = key_portfromsaddr(&saidx->dst);
+ udp->uh_sum = 0;
+#ifdef _IP_VHL
+ udp->uh_ulen = htons(m->m_pkthdr.len -
+ (IP_VHL_HL(ip->ip_vhl) << 2));
+#else
+ udp->uh_ulen = htons(m->m_pkthdr.len - (ip->ip_hl << 2));
+#endif
+ }
+#endif /* IPSEC_NAT_T */
+
switch (saidx->dst.sa.sa_family) {
#ifdef INET
case AF_INET:
/* Fix the header length, for AH processing. */
- mtod(m, struct ip *)->ip_len = htons(m->m_pkthdr.len);
+ ip = mtod(m, struct ip *);
+ ip->ip_len = htons(m->m_pkthdr.len);
+#ifdef IPSEC_NAT_T
+ if (sav->natt_type != 0)
+ ip->ip_p = IPPROTO_UDP;
+#endif /* IPSEC_NAT_T */
break;
#endif /* INET */
#ifdef INET6
@@ -128,8 +189,12 @@ ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
error = ENXIO; /*?*/
goto bad;
}
- mtod(m, struct ip6_hdr *)->ip6_plen =
- htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
+ ip6 = mtod(m, struct ip6_hdr *);
+ ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
+#ifdef IPSEC_NAT_T
+ if (sav->natt_type != 0)
+ ip6->ip6_nxt = IPPROTO_UDP;
+#endif /* IPSEC_NAT_T */
break;
#endif /* INET6 */
default:
@@ -190,7 +255,6 @@ ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
*/
switch (saidx->dst.sa.sa_family) {
#ifdef INET
- struct ip *ip;
case AF_INET:
ip = mtod(m, struct ip *);
#ifdef __FreeBSD__
diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
index ff4ea3f0479..29480451a35 100644
--- a/sys/netipsec/key.c
+++ b/sys/netipsec/key.c
@@ -1,7 +1,7 @@
-/* $NetBSD: key.c,v 1.47 2007/05/08 14:03:05 degroote Exp $ */
+/* $NetBSD: key.c,v 1.48 2007/06/27 20:38:33 degroote Exp $ */
/* $FreeBSD: src/sys/netipsec/key.c,v 1.3.2.3 2004/02/14 22:23:23 bms Exp $ */
/* $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $ */
-
+
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
* All rights reserved.
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.47 2007/05/08 14:03:05 degroote Exp $");
+__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.48 2007/06/27 20:38:33 degroote Exp $");
/*
* This code is referd to RFC 2367
@@ -353,16 +353,10 @@ do { \
* set parameters into secasindex buffer.
* Must allocate secasindex buffer before calling this function.
*/
-#define KEY_SETSECASIDX(p, m, r, s, d, idx) \
-do { \
- bzero((idx), sizeof(struct secasindex)); \
- (idx)->proto = (p); \
- (idx)->mode = (m); \
- (idx)->reqid = (r); \
- bcopy((s), &(idx)->src, ((const struct sockaddr *)(s))->sa_len); \
- bcopy((d), &(idx)->dst, ((const struct sockaddr *)(d))->sa_len); \
-} while (0)
-
+static int
+key_setsecasidx __P((int, int, int, const struct sadb_address *,
+ const struct sadb_address *, struct secasindex *));
+
/* key statistics */
struct _keystat {
u_long getspi_count; /* the avarage of count to try to get new SPI */
@@ -399,6 +393,10 @@ static int key_spddump __P((struct socket *, struct mbuf *,
const struct sadb_msghdr *));
static struct mbuf * key_setspddump __P((int *errorp, pid_t));
static struct mbuf * key_setspddump_chain __P((int *errorp, int *lenp, pid_t pid));
+#ifdef IPSEC_NAT_T
+static int key_nat_map __P((struct socket *, struct mbuf *,
+ const struct sadb_msghdr *));
+#endif
static struct mbuf *key_setdumpsp __P((struct secpolicy *,
u_int8_t, u_int32_t, pid_t));
static u_int key_getspreqmsglen __P((struct secpolicy *));
@@ -419,6 +417,12 @@ static int key_setsaval __P((struct secasvar *, struct mbuf *,
static int key_mature __P((struct secasvar *));
static struct mbuf *key_setdumpsa __P((struct secasvar *, u_int8_t,
u_int8_t, u_int32_t, u_int32_t));
+#ifdef IPSEC_NAT_T
+static struct mbuf *key_setsadbxport __P((u_int16_t, u_int16_t));
+static struct mbuf *key_setsadbxtype __P((u_int16_t));
+#endif
+static void key_porttosaddr __P((union sockaddr_union *, u_int16_t));
+static int key_checksalen __P((const union sockaddr_union *));
static struct mbuf *key_setsadbmsg __P((u_int8_t, u_int16_t, u_int8_t,
u_int32_t, pid_t, u_int16_t));
static struct mbuf *key_setsadbsa __P((struct secasvar *));
@@ -454,6 +458,10 @@ static int key_getspi __P((struct socket *, struct mbuf *,
const struct sadb_msghdr *));
static u_int32_t key_do_getnewspi __P((struct sadb_spirange *,
struct secasindex *));
+#ifdef IPSEC_NAT_T
+static int key_handle_natt_info __P((struct secasvar *,
+ const struct sadb_msghdr *));
+#endif
static int key_update __P((struct socket *, struct mbuf *,
const struct sadb_msghdr *));
#ifdef IPSEC_DOSEQCHECK
@@ -1037,24 +1045,34 @@ key_do_allocsa_policy(struct secashead *sah, u_int state)
* Note that, however, we do need to keep source address in IPsec SA.
* IKE specification and PF_KEY specification do assume that we
* keep source address in IPsec SA. We see a tricky situation here.
+ *
+ * sport and dport are used for NAT-T. network order is always used.
*/
struct secasvar *
key_allocsa(
const union sockaddr_union *dst,
u_int proto,
u_int32_t spi,
+ u_int16_t sport,
+ u_int16_t dport,
const char* where, int tag)
{
struct secashead *sah;
struct secasvar *sav;
u_int stateidx, state;
int s;
+ int chkport = 0;
int must_check_spi = 1;
int must_check_alg = 0;
u_int16_t cpi = 0;
u_int8_t algo = 0;
+#ifdef IPSEC_NAT_T
+ if ((sport != 0) && (dport != 0))
+ chkport = 1;
+#endif
+
IPSEC_ASSERT(dst != NULL, ("key_allocsa: null dst address"));
KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
@@ -1108,12 +1126,16 @@ key_allocsa(
continue;
#if 0 /* don't check src */
+ /* Fix port in src->sa */
+
/* check src address */
if (key_sockaddrcmp(&src->sa, &sav->sah->saidx.src.sa, 0) != 0)
continue;
#endif
+ /* fix port of dst address XXX*/
+ key_porttosaddr(__UNCONST(dst), dport);
/* check dst address */
- if (key_sockaddrcmp(&dst->sa, &sav->sah->saidx.dst.sa, 0) != 0)
+ if (key_sockaddrcmp(&dst->sa, &sav->sah->saidx.dst.sa, chkport) != 0)
continue;
SA_ADDREF(sav);
goto done;
@@ -2546,6 +2568,68 @@ key_spddump(so, m0, mhp)
return error;
}
+#ifdef IPSEC_NAT_T
+/*
+ * SADB_X_NAT_T_NEW_MAPPING. Unused by racoon as of 2005/04/23
+ */
+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;
+ struct sadb_x_nat_t_frag *frag;
+
+ /* 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);
+ }
+
+ if ((mhp->ext[SADB_X_EXT_NAT_T_FRAG] != NULL) &&
+ (mhp->extlen[SADB_X_EXT_NAT_T_FRAG] < sizeof(*frag))) {
+ 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];
+ frag = (struct sadb_x_nat_t_frag *) mhp->ext[SADB_X_EXT_NAT_T_FRAG];
+
+ printf("sadb_nat_map called\n");
+
+ /*
+ * XXX handle that, it should also contain a SA, or anything
+ * that enable to update the SA information.
+ */
+
+ return 0;
+}
+#endif /* IPSEC_NAT_T */
+
static struct mbuf *
key_setdumpsp(sp, type, seq, pid)
struct secpolicy *sp;
@@ -3128,6 +3212,10 @@ key_setsaval(sav, m, mhp)
sav->tdb_encalgxform = NULL; /* encoding algorithm */
sav->tdb_authalgxform = NULL; /* authentication algorithm */
sav->tdb_compalgxform = NULL; /* compression algorithm */
+#ifdef IPSEC_NAT_T
+ sav->natt_type = 0;
+ sav->esp_frag = 0;
+#endif
/* SA */
if (mhp->ext[SADB_EXT_SA] != NULL) {
@@ -3463,6 +3551,12 @@ key_setdumpsa(sav, type, satype, seq, pid)
SADB_EXT_ADDRESS_DST, SADB_EXT_ADDRESS_PROXY, SADB_EXT_KEY_AUTH,
SADB_EXT_KEY_ENCRYPT, SADB_EXT_IDENTITY_SRC,
SADB_EXT_IDENTITY_DST, SADB_EXT_SENSITIVITY,
+#ifdef IPSEC_NAT_T
+ SADB_X_EXT_NAT_T_TYPE, SADB_X_EXT_NAT_T_SPORT,
+ SADB_X_EXT_NAT_T_DPORT, SADB_X_EXT_NAT_T_OA,
+ SADB_X_EXT_NAT_T_FRAG,
+#endif
+
};
m = key_setsadbmsg(type, 0, satype, seq, pid, sav->refcnt);
@@ -3539,6 +3633,31 @@ key_setdumpsa(sav, type, satype, seq, pid)
p = sav->lft_s;
break;
+#ifdef IPSEC_NAT_T
+ case SADB_X_EXT_NAT_T_TYPE:
+ if ((m = key_setsadbxtype(sav->natt_type)) == NULL)
+ goto fail;
+ break;
+
+ case SADB_X_EXT_NAT_T_DPORT:
+ if ((m = key_setsadbxport(
+ key_portfromsaddr(&sav->sah->saidx.dst),
+ SADB_X_EXT_NAT_T_DPORT)) == NULL)
+ goto fail;
+ break;
+
+ case SADB_X_EXT_NAT_T_SPORT:
+ if ((m = key_setsadbxport(
+ key_portfromsaddr(&sav->sah->saidx.src),
+ SADB_X_EXT_NAT_T_SPORT)) == NULL)
+ goto fail;
+ break;
+
+ case SADB_X_EXT_NAT_T_OA:
+ case SADB_X_EXT_NAT_T_FRAG:
+ continue;
+#endif
+
case SADB_EXT_ADDRESS_PROXY:
case SADB_EXT_IDENTITY_SRC:
case SADB_EXT_IDENTITY_DST:
@@ -3592,6 +3711,155 @@ fail:
return NULL;
}
+
+#ifdef IPSEC_NAT_T
+/*
+ * set a type in sadb_x_nat_t_type
+ */
+static struct mbuf *
+key_setsadbxtype(type)
+ u_int16_t type;
+{
+ struct mbuf *m;
+ size_t len;
+ struct sadb_x_nat_t_type *p;
+
+ len = PFKEY_ALIGN8(sizeof(struct sadb_x_nat_t_type));
+
+ m = key_alloc_mbuf(len);
+ if (!m || m->m_next) { /*XXX*/
+ if (m)
+ m_freem(m);
+ return NULL;
+ }
+
+ p = mtod(m, struct sadb_x_nat_t_type *);
+
+ bzero(p, len);
+ p->sadb_x_nat_t_type_len = PFKEY_UNIT64(len);
+ p->sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
+ p->sadb_x_nat_t_type_type = type;
+
+ return m;
+}
+/*
+ * set a port in sadb_x_nat_t_port. port is in network order
+ */
+static struct mbuf *
+key_setsadbxport(port, type)
+ u_int16_t port;
+ u_int16_t type;
+{
+ struct mbuf *m;
+ size_t len;
+ struct sadb_x_nat_t_port *p;
+
+ len = PFKEY_ALIGN8(sizeof(struct sadb_x_nat_t_port));
+
+ m = key_alloc_mbuf(len);
+ if (!m || m->m_next) { /*XXX*/
+ if (m)
+ m_freem(m);
+ return NULL;
+ }
+
+ p = mtod(m, struct sadb_x_nat_t_port *);
+
+ bzero(p, len);
+ p->sadb_x_nat_t_port_len = PFKEY_UNIT64(len);
+ p->sadb_x_nat_t_port_exttype = type;
+ p->sadb_x_nat_t_port_port = port;
+
+ return m;
+}
+
+/*
+ * Get port from sockaddr, port is in network order
+ */
+u_int16_t
+key_portfromsaddr(saddr)
+ const union sockaddr_union *saddr;
+{
+ u_int16_t port;
+
+ switch (saddr->sa.sa_family) {
+ case AF_INET: {
+ port = saddr->sin.sin_port;
+ break;
+ }
+#ifdef INET6
+ case AF_INET6: {
+ port = saddr->sin6.sin6_port;
+ break;
+ }
+#endif
+ default:
+ printf("key_portfromsaddr: unexpected address family\n");
+ port = 0;
+ break;
+ }
+
+ return port;
+}
+
+#endif /* IPSEC_NAT_T */
+
+/*
+ * Set port is struct sockaddr. port is in network order
+ */
+static void
+key_porttosaddr(saddr, port)
+ union sockaddr_union *saddr;
+ u_int16_t port;
+{
+ switch (saddr->sa.sa_family) {
+ case AF_INET: {
+ saddr->sin.sin_port = port;
+ break;
+ }
+#ifdef INET6
+ case AF_INET6: {
+ saddr->sin6.sin6_port = port;
+ break;
+ }
+#endif
+ default:
+ printf("key_porttosaddr: unexpected address family %d\n",
+ saddr->sa.sa_family);
+ break;
+ }
+
+ return;
+}
+
+/*
+ * Safety check sa_len
+ */
+static int
+key_checksalen(saddr)
+ const union sockaddr_union *saddr;
+{
+ switch (saddr->sa.sa_family) {
+ case AF_INET:
+ if (saddr->sa.sa_len != sizeof(struct sockaddr_in))
+ return -1;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (saddr->sa.sa_len != sizeof(struct sockaddr_in6))
+ return -1;
+ break;
+#endif
+ default:
+ printf("key_checksalen: unexpected sa_family %d\n",
+ saddr->sa.sa_family);
+ return -1;
+ break;
+ }
+ return 0;
+}
+
+
/*
* set data into sadb_msg.
*/
@@ -3961,6 +4229,8 @@ key_cmpsaidx(
const struct secasindex *saidx1,
int flag)
{
+ int chkport = 0;
+
/* sanity */
if (saidx0 == NULL && saidx1 == NULL)
return 1;
@@ -3998,10 +4268,20 @@ key_cmpsaidx(
return 0;
}
- if (key_sockaddrcmp(&saidx0->src.sa, &saidx1->src.sa, 0) != 0) {
+ /*
+ * If NAT-T is enabled, check ports for tunnel mode.
+ * Don't do it for transport mode, as there is no
+ * port information available in the SP.
+ */
+#ifdef IPSEC_NAT_T
+ if (saidx1->mode == IPSEC_MODE_TUNNEL)
+ chkport = 1;
+#endif
+
+ if (key_sockaddrcmp(&saidx0->src.sa, &saidx1->src.sa, chkport) != 0) {
return 0;
}
- if (key_sockaddrcmp(&saidx0->dst.sa, &saidx1->dst.sa, 0) != 0) {
+ if (key_sockaddrcmp(&saidx0->dst.sa, &saidx1->dst.sa, chkport) != 0) {
return 0;
}
}
@@ -4597,6 +4877,40 @@ key_proto2satype(proto)
/* NOTREACHED */
}
+static int
+key_setsecasidx(proto, mode, reqid, src, dst, saidx)
+ int proto;
+ int mode;
+ int reqid;
+ const struct sadb_address * src;
+ const struct sadb_address * dst;
+ struct secasindex * saidx;
+{
+ const union sockaddr_union * src_u =
+ (const union sockaddr_union *) src;
+ const union sockaddr_union * dst_u =
+ (const union sockaddr_union *) dst;
+
+ /* sa len safety check */
+ if (key_checksalen(src_u) != 0)
+ return -1;
+ if (key_checksalen(dst_u) != 0)
+ return -1;
+
+ memset(saidx, 0, sizeof(*saidx));
+ saidx->proto = proto;
+ saidx->mode = mode;
+ saidx->reqid = reqid;
+ memcpy(&saidx->src, src_u, src_u->sa.sa_len);
+ memcpy(&saidx->dst, dst_u, dst_u->sa.sa_len);
+
+#ifndef IPSEC_NAT_T
+ key_porttosaddr(&((saidx)->src),0); \
+ key_porttosaddr(&((saidx)->dst),0);
+#endif
+ return 0;
+}
+
/* %%% PF_KEY */
/*
* SADB_GETSPI processing is to receive
@@ -4657,42 +4971,10 @@ key_getspi(so, m, mhp)
return key_senderror(so, m, EINVAL);
}
- /* make sure if port number is zero. */
- switch (((struct sockaddr *)(src0 + 1))->sa_family) {
- case AF_INET:
- if (((struct sockaddr *)(src0 + 1))->sa_len !=
- sizeof(struct sockaddr_in))
- return key_senderror(so, m, EINVAL);
- ((struct sockaddr_in *)(src0 + 1))->sin_port = 0;
- break;
- case AF_INET6:
- if (((struct sockaddr *)(src0 + 1))->sa_len !=
- sizeof(struct sockaddr_in6))
- return key_senderror(so, m, EINVAL);
- ((struct sockaddr_in6 *)(src0 + 1))->sin6_port = 0;
- break;
- default:
- ; /*???*/
- }
- switch (((struct sockaddr *)(dst0 + 1))->sa_family) {
- case AF_INET:
- if (((struct sockaddr *)(dst0 + 1))->sa_len !=
- sizeof(struct sockaddr_in))
- return key_senderror(so, m, EINVAL);
- ((struct sockaddr_in *)(dst0 + 1))->sin_port = 0;
- break;
- case AF_INET6:
- if (((struct sockaddr *)(dst0 + 1))->sa_len !=
- sizeof(struct sockaddr_in6))
- return key_senderror(so, m, EINVAL);
- ((struct sockaddr_in6 *)(dst0 + 1))->sin6_port = 0;
- break;
- default:
- ; /*???*/
- }
- /* XXX boundary check against sa_len */
- KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx);
+ if ((error = key_setsecasidx(proto, mode, reqid, src0 + 1,
+ dst0 + 1, &saidx)) != 0)
+ return key_senderror(so, m, EINVAL);
/* SPI allocation */
spi = key_do_getnewspi((struct sadb_spirange *)mhp->ext[SADB_EXT_SPIRANGE],
@@ -4872,6 +5154,76 @@ key_do_getnewspi(spirange, saidx)
return newspi;
}
+#ifdef IPSEC_NAT_T
+/* Handle IPSEC_NAT_T info if present */
+static int
+key_handle_natt_info(sav,mhp)
+ struct secasvar *sav;
+ const struct sadb_msghdr *mhp;
+{
+
+ if (mhp->ext[SADB_X_EXT_NAT_T_OA] != NULL)
+ printf("update: 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;
+ struct sadb_x_nat_t_frag *frag;
+
+ 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_update: "
+ "invalid message.\n"));
+ return -1;
+ }
+
+ if ((mhp->ext[SADB_X_EXT_NAT_T_OA] != NULL) &&
+ (mhp->extlen[SADB_X_EXT_NAT_T_OA] < sizeof(*addr))) {
+ ipseclog((LOG_DEBUG, "key_update: invalid message\n"));
+ return -1;
+ }
+
+ if ((mhp->ext[SADB_X_EXT_NAT_T_FRAG] != NULL) &&
+ (mhp->extlen[SADB_X_EXT_NAT_T_FRAG] < sizeof(*frag))) {
+ ipseclog((LOG_DEBUG, "key_update: invalid message\n"));
+ return -1;
+ }
+
+ 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];
+ frag = (struct sadb_x_nat_t_frag *)
+ mhp->ext[SADB_X_EXT_NAT_T_FRAG];
+
+ if (type)
+ sav->natt_type = type->sadb_x_nat_t_type_type;
+ if (sport)
+ key_porttosaddr(&sav->sah->saidx.src,
+ sport->sadb_x_nat_t_port_port);
+ if (dport)
+ key_porttosaddr(&sav->sah->saidx.dst,
+ dport->sadb_x_nat_t_port_port);
+ if (frag)
+ sav->esp_frag = frag->sadb_x_nat_t_frag_fraglen;
+ else
+ sav->esp_frag = IP_MAXPACKET;
+ }
+
+ return 0;
+}
+#endif
+
+
/*
* SADB_UPDATE processing
* receive
@@ -4944,8 +5296,10 @@ key_update(so, m, mhp)
src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]);
dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]);
- /* XXX boundary check against sa_len */
- KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx);
+ if ((error = key_setsecasidx(proto, mode, reqid, src0 + 1,
+ dst0 + 1, &saidx)) != 0)
+ return key_senderror(so, m, EINVAL);
+
/* get a SA header */
if ((sah = key_getsah(&saidx)) == NULL) {
@@ -5013,6 +5367,11 @@ key_update(so, m, mhp)
return key_senderror(so, m, 0);
}
+#ifdef IPSEC_NAT_T
+ if ((error = key_handle_natt_info(sav,mhp)) != 0)
+ return key_senderror(so, m, EINVAL);
+#endif /* IPSEC_NAT_T */
+
{
struct mbuf *n;
@@ -5139,8 +5498,9 @@ key_add(so, m, mhp)
src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC];
dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST];
- /* XXX boundary check against sa_len */
- KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx);
+ if ((error = key_setsecasidx(proto, mode, reqid, src0 + 1,
+ dst0 + 1, &saidx)) != 0)
+ return key_senderror(so, m, EINVAL);
/* get a SA header */
if ((newsah = key_getsah(&saidx)) == NULL) {
@@ -5175,6 +5535,11 @@ key_add(so, m, mhp)
return key_senderror(so, m, error);
}
+#ifdef IPSEC_NAT_T
+ if ((error = key_handle_natt_info(newsav, mhp)) != 0)
+ return key_senderror(so, m, EINVAL);
+#endif /* IPSEC_NAT_T */
+
/*
* don't call key_freesav() here, as we would like to keep the SA
* in the database on success.
@@ -5326,6 +5691,7 @@ key_delete(so, m, mhp)
struct secashead *sah;
struct secasvar *sav = NULL;
u_int16_t proto;
+ int error;
/* sanity check */
if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
@@ -5366,8 +5732,9 @@ key_delete(so, m, mhp)
src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]);
dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]);
- /* XXX boundary check against sa_len */
- KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
+ if ((error = key_setsecasidx(proto, IPSEC_MODE_ANY, 0, src0 + 1,
+ dst0 + 1, &saidx)) != 0)
+ return key_senderror(so, m, EINVAL);
/* get a SA header */
LIST_FOREACH(sah, &sahtree, chain) {
@@ -5428,12 +5795,14 @@ key_delete_all(so, m, mhp, proto)
struct secashead *sah;
struct secasvar *sav, *nextsav;
u_int stateidx, state;
+ int error;
src0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_SRC]);
dst0 = (struct sadb_address *)(mhp->ext[SADB_EXT_ADDRESS_DST]);
- /* XXX boundary check against sa_len */
- KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
+ if ((error = key_setsecasidx(proto, IPSEC_MODE_ANY, 0, src0 + 1,
+ dst0 + 1, &saidx)) != 0)
+ return key_senderror(so, m, EINVAL);
LIST_FOREACH(sah, &sahtree, chain) {
if (sah->state == SADB_SASTATE_DEAD)
@@ -5513,6 +5882,7 @@ key_get(so, m, mhp)
struct secashead *sah;
struct secasvar *sav = NULL;
u_int16_t proto;
+ int error;
/* sanity check */
if (so == NULL || m == NULL || mhp == NULL || mhp->msg == NULL)
@@ -5541,8 +5911,10 @@ key_get(so, m, mhp)
src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC];
dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST];
- /* XXX boundary check against sa_len */
- KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
+
+ if ((error = key_setsecasidx(proto, IPSEC_MODE_ANY, 0, src0 + 1,
+ dst0 + 1, &saidx)) != 0)
+ return key_senderror(so, m, EINVAL);
/* get a SA header */
LIST_FOREACH(sah, &sahtree, chain) {
@@ -6225,8 +6597,9 @@ key_acquire2(so, m, mhp)
src0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_SRC];
dst0 = (struct sadb_address *)mhp->ext[SADB_EXT_ADDRESS_DST];
- /* XXX boundary check against sa_len */
- KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
+ if ((error = key_setsecasidx(proto, IPSEC_MODE_ANY, 0, src0 + 1,
+ dst0 + 1, &saidx)) != 0)
+ return key_senderror(so, m, EINVAL);
/* get a SA index */
LIST_FOREACH(sah, &sahtree, chain) {
@@ -6913,7 +7286,9 @@ static int (*key_typesw[]) __P((struct socket *, struct mbuf *,
key_spdadd, /* SADB_X_SPDSETIDX */
NULL, /* SADB_X_SPDEXPIRE */
key_spddelete2, /* SADB_X_SPDDELETE2 */
- NULL, /* SADB_X_NAT_T_NEW_MAPPING */
+#ifdef IPSEC_NAT_T
+ key_nat_map, /* SADB_X_NAT_T_NEW_MAPPING */
+#endif
};
/*
@@ -7255,6 +7630,13 @@ key_align(m, mhp)
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:
+ case SADB_X_EXT_NAT_T_FRAG:
+#endif
/* duplicate check */
/*
* XXX Are there duplication payloads of either
diff --git a/sys/netipsec/key.h b/sys/netipsec/key.h
index fff017f6bfb..ad5d416d3b5 100644
--- a/sys/netipsec/key.h
+++ b/sys/netipsec/key.h
@@ -1,4 +1,4 @@
-/* $NetBSD: key.h,v 1.6 2007/03/04 06:03:29 christos Exp $ */
+/* $NetBSD: key.h,v 1.7 2007/06/27 20:38:33 degroote Exp $ */
/* $FreeBSD: src/sys/netipsec/key.h,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $ */
/* $KAME: key.h,v 1.21 2001/07/27 03:51:30 itojun Exp $ */
@@ -36,6 +36,8 @@
#ifdef _KERNEL
+#include "opt_ipsec.h"
+
struct secpolicy;
struct secpolicyindex;
struct ipsecrequest;
@@ -78,11 +80,11 @@ extern void _key_freesp(struct secpolicy **, const char*, int);
_key_freesp(spp, __FILE__, __LINE__)
extern struct secasvar *key_allocsa(const union sockaddr_union *,
- u_int, u_int32_t,const char*, int);
+ u_int, u_int32_t, u_int16_t, u_int16_t, const char*, int);
extern void key_freesav(struct secasvar **, const char*, int);
-#define KEY_ALLOCSA(dst, proto, spi) \
- key_allocsa(dst, proto, spi, __FILE__, __LINE__)
+#define KEY_ALLOCSA(dst, proto, spi, sport, dport) \
+ key_allocsa(dst, proto, spi, sport, dport, __FILE__, __LINE__)
#define KEY_FREESAV(psav) \
key_freesav(psav, __FILE__, __LINE__)
@@ -111,6 +113,12 @@ extern void key_sa_recordxfer __P((struct secasvar *, struct mbuf *));
extern void key_sa_routechange __P((struct sockaddr *));
extern void key_sa_stir_iv __P((struct secasvar *));
+#ifdef IPSEC_NAT_T
+u_int16_t key_portfromsaddr __P((const union sockaddr_union *));
+#endif
+
+
+
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_SECA);
#endif /* MALLOC_DECLARE */
diff --git a/sys/netipsec/keydb.h b/sys/netipsec/keydb.h
index 6a0677732b0..f6de4e0b056 100644
--- a/sys/netipsec/keydb.h
+++ b/sys/netipsec/keydb.h
@@ -1,4 +1,4 @@
-/* $NetBSD: keydb.h,v 1.4 2007/03/04 19:54:49 degroote Exp $ */
+/* $NetBSD: keydb.h,v 1.5 2007/06/27 20:38:33 degroote Exp $ */
/* $FreeBSD: src/sys/netipsec/keydb.h,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $ */
/* $KAME: keydb.h,v 1.14 2000/08/02 17:58:26 sakane Exp $ */
@@ -36,6 +36,8 @@
#ifdef _KERNEL
+#include "opt_ipsec.h"
+
#include <netipsec/key_var.h>
#include <net/route.h>
#include <netinet/in.h>
@@ -125,6 +127,11 @@ struct secasvar {
struct auth_hash *tdb_authalgxform; /* authentication algorithm */
struct comp_algo *tdb_compalgxform; /* compression algorithm */
u_int64_t tdb_cryptoid; /* crypto session id */
+
+#ifdef IPSEC_NAT_T
+ u_int16_t natt_type;
+ u_int16_t esp_frag;
+#endif
};
/* replay prevention */
diff --git a/sys/netipsec/xform_ah.c b/sys/netipsec/xform_ah.c
index c6be533ec8a..128ed537f24 100644
--- a/sys/netipsec/xform_ah.c
+++ b/sys/netipsec/xform_ah.c
@@ -1,4 +1,4 @@
-/* $NetBSD: xform_ah.c,v 1.17 2007/03/25 22:11:18 degroote Exp $ */
+/* $NetBSD: xform_ah.c,v 1.18 2007/06/27 20:38:33 degroote Exp $ */
/* $FreeBSD: src/sys/netipsec/xform_ah.c,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $ */
/* $OpenBSD: ip_ah.c,v 1.63 2001/06/26 06:18:58 angelos Exp $ */
/*
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xform_ah.c,v 1.17 2007/03/25 22:11:18 degroote Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xform_ah.c,v 1.18 2007/06/27 20:38:33 degroote Exp $");
#include "opt_inet.h"
#ifdef __FreeBSD__
@@ -794,6 +794,11 @@ ah_input_cb(struct cryptop *crp)
u_int8_t nxt;
char *ptr;
int s, authsize;
+ u_int16_t dport = 0;
+ u_int16_t sport = 0;
+#ifdef IPSEC_NAT_T
+ struct m_tag * tag = NULL;
+#endif
crd = crp->crp_desc;
@@ -805,9 +810,18 @@ ah_input_cb(struct cryptop *crp)
mtag = (struct m_tag *) tc->tc_ptr;
m = (struct mbuf *) crp->crp_buf;
+
+#ifdef IPSEC_NAT_T
+ /* find the source port for NAT-T */
+ if ((tag = m_tag_find(m, PACKET_TAG_IPSEC_NAT_T_PORTS, NULL))) {
+ sport = ((u_int16_t *)(tag + 1))[0];
+ dport = ((u_int16_t *)(tag + 1))[1];
+ }
+#endif
+
s = splsoftnet();
- sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
+ sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi, sport, dport);
if (sav == NULL) {
ahstat.ahs_notdb++;
DPRINTF(("ah_input_cb: SA expired while in crypto\n"));
@@ -1208,7 +1222,7 @@ ah_output_cb(struct cryptop *crp)
s = splsoftnet();
isr = tc->tc_isr;
- sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
+ sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi, 0, 0);
if (sav == NULL) {
ahstat.ahs_notdb++;
DPRINTF(("ah_output_cb: SA expired while in crypto\n"));
diff --git a/sys/netipsec/xform_esp.c b/sys/netipsec/xform_esp.c
index aa64f3bebac..8d97ac2ccaa 100644
--- a/sys/netipsec/xform_esp.c
+++ b/sys/netipsec/xform_esp.c
@@ -1,4 +1,4 @@
-/* $NetBSD: xform_esp.c,v 1.15 2007/03/04 21:17:55 degroote Exp $ */
+/* $NetBSD: xform_esp.c,v 1.16 2007/06/27 20:38:33 degroote Exp $ */
/* $FreeBSD: src/sys/netipsec/xform_esp.c,v 1.2.2.1 2003/01/24 05:11:36 sam Exp $ */
/* $OpenBSD: ip_esp.c,v 1.69 2001/06/26 06:18:59 angelos Exp $ */
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xform_esp.c,v 1.15 2007/03/04 21:17:55 degroote Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xform_esp.c,v 1.16 2007/06/27 20:38:33 degroote Exp $");
#include "opt_inet.h"
#ifdef __FreeBSD__
@@ -469,6 +469,11 @@ esp_input_cb(struct cryptop *crp)
struct secasvar *sav;
struct secasindex *saidx;
void *ptr;
+ u_int16_t dport = 0;
+ u_int16_t sport = 0;
+#ifdef IPSEC_NAT_T
+ struct m_tag * tag = NULL;
+#endif
crd = crp->crp_desc;
IPSEC_ASSERT(crd != NULL, ("esp_input_cb: null crypto descriptor!"));
@@ -480,9 +485,17 @@ esp_input_cb(struct cryptop *crp)
mtag = (struct m_tag *) tc->tc_ptr;
m = (struct mbuf *) crp->crp_buf;
+#ifdef IPSEC_NAT_T
+ /* find the source port for NAT-T */
+ if ((tag = m_tag_find(m, PACKET_TAG_IPSEC_NAT_T_PORTS, NULL))) {
+ sport = ((u_int16_t *)(tag + 1))[0];
+ dport = ((u_int16_t *)(tag + 1))[1];
+ }
+#endif
+
s = splsoftnet();
- sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
+ sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi, sport, dport);
if (sav == NULL) {
espstat.esps_notdb++;
DPRINTF(("esp_input_cb: SA expired while in crypto "
@@ -920,7 +933,7 @@ esp_output_cb(struct cryptop *crp)
s = splsoftnet();
isr = tc->tc_isr;
- sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
+ sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi, 0, 0);
if (sav == NULL) {
espstat.esps_notdb++;
DPRINTF(("esp_output_cb: SA expired while in crypto "
diff --git a/sys/netipsec/xform_ipcomp.c b/sys/netipsec/xform_ipcomp.c
index 3a631e599e2..71e24d9809b 100644
--- a/sys/netipsec/xform_ipcomp.c
+++ b/sys/netipsec/xform_ipcomp.c
@@ -1,4 +1,4 @@
-/* $NetBSD: xform_ipcomp.c,v 1.13 2007/03/04 21:17:55 degroote Exp $ */
+/* $NetBSD: xform_ipcomp.c,v 1.14 2007/06/27 20:38:33 degroote Exp $ */
/* $FreeBSD: src/sys/netipsec/xform_ipcomp.c,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $ */
/* $OpenBSD: ip_ipcomp.c,v 1.1 2001/07/05 12:08:52 jjbg Exp $ */
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xform_ipcomp.c,v 1.13 2007/03/04 21:17:55 degroote Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xform_ipcomp.c,v 1.14 2007/06/27 20:38:33 degroote Exp $");
/* IP payload compression protocol (IPComp), see RFC 2393 */
#include "opt_inet.h"
@@ -226,6 +226,11 @@ ipcomp_input_cb(struct cryptop *crp)
int s, hlen = IPCOMP_HLENGTH, error, clen;
u_int8_t nproto;
void *addr;
+ u_int16_t dport = 0;
+ u_int16_t sport = 0;
+#ifdef IPSEC_NAT_T
+ struct m_tag * tag = NULL;
+#endif
crd = crp->crp_desc;
@@ -236,9 +241,17 @@ ipcomp_input_cb(struct cryptop *crp)
mtag = (struct mtag *) tc->tc_ptr;
m = (struct mbuf *) crp->crp_buf;
+#ifdef IPSEC_NAT_T
+ /* find the source port for NAT-T */
+ if ((tag = m_tag_find(m, PACKET_TAG_IPSEC_NAT_T_PORTS, NULL))) {
+ sport = ((u_int16_t *)(tag + 1))[0];
+ dport = ((u_int16_t *)(tag + 1))[1];
+ }
+#endif
+
s = splsoftnet();
- sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
+ sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi, sport, dport);
if (sav == NULL) {
ipcompstat.ipcomps_notdb++;
DPRINTF(("ipcomp_input_cb: SA expired while in crypto\n"));
@@ -491,7 +504,7 @@ ipcomp_output_cb(struct cryptop *crp)
s = splsoftnet();
isr = tc->tc_isr;
- sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi);
+ sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi, 0, 0);
if (sav == NULL) {
ipcompstat.ipcomps_notdb++;
DPRINTF(("ipcomp_output_cb: SA expired while in crypto\n"));