Module Name: src
Committed By: knakahara
Date: Fri Nov 1 04:28:14 UTC 2019
Modified Files:
src/sys/net: if_ipsec.c if_ipsec.h
src/sys/netinet6: in6.h
src/sys/netipsec: ipsecif.c ipsecif.h
Log Message:
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
To generate a diff of this commit:
cvs rdiff -u -r1.24 -r1.25 src/sys/net/if_ipsec.c
cvs rdiff -u -r1.5 -r1.6 src/sys/net/if_ipsec.h
cvs rdiff -u -r1.97 -r1.98 src/sys/netinet6/in6.h
cvs rdiff -u -r1.17 -r1.18 src/sys/netipsec/ipsecif.c
cvs rdiff -u -r1.2 -r1.3 src/sys/netipsec/ipsecif.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/net/if_ipsec.c
diff -u src/sys/net/if_ipsec.c:1.24 src/sys/net/if_ipsec.c:1.25
--- src/sys/net/if_ipsec.c:1.24 Thu Sep 19 06:07:24 2019
+++ src/sys/net/if_ipsec.c Fri Nov 1 04:28:14 2019
@@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: if_ipsec.c,v
#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 @@ struct if_clone ipsec_cloner =
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 @@ ipsecifattach(int count)
iv_psref_class = psref_class_create("ipsecvar", IPL_SOFTNET);
+ if_ipsec_sysctl_setup();
+
if_clone_attach(&ipsec_cloner);
}
@@ -165,6 +300,7 @@ if_ipsec_clone_create(struct if_clone *i
{
struct ipsec_softc *sc;
struct ipsec_variant *var;
+ struct ifnet *ifp;
sc = kmem_zalloc(sizeof(*sc), KM_SLEEP);
@@ -172,6 +308,9 @@ if_ipsec_clone_create(struct if_clone *i
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);
Index: src/sys/net/if_ipsec.h
diff -u src/sys/net/if_ipsec.h:1.5 src/sys/net/if_ipsec.h:1.6
--- src/sys/net/if_ipsec.h:1.5 Thu Sep 19 06:07:24 2019
+++ src/sys/net/if_ipsec.h Fri Nov 1 04:28:14 2019
@@ -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 @@ struct ipsec_softc {
*/
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 */
};
Index: src/sys/netinet6/in6.h
diff -u src/sys/netinet6/in6.h:1.97 src/sys/netinet6/in6.h:1.98
--- src/sys/netinet6/in6.h:1.97 Wed Oct 30 03:45:59 2019
+++ src/sys/netinet6/in6.h Fri Nov 1 04:28:14 2019
@@ -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 @@ struct ip6_mtuinfo {
#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
Index: src/sys/netipsec/ipsecif.c
diff -u src/sys/netipsec/ipsecif.c:1.17 src/sys/netipsec/ipsecif.c:1.18
--- src/sys/netipsec/ipsecif.c:1.17 Thu Sep 19 06:07:25 2019
+++ src/sys/netipsec/ipsecif.c Fri Nov 1 04:28:14 2019
@@ -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 ipsecif6_filter6(const struct
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 @@ ipsecif6_output(struct ipsec_variant *va
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 @@ ipsecif6_output(struct ipsec_variant *va
}
/*
- * 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 {
+ switch (sc->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 ipsec_pmtu of %s %d\n",
+ __func__, ifp->if_xname, sc->ipsec_pmtu);
+#endif
+ flags = IPV6_MINMTU;
+ break;
+ }
+ }
+ error = ip6_output(m, 0, ro_pc, flags, 0, NULL, NULL);
out:
if (error)
Index: src/sys/netipsec/ipsecif.h
diff -u src/sys/netipsec/ipsecif.h:1.2 src/sys/netipsec/ipsecif.h:1.3
--- src/sys/netipsec/ipsecif.h:1.2 Fri Apr 6 10:38:53 2018
+++ src/sys/netipsec/ipsecif.h Fri Nov 1 04:28:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: ipsecif.h,v 1.2 2018/04/06 10:38:53 knakahara Exp $ */
+/* $NetBSD: ipsecif.h,v 1.3 2019/11/01 04:28:14 knakahara Exp $ */
/*
* Copyright (c) 2017 Internet Initiative Japan Inc.
@@ -35,6 +35,15 @@
#define IPSEC_HLIM 64
#ifdef _KERNEL
+#ifdef INET6
+extern int ip6_ipsec_hlim;
+extern int ip6_ipsec_pmtu;
+
+#define IPSEC_PMTU_SYSDEFAULT -1 /* Use system default value (ip6_gif_pmtu) */
+#define IPSEC_PMTU_MINMTU 0 /* Fragmented by IPV6_MINMTU */
+#define IPSEC_PMTU_OUTERMTU 1 /* Fragmented by Path MTU of outer path */
+#endif
+
int ipsecif4_encap_func(struct mbuf *, struct ip *, struct ipsec_variant *);
int ipsecif4_attach(struct ipsec_variant *);
int ipsecif4_detach(struct ipsec_variant *);