From 90b3510cbffde6fd4ec4508c59aaf4e3ca3c0bdd Mon Sep 17 00:00:00 2001 From: mvs Date: Sat, 27 Aug 2022 20:28:01 +0000 Subject: [PATCH] Move PRU_SEND request to (*pru_send)(). The former PRU_SEND error path of gre_usrreq() had `control' mbuf(9) leak. It was fixed in new gre_send(). The former pfkeyv2_send() was renamed to pfkeyv2_dosend(). ok bluhm@ --- sys/kern/uipc_usrreq.c | 208 ++++++++++++++++++++------------------ sys/net/pfkeyv2.c | 45 +++++++-- sys/net/pfkeyv2.h | 4 +- sys/net/rtsock.c | 41 ++++++-- sys/netinet/ip_divert.c | 16 ++- sys/netinet/ip_divert.h | 4 +- sys/netinet/ip_gre.c | 19 +++- sys/netinet/ip_gre.h | 7 +- sys/netinet/ip_var.h | 4 +- sys/netinet/raw_ip.c | 87 +++++++++------- sys/netinet/tcp_usrreq.c | 48 +++++++-- sys/netinet/tcp_var.h | 4 +- sys/netinet/udp_usrreq.c | 93 +++++++++-------- sys/netinet/udp_var.h | 4 +- sys/netinet6/ip6_divert.c | 16 ++- sys/netinet6/ip6_divert.h | 4 +- sys/netinet6/ip6_var.h | 4 +- sys/netinet6/raw_ip6.c | 87 +++++++++------- sys/sys/protosw.h | 7 +- sys/sys/unpcb.h | 4 +- 20 files changed, 438 insertions(+), 268 deletions(-) diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index fcbb08be5dc..2dbbabf689f 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_usrreq.c,v 1.175 2022/08/26 16:17:39 mvs Exp $ */ +/* $OpenBSD: uipc_usrreq.c,v 1.176 2022/08/27 20:28:01 mvs Exp $ */ /* $NetBSD: uipc_usrreq.c,v 1.18 1996/02/09 19:00:50 christos Exp $ */ /* @@ -137,6 +137,7 @@ const struct pr_usrreqs uipc_usrreqs = { .pru_disconnect = uipc_disconnect, .pru_shutdown = uipc_shutdown, .pru_rcvd = uipc_rcvd, + .pru_send = uipc_send, }; void @@ -244,102 +245,6 @@ uipc_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, } break; - case PRU_SEND: - if (control) { - sounlock(so); - error = unp_internalize(control, p); - solock(so); - if (error) - break; - } - switch (so->so_type) { - - case SOCK_DGRAM: { - const struct sockaddr *from; - - if (nam) { - if (unp->unp_conn) { - error = EISCONN; - break; - } - error = unp_connect(so, nam, p); - if (error) - break; - } - - if ((so2 = unp_solock_peer(so)) == NULL) { - if (nam != NULL) - error = ECONNREFUSED; - else - error = ENOTCONN; - break; - } - - if (unp->unp_addr) - from = mtod(unp->unp_addr, struct sockaddr *); - else - from = &sun_noname; - if (sbappendaddr(so2, &so2->so_rcv, from, m, control)) { - sorwakeup(so2); - m = NULL; - control = NULL; - } else - error = ENOBUFS; - - if (so2 != so) - sounlock(so2); - - if (nam) - unp_disconnect(unp); - break; - } - - case SOCK_STREAM: - case SOCK_SEQPACKET: - if (so->so_state & SS_CANTSENDMORE) { - error = EPIPE; - break; - } - if ((so2 = unp_solock_peer(so)) == NULL) { - error = ENOTCONN; - break; - } - - /* - * Send to paired receive port, and then raise - * send buffer counts to maintain backpressure. - * Wake up readers. - */ - if (control) { - if (sbappendcontrol(so2, &so2->so_rcv, m, - control)) { - control = NULL; - } else { - sounlock(so2); - error = ENOBUFS; - break; - } - } else if (so->so_type == SOCK_SEQPACKET) - sbappendrecord(so2, &so2->so_rcv, m); - else - sbappend(so2, &so2->so_rcv, m); - so->so_snd.sb_mbcnt = so2->so_rcv.sb_mbcnt; - so->so_snd.sb_cc = so2->so_rcv.sb_cc; - if (so2->so_rcv.sb_cc > 0) - sorwakeup(so2); - - sounlock(so2); - m = NULL; - break; - - default: - panic("uipc 4"); - } - /* we need to undo unp_internalize in case of errors */ - if (control && error) - unp_dispose(control); - break; - case PRU_ABORT: unp_detach(unp); sofree(so, 0); @@ -576,6 +481,115 @@ uipc_rcvd(struct socket *so) return (0); } +int +uipc_send(struct socket *so, struct mbuf *m, struct mbuf *nam, + struct mbuf *control) +{ + struct unpcb *unp = sotounpcb(so); + struct socket *so2; + int error; + + if (control) { + sounlock(so); + error = unp_internalize(control, curproc); + solock(so); + if (error) + goto out; + } + + switch (so->so_type) { + case SOCK_DGRAM: { + const struct sockaddr *from; + + if (nam) { + if (unp->unp_conn) { + error = EISCONN; + break; + } + error = unp_connect(so, nam, curproc); + if (error) + break; + } + + if ((so2 = unp_solock_peer(so)) == NULL) { + if (nam != NULL) + error = ECONNREFUSED; + else + error = ENOTCONN; + break; + } + + if (unp->unp_addr) + from = mtod(unp->unp_addr, struct sockaddr *); + else + from = &sun_noname; + if (sbappendaddr(so2, &so2->so_rcv, from, m, control)) { + sorwakeup(so2); + m = NULL; + control = NULL; + } else + error = ENOBUFS; + + if (so2 != so) + sounlock(so2); + + if (nam) + unp_disconnect(unp); + break; + } + + case SOCK_STREAM: + case SOCK_SEQPACKET: + if (so->so_state & SS_CANTSENDMORE) { + error = EPIPE; + break; + } + if ((so2 = unp_solock_peer(so)) == NULL) { + error = ENOTCONN; + break; + } + + /* + * Send to paired receive port, and then raise + * send buffer counts to maintain backpressure. + * Wake up readers. + */ + if (control) { + if (sbappendcontrol(so2, &so2->so_rcv, m, control)) { + control = NULL; + } else { + sounlock(so2); + error = ENOBUFS; + break; + } + } else if (so->so_type == SOCK_SEQPACKET) + sbappendrecord(so2, &so2->so_rcv, m); + else + sbappend(so2, &so2->so_rcv, m); + so->so_snd.sb_mbcnt = so2->so_rcv.sb_mbcnt; + so->so_snd.sb_cc = so2->so_rcv.sb_cc; + if (so2->so_rcv.sb_cc > 0) + sorwakeup(so2); + + sounlock(so2); + m = NULL; + break; + + default: + panic("uipc 4"); + } + + /* we need to undo unp_internalize in case of errors */ + if (control && error) + unp_dispose(control); + +out: + m_freem(control); + m_freem(m); + + return (error); +} + int uipc_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) diff --git a/sys/net/pfkeyv2.c b/sys/net/pfkeyv2.c index 6347579f317..995fb51036f 100644 --- a/sys/net/pfkeyv2.c +++ b/sys/net/pfkeyv2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfkeyv2.c,v 1.242 2022/08/26 16:17:39 mvs Exp $ */ +/* $OpenBSD: pfkeyv2.c,v 1.243 2022/08/27 20:28:01 mvs Exp $ */ /* * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 @@ -173,6 +173,8 @@ int pfkeyv2_attach(struct socket *, int); int pfkeyv2_detach(struct socket *); int pfkeyv2_disconnect(struct socket *); int pfkeyv2_shutdown(struct socket *); +int pfkeyv2_send(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); int pfkeyv2_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *); int pfkeyv2_output(struct mbuf *, struct socket *, struct sockaddr *, @@ -207,6 +209,7 @@ const struct pr_usrreqs pfkeyv2_usrreqs = { .pru_detach = pfkeyv2_detach, .pru_disconnect = pfkeyv2_disconnect, .pru_shutdown = pfkeyv2_shutdown, + .pru_send = pfkeyv2_send, }; const struct protosw pfkeysw[] = { @@ -350,6 +353,34 @@ pfkeyv2_shutdown(struct socket *so) return (0); } +int +pfkeyv2_send(struct socket *so, struct mbuf *m, struct mbuf *nam, + struct mbuf *control) +{ + int error; + + soassertlocked(so); + + if (control && control->m_len) { + error = EOPNOTSUPP; + goto out; + } + + if (nam) { + error = EISCONN; + goto out; + } + + error = (*so->so_proto->pr_output)(m, so, NULL, NULL); + m = NULL; + +out: + m_freem(control); + m_freem(m); + + return (error); +} + int pfkeyv2_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, struct mbuf *control, struct proc *p) @@ -399,14 +430,6 @@ pfkeyv2_usrreq(struct socket *so, int req, struct mbuf *m, 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: panic("pfkeyv2_usrreq"); } @@ -452,7 +475,7 @@ pfkeyv2_output(struct mbuf *mbuf, struct socket *so, */ sounlock(so); - error = pfkeyv2_send(so, message, mbuf->m_pkthdr.len); + error = pfkeyv2_dosend(so, message, mbuf->m_pkthdr.len); solock(so); ret: @@ -1134,7 +1157,7 @@ pfkeyv2_get_proto_alg(u_int8_t satype, u_int8_t *sproto, int *alg) * Handle all messages from userland to kernel. */ int -pfkeyv2_send(struct socket *so, void *message, int len) +pfkeyv2_dosend(struct socket *so, void *message, int len) { int i, j, rval = 0, mode = PFKEYV2_SENDMESSAGE_BROADCAST; int delflag = 0; diff --git a/sys/net/pfkeyv2.h b/sys/net/pfkeyv2.h index 2e2c64880fb..db0a7cd1433 100644 --- a/sys/net/pfkeyv2.h +++ b/sys/net/pfkeyv2.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfkeyv2.h,v 1.92 2022/03/02 09:27:34 claudio Exp $ */ +/* $OpenBSD: pfkeyv2.h,v 1.93 2022/08/27 20:28:01 mvs Exp $ */ /* * @(#)COPYRIGHT 1.1 (NRL) January 1998 * @@ -412,7 +412,7 @@ int pfkeyv2_acquire(struct ipsec_policy *, union sockaddr_union *, int pfkeyv2_get(struct tdb *, void **, void **, int *, int *); int pfkeyv2_policy(struct ipsec_acquire *, void **, void **, int *); -int pfkeyv2_send(struct socket *, void *, int); +int pfkeyv2_dosend(struct socket *, void *, int); int pfkeyv2_sendmessage(void **, int, struct socket *, u_int8_t, int, u_int); int pfkeyv2_dump_policy(struct ipsec_policy *, void **, void **, int *); int pfkeyv2_dump_walker(struct tdb *, void *, int); diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 08e05a7902e..19c77bd8538 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtsock.c,v 1.342 2022/08/26 16:17:39 mvs Exp $ */ +/* $OpenBSD: rtsock.c,v 1.343 2022/08/27 20:28:01 mvs Exp $ */ /* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd Exp $ */ /* @@ -117,6 +117,8 @@ int route_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, int route_disconnect(struct socket *); int route_shutdown(struct socket *); int route_rcvd(struct socket *); +int route_send(struct socket *, struct mbuf *, 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); @@ -260,14 +262,6 @@ route_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, 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: panic("route_usrreq"); } @@ -383,6 +377,34 @@ route_rcvd(struct socket *so) return (0); } +int +route_send(struct socket *so, struct mbuf *m, struct mbuf *nam, + struct mbuf *control) +{ + int error; + + soassertlocked(so); + + if (control && control->m_len) { + error = EOPNOTSUPP; + goto out; + } + + if (nam) { + error = EISCONN; + goto out; + } + + error = (*so->so_proto->pr_output)(m, so, NULL, NULL); + m = NULL; + +out: + m_freem(control); + m_freem(m); + + return (error); +} + int route_ctloutput(int op, struct socket *so, int level, int optname, struct mbuf *m) @@ -2425,6 +2447,7 @@ const struct pr_usrreqs route_usrreqs = { .pru_disconnect = route_disconnect, .pru_shutdown = route_shutdown, .pru_rcvd = route_rcvd, + .pru_send = route_send, }; const struct protosw routesw[] = { diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index bb2b637fe83..11583387f61 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_divert.c,v 1.77 2022/08/26 16:17:39 mvs Exp $ */ +/* $OpenBSD: ip_divert.c,v 1.78 2022/08/27 20:28:01 mvs Exp $ */ /* * Copyright (c) 2009 Michele Marchetto @@ -68,6 +68,7 @@ const struct pr_usrreqs divert_usrreqs = { .pru_detach = divert_detach, .pru_bind = divert_bind, .pru_shutdown = divert_shutdown, + .pru_send = divert_send, }; int divbhashsize = DIVERTHASHSIZE; @@ -269,9 +270,6 @@ divert_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *addr, } switch (req) { - case PRU_SEND: - return (divert_output(inp, m, addr, control)); - case PRU_ABORT: soisdisconnected(so); in_pcbdetach(inp); @@ -363,6 +361,16 @@ divert_shutdown(struct socket *so) return (0); } +int +divert_send(struct socket *so, struct mbuf *m, struct mbuf *addr, + struct mbuf *control) +{ + struct inpcb *inp = sotoinpcb(so); + + soassertlocked(so); + return (divert_output(inp, m, addr, control)); +} + int divert_sysctl_divstat(void *oldp, size_t *oldlenp, void *newp) { diff --git a/sys/netinet/ip_divert.h b/sys/netinet/ip_divert.h index c3009f6a16e..020f2ae2ef1 100644 --- a/sys/netinet/ip_divert.h +++ b/sys/netinet/ip_divert.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_divert.h,v 1.18 2022/08/22 21:18:48 mvs Exp $ */ +/* $OpenBSD: ip_divert.h,v 1.19 2022/08/27 20:28:01 mvs Exp $ */ /* * Copyright (c) 2009 Michele Marchetto @@ -76,5 +76,7 @@ int divert_attach(struct socket *, int); int divert_detach(struct socket *); int divert_bind(struct socket *, struct mbuf *, struct proc *); int divert_shutdown(struct socket *); +int divert_send(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); #endif /* _KERNEL */ #endif /* _IP_DIVERT_H_ */ diff --git a/sys/netinet/ip_gre.c b/sys/netinet/ip_gre.c index 6ffa80a60cc..55a853f45f8 100644 --- a/sys/netinet/ip_gre.c +++ b/sys/netinet/ip_gre.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_gre.c,v 1.79 2022/08/22 21:18:48 mvs Exp $ */ +/* $OpenBSD: ip_gre.c,v 1.80 2022/08/27 20:28:01 mvs Exp $ */ /* $NetBSD: ip_gre.c,v 1.9 1999/10/25 19:18:11 drochner Exp $ */ /* @@ -69,16 +69,24 @@ const struct pr_usrreqs gre_usrreqs = { .pru_connect = rip_connect, .pru_disconnect = rip_disconnect, .pru_shutdown = rip_shutdown, + .pru_send = gre_send, }; int gre_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, struct mbuf *control, struct proc *p) +{ + return rip_usrreq(so, req, m, nam, control, p); +} + +int +gre_send(struct socket *so, struct mbuf *m, struct mbuf *nam, + struct mbuf *control) { #ifdef PIPEX struct inpcb *inp = sotoinpcb(so); - if (inp != NULL && inp->inp_pipex && req == PRU_SEND) { + if (inp->inp_pipex) { struct sockaddr_in *sin4; struct in_addr *ina_dst; @@ -103,10 +111,13 @@ gre_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, } } - if (m == NULL) + if (m == NULL) { + m_freem(control); return (ENOMEM); + } } #endif - return rip_usrreq(so, req, m, nam, control, p); + return rip_send(so, m, nam, control); } + #endif /* if NGRE > 0 */ diff --git a/sys/netinet/ip_gre.h b/sys/netinet/ip_gre.h index 7bef90b3b75..b626e3115bb 100644 --- a/sys/netinet/ip_gre.h +++ b/sys/netinet/ip_gre.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_gre.h,v 1.17 2022/08/15 09:11:39 mvs Exp $ */ +/* $OpenBSD: ip_gre.h,v 1.18 2022/08/27 20:28:01 mvs Exp $ */ /* $NetBSD: ip_gre.h,v 1.3 1998/10/07 23:33:02 thorpej Exp $ */ /* @@ -56,6 +56,9 @@ extern const struct pr_usrreqs gre_usrreqs; -int gre_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *); +int gre_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, + struct mbuf *, struct proc *); +int gre_send(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); #endif /* _KERNEL */ #endif /* _NETINET_IP_GRE_H_ */ diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 6ad01c463c2..d96d55fa5b9 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_var.h,v 1.101 2022/08/22 21:18:48 mvs Exp $ */ +/* $OpenBSD: ip_var.h,v 1.102 2022/08/27 20:28:01 mvs Exp $ */ /* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */ /* @@ -264,6 +264,8 @@ int rip_bind(struct socket *so, struct mbuf *, struct proc *); int rip_connect(struct socket *, struct mbuf *); int rip_disconnect(struct socket *); int rip_shutdown(struct socket *); +int rip_send(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); #ifdef MROUTING extern struct socket *ip_mrouter[]; /* multicast routing daemon */ #endif diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index f226a7af9f5..958c5dddbb2 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -1,4 +1,4 @@ -/* $OpenBSD: raw_ip.c,v 1.138 2022/08/26 16:17:39 mvs Exp $ */ +/* $OpenBSD: raw_ip.c,v 1.139 2022/08/27 20:28:01 mvs Exp $ */ /* $NetBSD: raw_ip.c,v 1.25 1996/02/18 18:58:33 christos Exp $ */ /* @@ -111,6 +111,7 @@ const struct pr_usrreqs rip_usrreqs = { .pru_connect = rip_connect, .pru_disconnect = rip_disconnect, .pru_shutdown = rip_shutdown, + .pru_send = rip_send, }; /* @@ -491,42 +492,6 @@ rip_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, error = EOPNOTSUPP; break; - /* - * Ship a packet out. The appropriate raw output - * routine handles any massaging necessary. - */ - case PRU_SEND: - { - struct sockaddr_in dst; - - memset(&dst, 0, sizeof(dst)); - dst.sin_family = AF_INET; - dst.sin_len = sizeof(dst); - if (so->so_state & SS_ISCONNECTED) { - if (nam) { - error = EISCONN; - break; - } - dst.sin_addr = inp->inp_faddr; - } else { - struct sockaddr_in *addr; - - if (nam == NULL) { - error = ENOTCONN; - break; - } - if ((error = in_nam2sin(nam, &addr))) - break; - dst.sin_addr = addr->sin_addr; - } -#ifdef IPSEC - /* XXX Find an IPsec TDB */ -#endif - error = rip_output(m, so, sintosa(&dst), NULL); - m = NULL; - break; - } - case PRU_SENSE: /* * stat: don't bother with a blocksize. @@ -672,3 +637,51 @@ rip_shutdown(struct socket *so) return (0); } + +int +rip_send(struct socket *so, struct mbuf *m, struct mbuf *nam, + struct mbuf *control) +{ + struct inpcb *inp = sotoinpcb(so); + struct sockaddr_in dst; + int error; + + soassertlocked(so); + + /* + * Ship a packet out. The appropriate raw output + * routine handles any massaging necessary. + */ + memset(&dst, 0, sizeof(dst)); + dst.sin_family = AF_INET; + dst.sin_len = sizeof(dst); + if (so->so_state & SS_ISCONNECTED) { + if (nam) { + error = EISCONN; + goto out; + } + dst.sin_addr = inp->inp_faddr; + } else { + struct sockaddr_in *addr; + + if (nam == NULL) { + error = ENOTCONN; + goto out; + } + if ((error = in_nam2sin(nam, &addr))) + goto out; + dst.sin_addr = addr->sin_addr; + } +#ifdef IPSEC + /* XXX Find an IPsec TDB */ +#endif + error = rip_output(m, so, sintosa(&dst), NULL); + m = NULL; + +out: + m_freem(control); + m_freem(m); + + return (error); +} + diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 7c473d51146..af327f2bd56 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_usrreq.c,v 1.195 2022/08/26 16:17:39 mvs Exp $ */ +/* $OpenBSD: tcp_usrreq.c,v 1.196 2022/08/27 20:28:01 mvs Exp $ */ /* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */ /* @@ -122,6 +122,7 @@ const struct pr_usrreqs tcp_usrreqs = { .pru_disconnect = tcp_disconnect, .pru_shutdown = tcp_shutdown, .pru_rcvd = tcp_rcvd, + .pru_send = tcp_send, }; static int pr_slowhz = PR_SLOWHZ; @@ -225,15 +226,6 @@ tcp_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, error = EOPNOTSUPP; break; - /* - * Do a send by putting data in output queue and updating urgent - * marker if URG set. Possibly send more data. - */ - case PRU_SEND: - sbappendstream(so, &so->so_snd, m); - error = tcp_output(tp); - break; - /* * Abort the TCP. */ @@ -934,6 +926,42 @@ tcp_rcvd(struct socket *so) return (0); } +/* + * Do a send by putting data in output queue and updating urgent + * marker if URG set. Possibly send more data. + */ +int +tcp_send(struct socket *so, struct mbuf *m, struct mbuf *nam, + struct mbuf *control) +{ + struct inpcb *inp; + struct tcpcb *tp; + int error; + short ostate; + + soassertlocked(so); + + if ((error = tcp_sogetpcb(so, &inp, &tp))) + goto out; + + if (so->so_options & SO_DEBUG) + ostate = tp->t_state; + + sbappendstream(so, &so->so_snd, m); + m = NULL; + + error = tcp_output(tp); + + if (so->so_options & SO_DEBUG) + tcp_trace(TA_USER, ostate, tp, tp, NULL, PRU_SEND, 0); + +out: + m_freem(control); + m_freem(m); + + return (error); +} + /* * Initiate (or continue) disconnect. * If embryonic state, just send reset (once). diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index 6b9a237ba90..b07457c8613 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_var.h,v 1.148 2022/08/26 16:17:39 mvs Exp $ */ +/* $OpenBSD: tcp_var.h,v 1.149 2022/08/27 20:28:01 mvs Exp $ */ /* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */ /* @@ -721,6 +721,8 @@ int tcp_accept(struct socket *, struct mbuf *); int tcp_disconnect(struct socket *); int tcp_shutdown(struct socket *); int tcp_rcvd(struct socket *); +int tcp_send(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); void tcp_xmit_timer(struct tcpcb *, int); void tcpdropoldhalfopen(struct tcpcb *, u_int16_t); void tcp_sack_option(struct tcpcb *,struct tcphdr *,u_char *,int); diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 75b507c0552..a85645ed9be 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_usrreq.c,v 1.290 2022/08/26 16:17:39 mvs Exp $ */ +/* $OpenBSD: udp_usrreq.c,v 1.291 2022/08/27 20:28:01 mvs Exp $ */ /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */ /* @@ -130,6 +130,7 @@ const struct pr_usrreqs udp_usrreqs = { .pru_connect = udp_connect, .pru_disconnect = udp_disconnect, .pru_shutdown = udp_shutdown, + .pru_send = udp_send, }; const struct sysctl_bounded_args udpctl_vars[] = { @@ -1086,46 +1087,6 @@ udp_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *addr, error = EOPNOTSUPP; break; - case PRU_SEND: -#ifdef PIPEX - if (inp->inp_pipex) { - struct pipex_session *session; - - if (addr != NULL) - session = - pipex_l2tp_userland_lookup_session(m, - mtod(addr, struct sockaddr *)); - else -#ifdef INET6 - if (inp->inp_flags & INP_IPV6) - session = - pipex_l2tp_userland_lookup_session_ipv6( - m, inp->inp_faddr6); - else -#endif - session = - pipex_l2tp_userland_lookup_session_ipv4( - m, inp->inp_faddr); - if (session != NULL) { - m = pipex_l2tp_userland_output(m, session); - pipex_rele_session(session); - - if (m == NULL) { - error = ENOMEM; - goto release; - } - } - } -#endif - -#ifdef INET6 - if (inp->inp_flags & INP_IPV6) - error = udp6_output(inp, m, addr, control); - else -#endif - error = udp_output(inp, m, addr, control); - return (error); - case PRU_ABORT: soisdisconnected(so); in_pcbdetach(inp); @@ -1293,6 +1254,56 @@ udp_shutdown(struct socket *so) return (0); } +int +udp_send(struct socket *so, struct mbuf *m, struct mbuf *addr, + struct mbuf *control) +{ + struct inpcb *inp = sotoinpcb(so); + int error; + + soassertlocked(so); + +#ifdef PIPEX + if (inp->inp_pipex) { + struct pipex_session *session; + + if (addr != NULL) + session = + pipex_l2tp_userland_lookup_session(m, + mtod(addr, struct sockaddr *)); + else +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) + session = + pipex_l2tp_userland_lookup_session_ipv6( + m, inp->inp_faddr6); + else +#endif + session = + pipex_l2tp_userland_lookup_session_ipv4( + m, inp->inp_faddr); + if (session != NULL) { + m = pipex_l2tp_userland_output(m, session); + pipex_rele_session(session); + + if (m == NULL) { + m_freem(control); + return (ENOMEM); + } + } + } +#endif + +#ifdef INET6 + if (inp->inp_flags & INP_IPV6) + error = udp6_output(inp, m, addr, control); + else +#endif + error = udp_output(inp, m, addr, control); + + return (error); +} + /* * Sysctl for udp variables. */ diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h index 945695ba3c5..bdf2dff98b4 100644 --- a/sys/netinet/udp_var.h +++ b/sys/netinet/udp_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_var.h,v 1.42 2022/08/22 21:18:48 mvs Exp $ */ +/* $OpenBSD: udp_var.h,v 1.43 2022/08/27 20:28:01 mvs Exp $ */ /* $NetBSD: udp_var.h,v 1.12 1996/02/13 23:44:41 christos Exp $ */ /* @@ -147,5 +147,7 @@ int udp_bind(struct socket *, struct mbuf *, struct proc *); int udp_connect(struct socket *, struct mbuf *); int udp_disconnect(struct socket *); int udp_shutdown(struct socket *); +int udp_send(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); #endif /* _KERNEL */ #endif /* _NETINET_UDP_VAR_H_ */ diff --git a/sys/netinet6/ip6_divert.c b/sys/netinet6/ip6_divert.c index 2ecce90e31b..b9617bab118 100644 --- a/sys/netinet6/ip6_divert.c +++ b/sys/netinet6/ip6_divert.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_divert.c,v 1.76 2022/08/26 16:17:39 mvs Exp $ */ +/* $OpenBSD: ip6_divert.c,v 1.77 2022/08/27 20:28:01 mvs Exp $ */ /* * Copyright (c) 2009 Michele Marchetto @@ -69,6 +69,7 @@ const struct pr_usrreqs divert6_usrreqs = { .pru_detach = divert6_detach, .pru_bind = divert6_bind, .pru_shutdown = divert6_shutdown, + .pru_send = divert6_send, }; int divb6hashsize = DIVERTHASHSIZE; @@ -275,9 +276,6 @@ divert6_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *addr, } switch (req) { - case PRU_SEND: - return (divert6_output(inp, m, addr, control)); - case PRU_ABORT: soisdisconnected(so); in_pcbdetach(inp); @@ -371,6 +369,16 @@ divert6_shutdown(struct socket *so) return (0); } +int +divert6_send(struct socket *so, struct mbuf *m, struct mbuf *addr, + struct mbuf *control) +{ + struct inpcb *inp = sotoinpcb(so); + + soassertlocked(so); + return (divert6_output(inp, m, addr, control)); +} + int divert6_sysctl_div6stat(void *oldp, size_t *oldlenp, void *newp) { diff --git a/sys/netinet6/ip6_divert.h b/sys/netinet6/ip6_divert.h index 9bf1b6ab1ba..0414661edcf 100644 --- a/sys/netinet6/ip6_divert.h +++ b/sys/netinet6/ip6_divert.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_divert.h,v 1.16 2022/08/22 21:18:48 mvs Exp $ */ +/* $OpenBSD: ip6_divert.h,v 1.17 2022/08/27 20:28:01 mvs Exp $ */ /* * Copyright (c) 2009 Michele Marchetto @@ -76,6 +76,8 @@ int divert6_attach(struct socket *, int); int divert6_detach(struct socket *); int divert6_bind(struct socket *, struct mbuf *, struct proc *); int divert6_shutdown(struct socket *); +int divert6_send(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); #endif /* _KERNEL */ #endif /* _IP6_DIVERT_H_ */ diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h index 63ec50bfa04..e24406f826e 100644 --- a/sys/netinet6/ip6_var.h +++ b/sys/netinet6/ip6_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_var.h,v 1.99 2022/08/22 21:18:48 mvs Exp $ */ +/* $OpenBSD: ip6_var.h,v 1.100 2022/08/27 20:28:01 mvs Exp $ */ /* $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $ */ /* @@ -359,6 +359,8 @@ int rip6_bind(struct socket *, struct mbuf *, struct proc *); int rip6_connect(struct socket *, struct mbuf *); int rip6_disconnect(struct socket *); int rip6_shutdown(struct socket *); +int rip6_send(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); int rip6_sysctl(int *, u_int, void *, size_t *, void *, size_t); int dest6_input(struct mbuf **, int *, int, int); diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index 25715c8435e..c1270d73c8a 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: raw_ip6.c,v 1.158 2022/08/26 16:17:39 mvs Exp $ */ +/* $OpenBSD: raw_ip6.c,v 1.159 2022/08/27 20:28:01 mvs Exp $ */ /* $KAME: raw_ip6.c,v 1.69 2001/03/04 15:55:44 itojun Exp $ */ /* @@ -113,6 +113,7 @@ const struct pr_usrreqs rip6_usrreqs = { .pru_connect = rip6_connect, .pru_disconnect = rip6_disconnect, .pru_shutdown = rip6_shutdown, + .pru_send = rip6_send, }; /* @@ -609,42 +610,6 @@ rip6_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, error = EOPNOTSUPP; break; - /* - * Ship a packet out. The appropriate raw output - * routine handles any messaging necessary. - */ - case PRU_SEND: - { - struct sockaddr_in6 dst; - - /* always copy sockaddr to avoid overwrites */ - memset(&dst, 0, sizeof(dst)); - dst.sin6_family = AF_INET6; - dst.sin6_len = sizeof(dst); - if (so->so_state & SS_ISCONNECTED) { - if (nam) { - error = EISCONN; - break; - } - dst.sin6_addr = in6p->inp_faddr6; - } else { - struct sockaddr_in6 *addr6; - - if (nam == NULL) { - error = ENOTCONN; - break; - } - if ((error = in6_nam2sin6(nam, &addr6))) - break; - dst.sin6_addr = addr6->sin6_addr; - dst.sin6_scope_id = addr6->sin6_scope_id; - } - error = rip6_output(m, so, sin6tosa(&dst), control); - control = NULL; - m = NULL; - break; - } - case PRU_SENSE: /* * stat: don't bother with a blocksize @@ -806,6 +771,54 @@ rip6_shutdown(struct socket *so) return (0); } +int +rip6_send(struct socket *so, struct mbuf *m, struct mbuf *nam, + struct mbuf *control) +{ + struct inpcb *in6p = sotoinpcb(so); + struct sockaddr_in6 dst; + int error; + + soassertlocked(so); + + /* + * Ship a packet out. The appropriate raw output + * routine handles any messaging necessary. + */ + + /* always copy sockaddr to avoid overwrites */ + memset(&dst, 0, sizeof(dst)); + dst.sin6_family = AF_INET6; + dst.sin6_len = sizeof(dst); + if (so->so_state & SS_ISCONNECTED) { + if (nam) { + error = EISCONN; + goto out; + } + dst.sin6_addr = in6p->inp_faddr6; + } else { + struct sockaddr_in6 *addr6; + + if (nam == NULL) { + error = ENOTCONN; + goto out; + } + if ((error = in6_nam2sin6(nam, &addr6))) + goto out; + dst.sin6_addr = addr6->sin6_addr; + dst.sin6_scope_id = addr6->sin6_scope_id; + } + error = rip6_output(m, so, sin6tosa(&dst), control); + control = NULL; + m = NULL; + +out: + m_freem(control); + m_freem(m); + + return (error); +} + int rip6_sysctl_rip6stat(void *oldp, size_t *oldplen, void *newp) { diff --git a/sys/sys/protosw.h b/sys/sys/protosw.h index c7afdcada0d..cec2616288c 100644 --- a/sys/sys/protosw.h +++ b/sys/sys/protosw.h @@ -1,4 +1,4 @@ -/* $OpenBSD: protosw.h,v 1.44 2022/08/26 16:17:39 mvs Exp $ */ +/* $OpenBSD: protosw.h,v 1.45 2022/08/27 20:28:01 mvs Exp $ */ /* $NetBSD: protosw.h,v 1.10 1996/04/09 20:55:32 cgd Exp $ */ /*- @@ -73,6 +73,8 @@ struct pr_usrreqs { int (*pru_disconnect)(struct socket *); int (*pru_shutdown)(struct socket *); int (*pru_rcvd)(struct socket *); + int (*pru_send)(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); }; struct protosw { @@ -326,8 +328,7 @@ static inline int pru_send(struct socket *so, struct mbuf *top, struct mbuf *addr, struct mbuf *control) { - return (*so->so_proto->pr_usrreqs->pru_usrreq)(so, - PRU_SEND, top, addr, control, curproc); + return (*so->so_proto->pr_usrreqs->pru_send)(so, top, addr, control); } static inline int diff --git a/sys/sys/unpcb.h b/sys/sys/unpcb.h index 9248fb9295d..4521ceb25ba 100644 --- a/sys/sys/unpcb.h +++ b/sys/sys/unpcb.h @@ -1,4 +1,4 @@ -/* $OpenBSD: unpcb.h,v 1.34 2022/08/26 16:17:39 mvs Exp $ */ +/* $OpenBSD: unpcb.h,v 1.35 2022/08/27 20:28:01 mvs Exp $ */ /* $NetBSD: unpcb.h,v 1.6 1994/06/29 06:46:08 cgd Exp $ */ /* @@ -120,6 +120,8 @@ int uipc_accept(struct socket *, struct mbuf *); int uipc_disconnect(struct socket *); int uipc_shutdown(struct socket *); int uipc_rcvd(struct socket *); +int uipc_send(struct socket *, struct mbuf *, struct mbuf *, + struct mbuf *); void unp_init(void); int unp_bind(struct unpcb *, struct mbuf *, struct proc *); -- 2.20.1