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_input.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
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$
    6  */
    7 
    8 #include <sys/param.h>
    9 #include <sys/systm.h>
   10 #include <sys/kernel.h>
   11 #include <net/netisr.h>
   12 #include <sys/mbuf.h>
   13 #include <sys/socket.h>
   14 #include <sys/socketvar.h>
   15 #include <net/if.h>
   16 #include <net/route.h>
   17 #include <net/intrq.h>
   18 
   19 #include <netatalk/at.h>
   20 #include <netatalk/at_var.h>
   21 #include <netatalk/ddp.h>
   22 #include <netatalk/ddp_var.h>
   23 #include <netatalk/at_extern.h>
   24 
   25 static volatile int     ddp_forward = 1;
   26 static volatile int     ddp_firewall = 0;
   27 static struct ddpstat   ddpstat;
   28 static struct route     forwro;
   29 
   30 const int atintrq1_present = 1, atintrq2_present = 1;
   31 
   32 static void     ddp_input(struct mbuf *, struct ifnet *, struct elaphdr *, int);
   33 
   34 /*
   35  * Could probably merge these two code segments a little better...
   36  */
   37 static void
   38 atintr( void )
   39 {
   40     struct elaphdr      *elhp, elh;
   41     struct ifnet        *ifp;
   42     struct mbuf         *m;
   43     int                 s;
   44 
   45     /*
   46      * First pull off all the phase 2 packets.
   47      */
   48     for (;;) {
   49         s = splimp();
   50 
   51         IF_DEQUEUE( &atintrq2, m );
   52 
   53         splx( s );
   54 
   55         if ( m == 0 ) {                 /* no more queued packets */
   56             break;
   57         }
   58 
   59         ifp = m->m_pkthdr.rcvif;
   60         ddp_input( m, ifp, (struct elaphdr *)NULL, 2 );
   61     }
   62 
   63     /*
   64      * Then pull off all the phase 1 packets.
   65      */
   66     for (;;) {
   67         s = splimp();
   68 
   69         IF_DEQUEUE( &atintrq1, m );
   70 
   71         splx( s );
   72 
   73         if ( m == 0 ) {                 /* no more queued packets */
   74             break;
   75         }
   76 
   77         ifp = m->m_pkthdr.rcvif;
   78 
   79         if ( m->m_len < SZ_ELAPHDR &&
   80                 (( m = m_pullup( m, SZ_ELAPHDR )) == 0 )) {
   81             ddpstat.ddps_tooshort++;
   82             continue;
   83         }
   84 
   85         /*
   86          * this seems a little dubios, but I don't know phase 1 so leave it.
   87          */
   88         elhp = mtod( m, struct elaphdr *);
   89         m_adj( m, SZ_ELAPHDR );
   90 
   91         if ( elhp->el_type == ELAP_DDPEXTEND ) {
   92             ddp_input( m, ifp, (struct elaphdr *)NULL, 1 );
   93         } else {
   94             bcopy((caddr_t)elhp, (caddr_t)&elh, SZ_ELAPHDR );
   95             ddp_input( m, ifp, &elh, 1 );
   96         }
   97     }
   98     return;
   99 }
  100 
  101 static void
  102 netisr_atalk_setup(void *dummy __unused)
  103 {
  104         
  105         register_netisr(NETISR_ATALK, atintr);
  106 }
  107 SYSINIT(atalk_setup, SI_SUB_CPU, SI_ORDER_ANY, netisr_atalk_setup, NULL);
  108 
  109 static void
  110 ddp_input( m, ifp, elh, phase )
  111     struct mbuf         *m;
  112     struct ifnet        *ifp;
  113     struct elaphdr      *elh;
  114     int                 phase;
  115 {
  116     struct sockaddr_at  from, to;
  117     struct ddpshdr      *dsh, ddps;
  118     struct at_ifaddr    *aa;
  119     struct ddpehdr      *deh = NULL, ddpe;
  120     struct ddpcb        *ddp;
  121     int                 dlen, mlen;
  122     u_short             cksum = 0;
  123 
  124     bzero( (caddr_t)&from, sizeof( struct sockaddr_at ));
  125     bzero( (caddr_t)&to, sizeof( struct sockaddr_at ));
  126     if ( elh ) {
  127         /*
  128          * Extract the information in the short header.
  129          * netowrk information is defaulted to ATADDR_ANYNET
  130          * and node information comes from the elh info.
  131          * We must be phase 1.
  132          */
  133         ddpstat.ddps_short++;
  134 
  135         if ( m->m_len < sizeof( struct ddpshdr ) &&
  136                 (( m = m_pullup( m, sizeof( struct ddpshdr ))) == 0 )) {
  137             ddpstat.ddps_tooshort++;
  138             return;
  139         }
  140 
  141         dsh = mtod( m, struct ddpshdr *);
  142         bcopy( (caddr_t)dsh, (caddr_t)&ddps, sizeof( struct ddpshdr ));
  143         ddps.dsh_bytes = ntohl( ddps.dsh_bytes );
  144         dlen = ddps.dsh_len;
  145 
  146         to.sat_addr.s_net = ATADDR_ANYNET;
  147         to.sat_addr.s_node = elh->el_dnode;
  148         to.sat_port = ddps.dsh_dport;
  149         from.sat_addr.s_net = ATADDR_ANYNET;
  150         from.sat_addr.s_node = elh->el_snode;
  151         from.sat_port = ddps.dsh_sport;
  152 
  153         /* 
  154          * Make sure that we point to the phase1 ifaddr info 
  155          * and that it's valid for this packet.
  156          */
  157         for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
  158             if ( (aa->aa_ifp == ifp)
  159             && ( (aa->aa_flags & AFA_PHASE2) == 0)
  160             && ( (to.sat_addr.s_node == AA_SAT( aa )->sat_addr.s_node)
  161               || (to.sat_addr.s_node == ATADDR_BCAST))) {
  162                 break;
  163             }
  164         }
  165         /* 
  166          * maybe we got a broadcast not meant for us.. ditch it.
  167          */
  168         if ( aa == NULL ) {
  169             m_freem( m );
  170             return;
  171         }
  172     } else {
  173         /*
  174          * There was no 'elh' passed on. This could still be
  175          * either phase1 or phase2.
  176          * We have a long header, but we may be running on a phase 1 net.
  177          * Extract out all the info regarding this packet's src & dst.
  178          */
  179         ddpstat.ddps_long++;
  180 
  181         if ( m->m_len < sizeof( struct ddpehdr ) &&
  182                 (( m = m_pullup( m, sizeof( struct ddpehdr ))) == 0 )) {
  183             ddpstat.ddps_tooshort++;
  184             return;
  185         }
  186 
  187         deh = mtod( m, struct ddpehdr *);
  188         bcopy( (caddr_t)deh, (caddr_t)&ddpe, sizeof( struct ddpehdr ));
  189         ddpe.deh_bytes = ntohl( ddpe.deh_bytes );
  190         dlen = ddpe.deh_len;
  191 
  192         if (( cksum = ddpe.deh_sum ) == 0 ) {
  193             ddpstat.ddps_nosum++;
  194         }
  195 
  196         from.sat_addr.s_net = ddpe.deh_snet;
  197         from.sat_addr.s_node = ddpe.deh_snode;
  198         from.sat_port = ddpe.deh_sport;
  199         to.sat_addr.s_net = ddpe.deh_dnet;
  200         to.sat_addr.s_node = ddpe.deh_dnode;
  201         to.sat_port = ddpe.deh_dport;
  202 
  203         if ( to.sat_addr.s_net == ATADDR_ANYNET ) {
  204             /*
  205              * The TO address doesn't specify a net,
  206              * So by definition it's for this net.
  207              * Try find ifaddr info with the right phase, 
  208              * the right interface, and either to our node, a broadcast,
  209              * or looped back (though that SHOULD be covered in the other
  210              * cases).
  211              *
  212              * XXX If we have multiple interfaces, then the first with
  213              * this node number will match (which may NOT be what we want,
  214              * but it's probably safe in 99.999% of cases.
  215              */
  216             for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
  217                 if ( phase == 1 && ( aa->aa_flags & AFA_PHASE2 )) {
  218                     continue;
  219                 }
  220                 if ( phase == 2 && ( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
  221                     continue;
  222                 }
  223                 if ( (aa->aa_ifp == ifp)
  224                 && ( (to.sat_addr.s_node == AA_SAT( aa )->sat_addr.s_node)
  225                   || (to.sat_addr.s_node == ATADDR_BCAST)
  226                   || (ifp->if_flags & IFF_LOOPBACK))) {
  227                     break;
  228                 }
  229             }
  230         } else {
  231             /* 
  232              * A destination network was given. We just try to find 
  233              * which ifaddr info matches it.
  234              */
  235             for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
  236                 /*
  237                  * This is a kludge. Accept packets that are
  238                  * for any router on a local netrange.
  239                  */
  240                 if ( to.sat_addr.s_net == aa->aa_firstnet &&
  241                         to.sat_addr.s_node == 0 ) {
  242                     break;
  243                 }
  244                 /*
  245                  * Don't use ifaddr info for which we are totally outside the
  246                  * netrange, and it's not a startup packet.
  247                  * Startup packets are always implicitly allowed on to
  248                  * the next test.
  249                  */
  250                 if ((( ntohs( to.sat_addr.s_net ) < ntohs( aa->aa_firstnet ))
  251                     || (ntohs( to.sat_addr.s_net ) > ntohs( aa->aa_lastnet )))
  252                  && (( ntohs( to.sat_addr.s_net ) < 0xff00)
  253                     || (ntohs( to.sat_addr.s_net ) > 0xfffe ))) {
  254                     continue;
  255                 }
  256 
  257                 /*
  258                  * Don't record a match either if we just don't have a match
  259                  * in the node address. This can have if the interface
  260                  * is in promiscuous mode for example.
  261                  */
  262                 if (( to.sat_addr.s_node != AA_SAT( aa )->sat_addr.s_node)
  263                 && (to.sat_addr.s_node != ATADDR_BCAST) ) {
  264                     continue;
  265                 }
  266                 break;
  267             }
  268         }
  269     }
  270 
  271     /*
  272      * Adjust the length, removing any padding that may have been added
  273      * at a link layer.  We do this before we attempt to forward a packet,
  274      * possibly on a different media.
  275      */
  276     mlen = m->m_pkthdr.len;
  277     if ( mlen < dlen ) {
  278         ddpstat.ddps_toosmall++;
  279         m_freem( m );
  280         return;
  281     }
  282     if ( mlen > dlen ) {
  283         m_adj( m, dlen - mlen );
  284     }
  285 
  286     /*
  287      * If it aint for a net on any of our interfaces,
  288      * or it IS for a net on a different interface than it came in on,
  289      * (and it is not looped back) then consider if we should forward it.
  290      * As we are not really a router this is a bit cheeky, but it may be
  291      * useful some day.
  292      */
  293     if ( (aa == NULL)
  294     || ( (to.sat_addr.s_node == ATADDR_BCAST)
  295       && (aa->aa_ifp != ifp)
  296       && (( ifp->if_flags & IFF_LOOPBACK ) == 0 ))) {
  297         /* 
  298          * If we've explicitly disabled it, don't route anything
  299          */
  300         if ( ddp_forward == 0 ) {
  301             m_freem( m );
  302             return;
  303         }
  304         /* 
  305          * If the cached forwarding route is still valid, use it.
  306          */
  307         if ( forwro.ro_rt
  308         && ( satosat(&forwro.ro_dst)->sat_addr.s_net != to.sat_addr.s_net
  309           || satosat(&forwro.ro_dst)->sat_addr.s_node != to.sat_addr.s_node )) {
  310             RTFREE( forwro.ro_rt );
  311             forwro.ro_rt = (struct rtentry *)0;
  312         }
  313 
  314         /*
  315          * If we don't have a cached one (any more) or it's useless,
  316          * Then get a new route.
  317          * XXX this could cause a 'route leak'. check this!
  318          */
  319         if ( forwro.ro_rt == (struct rtentry *)0
  320         || forwro.ro_rt->rt_ifp == (struct ifnet *)0 ) {
  321             forwro.ro_dst.sa_len = sizeof( struct sockaddr_at );
  322             forwro.ro_dst.sa_family = AF_APPLETALK;
  323             satosat(&forwro.ro_dst)->sat_addr.s_net = to.sat_addr.s_net;
  324             satosat(&forwro.ro_dst)->sat_addr.s_node = to.sat_addr.s_node;
  325             rtalloc(&forwro);
  326         }
  327 
  328         /* 
  329          * If it's not going to get there on this hop, and it's
  330          * already done too many hops, then throw it away.
  331          */
  332         if ( (to.sat_addr.s_net != satosat( &forwro.ro_dst )->sat_addr.s_net)
  333         && (ddpe.deh_hops == DDP_MAXHOPS) ) {
  334             m_freem( m );
  335             return;
  336         }
  337 
  338         /*
  339          * A ddp router might use the same interface
  340          * to forward the packet, which this would not effect.
  341          * Don't allow packets to cross from one interface to another however.
  342          */
  343         if ( ddp_firewall
  344         && ( (forwro.ro_rt == NULL)
  345           || (forwro.ro_rt->rt_ifp != ifp))) {
  346             m_freem( m );
  347             return;
  348         }
  349 
  350         /*
  351          * Adjust the header.
  352          * If it was a short header then it would have not gotten here,
  353          * so we can assume there is room to drop the header in.
  354          * XXX what about promiscuous mode, etc...
  355          */
  356         ddpe.deh_hops++;
  357         ddpe.deh_bytes = htonl( ddpe.deh_bytes );
  358         bcopy( (caddr_t)&ddpe, (caddr_t)deh, sizeof( u_short )); /* XXX deh? */
  359         if ( ddp_route( m, &forwro )) {
  360             ddpstat.ddps_cantforward++;
  361         } else {
  362             ddpstat.ddps_forward++;
  363         }
  364         return;
  365     }
  366 
  367     /*
  368      * It was for us, and we have an ifaddr to use with it.
  369      */
  370     from.sat_len = sizeof( struct sockaddr_at );
  371     from.sat_family = AF_APPLETALK;
  372 
  373     /* 
  374      * We are no longer interested in the link layer.
  375      * so cut it off.
  376      */
  377     if ( elh ) {
  378         m_adj( m, sizeof( struct ddpshdr ));
  379     } else {
  380         if ( ddp_cksum && cksum && cksum != at_cksum( m, sizeof( int ))) {
  381             ddpstat.ddps_badsum++;
  382             m_freem( m );
  383             return;
  384         }
  385         m_adj( m, sizeof( struct ddpehdr ));
  386     }
  387 
  388     /* 
  389      * Search for ddp protocol control blocks that match these
  390      * addresses. 
  391      */
  392     if (( ddp = ddp_search( &from, &to, aa )) == NULL ) {
  393         m_freem( m );
  394         return;
  395     }
  396 
  397     /* 
  398      * If we found one, deliver th epacket to the socket
  399      */
  400     if ( sbappendaddr( &ddp->ddp_socket->so_rcv, (struct sockaddr *)&from,
  401             m, (struct mbuf *)0 ) == 0 ) {
  402         /* 
  403          * If the socket is full (or similar error) dump the packet.
  404          */
  405         ddpstat.ddps_nosockspace++;
  406         m_freem( m );
  407         return;
  408     }
  409     /*
  410      * And wake up whatever might be waiting for it
  411      */
  412     sorwakeup( ddp->ddp_socket );
  413 }
  414 
  415 #if 0
  416 /* As if we haven't got enough of this sort of think floating
  417 around the kernel :) */
  418 
  419 #define BPXLEN  48
  420 #define BPALEN  16
  421 #include <ctype.h>
  422 char    hexdig[] = "0123456789ABCDEF";
  423 
  424 static void
  425 bprint( char *data, int len )
  426 {
  427     char        xout[ BPXLEN ], aout[ BPALEN ];
  428     int         i = 0;
  429 
  430     bzero( xout, BPXLEN );
  431     bzero( aout, BPALEN );
  432 
  433     for ( ;; ) {
  434         if ( len < 1 ) {
  435             if ( i != 0 ) {
  436                 printf( "%s\t%s\n", xout, aout );
  437             }
  438             printf( "%s\n", "(end)" );
  439             break;
  440         }
  441 
  442         xout[ (i*3) ] = hexdig[ ( *data & 0xf0 ) >> 4 ];
  443         xout[ (i*3) + 1 ] = hexdig[ *data & 0x0f ];
  444 
  445         if ( (u_char)*data < 0x7f && (u_char)*data > 0x20 ) {
  446             aout[ i ] = *data;
  447         } else {
  448             aout[ i ] = '.';
  449         }
  450 
  451         xout[ (i*3) + 2 ] = ' ';
  452 
  453         i++;
  454         len--;
  455         data++;
  456 
  457         if ( i > BPALEN - 2 ) {
  458             printf( "%s\t%s\n", xout, aout );
  459             bzero( xout, BPXLEN );
  460             bzero( aout, BPALEN );
  461             i = 0;
  462             continue;
  463         }
  464     }
  465 }
  466 
  467 static void
  468 m_printm( struct mbuf *m )
  469 {
  470     for (; m; m = m->m_next ) {
  471         bprint( mtod( m, char * ), m->m_len );
  472     }
  473 }
  474 #endif

Cache object: c2a14a30bacffe97ec817608313a5891


[ 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.