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

Cache object: 9fc06965f2882f5e2a26dfd6f3036ac4


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