Re: IPsec IPv6 PMTU

2020-12-27 Thread Alexander Bluhm
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

2020-12-24 Thread Alexander Bluhm
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-