git: 2fa1b8617fdf - main - setkey(8): NAT-T manual configuration support

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Mon, 29 May 2023 22:10:09 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=2fa1b8617fdf68d0043efb7ae7c524702afba27c

commit 2fa1b8617fdf68d0043efb7ae7c524702afba27c
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2023-05-25 10:41:15 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2023-05-29 22:10:02 +0000

    setkey(8): NAT-T manual configuration support
    
    This is needed for testing of offload capabilities.
    
    Reviewed by:    ae
    Discussed with: bz
    Sponsored by:   NVidia networking
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D40300
---
 sbin/setkey/parse.y | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 sbin/setkey/token.l |  2 ++
 2 files changed, 88 insertions(+), 1 deletion(-)

diff --git a/sbin/setkey/parse.y b/sbin/setkey/parse.y
index d279546fada6..8e4866e7e848 100644
--- a/sbin/setkey/parse.y
+++ b/sbin/setkey/parse.y
@@ -43,6 +43,7 @@
 #include <netipsec/key_var.h>
 #include <netipsec/ipsec.h>
 #include <arpa/inet.h>
+#include <netinet/udp.h>
 
 #include <string.h>
 #include <unistd.h>
@@ -64,6 +65,10 @@ u_int32_t p_reqid;
 u_int p_key_enc_len, p_key_auth_len;
 caddr_t p_key_enc, p_key_auth;
 time_t p_lt_hard, p_lt_soft;
+u_int p_natt_type;
+struct addrinfo *p_natt_oai, *p_natt_oar;
+int p_natt_sport, p_natt_dport;
+int p_natt_fraglen;
 
 static int p_aiflags = 0, p_aifamily = PF_UNSPEC;
 
@@ -110,7 +115,7 @@ extern void yyerror(const char *);
 	/* SPD management */
 %token SPDADD SPDDELETE SPDDUMP SPDFLUSH
 %token F_POLICY PL_REQUESTS
-%token F_AIFLAGS
+%token F_AIFLAGS F_NATT F_NATT_MTU
 %token TAGGED
 
 %type <num> prefix protocol_spec upper_spec
@@ -521,6 +526,20 @@ extension
 		}
 	|	F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; }
 	|	F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; }
+	|	F_NATT ipaddr BLCL DECSTRING ELCL ipaddr BLCL DECSTRING ELCL
+		{
+			p_natt_type = UDP_ENCAP_ESPINUDP;
+			p_natt_oai = $2;
+			p_natt_oar = $6;
+			if (p_natt_oai == NULL || p_natt_oar == NULL)
+				return (-1);
+			p_natt_sport = $4;
+			p_natt_dport = $8;
+		}
+	|	F_NATT_MTU DECSTRING
+		{
+			p_natt_fraglen = $2;
+		}
 	;
 
 	/* definition about command for SPD management */
@@ -1019,6 +1038,9 @@ setkeymsg_add(unsigned type, unsigned satype, struct addrinfo *srcs,
 	struct sadb_address m_addr;
 	struct sadb_x_sa_replay m_replay;
 	struct addrinfo *s, *d;
+	struct sadb_x_nat_t_type m_natt_type;
+	struct sadb_x_nat_t_port m_natt_port;
+	struct sadb_x_nat_t_frag m_natt_frag;
 	int n;
 	int plen;
 	struct sockaddr *sa;
@@ -1128,6 +1150,64 @@ setkeymsg_add(unsigned type, unsigned satype, struct addrinfo *srcs,
 		memcpy(buf + l, &m_replay, len);
 		l += len;
 	}
+
+	if (p_natt_type != 0) {
+		len = sizeof(m_natt_type);
+		memset(&m_natt_type, 0, sizeof(m_natt_type));
+		m_natt_type.sadb_x_nat_t_type_len = PFKEY_UNIT64(len);
+		m_natt_type.sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
+		m_natt_type.sadb_x_nat_t_type_type = p_natt_type;
+		memcpy(buf + l, &m_natt_type, len);
+		l += len;
+
+		memset(&m_addr, 0, sizeof(m_addr));
+		m_addr.sadb_address_exttype = SADB_X_EXT_NAT_T_OAI;
+		sa = p_natt_oai->ai_addr;
+		salen = p_natt_oai->ai_addr->sa_len;
+		m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
+		    PFKEY_ALIGN8(salen));
+		m_addr.sadb_address_prefixlen = setkeymsg_plen(p_natt_oai);
+		setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
+		    sizeof(m_addr), (caddr_t)sa, salen);
+
+		len = sizeof(m_natt_port);
+		memset(&m_natt_port, 0, sizeof(m_natt_port));
+		m_natt_port.sadb_x_nat_t_port_len = PFKEY_UNIT64(len);
+		m_natt_port.sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_SPORT;
+		m_natt_port.sadb_x_nat_t_port_port = htons(p_natt_sport);
+		memcpy(buf + l, &m_natt_port, len);
+		l += len;
+
+		memset(&m_addr, 0, sizeof(m_addr));
+		m_addr.sadb_address_exttype = SADB_X_EXT_NAT_T_OAR;
+		sa = p_natt_oar->ai_addr;
+		salen = p_natt_oar->ai_addr->sa_len;
+		m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
+		    PFKEY_ALIGN8(salen));
+		m_addr.sadb_address_prefixlen = setkeymsg_plen(p_natt_oar);
+		setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
+		    sizeof(m_addr), (caddr_t)sa, salen);
+
+		len = sizeof(m_natt_port);
+		memset(&m_natt_port, 0, sizeof(m_natt_port));
+		m_natt_port.sadb_x_nat_t_port_len = PFKEY_UNIT64(len);
+		m_natt_port.sadb_x_nat_t_port_exttype = SADB_X_EXT_NAT_T_DPORT;
+		m_natt_port.sadb_x_nat_t_port_port = htons(p_natt_dport);
+		memcpy(buf + l, &m_natt_port, len);
+		l += len;
+
+		if (p_natt_fraglen != -1) {
+			len = sizeof(m_natt_frag);
+			memset(&m_natt_port, 0, sizeof(m_natt_frag));
+			m_natt_frag.sadb_x_nat_t_frag_len = PFKEY_UNIT64(len);
+			m_natt_frag.sadb_x_nat_t_frag_exttype =
+			    SADB_X_EXT_NAT_T_FRAG;
+			m_natt_frag.sadb_x_nat_t_frag_fraglen = p_natt_fraglen;
+			memcpy(buf + l, &m_natt_frag, len);
+			l += len;
+		}
+	}
+
 	l0 = l;
 	n = 0;
 
@@ -1271,6 +1351,11 @@ parse_init(void)
 
 	p_aiflags = 0;
 	p_aifamily = PF_UNSPEC;
+
+	p_natt_type = 0;
+	p_natt_oai = p_natt_oar = NULL;
+	p_natt_sport = p_natt_dport = 0;
+	p_natt_fraglen = -1;
 }
 
 void
diff --git a/sbin/setkey/token.l b/sbin/setkey/token.l
index 44b1ffbfaa32..ff15b959a585 100644
--- a/sbin/setkey/token.l
+++ b/sbin/setkey/token.l
@@ -186,6 +186,8 @@ nocyclic-seq	{ return(NOCYCLICSEQ); }
 {hyphen}r	{ return(F_REPLAY); }
 {hyphen}lh	{ return(F_LIFETIME_HARD); }
 {hyphen}ls	{ return(F_LIFETIME_SOFT); }
+{hyphen}natt	{ return(F_NATT); }
+{hyphen}natt_mtu { return(F_NATT_MTU); }
 
 	/* ... */
 any		{ return(ANY); }