The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netatalk/ddp_usrreq.c

Version: -  FREEBSD  -  FREEBSD11  -  FREEBSD10  -  FREEBSD9  -  FREEBSD92  -  FREEBSD91  -  FREEBSD90  -  FREEBSD8  -  FREEBSD82  -  FREEBSD81  -  FREEBSD80  -  FREEBSD7  -  FREEBSD74  -  FREEBSD73  -  FREEBSD72  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

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

Cache object: 939d1e99adce4a86a912aabc2636a898


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.