Path MTU discovery was slightly broken. I took two ICMP packets
authorbluhm <bluhm@openbsd.org>
Mon, 11 Jul 2016 13:06:31 +0000 (13:06 +0000)
committerbluhm <bluhm@openbsd.org>
Mon, 11 Jul 2016 13:06:31 +0000 (13:06 +0000)
to create and change the dynamic route.  This behavior was introduced
in net/route.c rev 1.269 when the gateway route allocation was moved
from rt_setgateway() to _rtalloc().  So rtrequest(RTM_ADD) could
return a route without a valid gateway route.  To fix this, call
rt_setgwroute() from _rtalloc() and rt_setgateway().
OK mpi@

sys/net/if_spppsubr.c
sys/net/route.c
sys/net/route.h
sys/net/rtsock.c

index b4ea8f6..4a480b2 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_spppsubr.c,v 1.154 2016/06/14 20:44:43 sthen Exp $ */
+/*     $OpenBSD: if_spppsubr.c,v 1.155 2016/07/11 13:06:31 bluhm Exp $ */
 /*
  * Synchronous PPP link level subroutines.
  *
@@ -4161,7 +4161,7 @@ sppp_update_gw_walker(struct rtentry *rt, void *arg, unsigned int id)
                    rt->rt_gateway->sa_family ||
                    !ISSET(rt->rt_flags, RTF_GATEWAY))
                        return (0);     /* do not modify non-gateway routes */
-               rt_setgate(rt, rt->rt_ifa->ifa_dstaddr);
+               rt_setgate(rt, rt->rt_ifa->ifa_dstaddr, ifp->if_rdomain);
        }
        return (0);
 }
index c5f2847..80cbd3a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: route.c,v 1.310 2016/07/11 09:23:06 mpi Exp $ */
+/*     $OpenBSD: route.c,v 1.311 2016/07/11 13:06:31 bluhm Exp $       */
 /*     $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $      */
 
 /*
@@ -153,6 +153,7 @@ struct pool         rtentry_pool;   /* pool for rtentry structures */
 struct pool            rttimer_pool;   /* pool for rttimer structures */
 
 void   rt_timer_init(void);
+void   rt_setgwroute(struct rtentry *, u_int);
 int    rtflushclone1(struct rtentry *, void *, u_int);
 void   rtflushclone(unsigned int, struct rtentry *);
 int    rt_if_remove_rtdelete(struct rtentry *, void *, u_int);
@@ -368,7 +369,7 @@ rtalloc(struct sockaddr *dst, int flags, unsigned int rtableid)
 struct rtentry *
 _rtalloc(struct sockaddr *dst, uint32_t *src, int flags, unsigned int rtableid)
 {
-       struct rtentry *rt, *nhrt;
+       struct rtentry *rt;
 
        rt = rt_match(dst, src, flags, rtableid);
 
@@ -380,6 +381,16 @@ _rtalloc(struct sockaddr *dst, uint32_t *src, int flags, unsigned int rtableid)
        if (rtisvalid(rt->rt_gwroute))
                return (rt);
 
+       rt_setgwroute(rt, rtableid);
+
+       return (rt);
+}
+
+void
+rt_setgwroute(struct rtentry *rt, u_int rtableid)
+{
+       struct rtentry *nhrt;
+
        rtfree(rt->rt_gwroute);
        rt->rt_gwroute = NULL;
 
@@ -391,10 +402,9 @@ _rtalloc(struct sockaddr *dst, uint32_t *src, int flags, unsigned int rtableid)
         * this behavior.  But it is safe since rt_checkgate() wont
         * allow us to us this route later on.
         */
-       nhrt = rt_match(rt->rt_gateway, NULL, flags | RT_RESOLVE,
-           rtable_l2(rtableid));
+       nhrt = rt_match(rt->rt_gateway, NULL, RT_RESOLVE, rtable_l2(rtableid));
        if (nhrt == NULL)
-               return (rt);
+               return;
 
        /*
         * Next hop must be reachable, this also prevents rtentry
@@ -402,13 +412,13 @@ _rtalloc(struct sockaddr *dst, uint32_t *src, int flags, unsigned int rtableid)
         */
        if (ISSET(nhrt->rt_flags, RTF_CLONING|RTF_GATEWAY)) {
                rtfree(nhrt);
-               return (rt);
+               return;
        }
 
        /* Next hop entry must be UP and on the same interface. */
        if (!ISSET(nhrt->rt_flags, RTF_UP) || nhrt->rt_ifidx != rt->rt_ifidx) {
                rtfree(nhrt);
-               return (rt);
+               return;
        }
 
        /*
@@ -423,8 +433,6 @@ _rtalloc(struct sockaddr *dst, uint32_t *src, int flags, unsigned int rtableid)
         * do the magic for us.
         */
        rt->rt_gwroute = nhrt;
-
-       return (rt);
 }
 
 void
@@ -593,7 +601,7 @@ create:
                        flags |= RTF_MODIFIED;
                        prio = rt->rt_priority;
                        stat = &rtstat.rts_newgateway;
-                       rt_setgate(rt, gateway);
+                       rt_setgate(rt, gateway, rdomain);
                }
        } else
                error = EHOSTUNREACH;
@@ -1086,7 +1094,8 @@ rtrequest(int req, struct rt_addrinfo *info, u_int8_t prio,
                 * the routing table because the radix MPATH code use
                 * it to (re)order routes.
                 */
-               if ((error = rt_setgate(rt, info->rti_info[RTAX_GATEWAY]))) {
+               if ((error = rt_setgate(rt, info->rti_info[RTAX_GATEWAY],
+                   tableid))) {
                        ifafree(ifa);
                        rtfree(rt->rt_parent);
                        rtfree(rt->rt_gwroute);
@@ -1146,7 +1155,7 @@ rtrequest(int req, struct rt_addrinfo *info, u_int8_t prio,
 }
 
 int
-rt_setgate(struct rtentry *rt, struct sockaddr *gate)
+rt_setgate(struct rtentry *rt, struct sockaddr *gate, u_int rtableid)
 {
        int glen = ROUNDUP(gate->sa_len);
        struct sockaddr *sa;
@@ -1160,8 +1169,8 @@ rt_setgate(struct rtentry *rt, struct sockaddr *gate)
        }
        memmove(rt->rt_gateway, gate, glen);
 
-       rtfree(rt->rt_gwroute);
-       rt->rt_gwroute = NULL;
+       if (ISSET(rt->rt_flags, RTF_GATEWAY))
+               rt_setgwroute(rt, rtableid);
 
        return (0);
 }
index 7652ea2..7e567cd 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: route.h,v 1.139 2016/07/11 09:23:06 mpi Exp $ */
+/*     $OpenBSD: route.h,v 1.140 2016/07/11 13:06:31 bluhm Exp $       */
 /*     $NetBSD: route.h,v 1.9 1996/02/13 22:00:49 christos Exp $       */
 
 /*
@@ -362,7 +362,7 @@ struct sockaddr *rt_plen2mask(struct rtentry *, struct sockaddr_in6 *);
 void    rt_sendmsg(struct rtentry *, int, u_int);
 void    rt_sendaddrmsg(struct rtentry *, int, struct ifaddr *);
 void    rt_missmsg(int, struct rt_addrinfo *, int, uint8_t, u_int, int, u_int);
-int     rt_setgate(struct rtentry *, struct sockaddr *);
+int     rt_setgate(struct rtentry *, struct sockaddr *, u_int);
 int     rt_checkgate(struct rtentry *, struct rtentry **);
 void    rt_setmetrics(u_long, const struct rt_metrics *, struct rt_kmetrics *);
 void    rt_getmetrics(const struct rt_kmetrics *, struct rt_metrics *);
index 6ab9ef9..af1147f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: rtsock.c,v 1.193 2016/07/11 09:23:06 mpi Exp $        */
+/*     $OpenBSD: rtsock.c,v 1.194 2016/07/11 13:06:31 bluhm Exp $      */
 /*     $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $  */
 
 /*
@@ -748,7 +748,8 @@ report:
                                ifa = info.rti_ifa;
                        }
                        if (info.rti_info[RTAX_GATEWAY] != NULL && (error =
-                           rt_setgate(rt, info.rti_info[RTAX_GATEWAY])))
+                           rt_setgate(rt, info.rti_info[RTAX_GATEWAY],
+                           tableid)))
                                goto flush;
                        if (ifa) {
                                if (rt->rt_ifa != ifa) {