diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-02-06 01:21:18 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-02-06 01:21:18 +0000 |
commit | b31ace77dd671ace8447db36f28b11a23a81a57d (patch) | |
tree | 0f6f53904c3902354c0370e95c252543fff8f867 /sys | |
parent | 47286185e96e409fa7f62bd27b0bab8ba972806f (diff) |
Change rt_mpath_conflict() to not rely on an initialized rtentry when
checking for actual conflict.
ok claudio@, henning@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/radix_mpath.c | 19 | ||||
-rw-r--r-- | sys/net/radix_mpath.h | 6 | ||||
-rw-r--r-- | sys/net/route.c | 28 |
3 files changed, 26 insertions, 27 deletions
diff --git a/sys/net/radix_mpath.c b/sys/net/radix_mpath.c index b5f14ba3b32..9622b8ac68a 100644 --- a/sys/net/radix_mpath.c +++ b/sys/net/radix_mpath.c @@ -1,4 +1,4 @@ -/* $OpenBSD: radix_mpath.c,v 1.27 2014/12/19 17:14:40 tedu Exp $ */ +/* $OpenBSD: radix_mpath.c,v 1.28 2015/02/06 01:21:17 mpi Exp $ */ /* $KAME: radix_mpath.c,v 1.13 2002/10/28 21:05:59 itojun Exp $ */ /* @@ -204,16 +204,15 @@ rt_mpath_matchgate(struct rtentry *rt, struct sockaddr *gate, u_int8_t prio) * check if we have the same key/mask/gateway on the table already. */ int -rt_mpath_conflict(struct radix_node_head *rnh, struct rtentry *rt, - struct sockaddr *netmask, int mpathok) +rt_mpath_conflict(struct radix_node_head *rnh, struct sockaddr *dst, + struct sockaddr *netmask, struct sockaddr *gate, u_int8_t prio, int mpathok) { - struct radix_node *rn, *rn1; + struct radix_node *rn1; struct rtentry *rt1; char *p, *q, *eq; int same, l, skip; - rn = (struct radix_node *)rt; - rn1 = rnh->rnh_lookup(rt_key(rt), netmask, rnh); + rn1 = rnh->rnh_lookup(dst, netmask, rnh); if (!rn1 || rn1->rn_flags & RNF_ROOT) return 0; @@ -224,8 +223,8 @@ rt_mpath_conflict(struct radix_node_head *rnh, struct rtentry *rt, rt1 = (struct rtentry *)rn1; /* compare key. */ - if (rt_key(rt1)->sa_len != rt_key(rt)->sa_len || - bcmp(rt_key(rt1), rt_key(rt), rt_key(rt1)->sa_len)) + if (rt_key(rt1)->sa_len != dst->sa_len || + bcmp(rt_key(rt1), dst, rt_key(rt1)->sa_len)) goto different; /* key was the same. compare netmask. hairy... */ @@ -277,11 +276,11 @@ rt_mpath_conflict(struct radix_node_head *rnh, struct rtentry *rt, } maskmatched: - if (!mpathok && rt1->rt_priority == rt->rt_priority) + if (!mpathok && rt1->rt_priority == prio) return EEXIST; /* key/mask were the same. compare gateway for all multipaths */ - if (rt_mpath_matchgate(rt1, rt->rt_gateway, rt->rt_priority)) + if (rt_mpath_matchgate(rt1, gate, prio)) /* all key/mask/gateway are the same. conflicting entry. */ return EEXIST; diff --git a/sys/net/radix_mpath.h b/sys/net/radix_mpath.h index afe86c9f0b8..5b3fe710973 100644 --- a/sys/net/radix_mpath.h +++ b/sys/net/radix_mpath.h @@ -1,4 +1,4 @@ -/* $OpenBSD: radix_mpath.h,v 1.14 2014/11/25 14:50:46 mpi Exp $ */ +/* $OpenBSD: radix_mpath.h,v 1.15 2015/02/06 01:21:17 mpi Exp $ */ /* $KAME: radix_mpath.h,v 1.9 2004/03/30 11:21:49 keiichi Exp $ */ /* @@ -54,8 +54,8 @@ void rn_mpath_adj_mpflag(struct radix_node *, u_int8_t); int rn_mpath_active_count(struct radix_node *); struct rtentry *rt_mpath_matchgate(struct rtentry *, struct sockaddr *, u_int8_t); -int rt_mpath_conflict(struct radix_node_head *, struct rtentry *, - struct sockaddr *, int); +int rt_mpath_conflict(struct radix_node_head *, struct sockaddr *, + struct sockaddr *, struct sockaddr *, u_int8_t, int); struct rtentry *rtalloc_mpath(struct sockaddr *, u_int32_t *, u_int); int rn_mpath_inithead(void **, int); #endif /* _KERNEL */ diff --git a/sys/net/route.c b/sys/net/route.c index af0255f61a2..97b3957ac45 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -1,4 +1,4 @@ -/* $OpenBSD: route.c,v 1.203 2015/01/28 22:10:13 mpi Exp $ */ +/* $OpenBSD: route.c,v 1.204 2015/02/06 01:21:17 mpi Exp $ */ /* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */ /* @@ -826,15 +826,25 @@ rtrequest1(int req, struct rt_addrinfo *info, u_int8_t prio, if (info->rti_ifa == NULL && (error = rt_getifa(info, tableid))) return (error); ifa = info->rti_ifa; + if (prio == 0) + prio = ifa->ifa_ifp->if_priority + RTP_STATIC; +#ifndef SMALL_KERNEL + if (rn_mpath_capable(rnh)) { + /* do not permit exactly the same dst/mask/gw pair */ + if (rt_mpath_conflict(rnh, info->rti_info[RTAX_DST], + info->rti_info[RTAX_NETMASK], + info->rti_info[RTAX_GATEWAY], prio, + info->rti_flags & RTF_MPATH)) { + return (EEXIST); + } + } +#endif rt = pool_get(&rtentry_pool, PR_NOWAIT | PR_ZERO); if (rt == NULL) return (ENOBUFS); rt->rt_flags = info->rti_flags; rt->rt_tableid = tableid; - - if (prio == 0) - prio = ifa->ifa_ifp->if_priority + RTP_STATIC; rt->rt_priority = prio; /* init routing priority */ LIST_INIT(&rt->rt_timer); if ((error = rt_setgate(rt, info->rti_info[RTAX_DST], @@ -851,16 +861,6 @@ rtrequest1(int req, struct rt_addrinfo *info, u_int8_t prio, info->rti_info[RTAX_DST]->sa_len); #ifndef SMALL_KERNEL if (rn_mpath_capable(rnh)) { - /* do not permit exactly the same dst/mask/gw pair */ - if (rt_mpath_conflict(rnh, rt, - info->rti_info[RTAX_NETMASK], - info->rti_flags & RTF_MPATH)) { - if (rt->rt_gwroute) - rtfree(rt->rt_gwroute); - free(rt_key(rt), M_RTABLE, 0); - pool_put(&rtentry_pool, rt); - return (EEXIST); - } /* check the link state since the table supports it */ if (LINK_STATE_IS_UP(ifa->ifa_ifp->if_link_state) && ifa->ifa_ifp->if_flags & IFF_UP) |