Re: IPsec IPv6 PMTU
On Thu, Dec 24, 2020 at 10:54:59PM +0100, Alexander Bluhm wrote: > It also makes v4 and v6 code look simmilar. If you want, I can > split this for easier review. This is the part of the diff that creates a path MTU host route for IPv6. Basically the code is copied from IPv4 and adapted. Some things are changed in v4 to make it look similar. - ip6_forward increases the noroute error counter, I think that should be done in ip_forward, too. - Pass more specific sockaddr_in6 to icmp6_mtudisc_clone(). Or should we use a sockaddr for both v4 and v6? - IPv6 may also use reject routes for PMTU clones. - To pass a route_in6 to ip6_output_ipsec_send() introduce one in ip6_forward(). That is the same what IPv4 does. Note that dst and sin6 switch roles. - Copy comments from ip_output_ipsec_send() to ip6_output_ipsec_send() to make code similar. - Implement dynamic IPv6 IPsec PMTU routes. ok? bluhm Index: netinet/icmp6.h === RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/icmp6.h,v retrieving revision 1.50 diff -u -p -r1.50 icmp6.h --- netinet/icmp6.h 28 Oct 2020 17:27:35 - 1.50 +++ netinet/icmp6.h 27 Dec 2020 15:16:56 - @@ -599,6 +599,7 @@ void icmp6_prepare(struct mbuf *); voidicmp6_redirect_input(struct mbuf *, int); voidicmp6_redirect_output(struct mbuf *, struct rtentry *); int icmp6_sysctl(int *, u_int, void *, size_t *, void *, size_t); +struct rtentry *icmp6_mtudisc_clone(struct sockaddr_in6 *, u_int, int); struct ip6ctlparam; void icmp6_mtudisc_update(struct ip6ctlparam *, int); Index: netinet/ip_input.c === RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_input.c,v retrieving revision 1.352 diff -u -p -r1.352 ip_input.c --- netinet/ip_input.c 16 Nov 2020 06:44:38 - 1.352 +++ netinet/ip_input.c 27 Dec 2020 15:16:56 - @@ -1418,8 +1418,8 @@ ip_forward(struct mbuf *m, struct ifnet goto freecopy; } + memset(&ro, 0, sizeof(ro)); sin = satosin(&ro.ro_dst); - memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_addr = ip->ip_dst; @@ -1429,6 +1429,7 @@ ip_forward(struct mbuf *m, struct ifnet rt = rtalloc_mpath(sintosa(sin), &ip->ip_src.s_addr, m->m_pkthdr.ph_rtableid); if (rt == NULL) { + ipstat_inc(ips_noroute); icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0); return; } Index: netinet/ip_output.c === RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_output.c,v retrieving revision 1.358 diff -u -p -r1.358 ip_output.c --- netinet/ip_output.c 20 Dec 2020 21:15:47 - 1.358 +++ netinet/ip_output.c 27 Dec 2020 15:16:56 - @@ -612,7 +612,7 @@ ip_output_ipsec_send(struct tdb *tdb, st ntohl(tdb->tdb_spi), tdb->tdb_mtu, rt, rt_mtucloned)); if (rt != NULL) { rt->rt_mtu = tdb->tdb_mtu; - if (ro && ro->ro_rt != NULL) { + if (ro != NULL && ro->ro_rt != NULL) { rtfree(ro->ro_rt); ro->ro_rt = rtalloc(&ro->ro_dst, RT_RESOLVE, m->m_pkthdr.ph_rtableid); Index: netinet6/icmp6.c === RCS file: /data/mirror/openbsd/cvs/src/sys/netinet6/icmp6.c,v retrieving revision 1.233 diff -u -p -r1.233 icmp6.c --- netinet6/icmp6.c28 Oct 2020 17:27:35 - 1.233 +++ netinet6/icmp6.c27 Dec 2020 15:16:56 - @@ -138,7 +138,6 @@ int icmp6_ratelimit(const struct in6_add const char *icmp6_redirect_diag(struct in6_addr *, struct in6_addr *, struct in6_addr *); inticmp6_notify_error(struct mbuf *, int, int, int); -struct rtentry *icmp6_mtudisc_clone(struct sockaddr *, u_int); void icmp6_mtudisc_timeout(struct rtentry *, struct rttimer *); void icmp6_redirect_timeout(struct rtentry *, struct rttimer *); @@ -1015,7 +1014,7 @@ icmp6_mtudisc_update(struct ip6ctlparam sin6.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.ph_ifidx, &sin6.sin6_addr); - rt = icmp6_mtudisc_clone(sin6tosa(&sin6), m->m_pkthdr.ph_rtableid); + rt = icmp6_mtudisc_clone(&sin6, m->m_pkthdr.ph_rtableid, 0); if (rt != NULL && ISSET(rt->rt_flags, RTF_HOST) && !(rt->rt_locks & RTV_MTU) && @@ -1784,15 +1783,18 @@ icmp6_ratelimit(const struct in6_addr *d } struct rtentry * -icmp6_mtudisc_clone(struct sockaddr *dst, u_int rtableid) +icmp6_mtudisc_clone(struct sockaddr_in6 *dst, u_int rtableid, int ipsec) { struct rtentry *rt; interror;
IPsec IPv6 PMTU
Hi, This diff makes path MTU discovery work for IPv6 IPsec ESP over IPv4 tunnel. Basically it ports code from v4 to v6. It also makes v4 and v6 code look simmilar. If you want, I can split this for easier review. ok? bluhm Index: netinet/icmp6.h === RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/icmp6.h,v retrieving revision 1.50 diff -u -p -r1.50 icmp6.h --- netinet/icmp6.h 28 Oct 2020 17:27:35 - 1.50 +++ netinet/icmp6.h 22 Dec 2020 17:05:39 - @@ -599,6 +599,7 @@ void icmp6_prepare(struct mbuf *); voidicmp6_redirect_input(struct mbuf *, int); voidicmp6_redirect_output(struct mbuf *, struct rtentry *); int icmp6_sysctl(int *, u_int, void *, size_t *, void *, size_t); +struct rtentry *icmp6_mtudisc_clone(struct sockaddr_in6 *, u_int, int); struct ip6ctlparam; void icmp6_mtudisc_update(struct ip6ctlparam *, int); Index: netinet/ip_input.c === RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_input.c,v retrieving revision 1.352 diff -u -p -r1.352 ip_input.c --- netinet/ip_input.c 16 Nov 2020 06:44:38 - 1.352 +++ netinet/ip_input.c 22 Dec 2020 17:05:39 - @@ -1418,8 +1418,8 @@ ip_forward(struct mbuf *m, struct ifnet goto freecopy; } + memset(&ro, 0, sizeof(ro)); sin = satosin(&ro.ro_dst); - memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_addr = ip->ip_dst; @@ -1429,6 +1429,7 @@ ip_forward(struct mbuf *m, struct ifnet rt = rtalloc_mpath(sintosa(sin), &ip->ip_src.s_addr, m->m_pkthdr.ph_rtableid); if (rt == NULL) { + ipstat_inc(ips_noroute); icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0); return; } Index: netinet/ip_ipsp.h === RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_ipsp.h,v retrieving revision 1.196 diff -u -p -r1.196 ip_ipsp.h --- netinet/ip_ipsp.h 5 Nov 2020 19:28:28 - 1.196 +++ netinet/ip_ipsp.h 22 Dec 2020 17:05:39 - @@ -610,6 +610,7 @@ voidesp4_ctlinput(int, struct sockaddr #ifdef INET6 intesp6_input(struct mbuf **, int *, int, int); +void esp6_ctlinput(int, struct sockaddr *, u_int, void *); #endif /* INET6 */ /* XF_IPCOMP */ Index: netinet/ip_output.c === RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_output.c,v retrieving revision 1.358 diff -u -p -r1.358 ip_output.c --- netinet/ip_output.c 20 Dec 2020 21:15:47 - 1.358 +++ netinet/ip_output.c 22 Dec 2020 17:05:39 - @@ -612,7 +612,7 @@ ip_output_ipsec_send(struct tdb *tdb, st ntohl(tdb->tdb_spi), tdb->tdb_mtu, rt, rt_mtucloned)); if (rt != NULL) { rt->rt_mtu = tdb->tdb_mtu; - if (ro && ro->ro_rt != NULL) { + if (ro != NULL && ro->ro_rt != NULL) { rtfree(ro->ro_rt); ro->ro_rt = rtalloc(&ro->ro_dst, RT_RESOLVE, m->m_pkthdr.ph_rtableid); Index: netinet/ipsec_input.c === RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ipsec_input.c,v retrieving revision 1.173 diff -u -p -r1.173 ipsec_input.c --- netinet/ipsec_input.c 1 Sep 2020 01:53:34 - 1.173 +++ netinet/ipsec_input.c 24 Dec 2020 19:22:09 - @@ -66,6 +66,7 @@ #ifdef INET6 #include #include +#include #include #include #endif /* INET6 */ @@ -83,6 +84,7 @@ #include "bpfilter.h" void ipsec_common_ctlinput(u_int, int, struct sockaddr *, void *, int); +void ipsec6_common_ctlinput(u_int, int, struct sockaddr *, void *, int); #ifdef ENCDEBUG #define DPRINTF(x) if (encdebug) printf x @@ -946,18 +948,43 @@ ipcomp4_input(struct mbuf **mp, int *off } void +ipsec_set_mtu(struct tdb *tdbp, u_int32_t mtu, uint64_t timeout, +const char *msg) +{ + ssize_t adjust; + + if (timeout == 0) + timeout = ip_mtudisc_timeout; + /* Walk the chain backwards to the first tdb */ + NET_ASSERT_LOCKED(); + for (; tdbp; tdbp = tdbp->tdb_inext) { + if (tdbp->tdb_flags & TDBF_INVALID || + (adjust = ipsec_hdrsz(tdbp)) == -1) + return; + + mtu -= adjust; + + /* Store adjusted MTU in tdb */ + tdbp->tdb_mtu = mtu; + tdbp->tdb_mtutimeout = gettime() + timeout; + DPRINTF(("%s: %s: spi %08x mtu %d adjust %ld timeout %llu\n", + __func__, msg, ntohl(tdbp-