diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2016-12-17 14:26:54 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2016-12-17 14:26:54 +0000 |
commit | 4d9be3b091561fd8eaaab2169b453b4dfccc8ff4 (patch) | |
tree | 45e07204b25fc205130eaad94e6b87036533764f | |
parent | c039194158f1b24bb7f51e0d6278797088ccd0b7 (diff) |
Insert RTF_CLONED routes at a higher priority than their partent to
prevent a mpath conflict for /32 RTF_CLONING routes.
Found the hardway by jsing@ on Google Compute Engine.
ok bluhm@, jsing@
-rw-r--r-- | sys/net/route.c | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/sys/net/route.c b/sys/net/route.c index 9919b9e036a..fdbb8a1160b 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -1,4 +1,4 @@ -/* $OpenBSD: route.c,v 1.343 2016/12/14 20:35:20 stsp Exp $ */ +/* $OpenBSD: route.c,v 1.344 2016/12/17 14:26:53 mpi Exp $ */ /* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */ /* @@ -252,8 +252,15 @@ rt_match(struct sockaddr *dst, uint32_t *src, int flags, unsigned int tableid) info.rti_info[RTAX_DST] = dst; KERNEL_LOCK(); - error = rtrequest(RTM_RESOLVE, &info, RTP_DEFAULT, - &rt, tableid); + /* + * The priority of cloned route should be different + * to avoid conflict with /32 cloning routes. + * + * It should also be higher to let the ARP layer find + * cloned routes instead of the cloning one. + */ + error = rtrequest(RTM_RESOLVE, &info, + rt->rt_priority - 1, &rt, tableid); if (error) { rt_missmsg(RTM_MISS, &info, 0, RTP_NONE, 0, error, tableid); @@ -1046,15 +1053,14 @@ rtrequest(int req, struct rt_addrinfo *info, u_int8_t prio, ifa->ifa_refcnt++; rt->rt_ifa = ifa; rt->rt_ifidx = ifp->if_index; - if (rt->rt_flags & RTF_CLONED) { - /* - * Copy both metrics and a back pointer to the cloned - * route's parent. - */ - rt->rt_rmx = (*ret_nrt)->rt_rmx; /* copy metrics */ - rt->rt_priority = (*ret_nrt)->rt_priority; - rt->rt_parent = *ret_nrt; /* Back ptr. to parent. */ - rtref(rt->rt_parent); + /* + * Copy metrics and a back pointer from the cloned + * route's parent. + */ + if (ISSET(rt->rt_flags, RTF_CLONED)) { + rtref(*ret_nrt); + rt->rt_parent = *ret_nrt; + rt->rt_rmx = (*ret_nrt)->rt_rmx; } /* |