diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2018-06-11 08:48:55 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2018-06-11 08:48:55 +0000 |
commit | 7559e7eb03267b3e8ce6a3940100d5db4fb01c62 (patch) | |
tree | 6a241bb74363018073fd13f21bce11cc4e52b8fa | |
parent | 6fa871355586760f3c952e5e1839b3bae1135c9e (diff) |
Push the KERNEL_LOCK() inside route_input().
ok visa@, tb@
-rw-r--r-- | sys/net/route.c | 10 | ||||
-rw-r--r-- | sys/net/rtsock.c | 74 | ||||
-rw-r--r-- | sys/netinet/if_ether.c | 4 | ||||
-rw-r--r-- | sys/netinet/in_pcb.c | 4 | ||||
-rw-r--r-- | sys/netinet6/nd6_nbr.c | 4 |
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); |