diff options
-rw-r--r-- | sys/net/route.c | 15 | ||||
-rw-r--r-- | sys/net/rtable.c | 98 | ||||
-rw-r--r-- | sys/net/rtable.h | 7 |
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_ */ |