summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2015-02-06 01:21:18 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2015-02-06 01:21:18 +0000
commitb31ace77dd671ace8447db36f28b11a23a81a57d (patch)
tree0f6f53904c3902354c0370e95c252543fff8f867 /sys
parent47286185e96e409fa7f62bd27b0bab8ba972806f (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.c19
-rw-r--r--sys/net/radix_mpath.h6
-rw-r--r--sys/net/route.c28
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)