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 *);