diff options
| author | degroote <degroote@NetBSD.org> | 2007-06-27 20:38:32 +0000 |
|---|---|---|
| committer | degroote <degroote@NetBSD.org> | 2007-06-27 20:38:32 +0000 |
| commit | 4ddfe916ff26f11fe4a4e85f93b6fdf0937bdf83 (patch) | |
| tree | 8bc2d1342852366985e53c63dcaac5821ba0e957 | |
| parent | f4e11163b69206beed1725024d5fb5336ffa996b (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.c | 6 | ||||
| -rw-r--r-- | sys/netipsec/ipsec_input.c | 27 | ||||
| -rw-r--r-- | sys/netipsec/ipsec_netbsd.c | 12 | ||||
| -rw-r--r-- | sys/netipsec/ipsec_output.c | 76 | ||||
| -rw-r--r-- | sys/netipsec/key.c | 510 | ||||
| -rw-r--r-- | sys/netipsec/key.h | 16 | ||||
| -rw-r--r-- | sys/netipsec/keydb.h | 9 | ||||
| -rw-r--r-- | sys/netipsec/xform_ah.c | 22 | ||||
| -rw-r--r-- | sys/netipsec/xform_esp.c | 21 | ||||
| -rw-r--r-- | sys/netipsec/xform_ipcomp.c | 21 |
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")); |
