summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2015-09-11 16:58:01 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2015-09-11 16:58:01 +0000
commitde0ae0e115858684c278009a66d3b8469c885c62 (patch)
tree2c31e905bfaf6b013822305de6f03c838b9c0c6d
parent0b5a4152d931d130356f85d2682762c2ccba1b1f (diff)
Introduce rtref(9) use it in rtable_lookup() before returning a route
entry. ok bluhm@, claudio@
-rw-r--r--sys/net/if.c16
-rw-r--r--sys/net/route.c26
-rw-r--r--sys/net/route.h3
-rw-r--r--sys/net/rtable.c33
-rw-r--r--sys/net/rtsock.c4
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()