Source-Changes-HG archive

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

[src/trunk]: src/sys/netipsec ipsecif(4) supports multiple peers in the same ...



details:   https://anonhg.NetBSD.org/src/rev/6a08084dca00
branches:  trunk
changeset: 446946:6a08084dca00
user:      knakahara <knakahara%NetBSD.org@localhost>
date:      Wed Dec 26 08:58:51 2018 +0000

description:
ipsecif(4) supports multiple peers in the same NAPT.

E.g. ipsec0 connects between NetBSD_A and NetBSD_B, ipsec1 connects
NetBSD_A and NetBSD_C at the following figure.

                                        +----------+
                                   +----| NetBSD_B |
 +----------+           +------+   |    +----------+
 | NetBSD_A |--- ... ---| NAPT |---+
 +----------+           +------+   |    +----------+
                                   +----| NetBSD_C |
                                        +----------+

Add ATF later.

diffstat:

 sys/netipsec/ipsec_output.c |  30 ++++++++++++++++++++++-----
 sys/netipsec/ipsecif.c      |  48 ++++++++++++++++++++++++++++++++++++++++++--
 sys/netipsec/key.c          |  12 +++++-----
 3 files changed, 75 insertions(+), 15 deletions(-)

diffs (213 lines):

diff -r 0282e3364856 -r 6a08084dca00 sys/netipsec/ipsec_output.c
--- a/sys/netipsec/ipsec_output.c       Wed Dec 26 08:55:14 2018 +0000
+++ b/sys/netipsec/ipsec_output.c       Wed Dec 26 08:58:51 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ipsec_output.c,v 1.81 2018/11/22 04:48:34 knakahara Exp $      */
+/*     $NetBSD: ipsec_output.c,v 1.82 2018/12/26 08:58:51 knakahara Exp $      */
 
 /*
  * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ipsec_output.c,v 1.81 2018/11/22 04:48:34 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipsec_output.c,v 1.82 2018/12/26 08:58:51 knakahara Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -289,6 +289,24 @@
 ipsec_fill_saidx_bymbuf(struct secasindex *saidx, const struct mbuf *m,
     const int af)
 {
+       struct m_tag *mtag;
+       u_int16_t natt_src = IPSEC_PORT_ANY;
+       u_int16_t natt_dst = IPSEC_PORT_ANY;
+
+       /*
+        * For NAT-T enabled ipsecif(4), set NAT-T port numbers
+        * even if the saidx uses transport mode.
+        *
+        * See also ipsecif[46]_output().
+        */
+       mtag = m_tag_find(m, PACKET_TAG_IPSEC_NAT_T_PORTS);
+       if (mtag) {
+               u_int16_t *natt_ports;
+
+               natt_ports = (u_int16_t *)(mtag + 1);
+               natt_src = natt_ports[1];
+               natt_dst = natt_ports[0];
+       }
 
        if (af == AF_INET) {
                struct sockaddr_in *sin;
@@ -298,14 +316,14 @@
                        sin = &saidx->src.sin;
                        sin->sin_len = sizeof(*sin);
                        sin->sin_family = AF_INET;
-                       sin->sin_port = IPSEC_PORT_ANY;
+                       sin->sin_port = natt_src;
                        sin->sin_addr = ip->ip_src;
                }
                if (saidx->dst.sa.sa_len == 0) {
                        sin = &saidx->dst.sin;
                        sin->sin_len = sizeof(*sin);
                        sin->sin_family = AF_INET;
-                       sin->sin_port = IPSEC_PORT_ANY;
+                       sin->sin_port = natt_dst;
                        sin->sin_addr = ip->ip_dst;
                }
        } else {
@@ -316,7 +334,7 @@
                        sin6 = (struct sockaddr_in6 *)&saidx->src;
                        sin6->sin6_len = sizeof(*sin6);
                        sin6->sin6_family = AF_INET6;
-                       sin6->sin6_port = IPSEC_PORT_ANY;
+                       sin6->sin6_port = natt_src;
                        sin6->sin6_addr = ip6->ip6_src;
                        if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
                                /* fix scope id for comparing SPD */
@@ -329,7 +347,7 @@
                        sin6 = (struct sockaddr_in6 *)&saidx->dst;
                        sin6->sin6_len = sizeof(*sin6);
                        sin6->sin6_family = AF_INET6;
-                       sin6->sin6_port = IPSEC_PORT_ANY;
+                       sin6->sin6_port = natt_dst;
                        sin6->sin6_addr = ip6->ip6_dst;
                        if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
                                /* fix scope id for comparing SPD */
diff -r 0282e3364856 -r 6a08084dca00 sys/netipsec/ipsecif.c
--- a/sys/netipsec/ipsecif.c    Wed Dec 26 08:55:14 2018 +0000
+++ b/sys/netipsec/ipsecif.c    Wed Dec 26 08:58:51 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ipsecif.c,v 1.12 2018/12/07 09:11:04 knakahara Exp $  */
+/*     $NetBSD: ipsecif.c,v 1.13 2018/12/26 08:58:51 knakahara Exp $  */
 
 /*
  * Copyright (c) 2017 Internet Initiative Japan Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ipsecif.c,v 1.12 2018/12/07 09:11:04 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipsecif.c,v 1.13 2018/12/26 08:58:51 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -71,6 +71,7 @@
 
 #include <net/if_ipsec.h>
 
+static int ipsecif_set_natt_ports(struct ipsec_variant *, struct mbuf *);
 static void ipsecif4_input(struct mbuf *, int, int, void *);
 static int ipsecif4_output(struct ipsec_variant *, int, struct mbuf *);
 static int ipsecif4_filter4(const struct ip *, struct ipsec_variant *,
@@ -102,6 +103,32 @@
 static const struct encapsw ipsecif6_encapsw;
 #endif
 
+static int
+ipsecif_set_natt_ports(struct ipsec_variant *var, struct mbuf *m)
+{
+
+       KASSERT(if_ipsec_heldref_variant(var));
+
+       if (var->iv_sport || var->iv_dport) {
+               struct m_tag *mtag;
+
+               mtag = m_tag_get(PACKET_TAG_IPSEC_NAT_T_PORTS,
+                   sizeof(uint16_t) + sizeof(uint16_t), M_DONTWAIT);
+               if (mtag) {
+                       uint16_t *natt_port;
+
+                       natt_port = (uint16_t *)(mtag + 1);
+                       natt_port[0] = var->iv_dport;
+                       natt_port[1] = var->iv_sport;
+                       m_tag_prepend(m, mtag);
+               } else {
+                       return ENOBUFS;
+               }
+       }
+
+       return 0;
+}
+
 static struct mbuf *
 ipsecif4_prepend_hdr(struct ipsec_variant *var, struct mbuf *m,
     uint8_t proto, uint8_t tos)
@@ -394,6 +421,13 @@
        if (mtu > 0)
                return ipsecif4_fragout(var, family, m, mtu);
 
+       /* set NAT-T ports */
+       error = ipsecif_set_natt_ports(var, m);
+       if (error) {
+               m_freem(m);
+               goto done;
+       }
+
        /* IPsec output */
        IP_STATINC(IP_STAT_LOCALOUT);
        error = ipsec4_process_packet(m, sp->req, &sa_mtu);
@@ -586,6 +620,13 @@
        }
        rtcache_unref(rt, &iro->ir_ro);
 
+       /* set NAT-T ports */
+       error = ipsecif_set_natt_ports(var, m);
+       if (error) {
+               m_freem(m);
+               goto out;
+       }
+
        /*
         * force fragmentation to minimum MTU, to avoid path MTU discovery.
         * it is too painful to ask for resend of inner packet, to achieve
@@ -593,9 +634,10 @@
         */
        error = ip6_output(m, 0, &iro->ir_ro,
            ip6_ipsec_pmtu ? 0 : IPV6_MINMTU, 0, NULL, NULL);
+
+out:
        if (error)
                rtcache_free(&iro->ir_ro);
-
        mutex_exit(iro->ir_lock);
        percpu_putref(sc->ipsec_ro_percpu);
 
diff -r 0282e3364856 -r 6a08084dca00 sys/netipsec/key.c
--- a/sys/netipsec/key.c        Wed Dec 26 08:55:14 2018 +0000
+++ b/sys/netipsec/key.c        Wed Dec 26 08:58:51 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: key.c,v 1.259 2018/12/26 08:55:14 knakahara Exp $      */
+/*     $NetBSD: key.c,v 1.260 2018/12/26 08:58:51 knakahara Exp $      */
 /*     $FreeBSD: 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.259 2018/12/26 08:55:14 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: key.c,v 1.260 2018/12/26 08:58:51 knakahara Exp $");
 
 /*
  * This code is referred to RFC 2367
@@ -4567,13 +4567,13 @@
                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
+                * For ipsecif(4), check ports for transport mode, too.
+                * 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)
+               if (saidx1->mode == IPSEC_MODE_TUNNEL ||
+                   saidx1->mode == IPSEC_MODE_TRANSPORT)
                        chkport = PORT_LOOSE;
                else
                        chkport = PORT_NONE;



Home | Main Index | Thread Index | Old Index