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);
 }
 

Reply via email to