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