From b37b7e610fda77961640712a65526d948a00aa6e Mon Sep 17 00:00:00 2001 From: bluhm Date: Mon, 11 Jul 2016 13:06:31 +0000 Subject: [PATCH] Path MTU discovery was slightly broken. I took two ICMP packets 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 | 4 ++-- sys/net/route.c | 37 +++++++++++++++++++++++-------------- sys/net/route.h | 4 ++-- sys/net/rtsock.c | 5 +++-- 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c index b4ea8f6dec6..4a480b2b177 100644 --- a/sys/net/if_spppsubr.c +++ b/sys/net/if_spppsubr.c @@ -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); } diff --git a/sys/net/route.c b/sys/net/route.c index c5f2847fb7b..80cbd3aa34a 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -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); } diff --git a/sys/net/route.h b/sys/net/route.h index 7652ea27243..7e567cd918e 100644 --- a/sys/net/route.h +++ b/sys/net/route.h @@ -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 *); diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 6ab9ef937ac..af1147fde81 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -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) { -- 2.20.1