summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/net/route.c15
-rw-r--r--sys/net/rtable.c98
-rw-r--r--sys/net/rtable.h7
3 files changed, 44 insertions, 76 deletions
diff --git a/sys/net/route.c b/sys/net/route.c
index 740cf242852..5d0d707913a 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: route.c,v 1.262 2015/10/25 11:58:11 mpi Exp $ */
+/* $OpenBSD: route.c,v 1.263 2015/10/25 14:48:51 mpi Exp $ */
/* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */
/*
@@ -837,15 +837,6 @@ rtrequest1(int req, struct rt_addrinfo *info, u_int8_t prio,
else
memcpy(ndst, info->rti_info[RTAX_DST], dlen);
-#ifndef SMALL_KERNEL
- /* Do not permit exactly the same dst/mask/gw pair. */
- if (rtable_mpath_conflict(tableid, ndst,
- info->rti_info[RTAX_NETMASK], info->rti_info[RTAX_GATEWAY],
- prio, info->rti_flags & RTF_MPATH)) {
- free(ndst, M_RTABLE, dlen);
- return (EEXIST);
- }
-#endif
rt = pool_get(&rtentry_pool, PR_NOWAIT | PR_ZERO);
if (rt == NULL) {
free(ndst, M_RTABLE, dlen);
@@ -953,13 +944,15 @@ rtrequest1(int req, struct rt_addrinfo *info, u_int8_t prio,
}
error = rtable_insert(tableid, ndst,
- info->rti_info[RTAX_NETMASK], rt->rt_priority, rt);
+ info->rti_info[RTAX_NETMASK], info->rti_info[RTAX_GATEWAY],
+ rt->rt_priority, rt);
if (error != 0 && (crt = rtalloc(ndst, 0, tableid)) != NULL) {
/* overwrite cloned route */
if ((crt->rt_flags & RTF_CLONED) != 0) {
rtdeletemsg(crt, tableid);
error = rtable_insert(tableid, ndst,
info->rti_info[RTAX_NETMASK],
+ info->rti_info[RTAX_GATEWAY],
rt->rt_priority, rt);
}
rtfree(crt);
diff --git a/sys/net/rtable.c b/sys/net/rtable.c
index dfbdc6975bb..5bc6eb9b6d3 100644
--- a/sys/net/rtable.c
+++ b/sys/net/rtable.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtable.c,v 1.14 2015/10/22 17:19:38 mpi Exp $ */
+/* $OpenBSD: rtable.c,v 1.15 2015/10/25 14:48:51 mpi Exp $ */
/*
* Copyright (c) 2014-2015 Martin Pieuchot
@@ -292,7 +292,8 @@ rtable_match(unsigned int rtableid, struct sockaddr *dst)
int
rtable_insert(unsigned int rtableid, struct sockaddr *dst,
- struct sockaddr *mask, uint8_t prio, struct rtentry *rt)
+ struct sockaddr *mask, struct sockaddr *gateway, uint8_t prio,
+ struct rtentry *rt)
{
struct radix_node_head *rnh;
struct radix_node *rn = (struct radix_node *)rt;
@@ -301,6 +302,15 @@ rtable_insert(unsigned int rtableid, struct sockaddr *dst,
if (rnh == NULL)
return (EAFNOSUPPORT);
+#ifndef SMALL_KERNEL
+ if (rnh->rnh_multipath) {
+ /* Do not permit exactly the same dst/mask/gw pair. */
+ if (rt_mpath_conflict(rnh, dst, mask, gateway, prio,
+ ISSET(rt->rt_flags, RTF_MPATH)))
+ return (EEXIST);
+ }
+#endif
+
rn = rn_addroute(dst, mask, rnh, rn, prio);
if (rn == NULL)
return (ESRCH);
@@ -382,22 +392,6 @@ rtable_mpath_match(unsigned int rtableid, struct rtentry *rt0,
return (rt);
}
-int
-rtable_mpath_conflict(unsigned int rtableid, struct sockaddr *dst,
- struct sockaddr *mask, struct sockaddr *gateway, uint8_t prio, int mpathok)
-{
- struct radix_node_head *rnh;
-
- rnh = rtable_get(rtableid, dst->sa_family);
- if (rnh == NULL)
- return (EAFNOSUPPORT);
-
- if (rnh->rnh_multipath == 0)
- return (0);
-
- return (rt_mpath_conflict(rnh, dst, mask, gateway, prio, mpathok));
-}
-
/* Gateway selection by Hash-Threshold (RFC 2992) */
struct rtentry *
rtable_mpath_select(struct rtentry *rt, uint32_t hash)
@@ -526,7 +520,8 @@ rtable_match(unsigned int rtableid, struct sockaddr *dst)
int
rtable_insert(unsigned int rtableid, struct sockaddr *dst,
- struct sockaddr *mask, uint8_t prio, struct rtentry *rt)
+ struct sockaddr *mask, struct sockaddr *gateway, uint8_t prio,
+ struct rtentry *rt)
{
#ifndef SMALL_KERNEL
struct rtentry *mrt;
@@ -545,6 +540,29 @@ rtable_insert(unsigned int rtableid, struct sockaddr *dst,
if (plen == -1)
return (EINVAL);
+#ifndef SMALL_KERNEL
+ /* Do not permit exactly the same dst/mask/gw pair. */
+ an = art_lookup(ar, addr, plen);
+ if (an != NULL && an->an_plen == plen &&
+ !memcmp(an->an_dst, dst, dst->sa_len)) {
+ struct rtentry *mrt;
+ int mpathok = ISSET(rt->rt_flags, RTF_MPATH);
+
+ LIST_FOREACH(mrt, &an->an_rtlist, rt_next) {
+ if (prio != RTP_ANY &&
+ (mrt->rt_priority & RTP_MASK) != (prio & RTP_MASK))
+ continue;
+
+ if (!mpathok)
+ return (EEXIST);
+
+ if (mrt->rt_gateway->sa_len == gateway->sa_len &&
+ !memcmp(mrt->rt_gateway, gateway, gateway->sa_len))
+ return (EEXIST);
+ }
+ }
+#endif
+
an = pool_get(&an_pool, PR_NOWAIT | PR_ZERO);
if (an == NULL)
return (ENOBUFS);
@@ -756,48 +774,6 @@ rtable_mpath_match(unsigned int rtableid, struct rtentry *rt0,
return (rt);
}
-int
-rtable_mpath_conflict(unsigned int rtableid, struct sockaddr *dst,
- struct sockaddr *mask, struct sockaddr *gateway, uint8_t prio, int mpathok)
-{
- struct art_root *ar;
- struct art_node *an;
- struct rtentry *rt;
- uint8_t *addr;
- int plen;
-
- ar = rtable_get(rtableid, dst->sa_family);
- if (ar == NULL)
- return (EAFNOSUPPORT);
-
- addr = satoaddr(ar, dst);
- plen = satoplen(ar, mask);
- if (plen == -1)
- return (EINVAL);
-
- an = art_lookup(ar, addr, plen);
- /* Make sure we've got a perfect match. */
- if (an == NULL || an->an_plen != plen ||
- memcmp(an->an_dst, dst, dst->sa_len))
- return (0);
-
- LIST_FOREACH(rt, &an->an_rtlist, rt_next) {
- if (prio != RTP_ANY &&
- (rt->rt_priority & RTP_MASK) != (prio & RTP_MASK))
- continue;
-
- if (!mpathok)
- return (EEXIST);
-
- if (rt->rt_gateway->sa_len == gateway->sa_len &&
- memcmp(rt->rt_gateway, gateway, gateway->sa_len) == 0)
- return (EEXIST);
- }
-
-
- return (0);
-}
-
/* Gateway selection by Hash-Threshold (RFC 2992) */
struct rtentry *
rtable_mpath_select(struct rtentry *rt, uint32_t hash)
diff --git a/sys/net/rtable.h b/sys/net/rtable.h
index 678d0e7940f..ce4c93146bd 100644
--- a/sys/net/rtable.h
+++ b/sys/net/rtable.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtable.h,v 1.7 2015/10/22 17:19:38 mpi Exp $ */
+/* $OpenBSD: rtable.h,v 1.8 2015/10/25 14:48:51 mpi Exp $ */
/*
* Copyright (c) 2014-2015 Martin Pieuchot
@@ -57,7 +57,8 @@ struct rtentry *rtable_lookup(unsigned int, struct sockaddr *,
struct sockaddr *);
struct rtentry *rtable_match(unsigned int, struct sockaddr *);
int rtable_insert(unsigned int, struct sockaddr *,
- struct sockaddr *, uint8_t, struct rtentry *);
+ struct sockaddr *, struct sockaddr *, uint8_t,
+ struct rtentry *);
int rtable_delete(unsigned int, struct sockaddr *,
struct sockaddr *, uint8_t, struct rtentry *);
int rtable_walk(unsigned int, sa_family_t,
@@ -66,8 +67,6 @@ int rtable_walk(unsigned int, sa_family_t,
int rtable_mpath_capable(unsigned int, sa_family_t);
struct rtentry *rtable_mpath_match(unsigned int, struct rtentry *,
struct sockaddr *, uint8_t);
-int rtable_mpath_conflict(unsigned int, struct sockaddr *,
- struct sockaddr *, struct sockaddr *, uint8_t, int);
struct rtentry *rtable_mpath_select(struct rtentry *, uint32_t);
void rtable_mpath_reprio(struct rtentry *, uint8_t);
#endif /* _NET_RTABLE_H_ */