| Commit | Line | Data |
|---|---|---|
| 9eeaa8a9 | 1 | /* |
| 66d6c637 JH |
2 | * Copyright (c) 2003, 2004 Jeffrey M. Hsu. All rights reserved. |
| 3 | * Copyright (c) 2003, 2004 The DragonFly Project. All rights reserved. | |
| 4 | * | |
| 5 | * This code is derived from software contributed to The DragonFly Project | |
| 6 | * by Jeffrey M. Hsu. | |
| 7 | * | |
| 9eeaa8a9 JH |
8 | * Redistribution and use in source and binary forms, with or without |
| 9 | * modification, are permitted provided that the following conditions | |
| 10 | * are met: | |
| 11 | * 1. Redistributions of source code must retain the above copyright | |
| 12 | * notice, this list of conditions and the following disclaimer. | |
| 13 | * 2. Redistributions in binary form must reproduce the above copyright | |
| 14 | * notice, this list of conditions and the following disclaimer in the | |
| 15 | * documentation and/or other materials provided with the distribution. | |
| 66d6c637 JH |
16 | * 3. Neither the name of The DragonFly Project nor the names of its |
| 17 | * contributors may be used to endorse or promote products derived | |
| 18 | * from this software without specific, prior written permission. | |
| 9eeaa8a9 | 19 | * |
| 66d6c637 JH |
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
| 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
| 24 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
| 25 | * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
| 26 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 27 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
| 28 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
| 29 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |
| 30 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 31 | * SUCH DAMAGE. | |
| 32 | * | |
| e3873585 | 33 | * $DragonFly: src/sys/kern/uipc_msg.c,v 1.26 2008/10/27 02:56:30 sephe Exp $ |
| 9eeaa8a9 JH |
34 | */ |
| 35 | ||
| 9eeaa8a9 JH |
36 | #include <sys/param.h> |
| 37 | #include <sys/systm.h> | |
| e71a125f | 38 | #include <sys/kernel.h> |
| 9eeaa8a9 | 39 | #include <sys/msgport.h> |
| 9eeaa8a9 JH |
40 | #include <sys/protosw.h> |
| 41 | #include <sys/socket.h> | |
| 42 | #include <sys/socketvar.h> | |
| 43 | #include <sys/socketops.h> | |
| 44 | #include <sys/thread.h> | |
| d3266d67 MD |
45 | #include <sys/thread2.h> |
| 46 | #include <sys/msgport2.h> | |
| 0ad8e15e | 47 | #include <sys/mbuf.h> |
| de0003fe | 48 | #include <vm/pmap.h> |
| 4599cf19 | 49 | #include <net/netmsg2.h> |
| 9eeaa8a9 JH |
50 | |
| 51 | #include <net/netisr.h> | |
| 52 | #include <net/netmsg.h> | |
| 53 | ||
| 4402d8a2 | 54 | /* |
| c3d495a1 MD |
55 | * Abort a socket and free it. Called from soabort() only. soabort() |
| 56 | * got a ref on the socket which we must free on reply. | |
| 4402d8a2 MD |
57 | */ |
| 58 | void | |
| 9eeaa8a9 JH |
59 | so_pru_abort(struct socket *so) |
| 60 | { | |
| 9eeaa8a9 | 61 | struct netmsg_pru_abort msg; |
| 9eeaa8a9 | 62 | |
| 002c1265 MD |
63 | netmsg_init(&msg.base, so, &curthread->td_msgport, |
| 64 | 0, so->so_proto->pr_usrreqs->pru_abort); | |
| 65 | (void)lwkt_domsg(so->so_port, &msg.base.lmsg, 0); | |
| c3d495a1 | 66 | sofree(msg.base.nm_so); |
| 4402d8a2 MD |
67 | } |
| 68 | ||
| 69 | /* | |
| 9116be8e | 70 | * Abort a socket and free it, asynchronously. Called from |
| c3d495a1 MD |
71 | * soaborta() only. soaborta() got a ref on the socket which we must |
| 72 | * free on reply. | |
| 4402d8a2 MD |
73 | */ |
| 74 | void | |
| 75 | so_pru_aborta(struct socket *so) | |
| 76 | { | |
| 77 | struct netmsg_pru_abort *msg; | |
| 4402d8a2 MD |
78 | |
| 79 | msg = kmalloc(sizeof(*msg), M_LWKTMSG, M_WAITOK | M_ZERO); | |
| c3d495a1 | 80 | netmsg_init(&msg->base, so, &netisr_afree_free_so_rport, |
| 002c1265 MD |
81 | 0, so->so_proto->pr_usrreqs->pru_abort); |
| 82 | lwkt_sendmsg(so->so_port, &msg->base.lmsg); | |
| 9eeaa8a9 JH |
83 | } |
| 84 | ||
| fd86a41c SZ |
85 | /* |
| 86 | * Abort a socket and free it. Called from soabort_oncpu() only. | |
| 87 | * Caller must make sure that the current CPU is inpcb's owner CPU. | |
| fd86a41c SZ |
88 | */ |
| 89 | void | |
| 90 | so_pru_abort_oncpu(struct socket *so) | |
| 91 | { | |
| 002c1265 MD |
92 | struct netmsg_pru_abort msg; |
| 93 | netisr_fn_t func = so->so_proto->pr_usrreqs->pru_abort; | |
| 94 | ||
| 95 | netmsg_init(&msg.base, so, &netisr_adone_rport, 0, func); | |
| 96 | msg.base.lmsg.ms_flags &= ~(MSGF_REPLY | MSGF_DONE); | |
| 97 | msg.base.lmsg.ms_flags |= MSGF_SYNC; | |
| 98 | func((netmsg_t)&msg); | |
| 0fec1ecd | 99 | KKASSERT(msg.base.lmsg.ms_flags & MSGF_DONE); |
| c3d495a1 | 100 | sofree(msg.base.nm_so); |
| fd86a41c SZ |
101 | } |
| 102 | ||
| 002c1265 MD |
103 | /* |
| 104 | * WARNING! Synchronous call from user context | |
| 105 | */ | |
| 9eeaa8a9 | 106 | int |
| 002c1265 | 107 | so_pru_accept_direct(struct socket *so, struct sockaddr **nam) |
| 9eeaa8a9 | 108 | { |
| 9eeaa8a9 | 109 | struct netmsg_pru_accept msg; |
| 002c1265 | 110 | netisr_fn_t func = so->so_proto->pr_usrreqs->pru_accept; |
| 9eeaa8a9 | 111 | |
| 002c1265 MD |
112 | netmsg_init(&msg.base, so, &netisr_adone_rport, 0, func); |
| 113 | msg.base.lmsg.ms_flags &= ~(MSGF_REPLY | MSGF_DONE); | |
| 114 | msg.base.lmsg.ms_flags |= MSGF_SYNC; | |
| 9eeaa8a9 | 115 | msg.nm_nam = nam; |
| 002c1265 | 116 | func((netmsg_t)&msg); |
| 0fec1ecd | 117 | KKASSERT(msg.base.lmsg.ms_flags & MSGF_DONE); |
| 002c1265 | 118 | return(msg.base.lmsg.ms_error); |
| 9eeaa8a9 JH |
119 | } |
| 120 | ||
| 121 | int | |
| 122 | so_pru_attach(struct socket *so, int proto, struct pru_attach_info *ai) | |
| 123 | { | |
| 9eeaa8a9 | 124 | struct netmsg_pru_attach msg; |
| 002c1265 | 125 | int error; |
| 9eeaa8a9 | 126 | |
| 002c1265 MD |
127 | netmsg_init(&msg.base, so, &curthread->td_msgport, |
| 128 | 0, so->so_proto->pr_usrreqs->pru_attach); | |
| 9eeaa8a9 JH |
129 | msg.nm_proto = proto; |
| 130 | msg.nm_ai = ai; | |
| 002c1265 | 131 | error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); |
| 9eeaa8a9 JH |
132 | return (error); |
| 133 | } | |
| 134 | ||
| 002c1265 MD |
135 | int |
| 136 | so_pru_attach_direct(struct socket *so, int proto, struct pru_attach_info *ai) | |
| 137 | { | |
| 138 | struct netmsg_pru_attach msg; | |
| 139 | netisr_fn_t func = so->so_proto->pr_usrreqs->pru_attach; | |
| 140 | ||
| 141 | netmsg_init(&msg.base, so, &netisr_adone_rport, 0, func); | |
| 142 | msg.base.lmsg.ms_flags &= ~(MSGF_REPLY | MSGF_DONE); | |
| 143 | msg.base.lmsg.ms_flags |= MSGF_SYNC; | |
| 144 | msg.nm_proto = proto; | |
| 145 | msg.nm_ai = ai; | |
| 146 | func((netmsg_t)&msg); | |
| 0fec1ecd | 147 | KKASSERT(msg.base.lmsg.ms_flags & MSGF_DONE); |
| 002c1265 MD |
148 | return(msg.base.lmsg.ms_error); |
| 149 | } | |
| 150 | ||
| 48e7b118 MD |
151 | /* |
| 152 | * NOTE: If the target port changes the bind operation will deal with it. | |
| 153 | */ | |
| 9eeaa8a9 JH |
154 | int |
| 155 | so_pru_bind(struct socket *so, struct sockaddr *nam, struct thread *td) | |
| 156 | { | |
| 9eeaa8a9 | 157 | struct netmsg_pru_bind msg; |
| 002c1265 | 158 | int error; |
| 9eeaa8a9 | 159 | |
| 002c1265 MD |
160 | netmsg_init(&msg.base, so, &curthread->td_msgport, |
| 161 | 0, so->so_proto->pr_usrreqs->pru_bind); | |
| 9eeaa8a9 | 162 | msg.nm_nam = nam; |
| 002c1265 MD |
163 | msg.nm_td = td; /* used only for prison_ip() */ |
| 164 | error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); | |
| 9eeaa8a9 JH |
165 | return (error); |
| 166 | } | |
| 167 | ||
| 168 | int | |
| 169 | so_pru_connect(struct socket *so, struct sockaddr *nam, struct thread *td) | |
| 170 | { | |
| 9eeaa8a9 | 171 | struct netmsg_pru_connect msg; |
| 002c1265 | 172 | int error; |
| 9eeaa8a9 | 173 | |
| 002c1265 MD |
174 | netmsg_init(&msg.base, so, &curthread->td_msgport, |
| 175 | 0, so->so_proto->pr_usrreqs->pru_connect); | |
| 9eeaa8a9 JH |
176 | msg.nm_nam = nam; |
| 177 | msg.nm_td = td; | |
| 002c1265 MD |
178 | msg.nm_m = NULL; |
| 179 | msg.nm_flags = 0; | |
| 180 | msg.nm_reconnect = 0; | |
| 181 | error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); | |
| 9eeaa8a9 JH |
182 | return (error); |
| 183 | } | |
| 184 | ||
| 185 | int | |
| 186 | so_pru_connect2(struct socket *so1, struct socket *so2) | |
| 187 | { | |
| 9eeaa8a9 | 188 | struct netmsg_pru_connect2 msg; |
| 002c1265 | 189 | int error; |
| 9eeaa8a9 | 190 | |
| 002c1265 MD |
191 | netmsg_init(&msg.base, so1, &curthread->td_msgport, |
| 192 | 0, so1->so_proto->pr_usrreqs->pru_connect2); | |
| 9eeaa8a9 JH |
193 | msg.nm_so1 = so1; |
| 194 | msg.nm_so2 = so2; | |
| 002c1265 | 195 | error = lwkt_domsg(so1->so_port, &msg.base.lmsg, 0); |
| 9eeaa8a9 JH |
196 | return (error); |
| 197 | } | |
| 198 | ||
| 002c1265 MD |
199 | /* |
| 200 | * WARNING! Synchronous call from user context. Control function may do | |
| 201 | * copyin/copyout. | |
| 202 | */ | |
| 9eeaa8a9 | 203 | int |
| 002c1265 MD |
204 | so_pru_control_direct(struct socket *so, u_long cmd, caddr_t data, |
| 205 | struct ifnet *ifp) | |
| 9eeaa8a9 | 206 | { |
| 9eeaa8a9 | 207 | struct netmsg_pru_control msg; |
| 002c1265 | 208 | netisr_fn_t func = so->so_proto->pr_usrreqs->pru_control; |
| 9eeaa8a9 | 209 | |
| 002c1265 MD |
210 | netmsg_init(&msg.base, so, &netisr_adone_rport, 0, func); |
| 211 | msg.base.lmsg.ms_flags &= ~(MSGF_REPLY | MSGF_DONE); | |
| 212 | msg.base.lmsg.ms_flags |= MSGF_SYNC; | |
| 9eeaa8a9 JH |
213 | msg.nm_cmd = cmd; |
| 214 | msg.nm_data = data; | |
| 215 | msg.nm_ifp = ifp; | |
| 002c1265 MD |
216 | msg.nm_td = curthread; |
| 217 | func((netmsg_t)&msg); | |
| 0fec1ecd | 218 | KKASSERT(msg.base.lmsg.ms_flags & MSGF_DONE); |
| 002c1265 | 219 | return(msg.base.lmsg.ms_error); |
| 9eeaa8a9 JH |
220 | } |
| 221 | ||
| 222 | int | |
| 223 | so_pru_detach(struct socket *so) | |
| 224 | { | |
| 9eeaa8a9 | 225 | struct netmsg_pru_detach msg; |
| 002c1265 | 226 | int error; |
| 9eeaa8a9 | 227 | |
| 002c1265 MD |
228 | netmsg_init(&msg.base, so, &curthread->td_msgport, |
| 229 | 0, so->so_proto->pr_usrreqs->pru_detach); | |
| 230 | error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); | |
| 9eeaa8a9 JH |
231 | return (error); |
| 232 | } | |
| 233 | ||
| acd31a69 SZ |
234 | void |
| 235 | so_pru_detach_direct(struct socket *so) | |
| 236 | { | |
| 237 | struct netmsg_pru_detach msg; | |
| 238 | netisr_fn_t func = so->so_proto->pr_usrreqs->pru_detach; | |
| 239 | ||
| 240 | netmsg_init(&msg.base, so, &netisr_adone_rport, 0, func); | |
| 241 | msg.base.lmsg.ms_flags &= ~(MSGF_REPLY | MSGF_DONE); | |
| 242 | msg.base.lmsg.ms_flags |= MSGF_SYNC; | |
| 243 | func((netmsg_t)&msg); | |
| 244 | KKASSERT(msg.base.lmsg.ms_flags & MSGF_DONE); | |
| 245 | } | |
| 246 | ||
| 9eeaa8a9 JH |
247 | int |
| 248 | so_pru_disconnect(struct socket *so) | |
| 249 | { | |
| 9eeaa8a9 | 250 | struct netmsg_pru_disconnect msg; |
| 002c1265 | 251 | int error; |
| 9eeaa8a9 | 252 | |
| 002c1265 MD |
253 | netmsg_init(&msg.base, so, &curthread->td_msgport, |
| 254 | 0, so->so_proto->pr_usrreqs->pru_disconnect); | |
| 255 | error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); | |
| 9eeaa8a9 JH |
256 | return (error); |
| 257 | } | |
| 258 | ||
| acd31a69 SZ |
259 | void |
| 260 | so_pru_disconnect_direct(struct socket *so) | |
| 261 | { | |
| 262 | struct netmsg_pru_disconnect msg; | |
| 263 | netisr_fn_t func = so->so_proto->pr_usrreqs->pru_disconnect; | |
| 264 | ||
| 265 | netmsg_init(&msg.base, so, &netisr_adone_rport, 0, func); | |
| 266 | msg.base.lmsg.ms_flags &= ~(MSGF_REPLY | MSGF_DONE); | |
| 267 | msg.base.lmsg.ms_flags |= MSGF_SYNC; | |
| 268 | func((netmsg_t)&msg); | |
| 269 | KKASSERT(msg.base.lmsg.ms_flags & MSGF_DONE); | |
| 270 | } | |
| 271 | ||
| 9eeaa8a9 JH |
272 | int |
| 273 | so_pru_listen(struct socket *so, struct thread *td) | |
| 274 | { | |
| 9eeaa8a9 | 275 | struct netmsg_pru_listen msg; |
| 002c1265 | 276 | int error; |
| 9eeaa8a9 | 277 | |
| 002c1265 MD |
278 | netmsg_init(&msg.base, so, &curthread->td_msgport, |
| 279 | 0, so->so_proto->pr_usrreqs->pru_listen); | |
| 9eeaa8a9 | 280 | msg.nm_td = td; /* used only for prison_ip() XXX JH */ |
| 002c1265 | 281 | error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); |
| 9eeaa8a9 JH |
282 | return (error); |
| 283 | } | |
| 284 | ||
| 285 | int | |
| 286 | so_pru_peeraddr(struct socket *so, struct sockaddr **nam) | |
| 287 | { | |
| 9eeaa8a9 | 288 | struct netmsg_pru_peeraddr msg; |
| 002c1265 | 289 | int error; |
| 9eeaa8a9 | 290 | |
| 002c1265 MD |
291 | netmsg_init(&msg.base, so, &curthread->td_msgport, |
| 292 | 0, so->so_proto->pr_usrreqs->pru_peeraddr); | |
| 9eeaa8a9 | 293 | msg.nm_nam = nam; |
| 002c1265 | 294 | error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); |
| 9eeaa8a9 JH |
295 | return (error); |
| 296 | } | |
| 297 | ||
| 298 | int | |
| 299 | so_pru_rcvd(struct socket *so, int flags) | |
| 300 | { | |
| 9eeaa8a9 | 301 | struct netmsg_pru_rcvd msg; |
| 002c1265 | 302 | int error; |
| 9eeaa8a9 | 303 | |
| 002c1265 MD |
304 | netmsg_init(&msg.base, so, &curthread->td_msgport, |
| 305 | 0, so->so_proto->pr_usrreqs->pru_rcvd); | |
| 9eeaa8a9 | 306 | msg.nm_flags = flags; |
| 002c1265 | 307 | error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); |
| 9eeaa8a9 JH |
308 | return (error); |
| 309 | } | |
| 310 | ||
| 311 | int | |
| 312 | so_pru_rcvoob(struct socket *so, struct mbuf *m, int flags) | |
| 313 | { | |
| 9eeaa8a9 | 314 | struct netmsg_pru_rcvoob msg; |
| 002c1265 | 315 | int error; |
| 9eeaa8a9 | 316 | |
| 002c1265 MD |
317 | netmsg_init(&msg.base, so, &curthread->td_msgport, |
| 318 | 0, so->so_proto->pr_usrreqs->pru_rcvoob); | |
| 9eeaa8a9 JH |
319 | msg.nm_m = m; |
| 320 | msg.nm_flags = flags; | |
| 002c1265 | 321 | error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); |
| 9eeaa8a9 JH |
322 | return (error); |
| 323 | } | |
| 324 | ||
| 48e7b118 | 325 | /* |
| 48e7b118 MD |
326 | * NOTE: If the target port changes the implied connect will deal with it. |
| 327 | */ | |
| 9eeaa8a9 | 328 | int |
| 48e7b118 MD |
329 | so_pru_send(struct socket *so, int flags, struct mbuf *m, |
| 330 | struct sockaddr *addr, struct mbuf *control, struct thread *td) | |
| 9eeaa8a9 | 331 | { |
| 9eeaa8a9 | 332 | struct netmsg_pru_send msg; |
| 002c1265 | 333 | int error; |
| 934c6849 | 334 | |
| 002c1265 MD |
335 | netmsg_init(&msg.base, so, &curthread->td_msgport, |
| 336 | 0, so->so_proto->pr_usrreqs->pru_send); | |
| 9eeaa8a9 JH |
337 | msg.nm_flags = flags; |
| 338 | msg.nm_m = m; | |
| 339 | msg.nm_addr = addr; | |
| 340 | msg.nm_control = control; | |
| 341 | msg.nm_td = td; | |
| 002c1265 | 342 | error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); |
| 9eeaa8a9 JH |
343 | return (error); |
| 344 | } | |
| 345 | ||
| f2a3782e SZ |
346 | void |
| 347 | so_pru_sync(struct socket *so) | |
| 348 | { | |
| 349 | struct netmsg_base msg; | |
| 350 | ||
| 351 | netmsg_init(&msg, so, &curthread->td_msgport, 0, | |
| 79f504ca | 352 | netmsg_sync_handler); |
| f2a3782e SZ |
353 | lwkt_domsg(so->so_port, &msg.lmsg, 0); |
| 354 | } | |
| 355 | ||
| 0ad8e15e SZ |
356 | void |
| 357 | so_pru_send_async(struct socket *so, int flags, struct mbuf *m, | |
| 358 | struct sockaddr *addr, struct mbuf *control, struct thread *td) | |
| 359 | { | |
| 360 | struct netmsg_pru_send *msg; | |
| 361 | ||
| 2ef7b293 SZ |
362 | KASSERT(so->so_proto->pr_flags & PR_ASYNC_SEND, |
| 363 | ("async pru_send is not supported\n")); | |
| 364 | ||
| 0ad8e15e SZ |
365 | msg = &m->m_hdr.mh_sndmsg; |
| 366 | netmsg_init(&msg->base, so, &netisr_apanic_rport, | |
| 367 | 0, so->so_proto->pr_usrreqs->pru_send); | |
| 368 | msg->nm_flags = flags | PRUS_NOREPLY; | |
| 369 | msg->nm_m = m; | |
| 370 | msg->nm_addr = addr; | |
| 371 | msg->nm_control = control; | |
| 372 | msg->nm_td = td; | |
| 373 | lwkt_sendmsg(so->so_port, &msg->base.lmsg); | |
| 374 | } | |
| 375 | ||
| 9eeaa8a9 JH |
376 | int |
| 377 | so_pru_sense(struct socket *so, struct stat *sb) | |
| 378 | { | |
| 9eeaa8a9 | 379 | struct netmsg_pru_sense msg; |
| 002c1265 | 380 | int error; |
| 9eeaa8a9 | 381 | |
| 002c1265 MD |
382 | netmsg_init(&msg.base, so, &curthread->td_msgport, |
| 383 | 0, so->so_proto->pr_usrreqs->pru_sense); | |
| 9eeaa8a9 | 384 | msg.nm_stat = sb; |
| 002c1265 | 385 | error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); |
| 9eeaa8a9 JH |
386 | return (error); |
| 387 | } | |
| 388 | ||
| 389 | int | |
| 390 | so_pru_shutdown(struct socket *so) | |
| 391 | { | |
| 9eeaa8a9 | 392 | struct netmsg_pru_shutdown msg; |
| 002c1265 | 393 | int error; |
| 9eeaa8a9 | 394 | |
| 002c1265 MD |
395 | netmsg_init(&msg.base, so, &curthread->td_msgport, |
| 396 | 0, so->so_proto->pr_usrreqs->pru_shutdown); | |
| 397 | error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); | |
| 9eeaa8a9 JH |
398 | return (error); |
| 399 | } | |
| 400 | ||
| 401 | int | |
| 402 | so_pru_sockaddr(struct socket *so, struct sockaddr **nam) | |
| 403 | { | |
| 9eeaa8a9 | 404 | struct netmsg_pru_sockaddr msg; |
| 002c1265 | 405 | int error; |
| 9eeaa8a9 | 406 | |
| 002c1265 MD |
407 | netmsg_init(&msg.base, so, &curthread->td_msgport, |
| 408 | 0, so->so_proto->pr_usrreqs->pru_sockaddr); | |
| 9eeaa8a9 | 409 | msg.nm_nam = nam; |
| 002c1265 | 410 | error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); |
| 9eeaa8a9 JH |
411 | return (error); |
| 412 | } | |
| 413 | ||
| 414 | int | |
| 002c1265 | 415 | so_pr_ctloutput(struct socket *so, struct sockopt *sopt) |
| 9eeaa8a9 | 416 | { |
| 002c1265 | 417 | struct netmsg_pr_ctloutput msg; |
| 9eeaa8a9 | 418 | int error; |
| de0003fe | 419 | |
| 792239df | 420 | KKASSERT(!sopt->sopt_val || kva_p(sopt->sopt_val)); |
| 002c1265 MD |
421 | netmsg_init(&msg.base, so, &curthread->td_msgport, |
| 422 | 0, so->so_proto->pr_ctloutput); | |
| 9eeaa8a9 | 423 | msg.nm_sopt = sopt; |
| 002c1265 | 424 | error = lwkt_domsg(so->so_port, &msg.base.lmsg, 0); |
| 9eeaa8a9 | 425 | return (error); |
| 9eeaa8a9 JH |
426 | } |
| 427 | ||
| 428 | /* | |
| e3873585 SZ |
429 | * Protocol control input, typically via icmp. |
| 430 | * | |
| 431 | * If the protocol pr_ctlport is not NULL we call it to figure out the | |
| 432 | * protocol port. If NULL is returned we can just return, otherwise | |
| 433 | * we issue a netmsg to call pr_ctlinput in the proper thread. | |
| 434 | * | |
| 435 | * This must be done synchronously as arg and/or extra may point to | |
| 436 | * temporary data. | |
| 437 | */ | |
| 438 | void | |
| 439 | so_pru_ctlinput(struct protosw *pr, int cmd, struct sockaddr *arg, void *extra) | |
| 440 | { | |
| 441 | struct netmsg_pru_ctlinput msg; | |
| 442 | lwkt_port_t port; | |
| 443 | ||
| 444 | if (pr->pr_ctlport == NULL) | |
| 445 | return; | |
| 446 | KKASSERT(pr->pr_ctlinput != NULL); | |
| 447 | port = pr->pr_ctlport(cmd, arg, extra); | |
| 448 | if (port == NULL) | |
| 449 | return; | |
| 002c1265 MD |
450 | netmsg_init(&msg.base, NULL, &curthread->td_msgport, |
| 451 | 0, pr->pr_ctlinput); | |
| e3873585 SZ |
452 | msg.nm_cmd = cmd; |
| 453 | msg.nm_arg = arg; | |
| 454 | msg.nm_extra = extra; | |
| 002c1265 | 455 | lwkt_domsg(port, &msg.base.lmsg, 0); |
| e3873585 SZ |
456 | } |
| 457 | ||
| 458 | /* | |
| b44419cb MD |
459 | * If we convert all the protosw pr_ functions for all the protocols |
| 460 | * to take a message directly, this layer can go away. For the moment | |
| 461 | * our dispatcher ignores the return value, but since we are handling | |
| 462 | * the replymsg ourselves we return EASYNC by convention. | |
| 9eeaa8a9 | 463 | */ |
| 4402d8a2 MD |
464 | |
| 465 | /* | |
| b44419cb MD |
466 | * Handle a predicate event request. This function is only called once |
| 467 | * when the predicate message queueing request is received. | |
| 468 | */ | |
| 4599cf19 | 469 | void |
| 002c1265 | 470 | netmsg_so_notify(netmsg_t msg) |
| b44419cb | 471 | { |
| e2b148c6 | 472 | struct lwkt_token *tok; |
| 6d49aa6f | 473 | struct signalsockbuf *ssb; |
| c1d0003c | 474 | |
| 002c1265 MD |
475 | ssb = (msg->notify.nm_etype & NM_REVENT) ? |
| 476 | &msg->base.nm_so->so_rcv : | |
| 477 | &msg->base.nm_so->so_snd; | |
| b44419cb MD |
478 | |
| 479 | /* | |
| 480 | * Reply immediately if the event has occured, otherwise queue the | |
| 481 | * request. | |
| e2b148c6 MD |
482 | * |
| 483 | * NOTE: Socket can change if this is an accept predicate so cache | |
| 484 | * the token. | |
| b44419cb | 485 | */ |
| e2b148c6 MD |
486 | tok = lwkt_token_pool_lookup(msg->base.nm_so); |
| 487 | lwkt_gettoken(tok); | |
| 002c1265 | 488 | if (msg->notify.nm_predicate(&msg->notify)) { |
| e2b148c6 | 489 | lwkt_reltoken(tok); |
| 002c1265 MD |
490 | lwkt_replymsg(&msg->base.lmsg, |
| 491 | msg->base.lmsg.ms_error); | |
| b44419cb | 492 | } else { |
| 002c1265 | 493 | TAILQ_INSERT_TAIL(&ssb->ssb_kq.ki_mlist, &msg->notify, nm_list); |
| 14343ad3 | 494 | atomic_set_int(&ssb->ssb_flags, SSB_MEVENT); |
| e2b148c6 | 495 | lwkt_reltoken(tok); |
| c1d0003c | 496 | } |
| 4599cf19 MD |
497 | } |
| 498 | ||
| 499 | /* | |
| 500 | * Called by doio when trying to abort a netmsg_so_notify message. | |
| 501 | * Unlike the other functions this one is dispatched directly by | |
| 502 | * the LWKT subsystem, so it takes a lwkt_msg_t as an argument. | |
| ebe43e15 MD |
503 | * |
| 504 | * The original message, lmsg, is under the control of the caller and | |
| 505 | * will not be destroyed until we return so we can safely reference it | |
| 506 | * in our synchronous abort request. | |
| 507 | * | |
| 508 | * This part of the abort request occurs on the originating cpu which | |
| 509 | * means we may race the message flags and the original message may | |
| 510 | * not even have been processed by the target cpu yet. | |
| 4599cf19 MD |
511 | */ |
| 512 | void | |
| 513 | netmsg_so_notify_doabort(lwkt_msg_t lmsg) | |
| 514 | { | |
| 515 | struct netmsg_so_notify_abort msg; | |
| 516 | ||
| ebe43e15 | 517 | if ((lmsg->ms_flags & (MSGF_DONE | MSGF_REPLY)) == 0) { |
| 002c1265 | 518 | netmsg_init(&msg.base, NULL, &curthread->td_msgport, |
| 48e7b118 | 519 | 0, netmsg_so_notify_abort); |
| 4599cf19 | 520 | msg.nm_notifymsg = (void *)lmsg; |
| 002c1265 | 521 | lwkt_domsg(lmsg->ms_target_port, &msg.base.lmsg, 0); |
| 4599cf19 | 522 | } |
| b44419cb MD |
523 | } |
| 524 | ||
| 525 | /* | |
| 526 | * Predicate requests can be aborted. This function is only called once | |
| 527 | * and will interlock against processing/reply races (since such races | |
| 528 | * occur on the same thread that controls the port where the abort is | |
| 529 | * requeued). | |
| ebe43e15 MD |
530 | * |
| 531 | * This part of the abort request occurs on the target cpu. The message | |
| 532 | * flags must be tested again in case the test that we did on the | |
| 533 | * originating cpu raced. Since messages are handled in sequence, the | |
| 534 | * original message will have already been handled by the loop and either | |
| 535 | * replied to or queued. | |
| 536 | * | |
| 537 | * We really only need to interlock with MSGF_REPLY (a bit that is set on | |
| 538 | * our cpu when we reply). Note that MSGF_DONE is not set until the | |
| 539 | * reply reaches the originating cpu. Test both bits anyway. | |
| b44419cb | 540 | */ |
| 4599cf19 | 541 | void |
| 002c1265 | 542 | netmsg_so_notify_abort(netmsg_t msg) |
| b44419cb | 543 | { |
| 002c1265 MD |
544 | struct netmsg_so_notify_abort *abrtmsg = &msg->notify_abort; |
| 545 | struct netmsg_so_notify *nmsg = abrtmsg->nm_notifymsg; | |
| 6d49aa6f | 546 | struct signalsockbuf *ssb; |
| c1d0003c | 547 | |
| 4599cf19 MD |
548 | /* |
| 549 | * The original notify message is not destroyed until after the | |
| ebe43e15 | 550 | * abort request is returned, so we can check its state. |
| 4599cf19 | 551 | */ |
| e2b148c6 | 552 | lwkt_getpooltoken(nmsg->base.nm_so); |
| 002c1265 MD |
553 | if ((nmsg->base.lmsg.ms_flags & (MSGF_DONE | MSGF_REPLY)) == 0) { |
| 554 | ssb = (nmsg->nm_etype & NM_REVENT) ? | |
| 555 | &nmsg->base.nm_so->so_rcv : | |
| 556 | &nmsg->base.nm_so->so_snd; | |
| 002c1265 | 557 | TAILQ_REMOVE(&ssb->ssb_kq.ki_mlist, nmsg, nm_list); |
| e2b148c6 | 558 | lwkt_relpooltoken(nmsg->base.nm_so); |
| 002c1265 | 559 | lwkt_replymsg(&nmsg->base.lmsg, EINTR); |
| e2b148c6 MD |
560 | } else { |
| 561 | lwkt_relpooltoken(nmsg->base.nm_so); | |
| 4599cf19 MD |
562 | } |
| 563 | ||
| 564 | /* | |
| 565 | * Reply to the abort message | |
| 566 | */ | |
| 002c1265 | 567 | lwkt_replymsg(&abrtmsg->base.lmsg, 0); |
| c1d0003c | 568 | } |