Module Name:    src
Committed By:   spz
Date:           Sun Sep  5 06:52:54 UTC 2010

Modified Files:
        src/sys/net: pfkeyv2.h
        src/sys/netipsec: key.c
        src/sys/netkey: key.c

Log Message:
fix two bugs in the PFKEY interface:

1) RFC2367 says in 2.3.3 Address Extension: "All non-address
   information in the sockaddrs, such as sin_zero for AF_INET sockaddrs,
   and sin6_flowinfo for AF_INET6 sockaddrs, MUST be zeroed out."
   the IPSEC_NAT_T code was expecting the port information it needs
   to be conveyed in the sockaddr instead of exclusively by
   SADB_X_EXT_NAT_T_SPORT and SADB_X_EXT_NAT_T_DPORT,
   and was not zeroing out the port information in the non-nat-traversal
   case.
   Since it was expecting the port information to reside in the sockaddr
   it could get away with (re)setting the ports after starting to use them.
   -> Set the natt ports before setting the SA mature.

2) RFC3947 has two Original Address fields, initiator and responder,
   so we need SADB_X_EXT_NAT_T_OAI and SADB_X_EXT_NAT_T_OAR and not just
   SADB_X_EXT_NAT_T_OA

The change has been created using vanhu's patch for FreeBSD as reference.

Note that establishing actual nat-t sessions has not yet been tested.

Likely fixes the following:
PR bin/41757
PR net/42592
PR net/42606


To generate a diff of this commit:
cvs rdiff -u -r1.26 -r1.27 src/sys/net/pfkeyv2.h
cvs rdiff -u -r1.63 -r1.64 src/sys/netipsec/key.c
cvs rdiff -u -r1.177 -r1.178 src/sys/netkey/key.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/net/pfkeyv2.h
diff -u src/sys/net/pfkeyv2.h:1.26 src/sys/net/pfkeyv2.h:1.27
--- src/sys/net/pfkeyv2.h:1.26	Wed Feb 20 17:05:53 2008
+++ src/sys/net/pfkeyv2.h	Sun Sep  5 06:52:53 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: pfkeyv2.h,v 1.26 2008/02/20 17:05:53 matt Exp $	*/
+/*	$NetBSD: pfkeyv2.h,v 1.27 2010/09/05 06:52:53 spz Exp $	*/
 /*	$KAME: pfkeyv2.h,v 1.36 2003/07/25 09:33:37 itojun Exp $	*/
 
 /*
@@ -310,14 +310,16 @@
 #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_X_EXT_NAT_T_FRAG	      24
+#define SADB_X_EXT_NAT_T_OA           23	/* compat */
+#define SADB_X_EXT_NAT_T_OAI          23
+#define SADB_X_EXT_NAT_T_OAR          24
+#define SADB_X_EXT_NAT_T_FRAG	      25
 #if 0
 #define	SADB_X_EXT_TAG		      25	/* KAME */
 #define	SADB_X_EXT_SA3		      26	/* KAME */
 #define	SADB_X_EXT_PACKET	      27	/* KAME */
 #endif
-#define SADB_EXT_MAX                  24
+#define SADB_EXT_MAX                  25
 
 #define SADB_SATYPE_UNSPEC	0
 #define SADB_SATYPE_AH		2

Index: src/sys/netipsec/key.c
diff -u src/sys/netipsec/key.c:1.63 src/sys/netipsec/key.c:1.64
--- src/sys/netipsec/key.c:1.63	Sun Jan 31 00:43:38 2010
+++ src/sys/netipsec/key.c	Sun Sep  5 06:52:53 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: key.c,v 1.63 2010/01/31 00:43:38 hubertf Exp $	*/
+/*	$NetBSD: key.c,v 1.64 2010/09/05 06:52:53 spz 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 $	*/
 	
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.63 2010/01/31 00:43:38 hubertf Exp $");
+__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.64 2010/09/05 06:52:53 spz Exp $");
 
 /*
  * This code is referd to RFC 2367
@@ -192,7 +192,8 @@
 	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 */
+	sizeof(struct sadb_address),		/* SADB_X_EXT_NAT_T_OAI */
+	sizeof(struct sadb_address),		/* SADB_X_EXT_NAT_T_OAR */
 	sizeof(struct sadb_x_nat_t_frag),	/* SADB_X_EXT_NAT_T_FRAG */
 };
 static const int maxsize[] = {
@@ -219,7 +220,8 @@
 	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 */
+	0,					/* SADB_X_EXT_NAT_T_OAI */
+	0,					/* SADB_X_EXT_NAT_T_OAR */
 	sizeof(struct sadb_x_nat_t_frag),	/* SADB_X_EXT_NAT_T_FRAG */
 };
 
@@ -465,6 +467,9 @@
 #ifdef IPSEC_NAT_T
 static int key_handle_natt_info (struct secasvar *, 
 				     const struct sadb_msghdr *);
+static int key_set_natt_ports (union sockaddr_union *,
+			 	union sockaddr_union *,
+				const struct sadb_msghdr *);
 #endif
 static int key_update (struct socket *, struct mbuf *,
 	const struct sadb_msghdr *);
@@ -2574,7 +2579,7 @@
 	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_address *iaddr, *raddr;
 	struct sadb_x_nat_t_frag *frag;
 
 	/* sanity check */
@@ -2594,8 +2599,14 @@
 		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))) {
+	if ((mhp->ext[SADB_X_EXT_NAT_T_OAI] != NULL) &&
+		(mhp->extlen[SADB_X_EXT_NAT_T_OAI] < sizeof(*iaddr))) {
+		ipseclog((LOG_DEBUG, "key_nat_map: invalid message\n"));
+		return key_senderror(so, m, EINVAL);
+	}
+
+	if ((mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL) &&
+		(mhp->extlen[SADB_X_EXT_NAT_T_OAR] < sizeof(*raddr))) {
 		ipseclog((LOG_DEBUG, "key_nat_map: invalid message\n"));
 		return key_senderror(so, m, EINVAL);
 	}
@@ -2609,7 +2620,8 @@
 	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];
+	iaddr = (struct sadb_address *)mhp->ext[SADB_X_EXT_NAT_T_OAI];
+	raddr = (struct sadb_address *)mhp->ext[SADB_X_EXT_NAT_T_OAR];
 	frag = (struct sadb_x_nat_t_frag *) mhp->ext[SADB_X_EXT_NAT_T_FRAG];
 
 	printf("sadb_nat_map called\n");
@@ -3522,8 +3534,9 @@
 		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_TYPE,
+		SADB_X_EXT_NAT_T_SPORT, SADB_X_EXT_NAT_T_DPORT,
+		SADB_X_EXT_NAT_T_OAI, SADB_X_EXT_NAT_T_OAR,
 		SADB_X_EXT_NAT_T_FRAG,
 #endif
 
@@ -3623,7 +3636,8 @@
 				goto fail;
 			break;
 
-		case SADB_X_EXT_NAT_T_OA:
+		case SADB_X_EXT_NAT_T_OAI:
+		case SADB_X_EXT_NAT_T_OAR:
 		case SADB_X_EXT_NAT_T_FRAG:
 			continue;
 #endif
@@ -4212,9 +4226,20 @@
 	 * 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.
+         * Also don't check ports if they are set to zero
+	 * in the SPD: This means we have a non-generated
+	 * SPD which can't know UDP ports.
 	 */
 #ifdef IPSEC_NAT_T
-	if (saidx1->mode == IPSEC_MODE_TUNNEL)
+	if (saidx1->mode == IPSEC_MODE_TUNNEL &&
+	    ((((const struct sockaddr *)(&saidx1->src))->sa_family == AF_INET &&
+	      ((const struct sockaddr *)(&saidx1->dst))->sa_family == AF_INET &&
+	      ((const struct sockaddr_in *)(&saidx1->src))->sin_port &&
+	      ((const struct sockaddr_in *)(&saidx1->dst))->sin_port) ||
+             (((const struct sockaddr *)(&saidx1->src))->sa_family == AF_INET6 &&
+	      ((const struct sockaddr *)(&saidx1->dst))->sa_family == AF_INET6 &&
+	      ((const struct sockaddr_in6 *)(&saidx1->src))->sin6_port &&
+	      ((const struct sockaddr_in6 *)(&saidx1->dst))->sin6_port)))
 		chkport = 1;
 #endif
 
@@ -4908,6 +4933,11 @@
 				     dst0 + 1, &saidx)) != 0)
 		return key_senderror(so, m, EINVAL);
 
+#ifdef IPSEC_NAT_T
+	if ((error = key_set_natt_ports(&saidx.src, &saidx.dst, mhp)) != 0)
+		return key_senderror(so, m, EINVAL);
+#endif
+
 	/* SPI allocation */
 	spi = key_do_getnewspi((struct sadb_spirange *)mhp->ext[SADB_EXT_SPIRANGE],
 	                       &saidx);
@@ -5092,8 +5122,10 @@
       		     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_OAI] != NULL)
+		ipseclog((LOG_DEBUG,"update: NAT-T OAi present\n"));
+	if (mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL)
+		ipseclog((LOG_DEBUG,"update: NAT-T OAr present\n"));
 
 	if ((mhp->ext[SADB_X_EXT_NAT_T_TYPE] != NULL) &&
 	    (mhp->ext[SADB_X_EXT_NAT_T_SPORT] != NULL) &&
@@ -5101,7 +5133,7 @@
 		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_address *iaddr, *raddr;
 		struct sadb_x_nat_t_frag *frag;
 
 		if ((mhp->extlen[SADB_X_EXT_NAT_T_TYPE] < sizeof(*type)) ||
@@ -5112,8 +5144,14 @@
 			return -1;
 		}
 
-		if ((mhp->ext[SADB_X_EXT_NAT_T_OA] != NULL) &&
-		    (mhp->extlen[SADB_X_EXT_NAT_T_OA] < sizeof(*addr))) {
+		if ((mhp->ext[SADB_X_EXT_NAT_T_OAI] != NULL) &&
+		    (mhp->extlen[SADB_X_EXT_NAT_T_OAI] < sizeof(*iaddr))) {
+			ipseclog((LOG_DEBUG, "key_update: invalid message\n"));
+			return -1;
+		}
+
+		if ((mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL) &&
+		    (mhp->extlen[SADB_X_EXT_NAT_T_OAR] < sizeof(*raddr))) {
 			ipseclog((LOG_DEBUG, "key_update: invalid message\n"));
 			return -1;
 		}
@@ -5130,11 +5168,19 @@
 		    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];
+		iaddr = (struct sadb_address *)
+		    mhp->ext[SADB_X_EXT_NAT_T_OAI];
+		raddr = (struct sadb_address *)
+		    mhp->ext[SADB_X_EXT_NAT_T_OAR];
 		frag = (struct sadb_x_nat_t_frag *)
 		    mhp->ext[SADB_X_EXT_NAT_T_FRAG];
 
+		ipseclog((LOG_DEBUG,
+			"key_update: 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));
+
 		if (type)
 			sav->natt_type = type->sadb_x_nat_t_type_type;
 		if (sport)
@@ -5151,6 +5197,48 @@
 
 	return 0;
 }
+
+/* Just update the IPSEC_NAT_T ports if present */
+static int
+key_set_natt_ports(union sockaddr_union *src, union sockaddr_union *dst,
+      		     const struct sadb_msghdr *mhp)
+{
+
+	if (mhp->ext[SADB_X_EXT_NAT_T_OAI] != NULL)
+		ipseclog((LOG_DEBUG,"update: NAT-T OAi present\n"));
+	if (mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL)
+		ipseclog((LOG_DEBUG,"update: NAT-T OAr 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;
+
+		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;
+		}
+
+		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];
+
+		if (sport)
+			key_porttosaddr(src, 
+			    sport->sadb_x_nat_t_port_port);
+		if (dport)
+			key_porttosaddr(dst,
+			    dport->sadb_x_nat_t_port_port);
+	}
+
+	return 0;
+}
 #endif
 
 
@@ -5227,6 +5315,10 @@
 				     dst0 + 1, &saidx)) != 0)
 		return key_senderror(so, m, EINVAL);
 
+#ifdef IPSEC_NAT_T
+	if ((error = key_set_natt_ports(&saidx.src, &saidx.dst, mhp)) != 0)
+		return key_senderror(so, m, EINVAL);
+#endif
 
 	/* get a SA header */
 	if ((sah = key_getsah(&saidx)) == NULL) {
@@ -5288,17 +5380,17 @@
 		return key_senderror(so, m, error);
 	}
 
+#ifdef IPSEC_NAT_T
+	if ((error = key_handle_natt_info(sav,mhp)) != 0)
+		return key_senderror(so, m, EINVAL);
+#endif /* IPSEC_NAT_T */
+
 	/* check SA values to be mature. */
 	if ((mhp->msg->sadb_msg_errno = key_mature(sav)) != 0) {
 		KEY_FREESAV(&sav);
 		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;
 
@@ -5425,6 +5517,11 @@
 				     dst0 + 1, &saidx)) != 0)
 		return key_senderror(so, m, EINVAL);
 
+#ifdef IPSEC_NAT_T
+	if ((error = key_set_natt_ports(&saidx.src, &saidx.dst, mhp)) != 0)
+		return key_senderror(so, m, EINVAL);
+#endif
+
 	/* get a SA header */
 	if ((newsah = key_getsah(&saidx)) == NULL) {
 		/* create a new SA header */
@@ -5452,17 +5549,17 @@
 		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 */
+
 	/* check SA values to be mature. */
 	if ((error = key_mature(newsav)) != 0) {
 		KEY_FREESAV(&newsav);
 		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.
@@ -5653,6 +5750,11 @@
 				     dst0 + 1, &saidx)) != 0)
 		return key_senderror(so, m, EINVAL);
 
+#ifdef IPSEC_NAT_T
+	if ((error = key_set_natt_ports(&saidx.src, &saidx.dst, mhp)) != 0)
+		return key_senderror(so, m, EINVAL);
+#endif
+
 	/* get a SA header */
 	LIST_FOREACH(sah, &sahtree, chain) {
 		if (sah->state == SADB_SASTATE_DEAD)
@@ -5718,6 +5820,11 @@
 				     dst0 + 1, &saidx)) != 0)
 		return key_senderror(so, m, EINVAL);
 
+#ifdef IPSEC_NAT_T
+	if ((error = key_set_natt_ports(&saidx.src, &saidx.dst, mhp)) != 0)
+		return key_senderror(so, m, EINVAL);
+#endif
+
 	LIST_FOREACH(sah, &sahtree, chain) {
 		if (sah->state == SADB_SASTATE_DEAD)
 			continue;
@@ -5828,6 +5935,11 @@
 				     dst0 + 1, &saidx)) != 0)
 		return key_senderror(so, m, EINVAL);
 
+#ifdef IPSEC_NAT_T
+	if ((error = key_set_natt_ports(&saidx.src, &saidx.dst, mhp)) != 0)
+		return key_senderror(so, m, EINVAL);
+#endif
+
 	/* get a SA header */
 	LIST_FOREACH(sah, &sahtree, chain) {
 		if (sah->state == SADB_SASTATE_DEAD)
@@ -6503,6 +6615,11 @@
 				     dst0 + 1, &saidx)) != 0)
 		return key_senderror(so, m, EINVAL);
 
+#ifdef IPSEC_NAT_T
+	if ((error = key_set_natt_ports(&saidx.src, &saidx.dst, mhp)) != 0)
+		return key_senderror(so, m, EINVAL);
+#endif
+
 	/* get a SA index */
 	LIST_FOREACH(sah, &sahtree, chain) {
 		if (sah->state == SADB_SASTATE_DEAD)
@@ -7523,7 +7640,8 @@
 		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_OAI:
+		case SADB_X_EXT_NAT_T_OAR:
 		case SADB_X_EXT_NAT_T_FRAG:
 #endif
 			/* duplicate check */

Index: src/sys/netkey/key.c
diff -u src/sys/netkey/key.c:1.177 src/sys/netkey/key.c:1.178
--- src/sys/netkey/key.c:1.177	Wed Mar  3 01:13:26 2010
+++ src/sys/netkey/key.c	Sun Sep  5 06:52:53 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: key.c,v 1.177 2010/03/03 01:13:26 pooka Exp $	*/
+/*	$NetBSD: key.c,v 1.178 2010/09/05 06:52:53 spz Exp $	*/
 /*	$KAME: key.c,v 1.310 2003/09/08 02:23:44 itojun Exp $	*/
 
 /*
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.177 2010/03/03 01:13:26 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.178 2010/09/05 06:52:53 spz Exp $");
 
 #include "opt_inet.h"
 #include "opt_ipsec.h"
@@ -201,7 +201,8 @@
 	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 */
+	sizeof(struct sadb_address),	/* SADB_X_EXT_NAT_T_OAI */
+	sizeof(struct sadb_address),	/* SADB_X_EXT_NAT_T_OAR */
 	sizeof(struct sadb_x_nat_t_frag),/* SADB_X_EXT_NAT_T_FRAG */
 #ifdef SADB_X_EXT_TAG
 	sizeof(struct sadb_x_tag),	/* SADB_X_TAG */
@@ -231,7 +232,8 @@
 	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 */
+	0,				/* SADB_X_EXT_NAT_T_OAI */
+	0,				/* SADB_X_EXT_NAT_T_OAR */
 	sizeof(struct sadb_x_nat_t_frag), /* SADB_X_EXT_NAT_T_FRAG */
 #ifdef SADB_X_EXT_TAG
 	sizeof(struct sadb_x_tag),	/* SADB_X_TAG */
@@ -360,6 +362,13 @@
 #ifdef IPSEC_NAT_T
 static int key_nat_map(struct socket *, struct mbuf *,
 	const struct sadb_msghdr *);
+static int key_handle_natt_info (struct secasvar *,
+                                     const struct sadb_msghdr *);
+static int key_set_natt_ports (struct sockaddr *, struct sockaddr *,
+                                const struct sadb_msghdr *);
+#define KEY_SET_NATT_PORTS(saddr, daddr, saidx) \
+	key_set_natt_ports((struct sockaddr *)(saddr), \
+			   (struct sockaddr *)(daddr), (saidx))
 #endif
 static struct mbuf *key_setspddump(int *);
 static u_int key_getspreqmsglen(struct secpolicy *);
@@ -2371,7 +2380,7 @@
 	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_address *iaddr, *raddr;
 	struct sadb_x_nat_t_frag *frag;
 
 	/* sanity check */
@@ -2391,8 +2400,14 @@
 		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))) {
+	if ((mhp->ext[SADB_X_EXT_NAT_T_OAI] != NULL) &&
+	    (mhp->extlen[SADB_X_EXT_NAT_T_OAI] < sizeof(*iaddr))) {
+		ipseclog((LOG_DEBUG, "key_nat_map: invalid message\n"));
+		return key_senderror(so, m, EINVAL);
+	}
+
+	if ((mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL) &&
+	    (mhp->extlen[SADB_X_EXT_NAT_T_OAR] < sizeof(*raddr))) {
 		ipseclog((LOG_DEBUG, "key_nat_map: invalid message\n"));
 		return key_senderror(so, m, EINVAL);
 	}
@@ -2406,7 +2421,8 @@
 	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];
+	iaddr = (struct sadb_address *)mhp->ext[SADB_X_EXT_NAT_T_OAI];
+	raddr = (struct sadb_address *)mhp->ext[SADB_X_EXT_NAT_T_OAR];
 	frag = (struct sadb_x_nat_t_frag *) mhp->ext[SADB_X_EXT_NAT_T_FRAG];
 
 	printf("sadb_nat_map called\n");
@@ -2418,6 +2434,137 @@
 
 	return 0;
 }
+
+/* Handle IPSEC_NAT_T info if present */
+static int
+key_handle_natt_info(struct secasvar *sav,
+		     const struct sadb_msghdr *mhp)
+{
+				
+	if (mhp->ext[SADB_X_EXT_NAT_T_OAI] != NULL)
+		ipseclog((LOG_DEBUG,"update: NAT-T OAi present\n"));
+	if (mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL) 
+		ipseclog((LOG_DEBUG,"update: NAT-T OAr 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 *iaddr, *raddr;
+		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_OAI] != NULL) &&
+		    (mhp->extlen[SADB_X_EXT_NAT_T_OAI] < sizeof(*iaddr))) {
+			ipseclog((LOG_DEBUG, "key_update: invalid message\n"));
+			return -1;
+		}
+
+		if ((mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL) &&
+		    (mhp->extlen[SADB_X_EXT_NAT_T_OAR] < sizeof(*raddr))) {
+			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];
+		iaddr = (struct sadb_address *)
+		    mhp->ext[SADB_X_EXT_NAT_T_OAI];
+		raddr = (struct sadb_address *)
+		    mhp->ext[SADB_X_EXT_NAT_T_OAR];
+		frag = (struct sadb_x_nat_t_frag *)
+		    mhp->ext[SADB_X_EXT_NAT_T_FRAG];
+
+		ipseclog((LOG_DEBUG,
+			"key_update: 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));
+
+		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;
+}
+
+/* Just update the IPSEC_NAT_T ports if present */
+static int
+key_set_natt_ports(struct sockaddr *src, struct sockaddr *dst,
+		     const struct sadb_msghdr *mhp)
+{
+
+	if (mhp->ext[SADB_X_EXT_NAT_T_OAI] != NULL)
+		ipseclog((LOG_DEBUG,"update: NAT-T OAi present\n"));
+	if (mhp->ext[SADB_X_EXT_NAT_T_OAR] != NULL)
+		ipseclog((LOG_DEBUG,"update: NAT-T OAr 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;
+
+		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;
+		}
+
+		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];
+
+		if (sport)
+			KEY_PORTTOSADDR(src,
+			    sport->sadb_x_nat_t_port_port);
+		else
+			KEY_PORTTOSADDR(src, 0);
+		if (dport)
+			KEY_PORTTOSADDR(dst,
+			    dport->sadb_x_nat_t_port_port);
+		else
+			KEY_PORTTOSADDR(dst, 0);
+	} else {
+		KEY_PORTTOSADDR(src, 0);
+		KEY_PORTTOSADDR(dst, 0);
+	}
+
+	return 0;
+}
 #endif /* IPSEC_NAT_T */
 
 static struct mbuf *
@@ -3494,8 +3641,9 @@
 		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_TYPE,
+		SADB_X_EXT_NAT_T_SPORT, SADB_X_EXT_NAT_T_DPORT,
+		SADB_X_EXT_NAT_T_OAI, SADB_X_EXT_NAT_T_OAR,
 		SADB_X_EXT_NAT_T_FRAG,
 #endif
 	};
@@ -3594,7 +3742,8 @@
 				goto fail;
 			break;
 
-		case SADB_X_EXT_NAT_T_OA:
+		case SADB_X_EXT_NAT_T_OAI:
+		case SADB_X_EXT_NAT_T_OAR:
 		case SADB_X_EXT_NAT_T_FRAG:
 			continue;
 #endif
@@ -4958,8 +5107,11 @@
 
 	KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx);
 
-	/* If not using NAT-T, make sure port numbers are set to zero. */
-#ifndef IPSEC_NAT_T
+#ifdef IPSEC_NAT_T
+	if ((error = KEY_SET_NATT_PORTS(&saidx.src, &saidx.dst, mhp)) != 0)
+		return key_senderror(so, m, EINVAL);
+#else
+	/* If not using NAT-T, make sure the port numbers are zero. */
 	KEY_PORTTOSADDR(&saidx.src, 0);
 	KEY_PORTTOSADDR(&saidx.dst, 0);
 #endif
@@ -5217,8 +5369,11 @@
 	
 	KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx);
 
-	/* If not using NAT-T, make sure if port number is zero. */
-#ifndef IPSEC_NAT_T
+#ifdef IPSEC_NAT_T
+	if ((error = KEY_SET_NATT_PORTS(&saidx.src, &saidx.dst, mhp)) != 0)
+		return key_senderror(so, m, EINVAL);
+#else
+	/* If not using NAT-T, make sure the port numbers are zero. */
 	KEY_PORTTOSADDR(&saidx.src, 0);
 	KEY_PORTTOSADDR(&saidx.dst, 0);
 #endif
@@ -5283,74 +5438,17 @@
 		return key_senderror(so, m, error);
 	}
 
+#ifdef IPSEC_NAT_T
+	if ((error = key_handle_natt_info(sav,mhp)) != 0)
+		return key_senderror(so, m, EINVAL);
+#endif /* IPSEC_NAT_T */
+
 	/* check SA values to be mature. */
 	if ((error = key_mature(sav)) != 0) {
 		key_freesav(sav);
 		return key_senderror(so, m, error);
 	}
 
-#ifdef IPSEC_NAT_T
-	/*
-	 * Handle NAT-T info if present
-	 */
-	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 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_update: 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_update: 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];
-
-		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;
-	}
-#endif /* IPSEC_NAT_T */
-
     {
 	struct mbuf *n;
 
@@ -5473,8 +5571,11 @@
 	
 	KEY_SETSECASIDX(proto, mode, reqid, src0 + 1, dst0 + 1, &saidx);
 
-	/* If not using NAT-T, make sure if port number is zero. */
-#ifndef IPSEC_NAT_T
+#ifdef IPSEC_NAT_T
+	if ((error = KEY_SET_NATT_PORTS(&saidx.src, &saidx.dst, mhp)) != 0)
+		return key_senderror(so, m, EINVAL);
+#else
+	/* If not using NAT-T, make sure the port numbers are zero. */
 	KEY_PORTTOSADDR(&saidx.src, 0);
 	KEY_PORTTOSADDR(&saidx.dst, 0);
 #endif
@@ -5506,74 +5607,17 @@
 		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 */
+
 	/* check SA values to be mature. */
 	if ((error = key_mature(newsav)) != 0) {
 		key_freesav(newsav);
 		return key_senderror(so, m, error);
 	}
 
-#ifdef IPSEC_NAT_T
-	/*
-	 * 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;
-		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_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);
-		}
-
-		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 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];
-
-		if (type)
-			newsav->natt_type = type->sadb_x_nat_t_type_type;
-		if (sport)
-			KEY_PORTTOSADDR(&newsav->sah->saidx.src, 
-			    sport->sadb_x_nat_t_port_port);
-		if (dport)
-			KEY_PORTTOSADDR(&newsav->sah->saidx.dst,
-			    dport->sadb_x_nat_t_port_port);
-		if (frag)
-			newsav->esp_frag = frag->sadb_x_nat_t_frag_fraglen;
-		else
-			newsav->esp_frag = IP_MAXPACKET;
-	}
-#endif /* IPSEC_NAT_T */
-
 	/*
 	 * don't call key_freesav() here, as we would like to keep the SA
 	 * in the database on success.
@@ -5765,8 +5809,11 @@
 
 	KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
 
-	/* If not using NAT-T, make sure if port number is zero. */
-#ifndef IPSEC_NAT_T
+#ifdef IPSEC_NAT_T
+	if (KEY_SET_NATT_PORTS(&saidx.src, &saidx.dst, mhp) != 0)
+		return key_senderror(so, m, EINVAL);
+#else
+	/* If not using NAT-T, make sure the port numbers are zero. */
 	KEY_PORTTOSADDR(&saidx.src, 0);
 	KEY_PORTTOSADDR(&saidx.dst, 0);
 #endif
@@ -5839,8 +5886,11 @@
 
 	KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
 
-	/* If not using NAT-T, make sure if port number is zero. */
-#ifndef IPSEC_NAT_T
+#ifdef IPSEC_NAT_T
+	if (KEY_SET_NATT_PORTS(&saidx.src, &saidx.dst, mhp) != 0)
+		return key_senderror(so, m, EINVAL);
+#else
+	/* If not using NAT-T, make sure the port numbers are zero. */
 	KEY_PORTTOSADDR(&saidx.src, 0);
 	KEY_PORTTOSADDR(&saidx.dst, 0);
 #endif
@@ -5956,8 +6006,11 @@
 
 	KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
 
-	/* If not using NAT-T, make sure if port number is zero. */
-#ifndef IPSEC_NAT_T
+#ifdef IPSEC_NAT_T
+	if (KEY_SET_NATT_PORTS(&saidx.src, &saidx.dst, mhp) != 0)
+		return key_senderror(so, m, EINVAL);
+#else
+	/* If not using NAT-T, make sure the port numbers are zero. */
 	KEY_PORTTOSADDR(&saidx.src, 0);
 	KEY_PORTTOSADDR(&saidx.dst, 0);
 #endif
@@ -6646,8 +6699,11 @@
 
 	KEY_SETSECASIDX(proto, IPSEC_MODE_ANY, 0, src0 + 1, dst0 + 1, &saidx);
 
-	/* If not using NAT-T, make sure if port number is zero. */
-#ifndef IPSEC_NAT_T
+#ifdef IPSEC_NAT_T
+	if ((error = KEY_SET_NATT_PORTS(&saidx.src, &saidx.dst, mhp)) != 0)
+		return key_senderror(so, m, EINVAL);
+#else
+	/* If not using NAT-T, make sure the port numbers are zero. */
 	KEY_PORTTOSADDR(&saidx.src, 0);
 	KEY_PORTTOSADDR(&saidx.dst, 0);
 #endif
@@ -7735,7 +7791,8 @@
 		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_OAI:
+		case SADB_X_EXT_NAT_T_OAR:
 		case SADB_X_EXT_NAT_T_FRAG:
 #endif
 #ifdef SADB_X_EXT_TAG

Reply via email to