Source-Changes-HG archive

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

[src/trunk]: src/sys Make global and per-interface ipsecif(4) pmtu tunable li...



details:   https://anonhg.NetBSD.org/src/rev/7c740c6e67dd
branches:  trunk
changeset: 846129:7c740c6e67dd
user:      knakahara <knakahara%NetBSD.org@localhost>
date:      Fri Nov 01 04:28:14 2019 +0000

description:
Make global and per-interface ipsecif(4) pmtu tunable like gif(4).

And make hop limit tunable same as gif(4).

See http://mail-index.netbsd.org/source-changes/2019/10/30/msg110426.html

diffstat:

 sys/net/if_ipsec.c     |  143 ++++++++++++++++++++++++++++++++++++++++++++++++-
 sys/net/if_ipsec.h     |    3 +-
 sys/netinet6/in6.h     |    4 +-
 sys/netipsec/ipsecif.c |   56 ++++++++++++++++---
 sys/netipsec/ipsecif.h |   11 +++-
 5 files changed, 203 insertions(+), 14 deletions(-)

diffs (truncated from 345 to 300 lines):

diff -r ce6946c4fb0f -r 7c740c6e67dd sys/net/if_ipsec.c
--- a/sys/net/if_ipsec.c        Fri Nov 01 04:23:21 2019 +0000
+++ b/sys/net/if_ipsec.c        Fri Nov 01 04:28:14 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_ipsec.c,v 1.24 2019/09/19 06:07:24 knakahara Exp $  */
+/*     $NetBSD: if_ipsec.c,v 1.25 2019/11/01 04:28:14 knakahara Exp $  */
 
 /*
  * Copyright (c) 2017 Internet Initiative Japan Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_ipsec.c,v 1.24 2019/09/19 06:07:24 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ipsec.c,v 1.25 2019/11/01 04:28:14 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -48,6 +48,7 @@
 #include <sys/mutex.h>
 #include <sys/pserialize.h>
 #include <sys/psref.h>
+#include <sys/sysctl.h>
 
 #include <net/if.h>
 #include <net/if_types.h>
@@ -147,6 +148,138 @@
     IF_CLONE_INITIALIZER("ipsec", if_ipsec_clone_create, if_ipsec_clone_destroy);
 static int max_ipsec_nesting = MAX_IPSEC_NEST;
 
+static struct sysctllog *if_ipsec_sysctl;
+
+#ifdef INET6
+static int
+sysctl_if_ipsec_pmtu_global(SYSCTLFN_ARGS)
+{
+       int error, pmtu;
+       struct sysctlnode node = *rnode;
+
+       pmtu = ip6_ipsec_pmtu;
+       node.sysctl_data = &pmtu;
+       error = sysctl_lookup(SYSCTLFN_CALL(&node));
+       if (error || newp == NULL)
+               return error;
+
+       switch (pmtu) {
+       case IPSEC_PMTU_MINMTU:
+       case IPSEC_PMTU_OUTERMTU:
+               ip6_ipsec_pmtu = pmtu;
+               break;
+       default:
+               return EINVAL;
+       }
+
+       return 0;
+}
+
+static int
+sysctl_if_ipsec_pmtu_perif(SYSCTLFN_ARGS)
+{
+       int error, pmtu;
+       struct sysctlnode node = *rnode;
+       struct ipsec_softc *sc = (struct ipsec_softc *)node.sysctl_data;
+
+       pmtu = sc->ipsec_pmtu;
+       node.sysctl_data = &pmtu;
+       error = sysctl_lookup(SYSCTLFN_CALL(&node));
+       if (error || newp == NULL)
+               return error;
+
+       switch (pmtu) {
+       case IPSEC_PMTU_SYSDEFAULT:
+       case IPSEC_PMTU_MINMTU:
+       case IPSEC_PMTU_OUTERMTU:
+               sc->ipsec_pmtu = pmtu;
+               break;
+       default:
+               return EINVAL;
+       }
+
+       return 0;
+}
+#endif
+
+static void
+if_ipsec_sysctl_setup(void)
+{
+       if_ipsec_sysctl = NULL;
+
+#ifdef INET6
+       /*
+        * Previously create "net.inet6.ip6" entry to avoid sysctl_createv error.
+        */
+       sysctl_createv(NULL, 0, NULL, NULL,
+                      CTLFLAG_PERMANENT,
+                      CTLTYPE_NODE, "inet6",
+                      SYSCTL_DESCR("PF_INET6 related settings"),
+                      NULL, 0, NULL, 0,
+                      CTL_NET, PF_INET6, CTL_EOL);
+       sysctl_createv(NULL, 0, NULL, NULL,
+                      CTLFLAG_PERMANENT,
+                      CTLTYPE_NODE, "ip6",
+                      SYSCTL_DESCR("IPv6 related settings"),
+                      NULL, 0, NULL, 0,
+                      CTL_NET, PF_INET6, IPPROTO_IPV6, CTL_EOL);
+
+       sysctl_createv(&if_ipsec_sysctl, 0, NULL, NULL,
+                      CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
+                      CTLTYPE_INT, "ipsecifhlim",
+                      SYSCTL_DESCR("Default hop limit for a ipsec tunnel datagram"),
+                      NULL, 0, &ip6_ipsec_hlim, 0,
+                      CTL_NET, PF_INET6, IPPROTO_IPV6,
+                      IPV6CTL_IPSEC_HLIM, CTL_EOL);
+
+       sysctl_createv(&if_ipsec_sysctl, 0, NULL, NULL,
+                      CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
+                      CTLTYPE_INT, "ipsecifpmtu",
+                      SYSCTL_DESCR("Default Path MTU setting for ipsec tunnels"),
+                      sysctl_if_ipsec_pmtu_global, 0, NULL, 0,
+                      CTL_NET, PF_INET6, IPPROTO_IPV6,
+                      IPV6CTL_IPSEC_PMTU, CTL_EOL);
+#endif
+}
+
+static void
+if_ipsec_perif_sysctl_setup(struct sysctllog **clog, struct ipsec_softc *sc)
+{
+#ifdef INET6
+       const struct sysctlnode *cnode, *rnode;
+       struct ifnet *ifp = &sc->ipsec_if;
+       const char *ifname = ifp->if_xname;
+       int rv;
+
+       /*
+        * Already created in sysctl_sndq_setup().
+        */
+       sysctl_createv(clog, 0, NULL, &rnode,
+                      CTLFLAG_PERMANENT,
+                      CTLTYPE_NODE, "interfaces",
+                      SYSCTL_DESCR("Per-interface controls"),
+                      NULL, 0, NULL, 0,
+                      CTL_NET, CTL_CREATE, CTL_EOL);
+       sysctl_createv(clog, 0, &rnode, &rnode,
+                      CTLFLAG_PERMANENT,
+                      CTLTYPE_NODE, ifname,
+                      SYSCTL_DESCR("Interface controls"),
+                      NULL, 0, NULL, 0,
+                      CTL_CREATE, CTL_EOL);
+
+       rv = sysctl_createv(clog, 0, &rnode, &cnode,
+                           CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
+                           CTLTYPE_INT, "pmtu",
+                           SYSCTL_DESCR("Path MTU setting for this ipsec tunnel"),
+                           sysctl_if_ipsec_pmtu_perif, 0, (void *)sc, 0,
+                           CTL_CREATE, CTL_EOL);
+       if (rv != 0)
+               log(LOG_WARNING, "%s: could not attach sysctl node pmtu\n", ifname);
+
+       sc->ipsec_pmtu = IPSEC_PMTU_SYSDEFAULT;
+#endif
+}
+
 /* ARGSUSED */
 void
 ipsecifattach(int count)
@@ -157,6 +290,8 @@
 
        iv_psref_class = psref_class_create("ipsecvar", IPL_SOFTNET);
 
+       if_ipsec_sysctl_setup();
+
        if_clone_attach(&ipsec_cloner);
 }
 
@@ -165,6 +300,7 @@
 {
        struct ipsec_softc *sc;
        struct ipsec_variant *var;
+       struct ifnet *ifp;
 
        sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
 
@@ -172,6 +308,9 @@
 
        if_ipsec_attach0(sc);
 
+       ifp = &sc->ipsec_if;
+       if_ipsec_perif_sysctl_setup(&ifp->if_sysctl_log, sc);
+
        var = kmem_zalloc(sizeof(*var), KM_SLEEP);
        var->iv_softc = sc;
        psref_target_init(&var->iv_psref, iv_psref_class);
diff -r ce6946c4fb0f -r 7c740c6e67dd sys/net/if_ipsec.h
--- a/sys/net/if_ipsec.h        Fri Nov 01 04:23:21 2019 +0000
+++ b/sys/net/if_ipsec.h        Fri Nov 01 04:28:14 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_ipsec.h,v 1.5 2019/09/19 06:07:24 knakahara Exp $  */
+/*     $NetBSD: if_ipsec.h,v 1.6 2019/11/01 04:28:14 knakahara Exp $  */
 
 /*
  * Copyright (c) 2017 Internet Initiative Japan Inc.
@@ -95,6 +95,7 @@
                                          */
        kmutex_t ipsec_lock;            /* writer lock for ipsec_var */
        pserialize_t ipsec_psz;
+       int ipsec_pmtu;
 
        LIST_ENTRY(ipsec_softc) ipsec_list; /* list of all gifs */
 };
diff -r ce6946c4fb0f -r 7c740c6e67dd sys/netinet6/in6.h
--- a/sys/netinet6/in6.h        Fri Nov 01 04:23:21 2019 +0000
+++ b/sys/netinet6/in6.h        Fri Nov 01 04:28:14 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in6.h,v 1.97 2019/10/30 03:45:59 knakahara Exp $       */
+/*     $NetBSD: in6.h,v 1.98 2019/11/01 04:28:14 knakahara Exp $       */
 /*     $KAME: in6.h,v 1.83 2001/03/29 02:55:07 jinmei Exp $    */
 
 /*
@@ -537,6 +537,8 @@
 #define IPV6CTL_RTADV_NUMROUTES 44     /* current number of routes */
                                        /* via router advertisement */
 #define IPV6CTL_GIF_PMTU       45      /* gif(4) Path MTU setting */
+#define IPV6CTL_IPSEC_HLIM     46      /* default HLIM for ipsecif encap packet */
+#define IPV6CTL_IPSEC_PMTU     47      /* ipsecif(4) Path MTU setting */
 #endif /* _NETBSD_SOURCE */
 
 #ifdef _KERNEL
diff -r ce6946c4fb0f -r 7c740c6e67dd sys/netipsec/ipsecif.c
--- a/sys/netipsec/ipsecif.c    Fri Nov 01 04:23:21 2019 +0000
+++ b/sys/netipsec/ipsecif.c    Fri Nov 01 04:28:14 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ipsecif.c,v 1.17 2019/09/19 06:07:25 knakahara Exp $  */
+/*     $NetBSD: ipsecif.c,v 1.18 2019/11/01 04:28:14 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.17 2019/09/19 06:07:25 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipsecif.c,v 1.18 2019/11/01 04:28:14 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -87,8 +87,8 @@
 static int ip_ipsec_ttl = IPSEC_TTL;
 static int ip_ipsec_copy_tos = 0;
 #ifdef INET6
-static int ip6_ipsec_hlim = IPSEC_HLIM;
-static int ip6_ipsec_pmtu = 0; /* XXX: per interface configuration?? */
+int ip6_ipsec_hlim = IPSEC_HLIM;
+int ip6_ipsec_pmtu = 0;
 static int ip6_ipsec_copy_tos = 0;
 #endif
 
@@ -506,7 +506,7 @@
        struct sockaddr_in6 *sin6_src;
        struct sockaddr_in6 *sin6_dst;
        struct ip6_hdr *ip6;
-       int proto, error;
+       int proto, error, flags;
        u_int8_t itos, otos;
        union {
                struct sockaddr         dst;
@@ -626,12 +626,50 @@
        }
 
        /*
-        * force fragmentation to minimum MTU, to avoid path MTU discovery.
-        * it is too painful to ask for resend of inner packet, to achieve
+        * - IPSEC_PMTU_MINMTU
+        *   Force fragmentation to minimum MTU to avoid path MTU discovery
+        * - IPSEC_PMTU_OUTERMTU
+        *   Trust outer MTU is large enough to send all packets
+        *
+        * It is too painful to ask for resend of inner packet, to achieve
         * path MTU discovery for encapsulated packets.
+        *
+        * See RFC4459.
         */
-       error = ip6_output(m, 0, ro_pc,
-           ip6_ipsec_pmtu ? 0 : IPV6_MINMTU, 0, NULL, NULL);
+       if (sc->ipsec_pmtu == IPSEC_PMTU_SYSDEFAULT) {
+               switch (ip6_ipsec_pmtu) {
+               case IPSEC_PMTU_MINMTU:
+                       flags = IPV6_MINMTU;
+                       break;
+               case IPSEC_PMTU_OUTERMTU:
+                       flags = 0;
+                       break;
+               default:
+#ifdef DEBUG
+                       log(LOG_DEBUG, "%s: ignore unexpected ip6_ipsec_pmtu %d\n",
+                           __func__, ip6_ipsec_pmtu);
+#endif
+                       flags = IPV6_MINMTU;
+                       break;
+               }
+       } else {



Home | Main Index | Thread Index | Old Index