kernel - Wait for I/O to finish in vm_object_terminate()
[dragonfly.git] / sys / netproto / atalk / ddp_usrreq.c
1 /*
2  * Copyright (c) 1990,1994 Regents of The University of Michigan.
3  * All Rights Reserved.  See COPYRIGHT.
4  *
5  * $DragonFly: src/sys/netproto/atalk/ddp_usrreq.c,v 1.14 2008/09/24 14:26:39 sephe Exp $
6  */
7
8 #include <sys/param.h>
9 #include <sys/systm.h>
10 #include <sys/proc.h>
11 #include <sys/priv.h>
12 #include <sys/malloc.h>
13 #include <sys/mbuf.h>
14 #include <sys/socket.h>
15 #include <sys/socketvar.h>
16 #include <sys/protosw.h>
17
18 #include <sys/thread2.h>
19 #include <sys/socketvar2.h>
20 #include <sys/mplock2.h>
21 #include <sys/msgport2.h>
22
23 #include <net/if.h>
24 #include <net/netisr.h>
25 #include <net/route.h>
26
27 #include "at.h"
28 #include "at_var.h"
29 #include "ddp_var.h"
30 #include "at_extern.h"
31
32 static void at_pcbdisconnect( struct ddpcb *ddp );
33 static void at_sockaddr(struct ddpcb *ddp, struct sockaddr **addr);
34 static int at_pcbsetaddr(struct ddpcb *ddp, struct sockaddr *addr,
35                           struct thread *td);
36 static int at_pcbconnect(struct ddpcb *ddp, struct sockaddr *addr, 
37                          struct thread *td);
38 static void at_pcbdetach(struct socket *so, struct ddpcb *ddp);
39 static int at_pcballoc(struct socket *so);
40
41 struct ddpcb    *ddp_ports[ ATPORT_LAST ];
42 struct ddpcb    *ddpcb = NULL;
43 static u_long   ddp_sendspace = DDP_MAXSZ; /* Max ddp size + 1 (ddp_type) */
44 static u_long   ddp_recvspace = 10 * ( 587 + sizeof( struct sockaddr_at ));
45
46 static void
47 ddp_attach(netmsg_t msg)
48 {
49         struct socket *so = msg->attach.base.nm_so;
50         struct pru_attach_info *ai = msg->attach.nm_ai;
51         struct ddpcb    *ddp;
52         int error;
53
54         ddp = sotoddpcb(so);
55         if (ddp != NULL) {
56                 error = EINVAL;
57                 goto out;
58         }
59
60         error = at_pcballoc(so);
61         if (error == 0) {
62                 error = soreserve(so, ddp_sendspace, ddp_recvspace,
63                                   ai->sb_rlimit);
64         }
65 out:
66         lwkt_replymsg(&msg->attach.base.lmsg, error);
67 }
68
69 static void
70 ddp_detach(netmsg_t msg)
71 {
72         struct socket *so = msg->detach.base.nm_so;
73         struct ddpcb    *ddp;
74         int error;
75         
76         ddp = sotoddpcb(so);
77         if (ddp == NULL) {
78                 error = EINVAL;
79         } else {
80                 at_pcbdetach(so, ddp);
81                 error = 0;
82         }
83         lwkt_replymsg(&msg->detach.base.lmsg, error);
84 }
85
86 static void
87 ddp_bind(netmsg_t msg)
88 {
89         struct socket *so = msg->bind.base.nm_so;
90         struct ddpcb *ddp;
91         int error;
92         
93         ddp = sotoddpcb(so);
94         if (ddp) {
95                 error = at_pcbsetaddr(ddp, msg->bind.nm_nam, msg->bind.nm_td);
96         } else {
97                 error = EINVAL;
98         }
99         lwkt_replymsg(&msg->bind.base.lmsg, error);
100 }
101     
102 static void
103 ddp_connect(netmsg_t msg)
104 {
105         struct socket *so = msg->connect.base.nm_so;
106         struct ddpcb *ddp;
107         int error;
108         
109         ddp = sotoddpcb(so);
110         if (ddp == NULL) {
111                 error = EINVAL;
112         } else if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT ) {
113                 error = EISCONN;
114         } else {
115                 error = at_pcbconnect(ddp, msg->connect.nm_nam,
116                                       msg->connect.nm_td);
117                 if (error == 0)
118                         soisconnected(so);
119         }
120         lwkt_replymsg(&msg->connect.base.lmsg, error);
121 }
122
123 static void
124 ddp_disconnect(netmsg_t msg)
125 {
126         struct socket *so = msg->disconnect.base.nm_so;
127         struct ddpcb *ddp;
128         int error;
129         
130         ddp = sotoddpcb(so);
131         if (ddp == NULL) {
132                 error = EINVAL;
133         } else if (ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE) {
134                 error = ENOTCONN;
135         } else {
136                 soreference(so);
137                 at_pcbdisconnect(ddp);
138                 ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
139                 soisdisconnected(so);
140                 sofree(so);             /* soref above */
141                 error = 0;
142         }
143         lwkt_replymsg(&msg->disconnect.base.lmsg, error);
144 }
145
146 static void
147 ddp_shutdown(netmsg_t msg)
148 {
149         struct socket *so = msg->shutdown.base.nm_so;
150         struct ddpcb    *ddp;
151         int error;
152
153         ddp = sotoddpcb(so);
154         if (ddp) {
155                 socantsendmore(so);
156                 error = 0;
157         } else {
158                 error = EINVAL;
159         }
160         lwkt_replymsg(&msg->shutdown.base.lmsg, error);
161 }
162
163 static void
164 ddp_send(netmsg_t msg)
165 {
166         struct socket *so = msg->send.base.nm_so;
167         struct mbuf *m = msg->send.nm_m;
168         struct sockaddr *addr = msg->send.nm_addr;
169         struct mbuf *control = msg->send.nm_control;
170         struct ddpcb *ddp;
171         int error;
172         
173         ddp = sotoddpcb(so);
174         if (ddp == NULL) {
175                 error = EINVAL;
176                 goto out;
177         }
178
179         if (control && control->m_len) {
180                 error = EINVAL;
181                 goto out;
182         }
183
184         if (addr) {
185                 if (ddp->ddp_fsat.sat_port != ATADDR_ANYPORT) {
186                         error = EISCONN;
187                         goto out;
188                 }
189
190                 error = at_pcbconnect(ddp, addr, msg->send.nm_td);
191                 if (error)
192                         goto out;
193         } else {
194                 if (ddp->ddp_fsat.sat_port == ATADDR_ANYPORT) {
195                         error = ENOTCONN;
196                         goto out;
197                 }
198         }
199
200         error = ddp_output(m, so);
201         m = NULL;
202         if (addr) {
203                 at_pcbdisconnect(ddp);
204         }
205 out:
206         if (m)
207                 m_freem(m);
208         if (control)
209                 m_freem(control);
210         lwkt_replymsg(&msg->send.base.lmsg, error);
211 }
212
213 /*
214  * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
215  *       will sofree() it when we return.
216  */
217 static void
218 ddp_abort(netmsg_t msg)
219 {
220         struct socket *so = msg->abort.base.nm_so;
221         struct ddpcb *ddp;
222         int error;
223         
224         ddp = sotoddpcb(so);
225         if (ddp) {
226                 soisdisconnected( so );
227                 at_pcbdetach( so, ddp );
228                 error = 0;
229         } else {
230                 error = EINVAL;
231         }
232         lwkt_replymsg(&msg->abort.base.lmsg, error);
233 }
234
235 static void
236 ddp_setpeeraddr(netmsg_t msg)
237 {
238         lwkt_replymsg(&msg->peeraddr.base.lmsg, EOPNOTSUPP);
239 }
240
241 static void
242 ddp_setsockaddr(netmsg_t msg)
243 {
244         struct socket *so = msg->sockaddr.base.nm_so;
245         struct sockaddr **nam = msg->sockaddr.nm_nam;
246         struct ddpcb    *ddp;
247         int error;
248
249         ddp = sotoddpcb(so);
250         if (ddp) {
251                 at_sockaddr(ddp, nam);
252                 error = 0;
253         } else {
254                 error = EINVAL;
255         }
256         lwkt_replymsg(&msg->sockaddr.base.lmsg, error);
257 }
258
259 static void
260 ddp_control(netmsg_t msg)
261 {
262         struct socket *so = msg->control.base.nm_so;
263         int error;
264
265         error = at_control(so, msg->control.nm_cmd,
266                            msg->control.nm_data,
267                            msg->control.nm_ifp,
268                            msg->control.nm_td);
269         lwkt_replymsg(&msg->control.base.lmsg, error);
270 }
271
272
273 static void
274 at_sockaddr(struct ddpcb *ddp, struct sockaddr **addr)
275 {
276     *addr = dup_sockaddr((struct sockaddr *)&ddp->ddp_lsat);
277 }
278
279 static int 
280 at_pcbsetaddr(struct ddpcb *ddp, struct sockaddr *addr, struct thread *td)
281 {
282     struct sockaddr_at  lsat, *sat;
283     struct at_ifaddr    *aa;
284     struct ddpcb        *ddpp;
285
286     if ( ddp->ddp_lsat.sat_port != ATADDR_ANYPORT ) { /* shouldn't be bound */
287         return( EINVAL );
288     }
289
290     if (addr != 0) {                    /* validate passed address */
291         sat = (struct sockaddr_at *)addr;
292         if (sat->sat_family != AF_APPLETALK) {
293             return(EAFNOSUPPORT);
294         }
295
296         if ( sat->sat_addr.s_node != ATADDR_ANYNODE ||
297                 sat->sat_addr.s_net != ATADDR_ANYNET ) {
298             for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
299                 if (( sat->sat_addr.s_net == AA_SAT( aa )->sat_addr.s_net ) &&
300                  ( sat->sat_addr.s_node == AA_SAT( aa )->sat_addr.s_node )) {
301                     break;
302                 }
303             }
304             if ( !aa ) {
305                 return( EADDRNOTAVAIL );
306             }
307         }
308
309         if ( sat->sat_port != ATADDR_ANYPORT ) {
310             if ( sat->sat_port < ATPORT_FIRST ||
311                     sat->sat_port >= ATPORT_LAST ) {
312                 return( EINVAL );
313             }
314             if ( sat->sat_port < ATPORT_RESERVED &&
315                  priv_check(td, PRIV_ROOT) ) {
316                 return( EACCES );
317             }
318         }
319     } else {
320         bzero( (caddr_t)&lsat, sizeof( struct sockaddr_at ));
321         lsat.sat_len = sizeof(struct sockaddr_at);
322         lsat.sat_addr.s_node = ATADDR_ANYNODE;
323         lsat.sat_addr.s_net = ATADDR_ANYNET;
324         lsat.sat_family = AF_APPLETALK;
325         sat = &lsat;
326     }
327
328     if ( sat->sat_addr.s_node == ATADDR_ANYNODE &&
329             sat->sat_addr.s_net == ATADDR_ANYNET ) {
330         if ( at_ifaddr == NULL ) {
331             return( EADDRNOTAVAIL );
332         }
333         sat->sat_addr = AA_SAT( at_ifaddr )->sat_addr;
334     }
335     ddp->ddp_lsat = *sat;
336
337     /*
338      * Choose port.
339      */
340     if ( sat->sat_port == ATADDR_ANYPORT ) {
341         for ( sat->sat_port = ATPORT_RESERVED;
342                 sat->sat_port < ATPORT_LAST; sat->sat_port++ ) {
343             if ( ddp_ports[ sat->sat_port - 1 ] == 0 ) {
344                 break;
345             }
346         }
347         if ( sat->sat_port == ATPORT_LAST ) {
348             return( EADDRNOTAVAIL );
349         }
350         ddp->ddp_lsat.sat_port = sat->sat_port;
351         ddp_ports[ sat->sat_port - 1 ] = ddp;
352     } else {
353         for ( ddpp = ddp_ports[ sat->sat_port - 1 ]; ddpp;
354                 ddpp = ddpp->ddp_pnext ) {
355             if ( ddpp->ddp_lsat.sat_addr.s_net == sat->sat_addr.s_net &&
356                     ddpp->ddp_lsat.sat_addr.s_node == sat->sat_addr.s_node ) {
357                 break;
358             }
359         }
360         if ( ddpp != NULL ) {
361             return( EADDRINUSE );
362         }
363         ddp->ddp_pnext = ddp_ports[ sat->sat_port - 1 ];
364         ddp_ports[ sat->sat_port - 1 ] = ddp;
365         if ( ddp->ddp_pnext ) {
366             ddp->ddp_pnext->ddp_pprev = ddp;
367         }
368     }
369
370     return( 0 );
371 }
372
373 static int
374 at_pcbconnect(struct ddpcb *ddp, struct sockaddr *addr, struct thread *td)
375 {
376     struct sockaddr_at  *sat = (struct sockaddr_at *)addr;
377     struct route        *ro;
378     struct at_ifaddr    *aa = 0;
379     struct ifnet        *ifp;
380     u_short             hintnet = 0, net;
381
382     if (sat->sat_family != AF_APPLETALK) {
383         return(EAFNOSUPPORT);
384     }
385
386     /*
387      * Under phase 2, network 0 means "the network".  We take "the
388      * network" to mean the network the control block is bound to.
389      * If the control block is not bound, there is an error.
390      */
391     if ( sat->sat_addr.s_net == ATADDR_ANYNET
392                 && sat->sat_addr.s_node != ATADDR_ANYNODE ) {
393         if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) {
394             return( EADDRNOTAVAIL );
395         }
396         hintnet = ddp->ddp_lsat.sat_addr.s_net;
397     }
398
399     ro = &ddp->ddp_route;
400     /*
401      * If we've got an old route for this pcb, check that it is valid.
402      * If we've changed our address, we may have an old "good looking"
403      * route here.  Attempt to detect it.
404      */
405     if ( ro->ro_rt ) {
406         if ( hintnet ) {
407             net = hintnet;
408         } else {
409             net = sat->sat_addr.s_net;
410         }
411         aa = 0;
412         if ((ifp = ro->ro_rt->rt_ifp) != NULL) {
413             for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
414                 if ( aa->aa_ifp == ifp &&
415                         ntohs( net ) >= ntohs( aa->aa_firstnet ) &&
416                         ntohs( net ) <= ntohs( aa->aa_lastnet )) {
417                     break;
418                 }
419             }
420         }
421         if ( aa == NULL || ( satosat( &ro->ro_dst )->sat_addr.s_net !=
422                 ( hintnet ? hintnet : sat->sat_addr.s_net ) ||
423                 satosat( &ro->ro_dst )->sat_addr.s_node !=
424                 sat->sat_addr.s_node )) {
425             RTFREE( ro->ro_rt );
426             ro->ro_rt = NULL;
427         }
428     }
429
430     /*
431      * If we've got no route for this interface, try to find one.
432      */
433     if ( ro->ro_rt == NULL ||
434          ro->ro_rt->rt_ifp == NULL ) {
435         ro->ro_dst.sa_len = sizeof( struct sockaddr_at );
436         ro->ro_dst.sa_family = AF_APPLETALK;
437         if ( hintnet ) {
438             satosat( &ro->ro_dst )->sat_addr.s_net = hintnet;
439         } else {
440             satosat( &ro->ro_dst )->sat_addr.s_net = sat->sat_addr.s_net;
441         }
442         satosat( &ro->ro_dst )->sat_addr.s_node = sat->sat_addr.s_node;
443         rtalloc( ro );
444     }
445
446     /*
447      * Make sure any route that we have has a valid interface.
448      */
449     aa = 0;
450     if ( ro->ro_rt && ( ifp = ro->ro_rt->rt_ifp )) {
451         for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
452             if ( aa->aa_ifp == ifp ) {
453                 break;
454             }
455         }
456     }
457     if ( aa == 0 ) {
458         return( ENETUNREACH );
459     }
460
461     ddp->ddp_fsat = *sat;
462     if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) {
463         return(at_pcbsetaddr(ddp, NULL, td));
464     }
465     return( 0 );
466 }
467
468 static void 
469 at_pcbdisconnect( struct ddpcb  *ddp )
470 {
471     ddp->ddp_fsat.sat_addr.s_net = ATADDR_ANYNET;
472     ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
473     ddp->ddp_fsat.sat_port = ATADDR_ANYPORT;
474 }
475
476 static int
477 at_pcballoc( struct socket *so )
478 {
479         struct ddpcb    *ddp;
480
481         MALLOC(ddp, struct ddpcb *, sizeof *ddp, M_PCB, M_WAITOK | M_ZERO);
482         ddp->ddp_lsat.sat_port = ATADDR_ANYPORT;
483
484         ddp->ddp_next = ddpcb;
485         ddp->ddp_prev = NULL;
486         ddp->ddp_pprev = NULL;
487         ddp->ddp_pnext = NULL;
488         if (ddpcb) {
489                 ddpcb->ddp_prev = ddp;
490         }
491         ddpcb = ddp;
492
493         ddp->ddp_socket = so;
494         so->so_pcb = (caddr_t)ddp;
495         return(0);
496 }
497
498 static void
499 at_pcbdetach( struct socket *so, struct ddpcb *ddp)
500 {
501     soisdisconnected(so);
502     so->so_pcb = NULL;
503     sofree(so);
504
505     /* remove ddp from ddp_ports list */
506     if ( ddp->ddp_lsat.sat_port != ATADDR_ANYPORT &&
507             ddp_ports[ ddp->ddp_lsat.sat_port - 1 ] != NULL ) {
508         if ( ddp->ddp_pprev != NULL ) {
509             ddp->ddp_pprev->ddp_pnext = ddp->ddp_pnext;
510         } else {
511             ddp_ports[ ddp->ddp_lsat.sat_port - 1 ] = ddp->ddp_pnext;
512         }
513         if ( ddp->ddp_pnext != NULL ) {
514             ddp->ddp_pnext->ddp_pprev = ddp->ddp_pprev;
515         }
516     }
517
518     if ( ddp->ddp_route.ro_rt ) {
519         rtfree( ddp->ddp_route.ro_rt );
520     }
521
522     if ( ddp->ddp_prev ) {
523         ddp->ddp_prev->ddp_next = ddp->ddp_next;
524     } else {
525         ddpcb = ddp->ddp_next;
526     }
527     if ( ddp->ddp_next ) {
528         ddp->ddp_next->ddp_prev = ddp->ddp_prev;
529     }
530     FREE(ddp, M_PCB);
531 }
532
533 /*
534  * For the moment, this just find the pcb with the correct local address.
535  * In the future, this will actually do some real searching, so we can use
536  * the sender's address to do de-multiplexing on a single port to many
537  * sockets (pcbs).
538  */
539 struct ddpcb *
540 ddp_search( struct sockaddr_at *from, struct sockaddr_at *to,
541                         struct at_ifaddr *aa)
542 {
543     struct ddpcb        *ddp;
544
545     /*
546      * Check for bad ports.
547      */
548     if ( to->sat_port < ATPORT_FIRST || to->sat_port >= ATPORT_LAST ) {
549         return( NULL );
550     }
551
552     /*
553      * Make sure the local address matches the sent address.  What about
554      * the interface?
555      */
556     for ( ddp = ddp_ports[ to->sat_port - 1 ]; ddp; ddp = ddp->ddp_pnext ) {
557         /* XXX should we handle 0.YY? */
558
559         /* XXXX.YY to socket on destination interface */
560         if ( to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net &&
561                 to->sat_addr.s_node == ddp->ddp_lsat.sat_addr.s_node ) {
562             break;
563         }
564
565         /* 0.255 to socket on receiving interface */
566         if ( to->sat_addr.s_node == ATADDR_BCAST && ( to->sat_addr.s_net == 0 ||
567                 to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net ) &&
568                 ddp->ddp_lsat.sat_addr.s_net == AA_SAT( aa )->sat_addr.s_net ) {
569             break;
570         }
571
572         /* XXXX.0 to socket on destination interface */
573         if ( to->sat_addr.s_net == aa->aa_firstnet &&
574                 to->sat_addr.s_node == 0 &&
575                 ntohs( ddp->ddp_lsat.sat_addr.s_net ) >=
576                 ntohs( aa->aa_firstnet ) &&
577                 ntohs( ddp->ddp_lsat.sat_addr.s_net ) <=
578                 ntohs( aa->aa_lastnet )) {
579             break;
580         }
581     }
582     return( ddp );
583 }
584
585 void 
586 ddp_init(void)
587 {
588         netisr_register(NETISR_ATALK1, at1intr, NULL);
589         netisr_register(NETISR_ATALK2, at2intr, NULL);
590         netisr_register(NETISR_AARP, aarpintr, NULL);
591 }
592
593 #if 0
594 static void 
595 ddp_clean(void)
596 {
597     struct ddpcb        *ddp;
598
599     for ( ddp = ddpcb; ddp; ddp = ddp->ddp_next ) {
600         at_pcbdetach( ddp->ddp_socket, ddp );
601     }
602 }
603 #endif
604
605 struct pr_usrreqs ddp_usrreqs = {
606         .pru_abort = ddp_abort,
607         .pru_accept = pr_generic_notsupp,
608         .pru_attach = ddp_attach,
609         .pru_bind = ddp_bind,
610         .pru_connect = ddp_connect,
611         .pru_connect2 = pr_generic_notsupp,
612         .pru_control = ddp_control,
613         .pru_detach = ddp_detach,
614         .pru_disconnect = ddp_disconnect,
615         .pru_listen = pr_generic_notsupp,
616         .pru_peeraddr = ddp_setpeeraddr,
617         .pru_rcvd = pr_generic_notsupp,
618         .pru_rcvoob = pr_generic_notsupp,
619         .pru_send = ddp_send,
620         .pru_sense = pru_sense_null,
621         .pru_shutdown = ddp_shutdown,
622         .pru_sockaddr = ddp_setsockaddr,
623         .pru_sosend = sosend,
624         .pru_soreceive = soreceive
625 };