Pass more information down to the protocol-specific socket dispatch function
[dragonfly.git] / sys / kern / uipc_msg.c
1 /*
2  * Copyright (c) 2003, 2004 Jeffrey Hsu.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by Jeffrey M. Hsu.
16  * 4. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  * 
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * $DragonFly: src/sys/kern/uipc_msg.c,v 1.10 2004/04/23 10:21:07 hsu Exp $
31  */
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/msgport.h>
36 #include <sys/protosw.h>
37 #include <sys/socket.h>
38 #include <sys/socketvar.h>
39 #include <sys/socketops.h>
40 #include <sys/thread.h>
41 #include <sys/thread2.h>
42 #include <sys/msgport2.h>
43
44 #include <net/netisr.h>
45 #include <net/netmsg.h>
46
47 int
48 so_pru_abort(struct socket *so)
49 {
50         int error;
51         struct netmsg_pru_abort msg;
52         lwkt_port_t port;
53
54         if (!so->so_proto->pr_mport)
55                 return ((*so->so_proto->pr_usrreqs->pru_abort)(so));
56
57         port = so->so_proto->pr_mport(so, NULL, PRU_ABORT);
58         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
59                 lwkt_cmd_func(netmsg_pru_abort), lwkt_cmd_op_none);
60         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_abort;
61         msg.nm_so = so;
62         error = lwkt_domsg(port, &msg.nm_lmsg);
63         return (error);
64 }
65
66 int
67 so_pru_accept(struct socket *so, struct sockaddr **nam)
68 {
69         int error;
70         struct netmsg_pru_accept msg;
71         lwkt_port_t port;
72
73         if (!so->so_proto->pr_mport)
74                 return ((*so->so_proto->pr_usrreqs->pru_accept)(so, nam));
75
76         port = so->so_proto->pr_mport(so, NULL, PRU_ACCEPT);
77         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
78                 lwkt_cmd_func(netmsg_pru_accept), lwkt_cmd_op_none);
79         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_accept;
80         msg.nm_so = so;
81         msg.nm_nam = nam;
82         error = lwkt_domsg(port, &msg.nm_lmsg);
83         return (error);
84 }
85
86 int
87 so_pru_attach(struct socket *so, int proto, struct pru_attach_info *ai)
88 {
89         int error;
90         struct netmsg_pru_attach msg;
91         lwkt_port_t port;
92
93         if (!so->so_proto->pr_mport)
94                 return ((*so->so_proto->pr_usrreqs->pru_attach)(so, proto, ai));
95
96         port = so->so_proto->pr_mport(NULL, NULL, PRU_ATTACH);
97         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
98                 lwkt_cmd_func(netmsg_pru_attach), lwkt_cmd_op_none);
99         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_attach;
100         msg.nm_so = so;
101         msg.nm_proto = proto;
102         msg.nm_ai = ai;
103         error = lwkt_domsg(port, &msg.nm_lmsg);
104         return (error);
105 }
106
107 int
108 so_pru_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
109 {
110         int error;
111         struct netmsg_pru_bind msg;
112         lwkt_port_t port;
113
114         if (!so->so_proto->pr_mport)
115                 return ((*so->so_proto->pr_usrreqs->pru_bind)(so, nam, td));
116
117         /* Send mesg to thread for new address. */
118         port = so->so_proto->pr_mport(NULL, nam, PRU_BIND);
119         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
120                 lwkt_cmd_func(netmsg_pru_bind), lwkt_cmd_op_none);
121         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_bind;
122         msg.nm_so = so;
123         msg.nm_nam = nam;
124         msg.nm_td = td;         /* used only for prison_ip() XXX JH */
125         error = lwkt_domsg(port, &msg.nm_lmsg);
126         return (error);
127 }
128
129 int
130 so_pru_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
131 {
132         int error;
133         struct netmsg_pru_connect msg;
134         lwkt_port_t port;
135
136         if (!so->so_proto->pr_mport)
137                 return ((*so->so_proto->pr_usrreqs->pru_connect)(so, nam, td));
138
139         port = so->so_proto->pr_mport(so, nam, PRU_CONNECT);
140         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
141                 lwkt_cmd_func(netmsg_pru_connect), lwkt_cmd_op_none);
142         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_connect;
143         msg.nm_so = so;
144         msg.nm_nam = nam;
145         msg.nm_td = td;
146         error = lwkt_domsg(port, &msg.nm_lmsg);
147         return (error);
148 }
149
150 int
151 so_pru_connect2(struct socket *so1, struct socket *so2)
152 {
153         int error;
154         struct netmsg_pru_connect2 msg;
155         lwkt_port_t port;
156
157         if (!so1->so_proto->pr_mport)
158                 return ((*so1->so_proto->pr_usrreqs->pru_connect2)(so1, so2));
159
160         /*
161          * Actually, connect2() is only called for Unix domain sockets
162          * and we currently short-circuit that above, so the following
163          * code is never reached.
164          */
165         panic("connect2 on socket type %d", so1->so_type);
166         port = so1->so_proto->pr_mport(so1, NULL, PRU_CONNECT2);
167         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
168                 lwkt_cmd_func(netmsg_pru_connect2), lwkt_cmd_op_none);
169         msg.nm_prufn = so1->so_proto->pr_usrreqs->pru_connect2;
170         msg.nm_so1 = so1;
171         msg.nm_so2 = so2;
172         error = lwkt_domsg(port, &msg.nm_lmsg);
173         return (error);
174 }
175
176 int
177 so_pru_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
178     struct thread *td)
179 {
180         return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd, data, ifp,
181             td));
182 #ifdef gag      /* does copyin and copyout deep inside stack XXX JH */
183         int error;
184         struct netmsg_pru_control msg;
185         lwkt_port_t port;
186
187         if (!so->so_proto->pr_mport)
188                 return ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd, data,
189                     ifp, td));
190
191         port = so->so_proto->pr_mport(so, NULL, PRU_CONTROL);
192         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
193                 lwkt_cmd_func(netmsg_pru_control), lwkt_cmd_op_none);
194         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_control;
195         msg.nm_so = so;
196         msg.nm_cmd = cmd;
197         msg.nm_data = data;
198         msg.nm_ifp = ifp;
199         msg.nm_td = td;
200         error = lwkt_domsg(port, &msg.nm_lmsg);
201         return (error);
202 #endif
203 }
204
205 int
206 so_pru_detach(struct socket *so)
207 {
208         int error;
209         struct netmsg_pru_detach msg;
210         lwkt_port_t port;
211
212         if (!so->so_proto->pr_mport)
213                 return ((*so->so_proto->pr_usrreqs->pru_detach)(so));
214
215         port = so->so_proto->pr_mport(so, NULL, PRU_DETACH);
216         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
217                 lwkt_cmd_func(netmsg_pru_detach), lwkt_cmd_op_none);
218         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_detach;
219         msg.nm_so = so;
220         error = lwkt_domsg(port, &msg.nm_lmsg);
221         return (error);
222 }
223
224 int
225 so_pru_disconnect(struct socket *so)
226 {
227         int error;
228         struct netmsg_pru_disconnect msg;
229         lwkt_port_t port;
230
231         if (!so->so_proto->pr_mport)
232                 return ((*so->so_proto->pr_usrreqs->pru_disconnect)(so));
233
234         port = so->so_proto->pr_mport(so, NULL, PRU_DISCONNECT);
235         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
236                 lwkt_cmd_func(netmsg_pru_disconnect), lwkt_cmd_op_none);
237         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_disconnect;
238         msg.nm_so = so;
239         error = lwkt_domsg(port, &msg.nm_lmsg);
240         return (error);
241 }
242
243 int
244 so_pru_listen(struct socket *so, struct thread *td)
245 {
246         int error;
247         struct netmsg_pru_listen msg;
248         lwkt_port_t port;
249
250         if (!so->so_proto->pr_mport)
251                 return ((*so->so_proto->pr_usrreqs->pru_listen)(so, td));
252
253         port = so->so_proto->pr_mport(so, NULL, PRU_LISTEN);
254         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
255                 lwkt_cmd_func(netmsg_pru_listen), lwkt_cmd_op_none);
256         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_listen;
257         msg.nm_so = so;
258         msg.nm_td = td;         /* used only for prison_ip() XXX JH */
259         error = lwkt_domsg(port, &msg.nm_lmsg);
260         return (error);
261 }
262
263 int
264 so_pru_peeraddr(struct socket *so, struct sockaddr **nam)
265 {
266         int error;
267         struct netmsg_pru_peeraddr msg;
268         lwkt_port_t port;
269
270         if (!so->so_proto->pr_mport)
271                 return ((*so->so_proto->pr_usrreqs->pru_peeraddr)(so, nam));
272
273         port = so->so_proto->pr_mport(so, NULL, PRU_PEERADDR);
274         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
275                 lwkt_cmd_func(netmsg_pru_peeraddr), lwkt_cmd_op_none);
276         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_peeraddr;
277         msg.nm_so = so;
278         msg.nm_nam = nam;
279         error = lwkt_domsg(port, &msg.nm_lmsg);
280         return (error);
281 }
282
283 int
284 so_pru_rcvd(struct socket *so, int flags)
285 {
286         int error;
287         struct netmsg_pru_rcvd msg;
288         lwkt_port_t port;
289
290         if (!so->so_proto->pr_mport)
291                 return ((*so->so_proto->pr_usrreqs->pru_rcvd)(so, flags));
292
293         port = so->so_proto->pr_mport(so, NULL, PRU_RCVD);
294         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
295                 lwkt_cmd_func(netmsg_pru_rcvd), lwkt_cmd_op_none);
296         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_rcvd;
297         msg.nm_so = so;
298         msg.nm_flags = flags;
299         error = lwkt_domsg(port, &msg.nm_lmsg);
300         return (error);
301 }
302
303 int
304 so_pru_rcvoob(struct socket *so, struct mbuf *m, int flags)
305 {
306         int error;
307         struct netmsg_pru_rcvoob msg;
308         lwkt_port_t port;
309
310         if (!so->so_proto->pr_mport)
311                 return ((*so->so_proto->pr_usrreqs->pru_rcvoob)(so, m, flags));
312
313         port = so->so_proto->pr_mport(so, NULL, PRU_RCVOOB);
314         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
315                 lwkt_cmd_func(netmsg_pru_rcvoob), lwkt_cmd_op_none);
316         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_rcvoob;
317         msg.nm_so = so;
318         msg.nm_m = m;
319         msg.nm_flags = flags;
320         error = lwkt_domsg(port, &msg.nm_lmsg);
321         return (error);
322 }
323
324 int
325 so_pru_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
326     struct mbuf *control, struct thread *td)
327 {
328         int error;
329         struct netmsg_pru_send msg;
330         lwkt_port_t port;
331
332         if (!so->so_proto->pr_mport)
333                 return ((*so->so_proto->pr_usrreqs->pru_send)(so, flags, m,
334                     addr, control, td));
335
336         port = so->so_proto->pr_mport(so, NULL, PRU_SEND);
337         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
338                 lwkt_cmd_func(netmsg_pru_send), lwkt_cmd_op_none);
339         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_send;
340         msg.nm_so = so;
341         msg.nm_flags = flags;
342         msg.nm_m = m;
343         msg.nm_addr = addr;
344         msg.nm_control = control;
345         msg.nm_td = td;
346         error = lwkt_domsg(port, &msg.nm_lmsg);
347         return (error);
348 }
349
350 int
351 so_pru_sense(struct socket *so, struct stat *sb)
352 {
353         int error;
354         struct netmsg_pru_sense msg;
355         lwkt_port_t port;
356
357         if (!so->so_proto->pr_mport)
358                 return ((*so->so_proto->pr_usrreqs->pru_sense)(so, sb));
359
360         port = so->so_proto->pr_mport(so, NULL, PRU_SENSE);
361         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
362                 lwkt_cmd_func(netmsg_pru_sense), lwkt_cmd_op_none);
363         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_sense;
364         msg.nm_so = so;
365         msg.nm_stat = sb;
366         error = lwkt_domsg(port, &msg.nm_lmsg);
367         return (error);
368 }
369
370 int
371 so_pru_shutdown(struct socket *so)
372 {
373         int error;
374         struct netmsg_pru_shutdown msg;
375         lwkt_port_t port;
376
377         if (!so->so_proto->pr_mport)
378                 return ((*so->so_proto->pr_usrreqs->pru_shutdown)(so));
379
380         port = so->so_proto->pr_mport(so, NULL, PRU_SHUTDOWN);
381         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
382                 lwkt_cmd_func(netmsg_pru_shutdown), lwkt_cmd_op_none);
383         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_shutdown;
384         msg.nm_so = so;
385         error = lwkt_domsg(port, &msg.nm_lmsg);
386         return (error);
387 }
388
389 int
390 so_pru_sockaddr(struct socket *so, struct sockaddr **nam)
391 {
392         int error;
393         struct netmsg_pru_sockaddr msg;
394         lwkt_port_t port;
395
396         if (!so->so_proto->pr_mport)
397                 return ((*so->so_proto->pr_usrreqs->pru_sockaddr)(so, nam));
398
399         port = so->so_proto->pr_mport(so, NULL, PRU_SOCKADDR);
400         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
401                 lwkt_cmd_func(netmsg_pru_sockaddr), lwkt_cmd_op_none);
402         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_sockaddr;
403         msg.nm_so = so;
404         msg.nm_nam = nam;
405         error = lwkt_domsg(port, &msg.nm_lmsg);
406         return (error);
407 }
408
409 int
410 so_pru_sopoll(struct socket *so, int events, struct ucred *cred,
411     struct thread *td)
412 {
413         int error;
414         struct netmsg_pru_sopoll msg;
415         lwkt_port_t port;
416
417         if (!so->so_proto->pr_mport)
418                 return ((*so->so_proto->pr_usrreqs->pru_sopoll)(so, events,
419                     cred, td));
420
421         port = so->so_proto->pr_mport(so, NULL, PRU_SOPOLL);
422         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
423                 lwkt_cmd_func(netmsg_pru_sopoll), lwkt_cmd_op_none);
424         msg.nm_prufn = so->so_proto->pr_usrreqs->pru_sopoll;
425         msg.nm_so = so;
426         msg.nm_events = events;
427         msg.nm_cred = cred;
428         msg.nm_td = td;
429         error = lwkt_domsg(port, &msg.nm_lmsg);
430         return (error);
431 }
432
433 int
434 so_pr_ctloutput(struct socket *so, struct sockopt *sopt)
435 {
436         return ((*so->so_proto->pr_ctloutput)(so, sopt));
437 #ifdef gag      /* does copyin and copyout deep inside stack XXX JH */
438         struct netmsg_pr_ctloutput msg;
439         lwkt_port_t port;
440         int error;
441
442         if (!so->so_proto->pr_mport)
443                 return ((*so->so_proto->pr_ctloutput)(so, sopt));
444
445         port = so->so_proto->pr_mport(so, NULL);
446         lwkt_initmsg(&msg.nm_lmsg, &curthread->td_msgport, 0,
447                 lwkt_cmd_func(netmsg_pru_ctloutput), lwkt_cmd_op_none);
448         msg.nm_prfn = so->so_proto->pr_ctloutput;
449         msg.nm_so = so;
450         msg.nm_sopt = sopt;
451         error = lwkt_domsg(port, &msg.nm_lmsg);
452         return (error);
453 #endif
454 }
455
456 /*
457  * If we convert all the protosw pr_ functions for all the protocols
458  * to take a message directly, this layer can go away.  For the moment
459  * our dispatcher ignores the return value, but since we are handling
460  * the replymsg ourselves we return EASYNC by convention.
461  */
462 int
463 netmsg_pru_abort(lwkt_msg_t msg)
464 {
465         struct netmsg_pru_abort *nm = (void *)msg;
466
467         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so));
468         return(EASYNC);
469 }
470
471 int
472 netmsg_pru_accept(lwkt_msg_t msg)
473 {
474         struct netmsg_pru_accept *nm = (void *)msg;
475
476         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_nam));
477         return(EASYNC);
478 }
479
480 int
481 netmsg_pru_attach(lwkt_msg_t msg)
482 {
483         struct netmsg_pru_attach *nm = (void *)msg;
484
485         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_proto, nm->nm_ai));
486         return(EASYNC);
487 }
488
489 int
490 netmsg_pru_bind(lwkt_msg_t msg)
491 {
492         struct netmsg_pru_bind *nm = (void *)msg;
493
494         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_nam, nm->nm_td));
495         return(EASYNC);
496 }
497
498 int
499 netmsg_pru_connect(lwkt_msg_t msg)
500 {
501         struct netmsg_pru_connect *nm = (void *)msg;
502
503         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_nam, nm->nm_td));
504         return(EASYNC);
505 }
506
507 int
508 netmsg_pru_connect2(lwkt_msg_t msg)
509 {
510         struct netmsg_pru_connect2 *nm = (void *)msg;
511
512         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so1, nm->nm_so2));
513         return(EASYNC);
514 }
515
516 int
517 netmsg_pru_control(lwkt_msg_t msg)
518 {
519         struct netmsg_pru_control *nm = (void *)msg;
520         int error;
521
522         error = nm->nm_prufn(nm->nm_so, nm->nm_cmd, nm->nm_data,
523                                 nm->nm_ifp, nm->nm_td);
524         lwkt_replymsg(msg, error);
525         return(EASYNC);
526 }
527
528 int
529 netmsg_pru_detach(lwkt_msg_t msg)
530 {
531         struct netmsg_pru_detach *nm = (void *)msg;
532
533         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so));
534         return(EASYNC);
535 }
536
537 int
538 netmsg_pru_disconnect(lwkt_msg_t msg)
539 {
540         struct netmsg_pru_disconnect *nm = (void *)msg;
541
542         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so));
543         return(EASYNC);
544 }
545
546 int
547 netmsg_pru_listen(lwkt_msg_t msg)
548 {
549         struct netmsg_pru_listen *nm = (void *)msg;
550
551         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_td));
552         return(EASYNC);
553 }
554
555 int
556 netmsg_pru_peeraddr(lwkt_msg_t msg)
557 {
558         struct netmsg_pru_peeraddr *nm = (void *)msg;
559
560         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_nam));
561         return(EASYNC);
562 }
563
564 int
565 netmsg_pru_rcvd(lwkt_msg_t msg)
566 {
567         struct netmsg_pru_rcvd *nm = (void *)msg;
568
569         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_flags));
570         return(EASYNC);
571 }
572
573 int
574 netmsg_pru_rcvoob(lwkt_msg_t msg)
575 {
576         struct netmsg_pru_rcvoob *nm = (void *)msg;
577
578         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_m, nm->nm_flags));
579         return(EASYNC);
580 }
581
582 int
583 netmsg_pru_send(lwkt_msg_t msg)
584 {
585         struct netmsg_pru_send *nm = (void *)msg;
586         int error;
587
588         error = nm->nm_prufn(nm->nm_so, nm->nm_flags, nm->nm_m,
589                                 nm->nm_addr, nm->nm_control, nm->nm_td);
590         lwkt_replymsg(msg, error);
591         return(EASYNC);
592 }
593
594 int
595 netmsg_pru_sense(lwkt_msg_t msg)
596 {
597         struct netmsg_pru_sense *nm = (void *)msg;
598
599         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_stat));
600         return(EASYNC);
601 }
602
603 int
604 netmsg_pru_shutdown(lwkt_msg_t msg)
605 {
606         struct netmsg_pru_shutdown *nm = (void *)msg;
607
608         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so));
609         return(EASYNC);
610 }
611
612 int
613 netmsg_pru_sockaddr(lwkt_msg_t msg)
614 {
615         struct netmsg_pru_sockaddr *nm = (void *)msg;
616
617         lwkt_replymsg(msg, nm->nm_prufn(nm->nm_so, nm->nm_nam));
618         return(EASYNC);
619 }
620
621 int
622 netmsg_pru_sopoll(lwkt_msg_t msg)
623 {
624         struct netmsg_pru_sopoll *nm = (void *)msg;
625         int error;
626
627         error = nm->nm_prufn(nm->nm_so, nm->nm_events, nm->nm_cred, nm->nm_td);
628         lwkt_replymsg(msg, error);
629         return(EASYNC);
630 }
631
632 int
633 netmsg_pr_ctloutput(lwkt_msg_t msg)
634 {
635         struct netmsg_pr_ctloutput *nm = (void *)msg;
636
637         lwkt_replymsg(msg, nm->nm_prfn(nm->nm_so, nm->nm_sopt));
638         return(EASYNC);
639 }
640
641 int
642 netmsg_pr_timeout(lwkt_msg_t msg)
643 {
644         struct netmsg_pr_timeout *nm = (void *)msg;
645
646         lwkt_replymsg(msg, nm->nm_prfn());
647         return(EASYNC);
648 }
649
650 /*
651  * Handle a predicate event request.  This function is only called once
652  * when the predicate message queueing request is received.
653  */
654 int
655 netmsg_so_notify(lwkt_msg_t lmsg)
656 {
657         struct netmsg_so_notify *msg = (void *)lmsg;
658         struct sockbuf *sb;
659
660         sb = (msg->nm_etype & NM_REVENT) ?
661                         &msg->nm_so->so_rcv :
662                         &msg->nm_so->so_snd;
663
664         /*
665          * Reply immediately if the event has occured, otherwise queue the
666          * request.
667          */
668         if (msg->nm_predicate((struct netmsg *)msg)) {
669                 lwkt_replymsg(lmsg, lmsg->ms_error);
670         } else {
671                 TAILQ_INSERT_TAIL(&sb->sb_sel.si_mlist, msg, nm_list);
672                 sb->sb_flags |= SB_MEVENT;
673         }
674         return(EASYNC);
675 }
676
677 /*
678  * Predicate requests can be aborted.  This function is only called once
679  * and will interlock against processing/reply races (since such races
680  * occur on the same thread that controls the port where the abort is 
681  * requeued).
682  */
683 int
684 netmsg_so_notify_abort(lwkt_msg_t lmsg)
685 {
686         struct netmsg_so_notify *msg = (void *)lmsg;
687         struct sockbuf *sb;
688
689         sb = (msg->nm_etype & NM_REVENT) ?
690                         &msg->nm_so->so_rcv :
691                         &msg->nm_so->so_snd;
692         TAILQ_REMOVE(&sb->sb_sel.si_mlist, msg, nm_list);
693         lwkt_replymsg(lmsg, EINTR);
694         return(EASYNC);
695 }
696