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

Cache object: 43ba9d775ca1109ccc0b4119ce2dfe6e


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