Hi,

In revision 1.87 of ip_icmp.c claudio@ added ignoring reject routes
to icmp_mtudisc_clone().  Otherwise TCP would clone these routes
for PMTU discovery.  They will not work, even after dynamic routing
has found a better route than the reject route.

With IPsec the use case is different.  First you need a route, but
then the flow handles the packet without routing.  Usually this
route should be a reject route to avoid sending unencrypted traffic
if the flow is missing.  But IPsec needs this route for PMTU
discovery, which currently does not work.

So accept reject and blackhole routes for IPsec PMTU discovery.

ok?

bluhm

Index: netinet/ip_icmp.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_icmp.c,v
retrieving revision 1.183
diff -u -p -r1.183 ip_icmp.c
--- netinet/ip_icmp.c   22 Aug 2020 17:55:54 -0000      1.183
+++ netinet/ip_icmp.c   18 Dec 2020 16:59:25 -0000
@@ -928,7 +928,7 @@ icmp_sysctl_icmpstat(void *oldp, size_t 
 }
 
 struct rtentry *
-icmp_mtudisc_clone(struct in_addr dst, u_int rtableid)
+icmp_mtudisc_clone(struct in_addr dst, u_int rtableid, int ipsec)
 {
        struct sockaddr_in sin;
        struct rtentry *rt;
@@ -942,7 +942,10 @@ icmp_mtudisc_clone(struct in_addr dst, u
        rt = rtalloc(sintosa(&sin), RT_RESOLVE, rtableid);
 
        /* Check if the route is actually usable */
-       if (!rtisvalid(rt) || (rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)))
+       if (!rtisvalid(rt))
+               goto bad;
+       /* IPsec needs the route only for PMTU, it can use reject for that */
+       if (!ipsec && (rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)))
                goto bad;
 
        /*
@@ -1000,7 +1003,7 @@ icmp_mtudisc(struct icmp *icp, u_int rta
        struct ifnet *ifp;
        u_long mtu = ntohs(icp->icmp_nextmtu);  /* Why a long?  IPv6 */
 
-       rt = icmp_mtudisc_clone(icp->icmp_ip.ip_dst, rtableid);
+       rt = icmp_mtudisc_clone(icp->icmp_ip.ip_dst, rtableid, 0);
        if (rt == NULL)
                return;
 
Index: netinet/ip_icmp.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_icmp.h,v
retrieving revision 1.31
diff -u -p -r1.31 ip_icmp.h
--- netinet/ip_icmp.h   5 Nov 2018 21:50:39 -0000       1.31
+++ netinet/ip_icmp.h   18 Dec 2020 16:59:25 -0000
@@ -239,7 +239,7 @@ int icmp_reflect(struct mbuf *, struct m
 void   icmp_send(struct mbuf *, struct mbuf *);
 int    icmp_sysctl(int *, u_int, void *, size_t *, void *, size_t);
 struct rtentry *
-       icmp_mtudisc_clone(struct in_addr, u_int);
+       icmp_mtudisc_clone(struct in_addr, u_int, int);
 void   icmp_mtudisc(struct icmp *, u_int);
 int    icmp_do_exthdr(struct mbuf *, u_int16_t, u_int8_t, void *, size_t);
 #endif /* _KERNEL */
Index: netinet/ip_output.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.357
diff -u -p -r1.357 ip_output.c
--- netinet/ip_output.c 24 Jun 2020 22:03:43 -0000      1.357
+++ netinet/ip_output.c 18 Dec 2020 16:59:25 -0000
@@ -605,7 +605,7 @@ ip_output_ipsec_send(struct tdb *tdb, st
                        rt = NULL;
                else if (rt == NULL || (rt->rt_flags & RTF_HOST) == 0) {
                        rt = icmp_mtudisc_clone(ip->ip_dst,
-                           m->m_pkthdr.ph_rtableid);
+                           m->m_pkthdr.ph_rtableid, 1);
                        rt_mtucloned = 1;
                }
                DPRINTF(("%s: spi %08x mtu %d rt %p cloned %d\n", __func__,
Index: netinet/tcp_timer.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/tcp_timer.c,v
retrieving revision 1.67
diff -u -p -r1.67 tcp_timer.c
--- netinet/tcp_timer.c 11 Jun 2018 07:40:26 -0000      1.67
+++ netinet/tcp_timer.c 18 Dec 2020 16:59:25 -0000
@@ -292,7 +292,7 @@ tcp_timer_rexmt(void *arg)
 #endif
                case PF_INET:
                        rt = icmp_mtudisc_clone(inp->inp_faddr,
-                           inp->inp_rtableid);
+                           inp->inp_rtableid, 0);
                        break;
                }
                if (rt != NULL) {

Reply via email to