19eeaa8a9SJeffrey Hsu /* 266d6c637SJeffrey Hsu * Copyright (c) 2003, 2004 Jeffrey M. Hsu. All rights reserved. 366d6c637SJeffrey Hsu * Copyright (c) 2003, 2004 The DragonFly Project. All rights reserved. 466d6c637SJeffrey Hsu * 566d6c637SJeffrey Hsu * This code is derived from software contributed to The DragonFly Project 666d6c637SJeffrey Hsu * by Jeffrey M. Hsu. 79eeaa8a9SJeffrey Hsu * 89eeaa8a9SJeffrey Hsu * Redistribution and use in source and binary forms, with or without 99eeaa8a9SJeffrey Hsu * modification, are permitted provided that the following conditions 109eeaa8a9SJeffrey Hsu * are met: 119eeaa8a9SJeffrey Hsu * 1. Redistributions of source code must retain the above copyright 129eeaa8a9SJeffrey Hsu * notice, this list of conditions and the following disclaimer. 139eeaa8a9SJeffrey Hsu * 2. Redistributions in binary form must reproduce the above copyright 149eeaa8a9SJeffrey Hsu * notice, this list of conditions and the following disclaimer in the 159eeaa8a9SJeffrey Hsu * documentation and/or other materials provided with the distribution. 1666d6c637SJeffrey Hsu * 3. Neither the name of The DragonFly Project nor the names of its 1766d6c637SJeffrey Hsu * contributors may be used to endorse or promote products derived 1866d6c637SJeffrey Hsu * from this software without specific, prior written permission. 1966d6c637SJeffrey Hsu * 2066d6c637SJeffrey Hsu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2166d6c637SJeffrey Hsu * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2266d6c637SJeffrey Hsu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 2366d6c637SJeffrey Hsu * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 2466d6c637SJeffrey Hsu * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2566d6c637SJeffrey Hsu * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 2666d6c637SJeffrey Hsu * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 2766d6c637SJeffrey Hsu * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 2866d6c637SJeffrey Hsu * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2966d6c637SJeffrey Hsu * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 3066d6c637SJeffrey Hsu * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3166d6c637SJeffrey Hsu * SUCH DAMAGE. 329eeaa8a9SJeffrey Hsu */ 339eeaa8a9SJeffrey Hsu 349eeaa8a9SJeffrey Hsu #include <sys/param.h> 359eeaa8a9SJeffrey Hsu #include <sys/systm.h> 36e71a125fSAggelos Economopoulos #include <sys/kernel.h> 379eeaa8a9SJeffrey Hsu #include <sys/msgport.h> 389eeaa8a9SJeffrey Hsu #include <sys/protosw.h> 399eeaa8a9SJeffrey Hsu #include <sys/socket.h> 409eeaa8a9SJeffrey Hsu #include <sys/socketvar.h> 419eeaa8a9SJeffrey Hsu #include <sys/socketops.h> 429eeaa8a9SJeffrey Hsu #include <sys/thread.h> 43d3266d67SMatthew Dillon #include <sys/thread2.h> 44d3266d67SMatthew Dillon #include <sys/msgport2.h> 4596c6eb29SSepherosa Ziehau #include <sys/spinlock2.h> 46f65f767cSSepherosa Ziehau #include <sys/sysctl.h> 470ad8e15eSSepherosa Ziehau #include <sys/mbuf.h> 48de0003feSAggelos Economopoulos #include <vm/pmap.h> 496999cd81SMatthew Dillon 504599cf19SMatthew Dillon #include <net/netmsg2.h> 516999cd81SMatthew Dillon #include <sys/socketvar2.h> 529eeaa8a9SJeffrey Hsu 539eeaa8a9SJeffrey Hsu #include <net/netisr.h> 549eeaa8a9SJeffrey Hsu #include <net/netmsg.h> 559eeaa8a9SJeffrey Hsu 56f65f767cSSepherosa Ziehau static int async_rcvd_drop_race = 0; 57f65f767cSSepherosa Ziehau SYSCTL_INT(_kern_ipc, OID_AUTO, async_rcvd_drop_race, CTLFLAG_RW, 58f65f767cSSepherosa Ziehau &async_rcvd_drop_race, 0, "# of asynchronized pru_rcvd msg drop races"); 59f65f767cSSepherosa Ziehau 604402d8a2SMatthew Dillon /* 61c3d495a1SMatthew Dillon * Abort a socket and free it. Called from soabort() only. soabort() 62c3d495a1SMatthew Dillon * got a ref on the socket which we must free on reply. 634402d8a2SMatthew Dillon */ 644402d8a2SMatthew Dillon void 659eeaa8a9SJeffrey Hsu so_pru_abort(struct socket *so) 669eeaa8a9SJeffrey Hsu { 679eeaa8a9SJeffrey Hsu struct netmsg_pru_abort msg; 689eeaa8a9SJeffrey Hsu 69002c1265SMatthew Dillon netmsg_init(&msg.base, so, &curthread->td_msgport, 70002c1265SMatthew Dillon 0, so->so_proto->pr_usrreqs->pru_abort); 71002c1265SMatthew Dillon (void)lwkt_domsg(so->so_port, &msg.base.lmsg, 0); 72c3d495a1SMatthew Dillon sofree(msg.base.nm_so); 734402d8a2SMatthew Dillon } 744402d8a2SMatthew Dillon 754402d8a2SMatthew Dillon /* 769116be8eSMatthew Dillon * Abort a socket and free it, asynchronously. Called from 77c3d495a1SMatthew Dillon * soaborta() only. soaborta() got a ref on the socket which we must 78c3d495a1SMatthew Dillon * free on reply. 794402d8a2SMatthew Dillon */ 804402d8a2SMatthew Dillon void 814402d8a2SMatthew Dillon so_pru_aborta(struct socket *so) 824402d8a2SMatthew Dillon { 834402d8a2SMatthew Dillon struct netmsg_pru_abort *msg; 844402d8a2SMatthew Dillon 854402d8a2SMatthew Dillon msg = kmalloc(sizeof(*msg), M_LWKTMSG, M_WAITOK | M_ZERO); 86c3d495a1SMatthew Dillon netmsg_init(&msg->base, so, &netisr_afree_free_so_rport, 87002c1265SMatthew Dillon 0, so->so_proto->pr_usrreqs->pru_abort); 88002c1265SMatthew Dillon lwkt_sendmsg(so->so_port, &msg->base.lmsg); 899eeaa8a9SJeffrey Hsu } 909eeaa8a9SJeffrey Hsu 91fd86a41cSSepherosa Ziehau /* 92fd86a41cSSepherosa Ziehau * Abort a socket and free it. Called from soabort_oncpu() only. 93fd86a41cSSepherosa Ziehau * Caller must make sure that the current CPU is inpcb's owner CPU. 94fd86a41cSSepherosa Ziehau */ 95fd86a41cSSepherosa Ziehau void 96fd86a41cSSepherosa Ziehau so_pru_abort_oncpu(struct socket *so) 97fd86a41cSSepherosa Ziehau { 98002c1265SMatthew Dillon struct netmsg_pru_abort msg; 99002c1265SMatthew Dillon netisr_fn_t func = so->so_proto->pr_usrreqs->pru_abort; 100002c1265SMatthew Dillon 101002c1265SMatthew Dillon netmsg_init(&msg.base, so, &netisr_adone_rport, 0, func); 102002c1265SMatthew Dillon msg.base.lmsg.ms_flags &= ~(MSGF_REPLY | MSGF_DONE); 103002c1265SMatthew Dillon msg.base.lmsg.ms_flags |= MSGF_SYNC; 104002c1265SMatthew Dillon func((netmsg_t)&msg); 1050fec1ecdSMatthew Dillon KKASSERT(msg.base.lmsg.ms_flags & MSGF_DONE); 106c3d495a1SMatthew Dillon sofree(msg.base.nm_so); 107fd86a41cSSepherosa Ziehau } 108fd86a41cSSepherosa Ziehau 1099eeaa8a9SJeffrey Hsu int 110f328adf5SSepherosa Ziehau so_pru_accept(struct socket *so, struct sockaddr **nam) 1119eeaa8a9SJeffrey Hsu { 1129eeaa8a9SJeffrey Hsu struct netmsg_pru_accept msg; 1139eeaa8a9SJeffrey Hsu 114f328adf5SSepherosa Ziehau netmsg_init(&msg.base, so, &curthread->td_msgport, 115f328adf5SSepherosa Ziehau 0, so->so_proto->pr_usrreqs->pru_accept); 1169eeaa8a9SJeffrey Hsu msg.nm_nam = nam; 117f328adf5SSepherosa Ziehau 118f328adf5SSepherosa Ziehau return lwkt_domsg(so->so_port, &msg.base.lmsg, 0); 1199eeaa8a9SJeffrey Hsu } 1209eeaa8a9SJeffrey Hsu 1219eeaa8a9SJeffrey Hsu int 1229eeaa8a9SJeffrey Hsu so_pru_attach(struct socket *so, int proto, struct pru_attach_info *ai) 1239eeaa8a9SJeffrey Hsu { 1249eeaa8a9SJeffrey Hsu struct netmsg_pru_attach msg; 125002c1265SMatthew Dillon int error; 1269eeaa8a9SJeffrey Hsu 127002c1265SMatthew Dillon netmsg_init(&msg.base, so, &curthread->td_msgport, 128002c1265SMatthew Dillon 0, so->so_proto->pr_usrreqs->pru_attach); 1299eeaa8a9SJeffrey Hsu msg.nm_proto = proto; 1309eeaa8a9SJeffrey Hsu msg.nm_ai = ai; 131002c1265SMatthew Dillon error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); 1329eeaa8a9SJeffrey Hsu return (error); 1339eeaa8a9SJeffrey Hsu } 1349eeaa8a9SJeffrey Hsu 135002c1265SMatthew Dillon int 136002c1265SMatthew Dillon so_pru_attach_direct(struct socket *so, int proto, struct pru_attach_info *ai) 137002c1265SMatthew Dillon { 138002c1265SMatthew Dillon struct netmsg_pru_attach msg; 139002c1265SMatthew Dillon netisr_fn_t func = so->so_proto->pr_usrreqs->pru_attach; 140002c1265SMatthew Dillon 141002c1265SMatthew Dillon netmsg_init(&msg.base, so, &netisr_adone_rport, 0, func); 142002c1265SMatthew Dillon msg.base.lmsg.ms_flags &= ~(MSGF_REPLY | MSGF_DONE); 143002c1265SMatthew Dillon msg.base.lmsg.ms_flags |= MSGF_SYNC; 144002c1265SMatthew Dillon msg.nm_proto = proto; 145002c1265SMatthew Dillon msg.nm_ai = ai; 146002c1265SMatthew Dillon func((netmsg_t)&msg); 1470fec1ecdSMatthew Dillon KKASSERT(msg.base.lmsg.ms_flags & MSGF_DONE); 148002c1265SMatthew Dillon return(msg.base.lmsg.ms_error); 149002c1265SMatthew Dillon } 150002c1265SMatthew Dillon 15148e7b118SMatthew Dillon /* 15248e7b118SMatthew Dillon * NOTE: If the target port changes the bind operation will deal with it. 15348e7b118SMatthew Dillon */ 1549eeaa8a9SJeffrey Hsu int 1559eeaa8a9SJeffrey Hsu so_pru_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 1569eeaa8a9SJeffrey Hsu { 1579eeaa8a9SJeffrey Hsu struct netmsg_pru_bind msg; 158002c1265SMatthew Dillon int error; 1599eeaa8a9SJeffrey Hsu 160002c1265SMatthew Dillon netmsg_init(&msg.base, so, &curthread->td_msgport, 161002c1265SMatthew Dillon 0, so->so_proto->pr_usrreqs->pru_bind); 1629eeaa8a9SJeffrey Hsu msg.nm_nam = nam; 163002c1265SMatthew Dillon msg.nm_td = td; /* used only for prison_ip() */ 164002c1265SMatthew Dillon error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); 1659eeaa8a9SJeffrey Hsu return (error); 1669eeaa8a9SJeffrey Hsu } 1679eeaa8a9SJeffrey Hsu 1689eeaa8a9SJeffrey Hsu int 1699eeaa8a9SJeffrey Hsu so_pru_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 1709eeaa8a9SJeffrey Hsu { 1719eeaa8a9SJeffrey Hsu struct netmsg_pru_connect msg; 172002c1265SMatthew Dillon int error; 1739eeaa8a9SJeffrey Hsu 174002c1265SMatthew Dillon netmsg_init(&msg.base, so, &curthread->td_msgport, 175002c1265SMatthew Dillon 0, so->so_proto->pr_usrreqs->pru_connect); 1769eeaa8a9SJeffrey Hsu msg.nm_nam = nam; 1779eeaa8a9SJeffrey Hsu msg.nm_td = td; 178002c1265SMatthew Dillon msg.nm_m = NULL; 179002c1265SMatthew Dillon msg.nm_flags = 0; 180002c1265SMatthew Dillon msg.nm_reconnect = 0; 181002c1265SMatthew Dillon error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); 1829eeaa8a9SJeffrey Hsu return (error); 1839eeaa8a9SJeffrey Hsu } 1849eeaa8a9SJeffrey Hsu 1859eeaa8a9SJeffrey Hsu int 1869eeaa8a9SJeffrey Hsu so_pru_connect2(struct socket *so1, struct socket *so2) 1879eeaa8a9SJeffrey Hsu { 1889eeaa8a9SJeffrey Hsu struct netmsg_pru_connect2 msg; 189002c1265SMatthew Dillon int error; 1909eeaa8a9SJeffrey Hsu 191002c1265SMatthew Dillon netmsg_init(&msg.base, so1, &curthread->td_msgport, 192002c1265SMatthew Dillon 0, so1->so_proto->pr_usrreqs->pru_connect2); 1939eeaa8a9SJeffrey Hsu msg.nm_so1 = so1; 1949eeaa8a9SJeffrey Hsu msg.nm_so2 = so2; 195002c1265SMatthew Dillon error = lwkt_domsg(so1->so_port, &msg.base.lmsg, 0); 1969eeaa8a9SJeffrey Hsu return (error); 1979eeaa8a9SJeffrey Hsu } 1989eeaa8a9SJeffrey Hsu 199002c1265SMatthew Dillon /* 200002c1265SMatthew Dillon * WARNING! Synchronous call from user context. Control function may do 201002c1265SMatthew Dillon * copyin/copyout. 202002c1265SMatthew Dillon */ 2039eeaa8a9SJeffrey Hsu int 204002c1265SMatthew Dillon so_pru_control_direct(struct socket *so, u_long cmd, caddr_t data, 205002c1265SMatthew Dillon struct ifnet *ifp) 2069eeaa8a9SJeffrey Hsu { 2079eeaa8a9SJeffrey Hsu struct netmsg_pru_control msg; 208002c1265SMatthew Dillon netisr_fn_t func = so->so_proto->pr_usrreqs->pru_control; 2099eeaa8a9SJeffrey Hsu 210002c1265SMatthew Dillon netmsg_init(&msg.base, so, &netisr_adone_rport, 0, func); 211002c1265SMatthew Dillon msg.base.lmsg.ms_flags &= ~(MSGF_REPLY | MSGF_DONE); 212002c1265SMatthew Dillon msg.base.lmsg.ms_flags |= MSGF_SYNC; 2139eeaa8a9SJeffrey Hsu msg.nm_cmd = cmd; 2149eeaa8a9SJeffrey Hsu msg.nm_data = data; 2159eeaa8a9SJeffrey Hsu msg.nm_ifp = ifp; 216002c1265SMatthew Dillon msg.nm_td = curthread; 217002c1265SMatthew Dillon func((netmsg_t)&msg); 2180fec1ecdSMatthew Dillon KKASSERT(msg.base.lmsg.ms_flags & MSGF_DONE); 219002c1265SMatthew Dillon return(msg.base.lmsg.ms_error); 2209eeaa8a9SJeffrey Hsu } 2219eeaa8a9SJeffrey Hsu 2229eeaa8a9SJeffrey Hsu int 2239eeaa8a9SJeffrey Hsu so_pru_detach(struct socket *so) 2249eeaa8a9SJeffrey Hsu { 2259eeaa8a9SJeffrey Hsu struct netmsg_pru_detach msg; 226002c1265SMatthew Dillon int error; 2279eeaa8a9SJeffrey Hsu 228002c1265SMatthew Dillon netmsg_init(&msg.base, so, &curthread->td_msgport, 229002c1265SMatthew Dillon 0, so->so_proto->pr_usrreqs->pru_detach); 230002c1265SMatthew Dillon error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); 2319eeaa8a9SJeffrey Hsu return (error); 2329eeaa8a9SJeffrey Hsu } 2339eeaa8a9SJeffrey Hsu 234acd31a69SSepherosa Ziehau void 235acd31a69SSepherosa Ziehau so_pru_detach_direct(struct socket *so) 236acd31a69SSepherosa Ziehau { 237acd31a69SSepherosa Ziehau struct netmsg_pru_detach msg; 238acd31a69SSepherosa Ziehau netisr_fn_t func = so->so_proto->pr_usrreqs->pru_detach; 239acd31a69SSepherosa Ziehau 240acd31a69SSepherosa Ziehau netmsg_init(&msg.base, so, &netisr_adone_rport, 0, func); 241acd31a69SSepherosa Ziehau msg.base.lmsg.ms_flags &= ~(MSGF_REPLY | MSGF_DONE); 242acd31a69SSepherosa Ziehau msg.base.lmsg.ms_flags |= MSGF_SYNC; 243acd31a69SSepherosa Ziehau func((netmsg_t)&msg); 244acd31a69SSepherosa Ziehau KKASSERT(msg.base.lmsg.ms_flags & MSGF_DONE); 245acd31a69SSepherosa Ziehau } 246acd31a69SSepherosa Ziehau 2479eeaa8a9SJeffrey Hsu int 2489eeaa8a9SJeffrey Hsu so_pru_disconnect(struct socket *so) 2499eeaa8a9SJeffrey Hsu { 2509eeaa8a9SJeffrey Hsu struct netmsg_pru_disconnect msg; 251002c1265SMatthew Dillon int error; 2529eeaa8a9SJeffrey Hsu 253002c1265SMatthew Dillon netmsg_init(&msg.base, so, &curthread->td_msgport, 254002c1265SMatthew Dillon 0, so->so_proto->pr_usrreqs->pru_disconnect); 255002c1265SMatthew Dillon error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); 2569eeaa8a9SJeffrey Hsu return (error); 2579eeaa8a9SJeffrey Hsu } 2589eeaa8a9SJeffrey Hsu 259acd31a69SSepherosa Ziehau void 260acd31a69SSepherosa Ziehau so_pru_disconnect_direct(struct socket *so) 261acd31a69SSepherosa Ziehau { 262acd31a69SSepherosa Ziehau struct netmsg_pru_disconnect msg; 263acd31a69SSepherosa Ziehau netisr_fn_t func = so->so_proto->pr_usrreqs->pru_disconnect; 264acd31a69SSepherosa Ziehau 265acd31a69SSepherosa Ziehau netmsg_init(&msg.base, so, &netisr_adone_rport, 0, func); 266acd31a69SSepherosa Ziehau msg.base.lmsg.ms_flags &= ~(MSGF_REPLY | MSGF_DONE); 267acd31a69SSepherosa Ziehau msg.base.lmsg.ms_flags |= MSGF_SYNC; 268acd31a69SSepherosa Ziehau func((netmsg_t)&msg); 269acd31a69SSepherosa Ziehau KKASSERT(msg.base.lmsg.ms_flags & MSGF_DONE); 270acd31a69SSepherosa Ziehau } 271acd31a69SSepherosa Ziehau 2729eeaa8a9SJeffrey Hsu int 2739eeaa8a9SJeffrey Hsu so_pru_listen(struct socket *so, struct thread *td) 2749eeaa8a9SJeffrey Hsu { 2759eeaa8a9SJeffrey Hsu struct netmsg_pru_listen msg; 276002c1265SMatthew Dillon int error; 2779eeaa8a9SJeffrey Hsu 278002c1265SMatthew Dillon netmsg_init(&msg.base, so, &curthread->td_msgport, 279002c1265SMatthew Dillon 0, so->so_proto->pr_usrreqs->pru_listen); 2809eeaa8a9SJeffrey Hsu msg.nm_td = td; /* used only for prison_ip() XXX JH */ 281002c1265SMatthew Dillon error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); 2829eeaa8a9SJeffrey Hsu return (error); 2839eeaa8a9SJeffrey Hsu } 2849eeaa8a9SJeffrey Hsu 2859eeaa8a9SJeffrey Hsu int 2869eeaa8a9SJeffrey Hsu so_pru_peeraddr(struct socket *so, struct sockaddr **nam) 2879eeaa8a9SJeffrey Hsu { 2889eeaa8a9SJeffrey Hsu struct netmsg_pru_peeraddr msg; 289002c1265SMatthew Dillon int error; 2909eeaa8a9SJeffrey Hsu 291002c1265SMatthew Dillon netmsg_init(&msg.base, so, &curthread->td_msgport, 292002c1265SMatthew Dillon 0, so->so_proto->pr_usrreqs->pru_peeraddr); 2939eeaa8a9SJeffrey Hsu msg.nm_nam = nam; 294002c1265SMatthew Dillon error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); 2959eeaa8a9SJeffrey Hsu return (error); 2969eeaa8a9SJeffrey Hsu } 2979eeaa8a9SJeffrey Hsu 2989eeaa8a9SJeffrey Hsu int 2999eeaa8a9SJeffrey Hsu so_pru_rcvd(struct socket *so, int flags) 3009eeaa8a9SJeffrey Hsu { 3019eeaa8a9SJeffrey Hsu struct netmsg_pru_rcvd msg; 302002c1265SMatthew Dillon int error; 3039eeaa8a9SJeffrey Hsu 304002c1265SMatthew Dillon netmsg_init(&msg.base, so, &curthread->td_msgport, 305002c1265SMatthew Dillon 0, so->so_proto->pr_usrreqs->pru_rcvd); 3069eeaa8a9SJeffrey Hsu msg.nm_flags = flags; 30796c6eb29SSepherosa Ziehau msg.nm_pru_flags = 0; 308002c1265SMatthew Dillon error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); 3099eeaa8a9SJeffrey Hsu return (error); 3109eeaa8a9SJeffrey Hsu } 3119eeaa8a9SJeffrey Hsu 31296c6eb29SSepherosa Ziehau void 31396c6eb29SSepherosa Ziehau so_pru_rcvd_async(struct socket *so) 31496c6eb29SSepherosa Ziehau { 31596c6eb29SSepherosa Ziehau lwkt_msg_t lmsg = &so->so_rcvd_msg.base.lmsg; 31696c6eb29SSepherosa Ziehau 31796c6eb29SSepherosa Ziehau KASSERT(so->so_proto->pr_flags & PR_ASYNC_RCVD, 31896c6eb29SSepherosa Ziehau ("async pru_rcvd is not supported")); 31996c6eb29SSepherosa Ziehau 3206999cd81SMatthew Dillon /* 3216999cd81SMatthew Dillon * WARNING! Spinlock is a bit dodgy, use hacked up sendmsg 3226999cd81SMatthew Dillon * to avoid deadlocking. 3236999cd81SMatthew Dillon */ 32496c6eb29SSepherosa Ziehau spin_lock(&so->so_rcvd_spin); 325a77d3dfeSSepherosa Ziehau if ((so->so_rcvd_msg.nm_pru_flags & PRUR_DEAD) == 0) { 3266999cd81SMatthew Dillon if (lmsg->ms_flags & MSGF_DONE) { 3276999cd81SMatthew Dillon lwkt_sendmsg_stage1(so->so_port, lmsg); 3286999cd81SMatthew Dillon spin_unlock(&so->so_rcvd_spin); 3296999cd81SMatthew Dillon lwkt_sendmsg_stage2(so->so_port, lmsg); 3306999cd81SMatthew Dillon } else { 3316999cd81SMatthew Dillon spin_unlock(&so->so_rcvd_spin); 3326999cd81SMatthew Dillon } 333a77d3dfeSSepherosa Ziehau } else { 33496c6eb29SSepherosa Ziehau spin_unlock(&so->so_rcvd_spin); 33596c6eb29SSepherosa Ziehau } 3366999cd81SMatthew Dillon } 33796c6eb29SSepherosa Ziehau 3389eeaa8a9SJeffrey Hsu int 3399eeaa8a9SJeffrey Hsu so_pru_rcvoob(struct socket *so, struct mbuf *m, int flags) 3409eeaa8a9SJeffrey Hsu { 3419eeaa8a9SJeffrey Hsu struct netmsg_pru_rcvoob msg; 342002c1265SMatthew Dillon int error; 3439eeaa8a9SJeffrey Hsu 344002c1265SMatthew Dillon netmsg_init(&msg.base, so, &curthread->td_msgport, 345002c1265SMatthew Dillon 0, so->so_proto->pr_usrreqs->pru_rcvoob); 3469eeaa8a9SJeffrey Hsu msg.nm_m = m; 3479eeaa8a9SJeffrey Hsu msg.nm_flags = flags; 348002c1265SMatthew Dillon error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); 3499eeaa8a9SJeffrey Hsu return (error); 3509eeaa8a9SJeffrey Hsu } 3519eeaa8a9SJeffrey Hsu 35248e7b118SMatthew Dillon /* 35348e7b118SMatthew Dillon * NOTE: If the target port changes the implied connect will deal with it. 35448e7b118SMatthew Dillon */ 3559eeaa8a9SJeffrey Hsu int 35648e7b118SMatthew Dillon so_pru_send(struct socket *so, int flags, struct mbuf *m, 35748e7b118SMatthew Dillon struct sockaddr *addr, struct mbuf *control, struct thread *td) 3589eeaa8a9SJeffrey Hsu { 3599eeaa8a9SJeffrey Hsu struct netmsg_pru_send msg; 360002c1265SMatthew Dillon int error; 3619eeaa8a9SJeffrey Hsu 362002c1265SMatthew Dillon netmsg_init(&msg.base, so, &curthread->td_msgport, 363002c1265SMatthew Dillon 0, so->so_proto->pr_usrreqs->pru_send); 3649eeaa8a9SJeffrey Hsu msg.nm_flags = flags; 3659eeaa8a9SJeffrey Hsu msg.nm_m = m; 3669eeaa8a9SJeffrey Hsu msg.nm_addr = addr; 3679eeaa8a9SJeffrey Hsu msg.nm_control = control; 3689eeaa8a9SJeffrey Hsu msg.nm_td = td; 369002c1265SMatthew Dillon error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); 3709eeaa8a9SJeffrey Hsu return (error); 3719eeaa8a9SJeffrey Hsu } 3729eeaa8a9SJeffrey Hsu 373f2a3782eSSepherosa Ziehau void 374f2a3782eSSepherosa Ziehau so_pru_sync(struct socket *so) 375f2a3782eSSepherosa Ziehau { 376f2a3782eSSepherosa Ziehau struct netmsg_base msg; 377f2a3782eSSepherosa Ziehau 378f2a3782eSSepherosa Ziehau netmsg_init(&msg, so, &curthread->td_msgport, 0, 37979f504caSSepherosa Ziehau netmsg_sync_handler); 380f2a3782eSSepherosa Ziehau lwkt_domsg(so->so_port, &msg.lmsg, 0); 381f2a3782eSSepherosa Ziehau } 382f2a3782eSSepherosa Ziehau 3830ad8e15eSSepherosa Ziehau void 3840ad8e15eSSepherosa Ziehau so_pru_send_async(struct socket *so, int flags, struct mbuf *m, 3857b7dc575SSepherosa Ziehau struct sockaddr *addr0, struct mbuf *control, struct thread *td) 3860ad8e15eSSepherosa Ziehau { 3870ad8e15eSSepherosa Ziehau struct netmsg_pru_send *msg; 3887b7dc575SSepherosa Ziehau struct sockaddr *addr = NULL; 3890ad8e15eSSepherosa Ziehau 3902ef7b293SSepherosa Ziehau KASSERT(so->so_proto->pr_flags & PR_ASYNC_SEND, 391ed20d0e3SSascha Wildner ("async pru_send is not supported")); 3922ef7b293SSepherosa Ziehau 3937b7dc575SSepherosa Ziehau flags |= PRUS_NOREPLY; 3947b7dc575SSepherosa Ziehau if (addr0 != NULL) { 3957b7dc575SSepherosa Ziehau addr = kmalloc(addr0->sa_len, M_SONAME, M_WAITOK); 3967b7dc575SSepherosa Ziehau memcpy(addr, addr0, addr0->sa_len); 3977b7dc575SSepherosa Ziehau flags |= PRUS_FREEADDR; 3987b7dc575SSepherosa Ziehau } 3997b7dc575SSepherosa Ziehau 4000ad8e15eSSepherosa Ziehau msg = &m->m_hdr.mh_sndmsg; 4010ad8e15eSSepherosa Ziehau netmsg_init(&msg->base, so, &netisr_apanic_rport, 4020ad8e15eSSepherosa Ziehau 0, so->so_proto->pr_usrreqs->pru_send); 4037b7dc575SSepherosa Ziehau msg->nm_flags = flags; 4040ad8e15eSSepherosa Ziehau msg->nm_m = m; 4050ad8e15eSSepherosa Ziehau msg->nm_addr = addr; 4060ad8e15eSSepherosa Ziehau msg->nm_control = control; 4070ad8e15eSSepherosa Ziehau msg->nm_td = td; 4080ad8e15eSSepherosa Ziehau lwkt_sendmsg(so->so_port, &msg->base.lmsg); 4090ad8e15eSSepherosa Ziehau } 4100ad8e15eSSepherosa Ziehau 4119eeaa8a9SJeffrey Hsu int 4129eeaa8a9SJeffrey Hsu so_pru_sense(struct socket *so, struct stat *sb) 4139eeaa8a9SJeffrey Hsu { 4149eeaa8a9SJeffrey Hsu struct netmsg_pru_sense msg; 415002c1265SMatthew Dillon int error; 4169eeaa8a9SJeffrey Hsu 417002c1265SMatthew Dillon netmsg_init(&msg.base, so, &curthread->td_msgport, 418002c1265SMatthew Dillon 0, so->so_proto->pr_usrreqs->pru_sense); 4199eeaa8a9SJeffrey Hsu msg.nm_stat = sb; 420002c1265SMatthew Dillon error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); 4219eeaa8a9SJeffrey Hsu return (error); 4229eeaa8a9SJeffrey Hsu } 4239eeaa8a9SJeffrey Hsu 4249eeaa8a9SJeffrey Hsu int 4259eeaa8a9SJeffrey Hsu so_pru_shutdown(struct socket *so) 4269eeaa8a9SJeffrey Hsu { 4279eeaa8a9SJeffrey Hsu struct netmsg_pru_shutdown msg; 428002c1265SMatthew Dillon int error; 4299eeaa8a9SJeffrey Hsu 430002c1265SMatthew Dillon netmsg_init(&msg.base, so, &curthread->td_msgport, 431002c1265SMatthew Dillon 0, so->so_proto->pr_usrreqs->pru_shutdown); 432002c1265SMatthew Dillon error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); 4339eeaa8a9SJeffrey Hsu return (error); 4349eeaa8a9SJeffrey Hsu } 4359eeaa8a9SJeffrey Hsu 4369eeaa8a9SJeffrey Hsu int 4379eeaa8a9SJeffrey Hsu so_pru_sockaddr(struct socket *so, struct sockaddr **nam) 4389eeaa8a9SJeffrey Hsu { 4399eeaa8a9SJeffrey Hsu struct netmsg_pru_sockaddr msg; 440002c1265SMatthew Dillon int error; 4419eeaa8a9SJeffrey Hsu 442002c1265SMatthew Dillon netmsg_init(&msg.base, so, &curthread->td_msgport, 443002c1265SMatthew Dillon 0, so->so_proto->pr_usrreqs->pru_sockaddr); 4449eeaa8a9SJeffrey Hsu msg.nm_nam = nam; 445002c1265SMatthew Dillon error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); 4469eeaa8a9SJeffrey Hsu return (error); 4479eeaa8a9SJeffrey Hsu } 4489eeaa8a9SJeffrey Hsu 4499eeaa8a9SJeffrey Hsu int 450002c1265SMatthew Dillon so_pr_ctloutput(struct socket *so, struct sockopt *sopt) 4519eeaa8a9SJeffrey Hsu { 452002c1265SMatthew Dillon struct netmsg_pr_ctloutput msg; 4539eeaa8a9SJeffrey Hsu int error; 4549eeaa8a9SJeffrey Hsu 455792239dfSAggelos Economopoulos KKASSERT(!sopt->sopt_val || kva_p(sopt->sopt_val)); 456002c1265SMatthew Dillon netmsg_init(&msg.base, so, &curthread->td_msgport, 457002c1265SMatthew Dillon 0, so->so_proto->pr_ctloutput); 4589eeaa8a9SJeffrey Hsu msg.nm_sopt = sopt; 459002c1265SMatthew Dillon error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); 4609eeaa8a9SJeffrey Hsu return (error); 4619eeaa8a9SJeffrey Hsu } 4629eeaa8a9SJeffrey Hsu 4639eeaa8a9SJeffrey Hsu /* 464e3873585SSepherosa Ziehau * Protocol control input, typically via icmp. 465e3873585SSepherosa Ziehau * 466e3873585SSepherosa Ziehau * If the protocol pr_ctlport is not NULL we call it to figure out the 467e3873585SSepherosa Ziehau * protocol port. If NULL is returned we can just return, otherwise 468e3873585SSepherosa Ziehau * we issue a netmsg to call pr_ctlinput in the proper thread. 469e3873585SSepherosa Ziehau * 470e3873585SSepherosa Ziehau * This must be done synchronously as arg and/or extra may point to 471e3873585SSepherosa Ziehau * temporary data. 472e3873585SSepherosa Ziehau */ 473e3873585SSepherosa Ziehau void 474e3873585SSepherosa Ziehau so_pru_ctlinput(struct protosw *pr, int cmd, struct sockaddr *arg, void *extra) 475e3873585SSepherosa Ziehau { 476e3873585SSepherosa Ziehau struct netmsg_pru_ctlinput msg; 477e3873585SSepherosa Ziehau lwkt_port_t port; 478e3873585SSepherosa Ziehau 479e3873585SSepherosa Ziehau if (pr->pr_ctlport == NULL) 480e3873585SSepherosa Ziehau return; 481e3873585SSepherosa Ziehau KKASSERT(pr->pr_ctlinput != NULL); 482e3873585SSepherosa Ziehau port = pr->pr_ctlport(cmd, arg, extra); 483e3873585SSepherosa Ziehau if (port == NULL) 484e3873585SSepherosa Ziehau return; 485002c1265SMatthew Dillon netmsg_init(&msg.base, NULL, &curthread->td_msgport, 486002c1265SMatthew Dillon 0, pr->pr_ctlinput); 487e3873585SSepherosa Ziehau msg.nm_cmd = cmd; 488e3873585SSepherosa Ziehau msg.nm_arg = arg; 489e3873585SSepherosa Ziehau msg.nm_extra = extra; 490002c1265SMatthew Dillon lwkt_domsg(port, &msg.base.lmsg, 0); 491e3873585SSepherosa Ziehau } 492e3873585SSepherosa Ziehau 493e3873585SSepherosa Ziehau /* 494b44419cbSMatthew Dillon * If we convert all the protosw pr_ functions for all the protocols 495b44419cbSMatthew Dillon * to take a message directly, this layer can go away. For the moment 496b44419cbSMatthew Dillon * our dispatcher ignores the return value, but since we are handling 497b44419cbSMatthew Dillon * the replymsg ourselves we return EASYNC by convention. 4989eeaa8a9SJeffrey Hsu */ 4994402d8a2SMatthew Dillon 5004402d8a2SMatthew Dillon /* 501b44419cbSMatthew Dillon * Handle a predicate event request. This function is only called once 502b44419cbSMatthew Dillon * when the predicate message queueing request is received. 5039eeaa8a9SJeffrey Hsu */ 5044599cf19SMatthew Dillon void 505002c1265SMatthew Dillon netmsg_so_notify(netmsg_t msg) 5069eeaa8a9SJeffrey Hsu { 507e2b148c6SMatthew Dillon struct lwkt_token *tok; 5086d49aa6fSMatthew Dillon struct signalsockbuf *ssb; 509c1d0003cSJeffrey Hsu 510002c1265SMatthew Dillon ssb = (msg->notify.nm_etype & NM_REVENT) ? 511002c1265SMatthew Dillon &msg->base.nm_so->so_rcv : 512002c1265SMatthew Dillon &msg->base.nm_so->so_snd; 513c1d0003cSJeffrey Hsu 514b44419cbSMatthew Dillon /* 515b44419cbSMatthew Dillon * Reply immediately if the event has occured, otherwise queue the 516b44419cbSMatthew Dillon * request. 517e2b148c6SMatthew Dillon * 518e2b148c6SMatthew Dillon * NOTE: Socket can change if this is an accept predicate so cache 519e2b148c6SMatthew Dillon * the token. 520b44419cbSMatthew Dillon */ 521e2b148c6SMatthew Dillon tok = lwkt_token_pool_lookup(msg->base.nm_so); 522e2b148c6SMatthew Dillon lwkt_gettoken(tok); 523002c1265SMatthew Dillon if (msg->notify.nm_predicate(&msg->notify)) { 524e2b148c6SMatthew Dillon lwkt_reltoken(tok); 525002c1265SMatthew Dillon lwkt_replymsg(&msg->base.lmsg, 526002c1265SMatthew Dillon msg->base.lmsg.ms_error); 527b44419cbSMatthew Dillon } else { 528002c1265SMatthew Dillon TAILQ_INSERT_TAIL(&ssb->ssb_kq.ki_mlist, &msg->notify, nm_list); 52914343ad3SMatthew Dillon atomic_set_int(&ssb->ssb_flags, SSB_MEVENT); 530e2b148c6SMatthew Dillon lwkt_reltoken(tok); 531c1d0003cSJeffrey Hsu } 5324599cf19SMatthew Dillon } 5334599cf19SMatthew Dillon 5344599cf19SMatthew Dillon /* 5354599cf19SMatthew Dillon * Called by doio when trying to abort a netmsg_so_notify message. 5364599cf19SMatthew Dillon * Unlike the other functions this one is dispatched directly by 5374599cf19SMatthew Dillon * the LWKT subsystem, so it takes a lwkt_msg_t as an argument. 538ebe43e15SMatthew Dillon * 539ebe43e15SMatthew Dillon * The original message, lmsg, is under the control of the caller and 540ebe43e15SMatthew Dillon * will not be destroyed until we return so we can safely reference it 541ebe43e15SMatthew Dillon * in our synchronous abort request. 542ebe43e15SMatthew Dillon * 543ebe43e15SMatthew Dillon * This part of the abort request occurs on the originating cpu which 544ebe43e15SMatthew Dillon * means we may race the message flags and the original message may 545ebe43e15SMatthew Dillon * not even have been processed by the target cpu yet. 5464599cf19SMatthew Dillon */ 5474599cf19SMatthew Dillon void 5484599cf19SMatthew Dillon netmsg_so_notify_doabort(lwkt_msg_t lmsg) 5494599cf19SMatthew Dillon { 5504599cf19SMatthew Dillon struct netmsg_so_notify_abort msg; 5514599cf19SMatthew Dillon 552ebe43e15SMatthew Dillon if ((lmsg->ms_flags & (MSGF_DONE | MSGF_REPLY)) == 0) { 553002c1265SMatthew Dillon netmsg_init(&msg.base, NULL, &curthread->td_msgport, 55448e7b118SMatthew Dillon 0, netmsg_so_notify_abort); 5554599cf19SMatthew Dillon msg.nm_notifymsg = (void *)lmsg; 556002c1265SMatthew Dillon lwkt_domsg(lmsg->ms_target_port, &msg.base.lmsg, 0); 5574599cf19SMatthew Dillon } 558b44419cbSMatthew Dillon } 559b44419cbSMatthew Dillon 560b44419cbSMatthew Dillon /* 561b44419cbSMatthew Dillon * Predicate requests can be aborted. This function is only called once 562b44419cbSMatthew Dillon * and will interlock against processing/reply races (since such races 563b44419cbSMatthew Dillon * occur on the same thread that controls the port where the abort is 564b44419cbSMatthew Dillon * requeued). 565ebe43e15SMatthew Dillon * 566ebe43e15SMatthew Dillon * This part of the abort request occurs on the target cpu. The message 567ebe43e15SMatthew Dillon * flags must be tested again in case the test that we did on the 568ebe43e15SMatthew Dillon * originating cpu raced. Since messages are handled in sequence, the 569ebe43e15SMatthew Dillon * original message will have already been handled by the loop and either 570ebe43e15SMatthew Dillon * replied to or queued. 571ebe43e15SMatthew Dillon * 572ebe43e15SMatthew Dillon * We really only need to interlock with MSGF_REPLY (a bit that is set on 573ebe43e15SMatthew Dillon * our cpu when we reply). Note that MSGF_DONE is not set until the 574ebe43e15SMatthew Dillon * reply reaches the originating cpu. Test both bits anyway. 575b44419cbSMatthew Dillon */ 5764599cf19SMatthew Dillon void 577002c1265SMatthew Dillon netmsg_so_notify_abort(netmsg_t msg) 578b44419cbSMatthew Dillon { 579002c1265SMatthew Dillon struct netmsg_so_notify_abort *abrtmsg = &msg->notify_abort; 580002c1265SMatthew Dillon struct netmsg_so_notify *nmsg = abrtmsg->nm_notifymsg; 5816d49aa6fSMatthew Dillon struct signalsockbuf *ssb; 582b44419cbSMatthew Dillon 5834599cf19SMatthew Dillon /* 5844599cf19SMatthew Dillon * The original notify message is not destroyed until after the 585ebe43e15SMatthew Dillon * abort request is returned, so we can check its state. 5864599cf19SMatthew Dillon */ 587e2b148c6SMatthew Dillon lwkt_getpooltoken(nmsg->base.nm_so); 588002c1265SMatthew Dillon if ((nmsg->base.lmsg.ms_flags & (MSGF_DONE | MSGF_REPLY)) == 0) { 589002c1265SMatthew Dillon ssb = (nmsg->nm_etype & NM_REVENT) ? 590002c1265SMatthew Dillon &nmsg->base.nm_so->so_rcv : 591002c1265SMatthew Dillon &nmsg->base.nm_so->so_snd; 592002c1265SMatthew Dillon TAILQ_REMOVE(&ssb->ssb_kq.ki_mlist, nmsg, nm_list); 593e2b148c6SMatthew Dillon lwkt_relpooltoken(nmsg->base.nm_so); 594002c1265SMatthew Dillon lwkt_replymsg(&nmsg->base.lmsg, EINTR); 595e2b148c6SMatthew Dillon } else { 596e2b148c6SMatthew Dillon lwkt_relpooltoken(nmsg->base.nm_so); 5974599cf19SMatthew Dillon } 5984599cf19SMatthew Dillon 5994599cf19SMatthew Dillon /* 6004599cf19SMatthew Dillon * Reply to the abort message 6014599cf19SMatthew Dillon */ 602002c1265SMatthew Dillon lwkt_replymsg(&abrtmsg->base.lmsg, 0); 603b44419cbSMatthew Dillon } 60496c6eb29SSepherosa Ziehau 60596c6eb29SSepherosa Ziehau void 60696c6eb29SSepherosa Ziehau so_async_rcvd_reply(struct socket *so) 60796c6eb29SSepherosa Ziehau { 6086999cd81SMatthew Dillon /* 6096999cd81SMatthew Dillon * Spinlock safe, reply runs to degenerate lwkt_null_replyport() 6106999cd81SMatthew Dillon */ 61196c6eb29SSepherosa Ziehau spin_lock(&so->so_rcvd_spin); 61296c6eb29SSepherosa Ziehau lwkt_replymsg(&so->so_rcvd_msg.base.lmsg, 0); 61396c6eb29SSepherosa Ziehau spin_unlock(&so->so_rcvd_spin); 61496c6eb29SSepherosa Ziehau } 61596c6eb29SSepherosa Ziehau 61696c6eb29SSepherosa Ziehau void 61796c6eb29SSepherosa Ziehau so_async_rcvd_drop(struct socket *so) 61896c6eb29SSepherosa Ziehau { 61996c6eb29SSepherosa Ziehau lwkt_msg_t lmsg = &so->so_rcvd_msg.base.lmsg; 62096c6eb29SSepherosa Ziehau 6216999cd81SMatthew Dillon /* 622f65f767cSSepherosa Ziehau * Spinlock safe, drop runs to degenerate lwkt_spin_dropmsg() 6236999cd81SMatthew Dillon */ 62496c6eb29SSepherosa Ziehau spin_lock(&so->so_rcvd_spin); 625f65f767cSSepherosa Ziehau so->so_rcvd_msg.nm_pru_flags |= PRUR_DEAD; 626f65f767cSSepherosa Ziehau again: 627*901b9bd6SSepherosa Ziehau lwkt_dropmsg(lmsg); 6286999cd81SMatthew Dillon if ((lmsg->ms_flags & MSGF_DONE) == 0) { 629f65f767cSSepherosa Ziehau ++async_rcvd_drop_race; 630f65f767cSSepherosa Ziehau ssleep(so, &so->so_rcvd_spin, 0, "soadrop", 1); 631d4cbc551SSepherosa Ziehau goto again; 6326999cd81SMatthew Dillon } 633f65f767cSSepherosa Ziehau spin_unlock(&so->so_rcvd_spin); 63496c6eb29SSepherosa Ziehau } 635