Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/netinet Clarify ESP-in-UDP.



details:   https://anonhg.NetBSD.org/src/rev/a22e6f005f5c
branches:  trunk
changeset: 319016:a22e6f005f5c
user:      maxv <maxv%NetBSD.org@localhost>
date:      Sun May 13 18:39:06 2018 +0000
description:
Clarify ESP-in-UDP.

diffstat:

 sys/netinet/udp_usrreq.c |  72 ++++++++++++++++++++++++++---------------------
 1 files changed, 40 insertions(+), 32 deletions(-)

diffs (147 lines):

diff -r 09c70746aceb -r a22e6f005f5c sys/netinet/udp_usrreq.c
--- a/sys/netinet/udp_usrreq.c  Sun May 13 18:34:59 2018 +0000
+++ b/sys/netinet/udp_usrreq.c  Sun May 13 18:39:06 2018 +0000
@@ -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 @@
 
 #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 @@
 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 @@
        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 @@
        }
 
        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 @@
 
        /*
         * 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) {



Home | Main Index | Thread Index | Old Index