Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 13 Apr 2017 14:44:17 +0000 (UTC)
From:      "Andrey V. Elsukov" <ae@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r316759 - in head: lib/libipsec sbin/setkey sys/netipsec
Message-ID:  <201704131444.v3DEiHUX078655@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ae
Date: Thu Apr 13 14:44:17 2017
New Revision: 316759
URL: https://svnweb.freebsd.org/changeset/base/316759

Log:
  Add large replay widow support to setkey(8) and libipsec.
  
  When the replay window size is large than UINT8_MAX, add to the request
  the SADB_X_EXT_SA_REPLAY extension header that was added in r309144.
  
  Also add support of 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_SA_REPLAY, SADB_X_EXT_NEW_ADDRESS_SRC, SADB_X_EXT_NEW_ADDRESS_DST
  extension headers to the key_debug that is used by `setkey -x`.
  
  Modify kdebug_sockaddr() to use inet_ntop() for IP addresses formatting.
  And modify kdebug_sadb_x_policy() to show policy scope and priority.
  
  Reviewed by:	gnn, Emeric Poupon
  MFC after:	2 weeks
  Differential Revision:	https://reviews.freebsd.org/D10375

Modified:
  head/lib/libipsec/pfkey.c
  head/sbin/setkey/Makefile
  head/sbin/setkey/parse.y
  head/sys/netipsec/key_debug.c

Modified: head/lib/libipsec/pfkey.c
==============================================================================
--- head/lib/libipsec/pfkey.c	Thu Apr 13 14:40:48 2017	(r316758)
+++ head/lib/libipsec/pfkey.c	Thu Apr 13 14:44:17 2017	(r316759)
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
 #include <netipsec/ipsec.h>
 
 #include <stdlib.h>
+#include <stdint.h>
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
@@ -69,6 +70,7 @@ static caddr_t pfkey_setsadbmsg(caddr_t,
 	u_int, u_int32_t, pid_t);
 static caddr_t pfkey_setsadbsa(caddr_t, caddr_t, u_int32_t, u_int,
 	u_int, u_int, u_int32_t);
+static caddr_t pfkey_setsadbxreplay(caddr_t, caddr_t, uint32_t);
 static caddr_t pfkey_setsadbaddr(caddr_t, caddr_t, u_int,
 	struct sockaddr *, u_int, u_int);
 static caddr_t pfkey_setsadbkey(caddr_t, caddr_t, u_int, caddr_t, u_int);
@@ -1196,6 +1198,13 @@ pfkey_send_x1(so, type, satype, mode, sr
 		+ sizeof(struct sadb_lifetime)
 		+ sizeof(struct sadb_lifetime);
 
+	if (wsize > UINT8_MAX) {
+		if (wsize > (UINT32_MAX - 32) >> 3) {
+			__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+			return (-1);
+		}
+		len += sizeof(struct sadb_x_sa_replay);
+	}
 	if (e_type != SADB_EALG_NONE)
 		len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(e_keylen));
 	if (a_type != SADB_AALG_NONE)
@@ -1223,6 +1232,13 @@ pfkey_send_x1(so, type, satype, mode, sr
 		free(newmsg);
 		return -1;
 	}
+	if (wsize > UINT8_MAX) {
+		p = pfkey_setsadbxreplay(p, ep, wsize);
+		if (!p) {
+			free(newmsg);
+			return (-1);
+		}
+	}
 	p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen,
 	    IPSEC_ULPROTO_ANY);
 	if (!p) {
@@ -1982,7 +1998,7 @@ pfkey_setsadbsa(buf, lim, spi, wsize, au
 	p->sadb_sa_len = PFKEY_UNIT64(len);
 	p->sadb_sa_exttype = SADB_EXT_SA;
 	p->sadb_sa_spi = spi;
-	p->sadb_sa_replay = wsize;
+	p->sadb_sa_replay = wsize > UINT8_MAX ? UINT8_MAX: wsize;
 	p->sadb_sa_state = SADB_SASTATE_LARVAL;
 	p->sadb_sa_auth = auth;
 	p->sadb_sa_encrypt = enc;
@@ -1992,6 +2008,31 @@ pfkey_setsadbsa(buf, lim, spi, wsize, au
 }
 
 /*
+ * Set data into sadb_x_sa_replay.
+ * `buf' must has been allocated sufficiently.
+ */
+static caddr_t
+pfkey_setsadbxreplay(caddr_t buf, caddr_t lim, uint32_t wsize)
+{
+	struct sadb_x_sa_replay *p;
+	u_int len;
+
+	p = (struct sadb_x_sa_replay *)buf;
+	len = sizeof(struct sadb_x_sa_replay);
+
+	if (buf + len > lim)
+		return (NULL);
+
+	memset(p, 0, len);
+	p->sadb_x_sa_replay_len = PFKEY_UNIT64(len);
+	p->sadb_x_sa_replay_exttype = SADB_X_EXT_SA_REPLAY;
+	/* Convert wsize from bytes to number of packets. */
+	p->sadb_x_sa_replay_replay = wsize << 3;
+
+	return (buf + len);
+}
+
+/*
  * set data into sadb_address.
  * `buf' must has been allocated sufficiently.
  * prefixlen is in bits.

Modified: head/sbin/setkey/Makefile
==============================================================================
--- head/sbin/setkey/Makefile	Thu Apr 13 14:40:48 2017	(r316758)
+++ head/sbin/setkey/Makefile	Thu Apr 13 14:44:17 2017	(r316759)
@@ -51,6 +51,9 @@ CFLAGS+= -I${SRCTOP}/sys
 SRCS+=	y.tab.h
 y.tab.h: parse.y
 CFLAGS+= -DIPSEC_DEBUG -DYY_NO_UNPUT
+.if ${MK_INET_SUPPORT} != "no"
+CFLAGS+= -DINET
+.endif
 .if ${MK_INET6_SUPPORT} != "no"
 CFLAGS+= -DINET6
 .endif

Modified: head/sbin/setkey/parse.y
==============================================================================
--- head/sbin/setkey/parse.y	Thu Apr 13 14:40:48 2017	(r316758)
+++ head/sbin/setkey/parse.y	Thu Apr 13 14:44:17 2017	(r316759)
@@ -45,6 +45,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <stdio.h>
+#include <stdint.h>
 #include <netdb.h>
 #include <ctype.h>
 #include <errno.h>
@@ -513,6 +514,8 @@ extension
 				return -1;
 			}
 			p_replay = $2;
+			if (p_replay > (UINT32_MAX - 32) >> 3)
+				yyerror("replay window is too large");
 		}
 	|	F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; }
 	|	F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; }
@@ -899,6 +902,7 @@ setkeymsg_addr(type, satype, srcs, dsts,
 	int l, l0, len;
 	struct sadb_sa m_sa;
 	struct sadb_x_sa2 m_sa2;
+	struct sadb_x_sa_replay m_replay;
 	struct sadb_address m_addr;
 	struct addrinfo *s, *d;
 	int n;
@@ -920,7 +924,8 @@ setkeymsg_addr(type, satype, srcs, dsts,
 		m_sa.sadb_sa_len = PFKEY_UNIT64(len);
 		m_sa.sadb_sa_exttype = SADB_EXT_SA;
 		m_sa.sadb_sa_spi = htonl(p_spi);
-		m_sa.sadb_sa_replay = p_replay;
+		m_sa.sadb_sa_replay = p_replay > UINT8_MAX ? UINT8_MAX:
+		    p_replay;
 		m_sa.sadb_sa_state = 0;
 		m_sa.sadb_sa_auth = p_alg_auth;
 		m_sa.sadb_sa_encrypt = p_alg_enc;
@@ -937,6 +942,17 @@ setkeymsg_addr(type, satype, srcs, dsts,
 
 		memcpy(buf + l, &m_sa2, len);
 		l += len;
+
+		if (p_replay > UINT8_MAX) {
+			len = sizeof(struct sadb_x_sa_replay);
+			m_replay.sadb_x_sa_replay_len = PFKEY_UNIT64(len);
+			m_replay.sadb_x_sa_replay_exttype =
+			    SADB_X_EXT_SA_REPLAY;
+			m_replay.sadb_x_sa_replay_replay = p_replay << 3;
+
+			memcpy(buf + l, &m_replay, len);
+			l += len;
+		}
 	}
 
 	l0 = l;
@@ -1017,6 +1033,7 @@ setkeymsg_add(type, satype, srcs, dsts)
 	struct sadb_sa m_sa;
 	struct sadb_x_sa2 m_sa2;
 	struct sadb_address m_addr;
+	struct sadb_x_sa_replay m_replay;
 	struct addrinfo *s, *d;
 	int n;
 	int plen;
@@ -1100,7 +1117,7 @@ setkeymsg_add(type, satype, srcs, dsts)
 	m_sa.sadb_sa_len = PFKEY_UNIT64(len);
 	m_sa.sadb_sa_exttype = SADB_EXT_SA;
 	m_sa.sadb_sa_spi = htonl(p_spi);
-	m_sa.sadb_sa_replay = p_replay;
+	m_sa.sadb_sa_replay = p_replay > UINT8_MAX ? UINT8_MAX: p_replay;
 	m_sa.sadb_sa_state = 0;
 	m_sa.sadb_sa_auth = p_alg_auth;
 	m_sa.sadb_sa_encrypt = p_alg_enc;
@@ -1118,6 +1135,15 @@ setkeymsg_add(type, satype, srcs, dsts)
 	memcpy(buf + l, &m_sa2, len);
 	l += len;
 
+	if (p_replay > UINT8_MAX) {
+		len = sizeof(struct sadb_x_sa_replay);
+		m_replay.sadb_x_sa_replay_len = PFKEY_UNIT64(len);
+		m_replay.sadb_x_sa_replay_exttype = SADB_X_EXT_SA_REPLAY;
+		m_replay.sadb_x_sa_replay_replay = p_replay << 3;
+
+		memcpy(buf + l, &m_replay, len);
+		l += len;
+	}
 	l0 = l;
 	n = 0;
 

Modified: head/sys/netipsec/key_debug.c
==============================================================================
--- head/sys/netipsec/key_debug.c	Thu Apr 13 14:40:48 2017	(r316758)
+++ head/sys/netipsec/key_debug.c	Thu Apr 13 14:44:17 2017	(r316759)
@@ -63,6 +63,7 @@
 #include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <arpa/inet.h>
 #endif /* !_KERNEL */
 
 static void kdebug_sadb_prop(struct sadb_ext *);
@@ -73,6 +74,8 @@ static void kdebug_sadb_sa(struct sadb_e
 static void kdebug_sadb_address(struct sadb_ext *);
 static void kdebug_sadb_key(struct sadb_ext *);
 static void kdebug_sadb_x_sa2(struct sadb_ext *);
+static void kdebug_sadb_x_sa_replay(struct sadb_ext *);
+static void kdebug_sadb_x_natt(struct sadb_ext *);
 
 #ifdef _KERNEL
 static void kdebug_secreplay(struct secreplay *);
@@ -131,6 +134,10 @@ kdebug_sadb(struct sadb_msg *base)
 		case SADB_EXT_ADDRESS_SRC:
 		case SADB_EXT_ADDRESS_DST:
 		case SADB_EXT_ADDRESS_PROXY:
+		case SADB_X_EXT_NAT_T_OAI:
+		case SADB_X_EXT_NAT_T_OAR:
+		case SADB_X_EXT_NEW_ADDRESS_SRC:
+		case SADB_X_EXT_NEW_ADDRESS_DST:
 			kdebug_sadb_address(ext);
 			break;
 		case SADB_EXT_KEY_AUTH:
@@ -159,6 +166,14 @@ kdebug_sadb(struct sadb_msg *base)
 		case SADB_X_EXT_SA2:
 			kdebug_sadb_x_sa2(ext);
 			break;
+		case SADB_X_EXT_SA_REPLAY:
+			kdebug_sadb_x_sa_replay(ext);
+			break;
+		case SADB_X_EXT_NAT_T_TYPE:
+		case SADB_X_EXT_NAT_T_SPORT:
+		case SADB_X_EXT_NAT_T_DPORT:
+			kdebug_sadb_x_natt(ext);
+			break;
 		default:
 			printf("%s: invalid ext_type %u\n", __func__,
 			    ext->sadb_ext_type);
@@ -342,8 +357,6 @@ kdebug_sadb_address(struct sadb_ext *ext
 	    ((u_char *)&addr->sadb_address_reserved)[1]);
 
 	kdebug_sockaddr((struct sockaddr *)((caddr_t)ext + sizeof(*addr)));
-
-	return;
 }
 
 static void
@@ -392,6 +405,41 @@ kdebug_sadb_x_sa2(struct sadb_ext *ext)
 	return;
 }
 
+static void
+kdebug_sadb_x_sa_replay(struct sadb_ext *ext)
+{
+	struct sadb_x_sa_replay *replay;
+
+	/* sanity check */
+	if (ext == NULL)
+		panic("%s: NULL pointer was passed.\n", __func__);
+
+	replay = (struct sadb_x_sa_replay *)ext;
+	printf("sadb_x_sa_replay{ replay=%u }\n",
+	    replay->sadb_x_sa_replay_replay);
+}
+
+static void
+kdebug_sadb_x_natt(struct sadb_ext *ext)
+{
+	struct sadb_x_nat_t_type *type;
+	struct sadb_x_nat_t_port *port;
+
+	/* sanity check */
+	if (ext == NULL)
+		panic("%s: NULL pointer was passed.\n", __func__);
+
+	if (ext->sadb_ext_type == SADB_X_EXT_NAT_T_TYPE) {
+		type = (struct sadb_x_nat_t_type *)ext;
+		printf("sadb_x_nat_t_type{ type=%u }\n",
+		    type->sadb_x_nat_t_type_type);
+	} else {
+		port = (struct sadb_x_nat_t_port *)ext;
+		printf("sadb_x_nat_t_port{ port=%u }\n",
+		    ntohs(port->sadb_x_nat_t_port_port));
+	}
+}
+
 void
 kdebug_sadb_x_policy(struct sadb_ext *ext)
 {
@@ -402,9 +450,11 @@ kdebug_sadb_x_policy(struct sadb_ext *ex
 	if (ext == NULL)
 		panic("%s: NULL pointer was passed.\n", __func__);
 
-	printf("sadb_x_policy{ type=%u dir=%u id=%x }\n",
+	printf("sadb_x_policy{ type=%u dir=%u id=%x scope=%u %s=%u }\n",
 		xpl->sadb_x_policy_type, xpl->sadb_x_policy_dir,
-		xpl->sadb_x_policy_id);
+		xpl->sadb_x_policy_id, xpl->sadb_x_policy_scope,
+		xpl->sadb_x_policy_scope == IPSEC_POLICYSCOPE_IFNET ?
+		"ifindex": "priority", xpl->sadb_x_policy_priority);
 
 	if (xpl->sadb_x_policy_type == IPSEC_POLICY_IPSEC) {
 		int tlen;
@@ -850,39 +900,42 @@ ipsec_sa2str(struct secasvar *sav, char 
 void
 kdebug_sockaddr(struct sockaddr *addr)
 {
-	struct sockaddr_in *sin4;
-#ifdef INET6
-	struct sockaddr_in6 *sin6;
-#endif
+	char buf[IPSEC_ADDRSTRLEN];
 
 	/* sanity check */
 	if (addr == NULL)
 		panic("%s: NULL pointer was passed.\n", __func__);
 
-	/* NOTE: We deal with port number as host byte order. */
-	printf("sockaddr{ len=%u family=%u", addr->sa_len, addr->sa_family);
-
 	switch (addr->sa_family) {
-	case AF_INET:
-		sin4 = (struct sockaddr_in *)addr;
-		printf(" port=%u\n", ntohs(sin4->sin_port));
-		ipsec_hexdump((caddr_t)&sin4->sin_addr, sizeof(sin4->sin_addr));
+#ifdef INET
+	case AF_INET: {
+		struct sockaddr_in *sin;
+
+		sin = (struct sockaddr_in *)addr;
+		inet_ntop(AF_INET, &sin->sin_addr, buf, sizeof(buf));
 		break;
+	}
+#endif
 #ifdef INET6
-	case AF_INET6:
+	case AF_INET6: {
+		struct sockaddr_in6 *sin6;
+
 		sin6 = (struct sockaddr_in6 *)addr;
-		printf(" port=%u\n", ntohs(sin6->sin6_port));
-		printf("  flowinfo=0x%08x, scope_id=0x%08x\n",
-		    sin6->sin6_flowinfo, sin6->sin6_scope_id);
-		ipsec_hexdump((caddr_t)&sin6->sin6_addr,
-		    sizeof(sin6->sin6_addr));
+		if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+			snprintf(buf, sizeof(buf), "%s%%%u",
+			    inet_ntop(AF_INET6, &sin6->sin6_addr, buf,
+			    sizeof(buf)), sin6->sin6_scope_id);
+		} else
+			inet_ntop(AF_INET6, &sin6->sin6_addr, buf,
+			    sizeof(buf));
 		break;
+	}
 #endif
+	default:
+		sprintf(buf, "unknown");
 	}
-
-	printf("  }\n");
-
-	return;
+	printf("sockaddr{ len=%u family=%u addr=%s }\n", addr->sa_len,
+	    addr->sa_family, buf);
 }
 
 void



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201704131444.v3DEiHUX078655>