raw_usrreq() is just unneeded abstraction. It is easier to just handle
all the PRU cases in route_usrreq() instead. Simplifies a few things
and will hopefully make further MP work easier.
This is a mix of raw_usrreq() and uipc_usrreq() (I think that raw_usrreq
is leaking mbufs in some cases). route regress, bgpd and route(8) are
happy with this.
--
:wq Claudio
Index: net/rtsock.c
===================================================================
RCS file: /cvs/src/sys/net/rtsock.c,v
retrieving revision 1.276
diff -u -p -r1.276 rtsock.c
--- net/rtsock.c 5 Jul 2018 21:48:32 -0000 1.276
+++ net/rtsock.c 9 Jul 2018 10:52:18 -0000
@@ -136,11 +136,7 @@ int sysctl_ifnames(struct walkarg *);
int sysctl_rtable_rtstat(void *, size_t *, void *);
struct rtpcb {
- struct rawcb rop_rcb;
-#define rop_socket rop_rcb.rcb_socket
-#define rop_faddr rop_rcb.rcb_faddr
-#define rop_laddr rop_rcb.rcb_laddr
-#define rop_proto rop_rcb.rcb_proto
+ struct socket *rop_socket;
SRPL_ENTRY(rtpcb) rop_list;
struct refcnt rop_refcnt;
@@ -148,6 +144,7 @@ struct rtpcb {
unsigned int rop_msgfilter;
unsigned int rop_flags;
u_int rop_rtableid;
+ unsigned short rop_proto;
u_char rop_priority;
};
#define sotortpcb(so) ((struct rtpcb *)(so)->so_pcb)
@@ -203,15 +200,54 @@ route_usrreq(struct socket *so, int req,
struct rtpcb *rop;
int error = 0;
+ if (req == PRU_CONTROL)
+ return (EOPNOTSUPP);
+
soassertlocked(so);
+ if (control && control->m_len) {
+ error = EOPNOTSUPP;
+ goto release;
+ }
+
rop = sotortpcb(so);
if (rop == NULL) {
- m_freem(m);
- return (EINVAL);
+ error = EINVAL;
+ goto release;
}
switch (req) {
+ /* no connect, bind, accept. Socket is connected from the start */
+ case PRU_CONNECT:
+ case PRU_BIND:
+ case PRU_CONNECT2:
+ case PRU_LISTEN:
+ case PRU_ACCEPT:
+ error = EOPNOTSUPP;
+ break;
+
+ case PRU_DISCONNECT:
+ case PRU_ABORT:
+ soisdisconnected(so);
+ break;
+ case PRU_SHUTDOWN:
+ socantsendmore(so);
+ break;
+ case PRU_SENSE:
+ /* stat: don't bother with a blocksize. */
+ return (0);
+
+ /* minimal support, just implement a fake peer address */
+ case PRU_SOCKADDR:
+ error = EINVAL;
+ break;
+ case PRU_PEERADDR:
+ bcopy(&route_src, mtod(nam, caddr_t), route_src.sa_len);
+ nam->m_len = route_src.sa_len;
+ break;
+
+ case PRU_RCVOOB:
+ return (EOPNOTSUPP);
case PRU_RCVD:
/*
* If we are in a FLUSH state, check if the buffer is
@@ -221,12 +257,26 @@ route_usrreq(struct socket *so, int req,
((sbspace(rop->rop_socket, &rop->rop_socket->so_rcv) ==
rop->rop_socket->so_rcv.sb_hiwat)))
rop->rop_flags &= ~ROUTECB_FLAG_FLUSH;
- break;
+ return (0);
+ case PRU_SENDOOB:
+ error = EOPNOTSUPP;
+ break;
+ case PRU_SEND:
+ if (nam) {
+ error = EISCONN;
+ break;
+ }
+ error = (*so->so_proto->pr_output)(m, so, NULL, NULL);
+ m = NULL;
+ break;
default:
- error = raw_usrreq(so, req, m, nam, control, p);
+ panic("route_usrreq");
}
+ release:
+ m_freem(control);
+ m_freem(m);
return (error);
}
@@ -257,16 +307,13 @@ route_attach(struct socket *so, int prot
}
rop->rop_socket = so;
- rop->rop_proto.sp_family = so->so_proto->pr_domain->dom_family;
- rop->rop_proto.sp_protocol = proto;
+ rop->rop_proto = proto;
rop->rop_rtableid = curproc->p_p->ps_rtableid;
soisconnected(so);
so->so_options |= SO_USELOOPBACK;
- rop->rop_faddr = &route_src;
-
rw_enter(&rtptable.rtp_lk, RW_WRITE);
SRPL_INSERT_HEAD_LOCKED(&rtptable.rtp_rc, &rtptable.rtp_list, rop,
rop_list);
rtptable.rtp_count++;
@@ -438,9 +485,8 @@ route_input(struct mbuf *m0, struct sock
* messages that match the address family. Address family
* agnostic messages are always sent.
*/
- if (sa_family != AF_UNSPEC &&
- rop->rop_proto.sp_protocol != AF_UNSPEC &&
- rop->rop_proto.sp_protocol != sa_family)
+ if (sa_family != AF_UNSPEC && rop->rop_proto != AF_UNSPEC &&
+ rop->rop_proto != sa_family)
continue;