Routing sockets do not really need the NET_LOCK(), only route_output()
needs it.
This diff change the socket layer to treat PF_ROUTE sockets just like
PF_LOCAL ones.
While here fix a rtentry leak in the error path of route_output().
Comments, oks?
Index: net/raw_usrreq.c
===================================================================
RCS file: /cvs/src/sys/net/raw_usrreq.c,v
retrieving revision 1.28
diff -u -p -r1.28 raw_usrreq.c
--- net/raw_usrreq.c 23 Jan 2017 16:31:24 -0000 1.28
+++ net/raw_usrreq.c 28 Feb 2017 11:40:18 -0000
@@ -63,7 +63,7 @@ raw_usrreq(struct socket *so, int req, s
int error = 0;
int len;
- NET_ASSERT_LOCKED();
+ soassertlocked(so);
if (req == PRU_CONTROL)
return (EOPNOTSUPP);
Index: net/route.h
===================================================================
RCS file: /cvs/src/sys/net/route.h,v
retrieving revision 1.156
diff -u -p -r1.156 route.h
--- net/route.h 23 Jan 2017 00:59:22 -0000 1.156
+++ net/route.h 28 Feb 2017 12:09:27 -0000
@@ -383,9 +383,6 @@ struct sockaddr_in6;
struct bfd_config;
void route_init(void);
-int route_output(struct mbuf *, ...);
-int route_usrreq(struct socket *, int, struct mbuf *,
- struct mbuf *, struct mbuf *, struct proc *);
void rt_ifmsg(struct ifnet *);
void rt_ifannouncemsg(struct ifnet *, int);
void rt_bfdmsg(struct bfd_config *);
Index: net/rtsock.c
===================================================================
RCS file: /cvs/src/sys/net/rtsock.c,v
retrieving revision 1.223
diff -u -p -r1.223 rtsock.c
--- net/rtsock.c 22 Feb 2017 19:34:42 -0000 1.223
+++ net/rtsock.c 28 Feb 2017 12:21:07 -0000
@@ -98,7 +98,10 @@ struct walkarg {
caddr_t w_where, w_tmem;
};
+int route_output(struct mbuf *, ...);
int route_ctloutput(int, struct socket *, int, int, struct mbuf *);
+int route_usrreq(struct socket *, int, struct mbuf *, struct mbuf *,
+ struct mbuf *, struct proc *);
void route_input(struct mbuf *m0, sa_family_t);
int route_arp_conflict(struct rtentry *, struct rt_addrinfo *);
int route_cleargateway(struct rtentry *, void *, unsigned int);
@@ -152,8 +155,6 @@ route_usrreq(struct socket *so, int req,
int af;
int error = 0;
- NET_ASSERT_LOCKED();
-
rp = sotorawcb(so);
switch (req) {
@@ -338,6 +339,8 @@ route_input(struct mbuf *m0, sa_family_t
struct socket *last = NULL;
struct sockaddr *sosrc, *sodst;
+ KERNEL_ASSERT_LOCKED();
+
sosrc = &route_src;
sodst = &route_dst;
@@ -532,7 +535,7 @@ route_output(struct mbuf *m, ...)
struct rt_msghdr *rtm = NULL;
struct rtentry *rt = NULL;
struct rt_addrinfo info;
- int plen, len, seq, newgate = 0, error = 0;
+ int s, plen, len, seq, newgate = 0, error = 0;
struct ifnet *ifp = NULL;
struct ifaddr *ifa = NULL;
struct socket *so;
@@ -675,6 +678,7 @@ route_output(struct mbuf *m, ...)
* may be not consistent and could cause unexpected behaviour in other
* userland clients. Use goto fail instead.
*/
+ NET_LOCK(s);
switch (rtm->rtm_type) {
case RTM_ADD:
if (info.rti_info[RTAX_GATEWAY] == NULL) {
@@ -943,20 +947,16 @@ change:
seq = rtm->rtm_seq;
free(rtm, M_RTABLE, 0);
rtm = rt_report(rt, type, seq, tableid);
+flush:
+ NET_UNLOCK(s);
+ rtfree(rt);
if (rtm == NULL) {
error = ENOBUFS;
goto fail;
- }
-
-flush:
- if (rt)
- rtfree(rt);
- if (rtm) {
- if (error)
- rtm->rtm_errno = error;
- else {
- rtm->rtm_flags |= RTF_DONE;
- }
+ } else if (error) {
+ rtm->rtm_errno = error;
+ } else {
+ rtm->rtm_flags |= RTF_DONE;
}
/*
Index: kern/uipc_socket.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.177
diff -u -p -r1.177 uipc_socket.c
--- kern/uipc_socket.c 14 Feb 2017 09:46:21 -0000 1.177
+++ kern/uipc_socket.c 28 Feb 2017 10:47:11 -0000
@@ -1038,11 +1038,12 @@ sorflush(struct socket *so)
{
struct sockbuf *sb = &so->so_rcv;
struct protosw *pr = so->so_proto;
+ sa_family_t af = pr->pr_domain->dom_family;
struct sockbuf asb;
sb->sb_flags |= SB_NOINTR;
sblock(sb, M_WAITOK,
- (pr->pr_domain->dom_family != PF_LOCAL) ? &netlock : NULL);
+ (af != PF_LOCAL && af != PF_ROUTE) ? &netlock : NULL);
socantrcvmore(so);
sbunlock(sb);
asb = *sb;
Index: kern/uipc_socket2.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_socket2.c,v
retrieving revision 1.72
diff -u -p -r1.72 uipc_socket2.c
--- kern/uipc_socket2.c 14 Feb 2017 09:46:21 -0000 1.72
+++ kern/uipc_socket2.c 28 Feb 2017 10:46:29 -0000
@@ -273,7 +273,8 @@ solock(struct socket *so)
{
int s;
- if (so->so_proto->pr_domain->dom_family != PF_LOCAL)
+ if ((so->so_proto->pr_domain->dom_family != PF_LOCAL) &&
+ (so->so_proto->pr_domain->dom_family != PF_ROUTE))
NET_LOCK(s);
else
s = -42;
@@ -291,16 +292,18 @@ sounlock(int s)
void
soassertlocked(struct socket *so)
{
- if (so->so_proto->pr_domain->dom_family != PF_LOCAL)
+ if ((so->so_proto->pr_domain->dom_family != PF_LOCAL) &&
+ (so->so_proto->pr_domain->dom_family != PF_ROUTE))
NET_ASSERT_LOCKED();
}
int
sosleep(struct socket *so, void *ident, int prio, const char *wmesg, int timo)
{
- if (so->so_proto->pr_domain->dom_family != PF_LOCAL)
+ if ((so->so_proto->pr_domain->dom_family != PF_LOCAL) &&
+ (so->so_proto->pr_domain->dom_family != PF_ROUTE)) {
return rwsleep(ident, &netlock, prio, wmesg, timo);
- else
+ } else
return tsleep(ident, prio, wmesg, timo);
}