diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-09-11 16:58:01 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-09-11 16:58:01 +0000 |
commit | de0ae0e115858684c278009a66d3b8469c885c62 (patch) | |
tree | 2c31e905bfaf6b013822305de6f03c838b9c0c6d | |
parent | 0b5a4152d931d130356f85d2682762c2ccba1b1f (diff) |
Introduce rtref(9) use it in rtable_lookup() before returning a route
entry.
ok bluhm@, claudio@
-rw-r--r-- | sys/net/if.c | 16 | ||||
-rw-r--r-- | sys/net/route.c | 26 | ||||
-rw-r--r-- | sys/net/route.h | 3 | ||||
-rw-r--r-- | sys/net/rtable.c | 33 | ||||
-rw-r--r-- | sys/net/rtsock.c | 4 |
5 files changed, 55 insertions, 27 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index 1ff5b2b5203..0b13189a026 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if.c,v 1.372 2015/09/11 09:15:56 dlg Exp $ */ +/* $OpenBSD: if.c,v 1.373 2015/09/11 16:58:00 mpi Exp $ */ /* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */ /* @@ -2256,7 +2256,7 @@ if_group_egress_build(void) #ifdef INET6 struct sockaddr_in6 sa_in6; #endif - struct rtentry *rt; + struct rtentry *rt0, *rt; TAILQ_FOREACH(ifg, &ifg_head, ifg_next) if (!strcmp(ifg->ifg_group, IFG_EGRESS)) @@ -2269,8 +2269,9 @@ if_group_egress_build(void) bzero(&sa_in, sizeof(sa_in)); sa_in.sin_len = sizeof(sa_in); sa_in.sin_family = AF_INET; - rt = rtable_lookup(0, sintosa(&sa_in), sintosa(&sa_in)); - if (rt != NULL) { + rt0 = rtable_lookup(0, sintosa(&sa_in), sintosa(&sa_in)); + if (rt0 != NULL) { + rt = rt0; do { if (rt->rt_ifp) if_addgroup(rt->rt_ifp, IFG_EGRESS); @@ -2281,11 +2282,13 @@ if_group_egress_build(void) #endif } while (rt != NULL); } + rtfree(rt0); #ifdef INET6 bcopy(&sa6_any, &sa_in6, sizeof(sa_in6)); - rt = rtable_lookup(0, sin6tosa(&sa_in6), sin6tosa(&sa_in6)); - if (rt != NULL) { + rt0 = rtable_lookup(0, sin6tosa(&sa_in6), sin6tosa(&sa_in6)); + if (rt0 != NULL) { + rt = rt0; do { if (rt->rt_ifp) if_addgroup(rt->rt_ifp, IFG_EGRESS); @@ -2297,6 +2300,7 @@ if_group_egress_build(void) } while (rt != NULL); } #endif + rtfree(rt0); return (0); } diff --git a/sys/net/route.c b/sys/net/route.c index 9d680d0d62e..70bb8c17540 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -1,4 +1,4 @@ -/* $OpenBSD: route.c,v 1.235 2015/09/11 15:38:13 mpi Exp $ */ +/* $OpenBSD: route.c,v 1.236 2015/09/11 16:58:00 mpi Exp $ */ /* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */ /* @@ -408,6 +408,12 @@ rtalloc_mpath(struct sockaddr *dst, uint32_t *src, unsigned int rtableid) #endif /* SMALL_KERNEL */ void +rtref(struct rtentry *rt) +{ + rt->rt_refcnt++; +} + +void rtfree(struct rtentry *rt) { struct ifaddr *ifa; @@ -807,8 +813,10 @@ rtrequest1(int req, struct rt_addrinfo *info, u_int8_t prio, * a matching gateway. */ if ((rt->rt_flags & RTF_MPATH) && - info->rti_info[RTAX_GATEWAY] == NULL) + info->rti_info[RTAX_GATEWAY] == NULL) { + rtfree(rt); return (ESRCH); + } #endif /* @@ -817,19 +825,17 @@ rtrequest1(int req, struct rt_addrinfo *info, u_int8_t prio, * kernel. */ if ((rt->rt_flags & (RTF_LOCAL|RTF_BROADCAST)) && - prio != RTP_LOCAL) + prio != RTP_LOCAL) { + rtfree(rt); return (EINVAL); + } error = rtable_delete(tableid, info->rti_info[RTAX_DST], info->rti_info[RTAX_NETMASK], prio, rt); - if (error != 0) + if (error != 0) { + rtfree(rt); return (ESRCH); - - /* - * We need to hold a reference to ensure rtflushclone() - * wont free us through rt->rt_parent. - */ - rt->rt_refcnt++; + } /* clean up any cloned children */ if ((rt->rt_flags & RTF_CLONING) != 0) diff --git a/sys/net/route.h b/sys/net/route.h index 26d58590cc4..bc80c49887e 100644 --- a/sys/net/route.h +++ b/sys/net/route.h @@ -1,4 +1,4 @@ -/* $OpenBSD: route.h,v 1.111 2015/09/01 12:50:03 mpi Exp $ */ +/* $OpenBSD: route.h,v 1.112 2015/09/11 16:58:00 mpi Exp $ */ /* $NetBSD: route.h,v 1.9 1996/02/13 22:00:49 christos Exp $ */ /* @@ -384,6 +384,7 @@ int rtisvalid(struct rtentry *); struct rtentry *rtalloc_mpath(struct sockaddr *, uint32_t *, u_int); #endif struct rtentry *rtalloc(struct sockaddr *, int, unsigned int); +void rtref(struct rtentry *); void rtfree(struct rtentry *); int rt_getifa(struct rt_addrinfo *, u_int); diff --git a/sys/net/rtable.c b/sys/net/rtable.c index 3a4ff39cd47..11cefbb7c27 100644 --- a/sys/net/rtable.c +++ b/sys/net/rtable.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtable.c,v 1.4 2015/09/04 08:43:39 mpi Exp $ */ +/* $OpenBSD: rtable.c,v 1.5 2015/09/11 16:58:00 mpi Exp $ */ /* * Copyright (c) 2014-2015 Martin Pieuchot @@ -54,6 +54,7 @@ rtable_lookup(unsigned int rtableid, struct sockaddr *dst, { struct radix_node_head *rnh; struct radix_node *rn; + struct rtentry *rt; rnh = rtable_get(rtableid, dst->sa_family); if (rnh == NULL) @@ -63,7 +64,10 @@ rtable_lookup(unsigned int rtableid, struct sockaddr *dst, if (rn == NULL || (rn->rn_flags & RNF_ROOT) != 0) return (NULL); - return ((struct rtentry *)rn); + rt = ((struct rtentry *)rn); + rtref(rt); + + return (rt); } struct rtentry * @@ -163,16 +167,21 @@ rtable_mpath_capable(unsigned int rtableid, sa_family_t af) } struct rtentry * -rtable_mpath_match(unsigned int rtableid, struct rtentry *rt, +rtable_mpath_match(unsigned int rtableid, struct rtentry *rt0, struct sockaddr *gateway, uint8_t prio) { struct radix_node_head *rnh; + struct rtentry *rt; - rnh = rtable_get(rtableid, rt_key(rt)->sa_family); + rnh = rtable_get(rtableid, rt_key(rt0)->sa_family); if (rnh == NULL || rnh->rnh_multipath == 0) - return (rt); + return (rt0); + + rt = rt_mpath_matchgate(rt0, gateway, prio); - rt = rt_mpath_matchgate(rt, gateway, prio); + if (rt != NULL) + rtref(rt); + rtfree(rt0); return (rt); } @@ -233,6 +242,7 @@ rtable_lookup(unsigned int rtableid, struct sockaddr *dst, { struct art_root *ar; struct art_node *an; + struct rtentry *rt; uint8_t *addr; int plen; @@ -260,7 +270,10 @@ rtable_lookup(unsigned int rtableid, struct sockaddr *dst, if (an == NULL) return (NULL); - return (LIST_FIRST(&an->an_rtlist)); + rt = LIST_FIRST(&an->an_rtlist); + rtref(rt); + + return (rt); } struct rtentry * @@ -525,13 +538,17 @@ rtable_mpath_match(unsigned int rtableid, struct rtentry *rt0, continue; if (gateway == NULL) - return (rt); + break; if (rt->rt_gateway->sa_len == gateway->sa_len && memcmp(rt->rt_gateway, gateway, gateway->sa_len) == 0) break; } + if (rt != NULL) + rtref(rt); + rtfree(rt0); + return (rt); } diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 291bc3e2be1..77adb3f9b0c 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtsock.c,v 1.169 2015/08/24 22:11:33 mpi Exp $ */ +/* $OpenBSD: rtsock.c,v 1.170 2015/09/11 16:58:00 mpi Exp $ */ /* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */ /* @@ -654,13 +654,13 @@ route_output(struct mbuf *m, ...) */ if (info.rti_info[RTAX_GATEWAY] == NULL && rtm->rtm_type != RTM_GET) { + rtfree(rt); rt = NULL; error = ESRCH; goto flush; } } #endif - rt->rt_refcnt++; /* * RTM_CHANGE/LOCK need a perfect match, rn_lookup() |