Move PRU_SEND request to (*pru_send)().
authormvs <mvs@openbsd.org>
Sat, 27 Aug 2022 20:28:01 +0000 (20:28 +0000)
committermvs <mvs@openbsd.org>
Sat, 27 Aug 2022 20:28:01 +0000 (20:28 +0000)
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@

20 files changed:
sys/kern/uipc_usrreq.c
sys/net/pfkeyv2.c
sys/net/pfkeyv2.h
sys/net/rtsock.c
sys/netinet/ip_divert.c
sys/netinet/ip_divert.h
sys/netinet/ip_gre.c
sys/netinet/ip_gre.h
sys/netinet/ip_var.h
sys/netinet/raw_ip.c
sys/netinet/tcp_usrreq.c
sys/netinet/tcp_var.h
sys/netinet/udp_usrreq.c
sys/netinet/udp_var.h
sys/netinet6/ip6_divert.c
sys/netinet6/ip6_divert.h
sys/netinet6/ip6_var.h
sys/netinet6/raw_ip6.c
sys/sys/protosw.h
sys/sys/unpcb.h

index fcbb08b..2dbbabf 100644 (file)
@@ -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)
index 6347579..995fb51 100644 (file)
@@ -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;
index 2e2c648..db0a7cd 100644 (file)
@@ -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);
index 08e05a7..19c77bd 100644 (file)
@@ -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[] = {
index bb2b637..1158338 100644 (file)
@@ -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 <michele@openbsd.org>
@@ -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)
 {
index c3009f6..020f2ae 100644 (file)
@@ -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 <michele@openbsd.org>
@@ -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_ */
index 6ffa80a..55a853f 100644 (file)
@@ -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 */
index 7bef90b..b626e31 100644 (file)
@@ -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_ */
index 6ad01c4..d96d55f 100644 (file)
@@ -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
index f226a7a..958c5dd 100644 (file)
@@ -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);
+}
+
index 7c473d5..af327f2 100644 (file)
@@ -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).
index 6b9a237..b07457c 100644 (file)
@@ -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);
index 75b507c..a85645e 100644 (file)
@@ -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.
  */
index 945695b..bdf2dff 100644 (file)
@@ -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_ */
index 2ecce90..b9617ba 100644 (file)
@@ -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 <michele@openbsd.org>
@@ -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)
 {
index 9bf1b6a..0414661 100644 (file)
@@ -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 <michele@openbsd.org>
@@ -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_ */
index 63ec50b..e24406f 100644 (file)
@@ -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);
index 25715c8..c1270d7 100644 (file)
@@ -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)
 {
index c7afdca..cec2616 100644 (file)
@@ -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
index 9248fb9..4521ceb 100644 (file)
@@ -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 *);