xref: /dflybsd-src/sys/kern/uipc_msg.c (revision 90ea502b8c5d21f908cedff6680ee2bc9e74ce74)
1 /*
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  *
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.
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.
19  *
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  *
33  * $DragonFly: src/sys/kern/uipc_msg.c,v 1.26 2008/10/27 02:56:30 sephe Exp $
34  */
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/msgport.h>
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>
45 #include <sys/thread2.h>
46 #include <sys/msgport2.h>
47 #include <vm/pmap.h>
48 #include <net/netmsg2.h>
49 
50 #include <net/netisr.h>
51 #include <net/netmsg.h>
52 
53 /*
54  * Abort a socket and free it.  Called from soabort() only.
55  *
56  * The SS_ABORTING flag must already be set.
57  */
58 void
59 so_pru_abort(struct socket *so)
60 {
61 	struct netmsg_pru_abort msg;
62 
63 	KKASSERT(so->so_state & SS_ABORTING);
64 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
65 		    0, netmsg_pru_abort);
66 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_abort;
67 	(void)lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
68 }
69 
70 /*
71  * Abort a socket and free it, asynchronously.  Called from
72  * soaborta() only.
73  *
74  * The SS_ABORTING flag must already be set.
75  */
76 void
77 so_pru_aborta(struct socket *so)
78 {
79 	struct netmsg_pru_abort *msg;
80 
81 	KKASSERT(so->so_state & SS_ABORTING);
82 	msg = kmalloc(sizeof(*msg), M_LWKTMSG, M_WAITOK | M_ZERO);
83 	netmsg_init(&msg->nm_netmsg, so, &netisr_afree_rport,
84 		    0, netmsg_pru_abort);
85 	msg->nm_prufn = so->so_proto->pr_usrreqs->pru_abort;
86 	lwkt_sendmsg(so->so_port, &msg->nm_netmsg.nm_lmsg);
87 }
88 
89 /*
90  * Abort a socket and free it.  Called from soabort_oncpu() only.
91  * Caller must make sure that the current CPU is inpcb's owner CPU.
92  *
93  * The SS_ABORTING flag must already be set.
94  */
95 void
96 so_pru_abort_oncpu(struct socket *so)
97 {
98 	so->so_proto->pr_usrreqs->pru_abort(so);
99 }
100 
101 int
102 so_pru_accept(struct socket *so, struct sockaddr **nam)
103 {
104 	/* Block (memory allocation) in process context. XXX JH */
105 	return ((*so->so_proto->pr_usrreqs->pru_accept)(so, nam));
106 
107 #ifdef notdef
108 	int error;
109 	struct netmsg_pru_accept msg;
110 
111 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
112 		    0, netmsg_pru_accept);
113 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_accept;
114 	msg.nm_nam = nam;
115 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
116 	return (error);
117 #endif
118 }
119 
120 int
121 so_pru_attach(struct socket *so, int proto, struct pru_attach_info *ai)
122 {
123 	int error;
124 	struct netmsg_pru_attach msg;
125 
126 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
127 		    0, netmsg_pru_attach);
128 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_attach;
129 	msg.nm_proto = proto;
130 	msg.nm_ai = ai;
131 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
132 	return (error);
133 }
134 
135 /*
136  * NOTE: If the target port changes the bind operation will deal with it.
137  */
138 int
139 so_pru_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
140 {
141 	int error;
142 	struct netmsg_pru_bind msg;
143 
144 #if 0
145 	port = so->so_proto->pr_mport(NULL, nam, NULL);
146 #endif
147 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
148 		    0, netmsg_pru_bind);
149 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_bind;
150 	msg.nm_nam = nam;
151 	msg.nm_td = td;		/* used only for prison_ip() XXX JH */
152 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
153 	return (error);
154 }
155 
156 int
157 so_pru_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
158 {
159 	int error;
160 	struct netmsg_pru_connect msg;
161 
162 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
163 		    0, netmsg_pru_connect);
164 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_connect;
165 	msg.nm_nam = nam;
166 	msg.nm_td = td;
167 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
168 	return (error);
169 }
170 
171 int
172 so_pru_connect2(struct socket *so1, struct socket *so2)
173 {
174 	int error;
175 	struct netmsg_pru_connect2 msg;
176 
177 	netmsg_init(&msg.nm_netmsg, so1, &curthread->td_msgport,
178 		    0, netmsg_pru_connect2);
179 	msg.nm_prufn = so1->so_proto->pr_usrreqs->pru_connect2;
180 	msg.nm_so1 = so1;
181 	msg.nm_so2 = so2;
182 	error = lwkt_domsg(so1->so_port, &msg.nm_netmsg.nm_lmsg, 0);
183 	return (error);
184 }
185 
186 int
187 so_pru_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp)
188 {
189 	return ((*so->so_proto->pr_usrreqs->pru_control)(
190 			so, cmd, data, ifp, curthread));
191 #ifdef gag	/* does copyin and copyout deep inside stack XXX JH */
192 	int error;
193 	struct netmsg_pru_control msg;
194 
195 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
196 		    0, netmsg_pru_control);
197 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_control;
198 	msg.nm_cmd = cmd;
199 	msg.nm_data = data;
200 	msg.nm_ifp = ifp;
201 	msg.nm_td = td;
202 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
203 	return (error);
204 #endif
205 }
206 
207 int
208 so_pru_detach(struct socket *so)
209 {
210 	int error;
211 	struct netmsg_pru_detach msg;
212 
213 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
214 		    0, netmsg_pru_detach);
215 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_detach;
216 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
217 	return (error);
218 }
219 
220 int
221 so_pru_disconnect(struct socket *so)
222 {
223 	int error;
224 	struct netmsg_pru_disconnect msg;
225 
226 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
227 		    0, netmsg_pru_disconnect);
228 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_disconnect;
229 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
230 	return (error);
231 }
232 
233 int
234 so_pru_listen(struct socket *so, struct thread *td)
235 {
236 	int error;
237 	struct netmsg_pru_listen msg;
238 
239 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
240 		    0, netmsg_pru_listen);
241 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_listen;
242 	msg.nm_td = td;		/* used only for prison_ip() XXX JH */
243 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
244 	return (error);
245 }
246 
247 int
248 so_pru_peeraddr(struct socket *so, struct sockaddr **nam)
249 {
250 	int error;
251 	struct netmsg_pru_peeraddr msg;
252 
253 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
254 		    0, netmsg_pru_peeraddr);
255 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_peeraddr;
256 	msg.nm_nam = nam;
257 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
258 	return (error);
259 }
260 
261 int
262 so_pru_rcvd(struct socket *so, int flags)
263 {
264 	int error;
265 	struct netmsg_pru_rcvd msg;
266 
267 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
268 		    0, netmsg_pru_rcvd);
269 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_rcvd;
270 	msg.nm_flags = flags;
271 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
272 	return (error);
273 }
274 
275 int
276 so_pru_rcvoob(struct socket *so, struct mbuf *m, int flags)
277 {
278 	int error;
279 	struct netmsg_pru_rcvoob msg;
280 
281 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
282 		    0, netmsg_pru_rcvoob);
283 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_rcvoob;
284 	msg.nm_m = m;
285 	msg.nm_flags = flags;
286 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
287 	return (error);
288 }
289 
290 /*
291  * NOTE: so_pru_send() is the only code which uses pr_mport() now.
292  *
293  * NOTE: If the target port changes the implied connect will deal with it.
294  */
295 int
296 so_pru_send(struct socket *so, int flags, struct mbuf *m,
297 	    struct sockaddr *addr, struct mbuf *control, struct thread *td)
298 {
299 	int error;
300 	struct netmsg_pru_send msg;
301 	lwkt_port_t port;
302 
303 	port = so->so_proto->pr_mport(so, addr, &m);
304 	if (port == NULL) {
305 		KKASSERT(m == NULL);
306 		return EINVAL;
307 	}
308 
309 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
310 		    0, netmsg_pru_send);
311 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_send;
312 	msg.nm_flags = flags;
313 	msg.nm_m = m;
314 	msg.nm_addr = addr;
315 	msg.nm_control = control;
316 	msg.nm_td = td;
317 	error = lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0);
318 	return (error);
319 }
320 
321 /*
322  * MPSAFE
323  */
324 int
325 so_pru_sense(struct socket *so, struct stat *sb)
326 {
327 	int error;
328 	struct netmsg_pru_sense msg;
329 
330 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
331 		    0, netmsg_pru_sense);
332 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_sense;
333 	msg.nm_stat = sb;
334 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
335 	return (error);
336 }
337 
338 int
339 so_pru_shutdown(struct socket *so)
340 {
341 	int error;
342 	struct netmsg_pru_shutdown msg;
343 
344 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
345 		    0, netmsg_pru_shutdown);
346 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_shutdown;
347 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
348 	return (error);
349 }
350 
351 int
352 so_pru_sockaddr(struct socket *so, struct sockaddr **nam)
353 {
354 	int error;
355 	struct netmsg_pru_sockaddr msg;
356 
357 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
358 		    0, netmsg_pru_sockaddr);
359 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_sockaddr;
360 	msg.nm_nam = nam;
361 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
362 	return (error);
363 }
364 
365 int
366 so_pru_sopoll(struct socket *so, int events, struct ucred *cred)
367 {
368 	int error;
369 	struct netmsg_pru_sopoll msg;
370 
371 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
372 		    0, netmsg_pru_sopoll);
373 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_sopoll;
374 	msg.nm_events = events;
375 	msg.nm_cred = cred;
376 	msg.nm_td = curthread;
377 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
378 	return (error);
379 }
380 
381 int
382 so_pru_ctloutput(struct socket *so, struct sockopt *sopt)
383 {
384 	struct netmsg_pru_ctloutput msg;
385 	int error;
386 
387 	KKASSERT(!sopt->sopt_val || kva_p(sopt->sopt_val));
388 	netmsg_init(&msg.nm_netmsg, so, &curthread->td_msgport,
389 		    0, netmsg_pru_ctloutput);
390 	/* TBD: move pr_ctloutput to pr_usrreqs */
391 	msg.nm_prufn = so->so_proto->pr_ctloutput;
392 	msg.nm_sopt = sopt;
393 	error = lwkt_domsg(so->so_port, &msg.nm_netmsg.nm_lmsg, 0);
394 	return (error);
395 }
396 
397 /*
398  * Protocol control input, typically via icmp.
399  *
400  * If the protocol pr_ctlport is not NULL we call it to figure out the
401  * protocol port.  If NULL is returned we can just return, otherwise
402  * we issue a netmsg to call pr_ctlinput in the proper thread.
403  *
404  * This must be done synchronously as arg and/or extra may point to
405  * temporary data.
406  */
407 void
408 so_pru_ctlinput(struct protosw *pr, int cmd, struct sockaddr *arg, void *extra)
409 {
410 	struct netmsg_pru_ctlinput msg;
411 	lwkt_port_t port;
412 
413 	if (pr->pr_ctlport == NULL)
414 		return;
415 	KKASSERT(pr->pr_ctlinput != NULL);
416 	port = pr->pr_ctlport(cmd, arg, extra);
417 	if (port == NULL)
418 		return;
419 	netmsg_init(&msg.nm_netmsg, NULL, &curthread->td_msgport,
420 		    0, netmsg_pru_ctlinput);
421 	msg.nm_prufn = pr->pr_ctlinput;
422 	msg.nm_cmd = cmd;
423 	msg.nm_arg = arg;
424 	msg.nm_extra = extra;
425 	lwkt_domsg(port, &msg.nm_netmsg.nm_lmsg, 0);
426 }
427 
428 /*
429  * If we convert all the protosw pr_ functions for all the protocols
430  * to take a message directly, this layer can go away.  For the moment
431  * our dispatcher ignores the return value, but since we are handling
432  * the replymsg ourselves we return EASYNC by convention.
433  */
434 
435 /*
436  * Abort and destroy a socket.
437  */
438 void
439 netmsg_pru_abort(netmsg_t msg)
440 {
441 	struct netmsg_pru_abort *nm = (void *)msg;
442 	struct socket *so = msg->nm_so;
443 	int error;
444 
445 	KKASSERT(so->so_state & SS_ABORTING);
446 	so->so_state &= ~SS_ABORTING;
447 	error = nm->nm_prufn(so);
448 	if (error)
449 		sofree(so);
450 	lwkt_replymsg(&msg->nm_lmsg, error);
451 }
452 
453 #ifdef notused
454 void
455 netmsg_pru_accept(netmsg_t msg)
456 {
457 	struct netmsg_pru_accept *nm = (void *)msg;
458 
459 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_nam));
460 }
461 #endif
462 
463 void
464 netmsg_pru_attach(netmsg_t msg)
465 {
466 	struct netmsg_pru_attach *nm = (void *)msg;
467 
468 	lwkt_replymsg(&msg->nm_lmsg,
469 		      nm->nm_prufn(msg->nm_so, nm->nm_proto, nm->nm_ai));
470 }
471 
472 void
473 netmsg_pru_bind(netmsg_t msg)
474 {
475 	struct netmsg_pru_bind *nm = (void *)msg;
476 
477 	lwkt_replymsg(&msg->nm_lmsg,
478 		      nm->nm_prufn(msg->nm_so, nm->nm_nam, nm->nm_td));
479 }
480 
481 void
482 netmsg_pru_connect(netmsg_t msg)
483 {
484 	struct netmsg_pru_connect *nm = (void *)msg;
485 
486 	lwkt_replymsg(&msg->nm_lmsg,
487 		      nm->nm_prufn(msg->nm_so, nm->nm_nam, nm->nm_td));
488 }
489 
490 void
491 netmsg_pru_connect2(netmsg_t msg)
492 {
493 	struct netmsg_pru_connect2 *nm = (void *)msg;
494 
495 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(nm->nm_so1, nm->nm_so2));
496 }
497 
498 void
499 netmsg_pru_control(netmsg_t msg)
500 {
501 	struct netmsg_pru_control *nm = (void *)msg;
502 	int error;
503 
504 	error = nm->nm_prufn(msg->nm_so, nm->nm_cmd, nm->nm_data,
505 				nm->nm_ifp, nm->nm_td);
506 	lwkt_replymsg(&msg->nm_lmsg, error);
507 }
508 
509 void
510 netmsg_pru_detach(netmsg_t msg)
511 {
512 	struct netmsg_pru_detach *nm = (void *)msg;
513 
514 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so));
515 }
516 
517 void
518 netmsg_pru_disconnect(netmsg_t msg)
519 {
520 	struct netmsg_pru_disconnect *nm = (void *)msg;
521 
522 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so));
523 }
524 
525 void
526 netmsg_pru_listen(netmsg_t msg)
527 {
528 	struct netmsg_pru_listen *nm = (void *)msg;
529 
530 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_td));
531 }
532 
533 void
534 netmsg_pru_peeraddr(netmsg_t msg)
535 {
536 	struct netmsg_pru_peeraddr *nm = (void *)msg;
537 
538 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_nam));
539 }
540 
541 void
542 netmsg_pru_rcvd(netmsg_t msg)
543 {
544 	struct netmsg_pru_rcvd *nm = (void *)msg;
545 
546 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_flags));
547 }
548 
549 void
550 netmsg_pru_rcvoob(netmsg_t msg)
551 {
552 	struct netmsg_pru_rcvoob *nm = (void *)msg;
553 
554 	lwkt_replymsg(&msg->nm_lmsg,
555 		      nm->nm_prufn(msg->nm_so, nm->nm_m, nm->nm_flags));
556 }
557 
558 void
559 netmsg_pru_send(netmsg_t msg)
560 {
561 	struct netmsg_pru_send *nm = (void *)msg;
562 	int error;
563 
564 	error = nm->nm_prufn(msg->nm_so, nm->nm_flags, nm->nm_m,
565 				nm->nm_addr, nm->nm_control, nm->nm_td);
566 	lwkt_replymsg(&msg->nm_lmsg, error);
567 }
568 
569 void
570 netmsg_pru_sense(netmsg_t msg)
571 {
572 	struct netmsg_pru_sense *nm = (void *)msg;
573 
574 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_stat));
575 }
576 
577 void
578 netmsg_pru_shutdown(netmsg_t msg)
579 {
580 	struct netmsg_pru_shutdown *nm = (void *)msg;
581 
582 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so));
583 }
584 
585 void
586 netmsg_pru_sockaddr(netmsg_t msg)
587 {
588 	struct netmsg_pru_sockaddr *nm = (void *)msg;
589 
590 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_nam));
591 }
592 
593 void
594 netmsg_pru_sopoll(netmsg_t msg)
595 {
596 	struct netmsg_pru_sopoll *nm = (void *)msg;
597 	int error;
598 
599 	error = nm->nm_prufn(msg->nm_so, nm->nm_events, nm->nm_cred, nm->nm_td);
600 	lwkt_replymsg(&msg->nm_lmsg, error);
601 }
602 
603 void
604 netmsg_pru_ctloutput(netmsg_t msg)
605 {
606 	struct netmsg_pru_ctloutput *nm = (void *)msg;
607 
608 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prufn(msg->nm_so, nm->nm_sopt));
609 }
610 
611 void
612 netmsg_pru_ctlinput(netmsg_t msg)
613 {
614 	struct netmsg_pru_ctlinput *nm = (void *)msg;
615 
616 	nm->nm_prufn(nm->nm_cmd, nm->nm_arg, nm->nm_extra);
617 	lwkt_replymsg(&nm->nm_netmsg.nm_lmsg, 0);
618 }
619 
620 void
621 netmsg_pr_timeout(netmsg_t msg)
622 {
623 	struct netmsg_pr_timeout *nm = (void *)msg;
624 
625 	lwkt_replymsg(&msg->nm_lmsg, nm->nm_prfn());
626 }
627 
628 /*
629  * Handle a predicate event request.  This function is only called once
630  * when the predicate message queueing request is received.
631  */
632 void
633 netmsg_so_notify(netmsg_t netmsg)
634 {
635 	struct netmsg_so_notify *msg = (void *)netmsg;
636 	struct signalsockbuf *ssb;
637 
638 	ssb = (msg->nm_etype & NM_REVENT) ?
639 			&msg->nm_so->so_rcv :
640 			&msg->nm_so->so_snd;
641 
642 	/*
643 	 * Reply immediately if the event has occured, otherwise queue the
644 	 * request.
645 	 */
646 	if (msg->nm_predicate(&msg->nm_netmsg)) {
647 		lwkt_replymsg(&msg->nm_netmsg.nm_lmsg,
648 			      msg->nm_netmsg.nm_lmsg.ms_error);
649 	} else {
650 		TAILQ_INSERT_TAIL(&ssb->ssb_sel.si_mlist, msg, nm_list);
651 		ssb->ssb_flags |= SSB_MEVENT;
652 	}
653 }
654 
655 /*
656  * Called by doio when trying to abort a netmsg_so_notify message.
657  * Unlike the other functions this one is dispatched directly by
658  * the LWKT subsystem, so it takes a lwkt_msg_t as an argument.
659  *
660  * The original message, lmsg, is under the control of the caller and
661  * will not be destroyed until we return so we can safely reference it
662  * in our synchronous abort request.
663  *
664  * This part of the abort request occurs on the originating cpu which
665  * means we may race the message flags and the original message may
666  * not even have been processed by the target cpu yet.
667  */
668 void
669 netmsg_so_notify_doabort(lwkt_msg_t lmsg)
670 {
671 	struct netmsg_so_notify_abort msg;
672 
673 	if ((lmsg->ms_flags & (MSGF_DONE | MSGF_REPLY)) == 0) {
674 		netmsg_init(&msg.nm_netmsg, NULL, &curthread->td_msgport,
675 			    0, netmsg_so_notify_abort);
676 		msg.nm_notifymsg = (void *)lmsg;
677 		lwkt_domsg(lmsg->ms_target_port, &msg.nm_netmsg.nm_lmsg, 0);
678 	}
679 }
680 
681 /*
682  * Predicate requests can be aborted.  This function is only called once
683  * and will interlock against processing/reply races (since such races
684  * occur on the same thread that controls the port where the abort is
685  * requeued).
686  *
687  * This part of the abort request occurs on the target cpu.  The message
688  * flags must be tested again in case the test that we did on the
689  * originating cpu raced.  Since messages are handled in sequence, the
690  * original message will have already been handled by the loop and either
691  * replied to or queued.
692  *
693  * We really only need to interlock with MSGF_REPLY (a bit that is set on
694  * our cpu when we reply).  Note that MSGF_DONE is not set until the
695  * reply reaches the originating cpu.  Test both bits anyway.
696  */
697 void
698 netmsg_so_notify_abort(netmsg_t netmsg)
699 {
700 	struct netmsg_so_notify_abort *abrtmsg = (void *)netmsg;
701 	struct netmsg_so_notify *msg = abrtmsg->nm_notifymsg;
702 	struct signalsockbuf *ssb;
703 
704 	/*
705 	 * The original notify message is not destroyed until after the
706 	 * abort request is returned, so we can check its state.
707 	 */
708 	if ((msg->nm_netmsg.nm_lmsg.ms_flags & (MSGF_DONE | MSGF_REPLY)) == 0) {
709 		ssb = (msg->nm_etype & NM_REVENT) ?
710 				&msg->nm_so->so_rcv :
711 				&msg->nm_so->so_snd;
712 		TAILQ_REMOVE(&ssb->ssb_sel.si_mlist, msg, nm_list);
713 		lwkt_replymsg(&msg->nm_netmsg.nm_lmsg, EINTR);
714 	}
715 
716 	/*
717 	 * Reply to the abort message
718 	 */
719 	lwkt_replymsg(&abrtmsg->nm_netmsg.nm_lmsg, 0);
720 }
721 
722