Module Name:    src
Committed By:   maxv
Date:           Sun May 13 18:39:06 UTC 2018

Modified Files:
        src/sys/netinet: udp_usrreq.c

Log Message:
Clarify ESP-in-UDP.


To generate a diff of this commit:
cvs rdiff -u -r1.250 -r1.251 src/sys/netinet/udp_usrreq.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/netinet/udp_usrreq.c
diff -u src/sys/netinet/udp_usrreq.c:1.250 src/sys/netinet/udp_usrreq.c:1.251
--- src/sys/netinet/udp_usrreq.c:1.250	Tue May  1 08:42:41 2018
+++ src/sys/netinet/udp_usrreq.c	Sun May 13 18:39:06 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: udp_usrreq.c,v 1.250 2018/05/01 08:42:41 maxv Exp $	*/
+/*	$NetBSD: udp_usrreq.c,v 1.251 2018/05/13 18:39:06 maxv Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.250 2018/05/01 08:42:41 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.251 2018/05/13 18:39:06 maxv Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -1239,6 +1239,14 @@ udp_statinc(u_int stat)
 
 #if defined(INET) && defined(IPSEC)
 /*
+ * Handle ESP-in-UDP packets (RFC3948).
+ *
+ * We need to distinguish between ESP packets and IKE packets. We do so by
+ * looking at the Non-ESP and Non-IKE markers.
+ *
+ * If IKE, we process the UDP packet as usual. Otherwise, ESP, we invoke
+ * IPsec.
+ *
  * Returns:
  *     1 if the packet was processed
  *     0 if normal UDP processing should take place
@@ -1248,7 +1256,7 @@ static int
 udp4_espinudp(struct mbuf **mp, int off, struct socket *so)
 {
 	size_t len;
-	void *data;
+	uint8_t *data;
 	struct inpcb *inp;
 	size_t skip = 0;
 	size_t minlen;
@@ -1260,10 +1268,10 @@ udp4_espinudp(struct mbuf **mp, int off,
 	struct mbuf *m = *mp;
 
 	/*
-	 * Collapse the mbuf chain if the first mbuf is too short
-	 * The longest case is: UDP + non ESP marker + ESP.
+	 * Collapse the mbuf chain if the first mbuf is too short.
+	 * The longest case is: UDP + max(Non-ESP, Non-IKE) + ESP.
 	 */
-	minlen = off + sizeof(u_int64_t) + sizeof(struct esp);
+	minlen = off + 2 * sizeof(uint32_t) + sizeof(struct esp);
 	if (minlen > m->m_pkthdr.len)
 		minlen = m->m_pkthdr.len;
 
@@ -1275,51 +1283,52 @@ udp4_espinudp(struct mbuf **mp, int off,
 	}
 
 	len = m->m_len - off;
-	data = mtod(m, char *) + off;
+	data = mtod(m, uint8_t *) + off;
 	inp = sotoinpcb(so);
 
-	/* Ignore keepalive packets */
-	if ((len == 1) && (*(unsigned char *)data == 0xff)) {
+	/* Ignore keepalive packets. */
+	if ((len == 1) && (*data == 0xff)) {
 		m_freem(m);
-		*mp = NULL; /* avoid any further processing by caller ... */
+		*mp = NULL; /* avoid any further processing by caller */
 		return 1;
 	}
 
-	/*
-	 * Check that the payload is long enough to hold
-	 * an ESP header and compute the length of encapsulation
-	 * header to remove
-	 */
+	/* Handle Non-ESP marker (32bit). If zero, then IKE. */
 	if (inp->inp_flags & INP_ESPINUDP) {
-		u_int32_t *st = (u_int32_t *)data;
+		uint32_t *marker = (uint32_t *)data;
 
-		if ((len <= sizeof(struct esp)) || (*st == 0))
-			return 0; /* Normal UDP processing */
+		if (len <= sizeof(uint32_t))
+			return 0;
+		if (marker[0] == 0)
+			return 0;
 
 		skip = sizeof(struct udphdr);
 	}
 
+	/* Handle Non-IKE marker (64bit). If non-zero, then IKE. */
 	if (inp->inp_flags & INP_ESPINUDP_NON_IKE) {
-		u_int32_t *st = (u_int32_t *)data;
+		uint32_t *marker = (uint32_t *)data;
 
-		if ((len <= sizeof(u_int64_t) + sizeof(struct esp)) ||
-		    ((st[0] | st[1]) != 0))
-			return 0; /* Normal UDP processing */
+		if (len <= 2 * sizeof(uint32_t) + sizeof(struct esp))
+			return 0;
+		if (marker[0] != 0 || marker[1] != 0)
+			return 0;
 
-		skip = sizeof(struct udphdr) + sizeof(u_int64_t);
+		skip = sizeof(struct udphdr) + 2 * sizeof(uint32_t);
 	}
 
 	/*
-	 * Get the UDP ports. They are handled in network
-	 * order everywhere in IPSEC_NAT_T code.
+	 * Get the UDP ports. They are handled in network order
+	 * everywhere in the IPSEC_NAT_T code.
 	 */
 	udphdr = (struct udphdr *)((char *)data - skip);
 	sport = udphdr->uh_sport;
 	dport = udphdr->uh_dport;
 
 	/*
-	 * Remove the UDP header (and possibly the non ESP marker)
-	 * IP header length is iphdrlen
+	 * Remove the UDP header, plus a possible marker. IP header
+	 * length is iphdrlen.
+	 *
 	 * Before:
 	 *   <--- off --->
 	 *   +----+------+-----+
@@ -1342,12 +1351,11 @@ udp4_espinudp(struct mbuf **mp, int off,
 
 	/*
 	 * We have modified the packet - it is now ESP, so we should not
-	 * return to UDP processing ...
+	 * return to UDP processing.
 	 *
-	 * Add a PACKET_TAG_IPSEC_NAT_T_PORT tag to remember
-	 * the source UDP port. This is required if we want
-	 * to select the right SPD for multiple hosts behind
-	 * same NAT
+	 * Add a PACKET_TAG_IPSEC_NAT_T_PORTS tag to remember the source
+	 * UDP port. This is required if we want to select the right SPD
+	 * for multiple hosts behind same NAT.
 	 */
 	if ((tag = m_tag_get(PACKET_TAG_IPSEC_NAT_T_PORTS,
 	    sizeof(sport) + sizeof(dport), M_DONTWAIT)) == NULL) {

Reply via email to