summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2018-06-11 08:48:55 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2018-06-11 08:48:55 +0000
commit7559e7eb03267b3e8ce6a3940100d5db4fb01c62 (patch)
tree6a241bb74363018073fd13f21bce11cc4e52b8fa
parent6fa871355586760f3c952e5e1839b3bae1135c9e (diff)
Push the KERNEL_LOCK() inside route_input().
ok visa@, tb@
-rw-r--r--sys/net/route.c10
-rw-r--r--sys/net/rtsock.c74
-rw-r--r--sys/netinet/if_ether.c4
-rw-r--r--sys/netinet/in_pcb.c4
-rw-r--r--sys/netinet6/nd6_nbr.c4
5 files changed, 56 insertions, 40 deletions
diff --git a/sys/net/route.c b/sys/net/route.c
index f80a5ecd237..d80368a41ce 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: route.c,v 1.374 2018/04/24 06:19:47 florian Exp $ */
+/* $OpenBSD: route.c,v 1.375 2018/06/11 08:48:54 mpi Exp $ */
/* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */
/*
@@ -254,7 +254,6 @@ rt_clone(struct rtentry **rtp, struct sockaddr *dst, unsigned int rtableid)
memset(&info, 0, sizeof(info));
info.rti_info[RTAX_DST] = dst;
- KERNEL_LOCK();
/*
* The priority of cloned route should be different
* to avoid conflict with /32 cloning routes.
@@ -262,8 +261,10 @@ rt_clone(struct rtentry **rtp, struct sockaddr *dst, unsigned int rtableid)
* It should also be higher to let the ARP layer find
* cloned routes instead of the cloning one.
*/
+ KERNEL_LOCK();
error = rtrequest(RTM_RESOLVE, &info, rt->rt_priority - 1, &rt,
rtableid);
+ KERNEL_UNLOCK();
if (error) {
rtm_miss(RTM_MISS, &info, 0, RTP_NONE, 0, error, rtableid);
} else {
@@ -272,7 +273,6 @@ rt_clone(struct rtentry **rtp, struct sockaddr *dst, unsigned int rtableid)
rtfree(*rtp);
*rtp = rt;
}
- KERNEL_UNLOCK();
return (error);
}
@@ -655,9 +655,7 @@ out:
info.rti_info[RTAX_DST] = dst;
info.rti_info[RTAX_GATEWAY] = gateway;
info.rti_info[RTAX_AUTHOR] = src;
- KERNEL_LOCK();
rtm_miss(RTM_REDIRECT, &info, flags, prio, ifidx, error, rdomain);
- KERNEL_UNLOCK();
}
/*
@@ -683,9 +681,7 @@ rtdeletemsg(struct rtentry *rt, struct ifnet *ifp, u_int tableid)
if (!ISSET(rt->rt_flags, RTF_HOST))
info.rti_info[RTAX_NETMASK] = rt_plen2mask(rt, &sa_mask);
error = rtrequest_delete(&info, rt->rt_priority, ifp, &rt, tableid);
- KERNEL_LOCK();
rtm_send(rt, RTM_DELETE, error, tableid);
- KERNEL_UNLOCK();
if (error == 0)
rtfree(rt);
return (error);
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index e701b12fdf7..98f49e6f1c2 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtsock.c,v 1.268 2018/06/06 07:12:52 mpi Exp $ */
+/* $OpenBSD: rtsock.c,v 1.269 2018/06/11 08:48:54 mpi Exp $ */
/* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */
/*
@@ -113,7 +113,8 @@ int route_usrreq(struct socket *, int, struct mbuf *, struct mbuf *,
void route_input(struct mbuf *m0, struct socket *, sa_family_t);
int route_arp_conflict(struct rtentry *, struct rt_addrinfo *);
int route_cleargateway(struct rtentry *, void *, unsigned int);
-void rtm_senddesync(void *);
+void rtm_senddesync_timer(void *);
+void rtm_senddesync(struct socket *);
int rtm_sendup(struct socket *, struct mbuf *, int);
int rtm_getifa(struct rt_addrinfo *, unsigned int);
@@ -243,7 +244,7 @@ route_attach(struct socket *so, int proto)
rop = malloc(sizeof(struct routecb), M_PCB, M_WAITOK|M_ZERO);
so->so_pcb = rop;
/* Init the timeout structure */
- timeout_set(&rop->rop_timeout, rtm_senddesync, rop);
+ timeout_set(&rop->rop_timeout, rtm_senddesync_timer, so);
refcnt_init(&rop->rop_refcnt);
if (curproc == NULL)
@@ -374,12 +375,23 @@ route_ctloutput(int op, struct socket *so, int level, int optname,
}
void
-rtm_senddesync(void *data)
+rtm_senddesync_timer(void *xso)
{
- struct routecb *rop;
+ struct socket *so = xso;
+ int s;
+
+ s = solock(so);
+ rtm_senddesync(so);
+ sounlock(so, s);
+}
+
+void
+rtm_senddesync(struct socket *so)
+{
+ struct routecb *rop = sotoroutecb(so);
struct mbuf *desync_mbuf;
- rop = (struct routecb *)data;
+ soassertlocked(so);
/* If we are in a DESYNC state, try to send a RTM_DESYNC packet */
if ((rop->rop_flags & ROUTECB_FLAG_DESYNC) == 0)
@@ -391,7 +403,6 @@ rtm_senddesync(void *data)
*/
desync_mbuf = rtm_msg1(RTM_DESYNC, NULL);
if (desync_mbuf != NULL) {
- struct socket *so = rop->rop_socket;
if (sbappendaddr(so, &so->so_rcv, &route_src,
desync_mbuf, NULL) != 0) {
rop->rop_flags &= ~ROUTECB_FLAG_DESYNC;
@@ -405,15 +416,15 @@ rtm_senddesync(void *data)
}
void
-route_input(struct mbuf *m0, struct socket *so, sa_family_t sa_family)
+route_input(struct mbuf *m0, struct socket *so0, sa_family_t sa_family)
{
+ struct socket *so;
struct routecb *rop;
struct rt_msghdr *rtm;
struct mbuf *m = m0;
struct socket *last = NULL;
struct srp_ref sr;
-
- KERNEL_ASSERT_LOCKED();
+ int s;
/* ensure that we can access the rtm_type via mtod() */
if (m->m_len < offsetof(struct rt_msghdr, rtm_type) + 1) {
@@ -422,14 +433,6 @@ route_input(struct mbuf *m0, struct socket *so, sa_family_t sa_family)
}
SRPL_FOREACH(rop, &sr, &route_cb.rcb, rop_list) {
- if (!(rop->rop_socket->so_state & SS_ISCONNECTED))
- continue;
- if (rop->rop_socket->so_state & SS_CANTRCVMORE)
- continue;
- /* Check to see if we don't want our own messages. */
- if (so == rop->rop_socket && !(so->so_options & SO_USELOOPBACK))
- continue;
-
/*
* If route socket is bound to an address family only send
* messages that match the address family. Address family
@@ -440,15 +443,31 @@ route_input(struct mbuf *m0, struct socket *so, sa_family_t sa_family)
rop->rop_proto.sp_protocol != sa_family)
continue;
+
+ so = rop->rop_socket;
+ s = solock(so);
+
+ /*
+ * Check to see if we don't want our own messages and
+ * if we can receive anything.
+ */
+ if ((so0 == so && !(so0->so_options & SO_USELOOPBACK)) ||
+ !(so->so_state & SS_ISCONNECTED) ||
+ (so->so_state & SS_CANTRCVMORE)) {
+next:
+ sounlock(so, s);
+ continue;
+ }
+
/* filter messages that the process does not want */
rtm = mtod(m, struct rt_msghdr *);
/* but RTM_DESYNC can't be filtered */
if (rtm->rtm_type != RTM_DESYNC && rop->rop_msgfilter != 0 &&
!(rop->rop_msgfilter & (1 << rtm->rtm_type)))
- continue;
+ goto next;
if (rop->rop_priority != 0 &&
rop->rop_priority < rtm->rtm_priority)
- continue;
+ goto next;
switch (rtm->rtm_type) {
case RTM_IFANNOUNCE:
case RTM_DESYNC:
@@ -461,13 +480,13 @@ route_input(struct mbuf *m0, struct socket *so, sa_family_t sa_family)
/* check against rdomain id */
if (rop->rop_rtableid != RTABLE_ANY &&
rtable_l2(rop->rop_rtableid) != rtm->rtm_tableid)
- continue;
+ goto next;
break;
default:
/* check against rtable id */
if (rop->rop_rtableid != RTABLE_ANY &&
rop->rop_rtableid != rtm->rtm_tableid)
- continue;
+ goto next;
break;
}
@@ -476,10 +495,13 @@ route_input(struct mbuf *m0, struct socket *so, sa_family_t sa_family)
* any more messages until the flag is cleared.
*/
if ((rop->rop_flags & ROUTECB_FLAG_FLUSH) != 0)
- continue;
+ goto next;
+ sounlock(so, s);
if (last) {
+ s = solock(last);
rtm_sendup(last, m, 1);
+ sounlock(last, s);
refcnt_rele_wake(&sotoroutecb(last)->rop_refcnt);
}
/* keep a reference for last */
@@ -489,7 +511,9 @@ route_input(struct mbuf *m0, struct socket *so, sa_family_t sa_family)
SRPL_LEAVE(&sr);
if (last) {
+ s = solock(last);
rtm_sendup(last, m, 0);
+ sounlock(last, s);
refcnt_rele_wake(&sotoroutecb(last)->rop_refcnt);
} else
m_freem(m);
@@ -501,6 +525,8 @@ rtm_sendup(struct socket *so, struct mbuf *m0, int more)
struct routecb *rop = sotoroutecb(so);
struct mbuf *m;
+ soassertlocked(so);
+
if (more) {
m = m_copym(m0, 0, M_COPYALL, M_NOWAIT);
if (m == NULL)
@@ -512,7 +538,7 @@ rtm_sendup(struct socket *so, struct mbuf *m0, int more)
sbappendaddr(so, &so->so_rcv, &route_src, m, NULL) == 0) {
/* Flag socket as desync'ed and flush required */
rop->rop_flags |= ROUTECB_FLAG_DESYNC | ROUTECB_FLAG_FLUSH;
- rtm_senddesync(rop);
+ rtm_senddesync(so);
m_freem(m);
return (ENOBUFS);
}
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index 1ceeaaae82a..2965ec08c5d 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ether.c,v 1.235 2018/03/31 15:07:09 stsp Exp $ */
+/* $OpenBSD: if_ether.c,v 1.236 2018/06/11 08:48:54 mpi Exp $ */
/* $NetBSD: if_ether.c,v 1.31 1996/05/11 12:59:58 mycroft Exp $ */
/*
@@ -664,9 +664,7 @@ arpcache(struct ifnet *ifp, struct ether_arp *ea, struct rtentry *rt)
/* Notify userland that an ARP resolution has been done. */
if (la->la_asked || changed) {
- KERNEL_LOCK();
rtm_send(rt, RTM_RESOLVE, 0, ifp->if_rdomain);
- KERNEL_UNLOCK();
}
la->la_asked = 0;
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 4c4ca0c8b10..690263a4130 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_pcb.c,v 1.235 2018/06/07 08:46:24 bluhm Exp $ */
+/* $OpenBSD: in_pcb.c,v 1.236 2018/06/11 08:48:54 mpi Exp $ */
/* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */
/*
@@ -722,10 +722,8 @@ in_losing(struct inpcb *inp)
info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
info.rti_info[RTAX_NETMASK] = rt_plen2mask(rt, &sa_mask);
- KERNEL_LOCK();
rtm_miss(RTM_LOSING, &info, rt->rt_flags, rt->rt_priority,
rt->rt_ifidx, 0, inp->inp_rtableid);
- KERNEL_UNLOCK();
if (rt->rt_flags & RTF_DYNAMIC) {
struct ifnet *ifp;
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
index cb5c04c24ed..d63279a0b8b 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nd6_nbr.c,v 1.122 2017/11/23 13:32:25 mpi Exp $ */
+/* $OpenBSD: nd6_nbr.c,v 1.123 2018/06/11 08:48:54 mpi Exp $ */
/* $KAME: nd6_nbr.c,v 1.61 2001/02/10 16:06:14 jinmei Exp $ */
/*
@@ -720,9 +720,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
ln->ln_state = ND6_LLINFO_REACHABLE;
ln->ln_byhint = 0;
/* Notify userland that a new ND entry is reachable. */
- KERNEL_LOCK();
rtm_send(rt, RTM_RESOLVE, 0, ifp->if_rdomain);
- KERNEL_UNLOCK();
if (!ND6_LLINFO_PERMANENT(ln)) {
nd6_llinfo_settimer(ln,
ND_IFINFO(ifp)->reachable);