On Sat, Aug 27, 2022 at 02:48:35AM +0300, Vitaliy Makkoveev wrote:
> 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().

You forgot to delete case PRU_SEND from route_usrreq().

With that OK bluhm@

> Index: sys/kern/uipc_usrreq.c
> ===================================================================
> RCS file: /cvs/src/sys/kern/uipc_usrreq.c,v
> retrieving revision 1.175
> diff -u -p -r1.175 uipc_usrreq.c
> --- sys/kern/uipc_usrreq.c    26 Aug 2022 16:17:39 -0000      1.175
> +++ sys/kern/uipc_usrreq.c    26 Aug 2022 23:00:24 -0000
> @@ -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, 
>               }
>               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);
> @@ -574,6 +479,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
> Index: sys/net/pfkeyv2.c
> ===================================================================
> RCS file: /cvs/src/sys/net/pfkeyv2.c,v
> retrieving revision 1.242
> diff -u -p -r1.242 pfkeyv2.c
> --- sys/net/pfkeyv2.c 26 Aug 2022 16:17:39 -0000      1.242
> +++ sys/net/pfkeyv2.c 26 Aug 2022 23:00:24 -0000
> @@ -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[] = {
> @@ -351,6 +354,34 @@ pfkeyv2_shutdown(struct socket *so)
>  }
>  
>  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 re
>       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
>        */
>  
>       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
>   * 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: sys/net/pfkeyv2.h
> ===================================================================
> RCS file: /cvs/src/sys/net/pfkeyv2.h,v
> retrieving revision 1.92
> diff -u -p -r1.92 pfkeyv2.h
> --- sys/net/pfkeyv2.h 2 Mar 2022 09:27:34 -0000       1.92
> +++ sys/net/pfkeyv2.h 26 Aug 2022 23:00:24 -0000
> @@ -412,7 +412,7 @@ int pfkeyv2_acquire(struct ipsec_policy 
>  
>  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: sys/net/rtsock.c
> ===================================================================
> RCS file: /cvs/src/sys/net/rtsock.c,v
> retrieving revision 1.342
> diff -u -p -r1.342 rtsock.c
> --- sys/net/rtsock.c  26 Aug 2022 16:17:39 -0000      1.342
> +++ sys/net/rtsock.c  26 Aug 2022 23:00:24 -0000
> @@ -117,6 +117,8 @@ int       route_usrreq(struct socket *, int, s
>  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);
> @@ -384,6 +386,34 @@ route_rcvd(struct socket *so)
>  }
>  
>  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 +2455,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: sys/netinet/ip_divert.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_divert.c,v
> retrieving revision 1.77
> diff -u -p -r1.77 ip_divert.c
> --- sys/netinet/ip_divert.c   26 Aug 2022 16:17:39 -0000      1.77
> +++ sys/netinet/ip_divert.c   26 Aug 2022 23:00:24 -0000
> @@ -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
>       }
>       switch (req) {
>  
> -     case PRU_SEND:
> -             return (divert_output(inp, m, addr, control));
> -
>       case PRU_ABORT:
>               soisdisconnected(so);
>               in_pcbdetach(inp);
> @@ -361,6 +359,16 @@ divert_shutdown(struct socket *so)
>       soassertlocked(so);
>       socantsendmore(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
> Index: sys/netinet/ip_divert.h
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_divert.h,v
> retrieving revision 1.18
> diff -u -p -r1.18 ip_divert.h
> --- sys/netinet/ip_divert.h   22 Aug 2022 21:18:48 -0000      1.18
> +++ sys/netinet/ip_divert.h   26 Aug 2022 23:00:24 -0000
> @@ -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: sys/netinet/ip_gre.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_gre.c,v
> retrieving revision 1.79
> diff -u -p -r1.79 ip_gre.c
> --- sys/netinet/ip_gre.c      22 Aug 2022 21:18:48 -0000      1.79
> +++ sys/netinet/ip_gre.c      26 Aug 2022 23:00:24 -0000
> @@ -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, s
>                       }
>               }
>  
> -             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: sys/netinet/ip_gre.h
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_gre.h,v
> retrieving revision 1.17
> diff -u -p -r1.17 ip_gre.h
> --- sys/netinet/ip_gre.h      15 Aug 2022 09:11:39 -0000      1.17
> +++ sys/netinet/ip_gre.h      26 Aug 2022 23:00:24 -0000
> @@ -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: sys/netinet/ip_var.h
> ===================================================================
> RCS file: /cvs/src/sys/netinet/ip_var.h,v
> retrieving revision 1.101
> diff -u -p -r1.101 ip_var.h
> --- sys/netinet/ip_var.h      22 Aug 2022 21:18:48 -0000      1.101
> +++ sys/netinet/ip_var.h      26 Aug 2022 23:00:24 -0000
> @@ -264,6 +264,8 @@ int        rip_bind(struct socket *so, struct 
>  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: sys/netinet/raw_ip.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/raw_ip.c,v
> retrieving revision 1.138
> diff -u -p -r1.138 raw_ip.c
> --- sys/netinet/raw_ip.c      26 Aug 2022 16:17:39 -0000      1.138
> +++ sys/netinet/raw_ip.c      26 Aug 2022 23:00:24 -0000
> @@ -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, s
>               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: sys/netinet/tcp_usrreq.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/tcp_usrreq.c,v
> retrieving revision 1.195
> diff -u -p -r1.195 tcp_usrreq.c
> --- sys/netinet/tcp_usrreq.c  26 Aug 2022 16:17:39 -0000      1.195
> +++ sys/netinet/tcp_usrreq.c  26 Aug 2022 23:00:24 -0000
> @@ -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;
> @@ -226,15 +227,6 @@ tcp_usrreq(struct socket *so, int req, s
>               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.
>        */
>       case PRU_ABORT:
> @@ -932,6 +924,42 @@ tcp_rcvd(struct socket *so)
>       if (so->so_options & SO_DEBUG)
>               tcp_trace(TA_USER, ostate, tp, tp, NULL, PRU_RCVD, 0);
>       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);
>  }
>  
>  /*
> Index: sys/netinet/tcp_var.h
> ===================================================================
> RCS file: /cvs/src/sys/netinet/tcp_var.h,v
> retrieving revision 1.148
> diff -u -p -r1.148 tcp_var.h
> --- sys/netinet/tcp_var.h     26 Aug 2022 16:17:39 -0000      1.148
> +++ sys/netinet/tcp_var.h     26 Aug 2022 23:00:24 -0000
> @@ -721,6 +721,8 @@ int        tcp_accept(struct socket *, struct 
>  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: sys/netinet/udp_usrreq.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet/udp_usrreq.c,v
> retrieving revision 1.290
> diff -u -p -r1.290 udp_usrreq.c
> --- sys/netinet/udp_usrreq.c  26 Aug 2022 16:17:39 -0000      1.290
> +++ sys/netinet/udp_usrreq.c  26 Aug 2022 23:00:24 -0000
> @@ -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, s
>               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);
> @@ -1291,6 +1252,56 @@ udp_shutdown(struct socket *so)
>       soassertlocked(so);
>       socantsendmore(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);
>  }
>  
>  /*
> Index: sys/netinet/udp_var.h
> ===================================================================
> RCS file: /cvs/src/sys/netinet/udp_var.h,v
> retrieving revision 1.42
> diff -u -p -r1.42 udp_var.h
> --- sys/netinet/udp_var.h     22 Aug 2022 21:18:48 -0000      1.42
> +++ sys/netinet/udp_var.h     26 Aug 2022 23:00:24 -0000
> @@ -147,5 +147,7 @@ int        udp_bind(struct socket *, struct mb
>  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: sys/netinet6/ip6_divert.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_divert.c,v
> retrieving revision 1.76
> diff -u -p -r1.76 ip6_divert.c
> --- sys/netinet6/ip6_divert.c 26 Aug 2022 16:17:39 -0000      1.76
> +++ sys/netinet6/ip6_divert.c 26 Aug 2022 23:00:24 -0000
> @@ -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 re
>       }
>       switch (req) {
>  
> -     case PRU_SEND:
> -             return (divert6_output(inp, m, addr, control));
> -
>       case PRU_ABORT:
>               soisdisconnected(so);
>               in_pcbdetach(inp);
> @@ -369,6 +367,16 @@ divert6_shutdown(struct socket *so)
>       socantsendmore(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
> Index: sys/netinet6/ip6_divert.h
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_divert.h,v
> retrieving revision 1.16
> diff -u -p -r1.16 ip6_divert.h
> --- sys/netinet6/ip6_divert.h 22 Aug 2022 21:18:48 -0000      1.16
> +++ sys/netinet6/ip6_divert.h 26 Aug 2022 23:00:24 -0000
> @@ -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: sys/netinet6/ip6_var.h
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_var.h,v
> retrieving revision 1.99
> diff -u -p -r1.99 ip6_var.h
> --- sys/netinet6/ip6_var.h    22 Aug 2022 21:18:48 -0000      1.99
> +++ sys/netinet6/ip6_var.h    26 Aug 2022 23:00:24 -0000
> @@ -359,6 +359,8 @@ int       rip6_bind(struct socket *, struct mb
>  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: sys/netinet6/raw_ip6.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/raw_ip6.c,v
> retrieving revision 1.158
> diff -u -p -r1.158 raw_ip6.c
> --- sys/netinet6/raw_ip6.c    26 Aug 2022 16:17:39 -0000      1.158
> +++ sys/netinet6/raw_ip6.c    26 Aug 2022 23:00:24 -0000
> @@ -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, 
>               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
> @@ -804,6 +769,54 @@ rip6_shutdown(struct socket *so)
>       soassertlocked(so);
>       socantsendmore(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
> Index: sys/sys/protosw.h
> ===================================================================
> RCS file: /cvs/src/sys/sys/protosw.h,v
> retrieving revision 1.44
> diff -u -p -r1.44 protosw.h
> --- sys/sys/protosw.h 26 Aug 2022 16:17:39 -0000      1.44
> +++ sys/sys/protosw.h 26 Aug 2022 23:00:24 -0000
> @@ -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: sys/sys/unpcb.h
> ===================================================================
> RCS file: /cvs/src/sys/sys/unpcb.h,v
> retrieving revision 1.34
> diff -u -p -r1.34 unpcb.h
> --- sys/sys/unpcb.h   26 Aug 2022 16:17:39 -0000      1.34
> +++ sys/sys/unpcb.h   26 Aug 2022 23:00:24 -0000
> @@ -120,6 +120,8 @@ int       uipc_accept(struct socket *, struct 
>  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 *);

Reply via email to