Module Name:    src
Committed By:   christos
Date:           Sat Mar  5 20:13:40 UTC 2016

Modified Files:
        src/sys/netipsec: key.c

Log Message:
Fix port matching; we need to ignore ports when they are 0 not only in
the second saidx but the first one too. Fixes NAT-T issue with NetBSD
being the host behind NAT.


To generate a diff of this commit:
cvs rdiff -u -r1.93 -r1.94 src/sys/netipsec/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/netipsec/key.c
diff -u src/sys/netipsec/key.c:1.93 src/sys/netipsec/key.c:1.94
--- src/sys/netipsec/key.c:1.93	Sat Mar  5 15:12:23 2016
+++ src/sys/netipsec/key.c	Sat Mar  5 15:13:40 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: key.c,v 1.93 2016/03/05 20:12:23 christos Exp $	*/
+/*	$NetBSD: key.c,v 1.94 2016/03/05 20:13:40 christos 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.93 2016/03/05 20:12:23 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.94 2016/03/05 20:13:40 christos Exp $");
 
 /*
  * This code is referd to RFC 2367
@@ -4191,6 +4191,19 @@ key_ismyaddr6(const struct sockaddr_in6 
 }
 #endif /*INET6*/
 
+static in_port_t
+key_getport(const void *v)
+{
+	const struct sockaddr *sa = v;
+	switch (sa->sa_family) {
+	case AF_INET:
+		return ((const struct sockaddr_in *)v)->sin_port;
+	case AF_INET6:
+		return ((const struct sockaddr_in6 *)v)->sin6_port;
+	default:
+		return 0;
+	}
+}
 /*
  * compare two secasindex structure.
  * flag can specify to compare 2 saidxes.
@@ -4210,6 +4223,7 @@ key_cmpsaidx(
 	int flag)
 {
 	int chkport = 0;
+	const struct sockaddr *sa0src, *sa0dst, *sa1src, *sa1dst;
 
 	/* sanity */
 	if (saidx0 == NULL && saidx1 == NULL)
@@ -4248,29 +4262,28 @@ key_cmpsaidx(
 				return 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.
-         * 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.
-	 */
-	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;
 
-		if (key_sockaddrcmp(&saidx0->src.sa, &saidx1->src.sa, chkport) != 0) {
+		sa0src = &saidx0->src.sa;
+		sa0dst = &saidx0->dst.sa;
+		sa1src = &saidx1->src.sa;
+		sa1dst = &saidx1->dst.sa;
+		/*
+		 * 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.
+		 */
+		if (saidx1->mode == IPSEC_MODE_TUNNEL) {
+			chkport = key_getport(sa0src) && key_getport(sa0dst) &&
+			    key_getport(sa1src) && key_getport(sa1dst);
+		}
+
+		if (key_sockaddrcmp(sa0src, sa1src, chkport) != 0) {
 			return 0;
 		}
-		if (key_sockaddrcmp(&saidx0->dst.sa, &saidx1->dst.sa, chkport) != 0) {
+		if (key_sockaddrcmp(sa0dst, &sa1dst, chkport) != 0) {
 			return 0;
 		}
 	}

Reply via email to