root/netatalk/ddp_input.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. atintr
  2. ddp_input
  3. m_printm
  4. bprint

    1 /*      $OpenBSD: ddp_input.c,v 1.4 2006/03/04 22:40:16 brad Exp $      */
    2 
    3 /*
    4  * Copyright (c) 1990,1994 Regents of The University of Michigan.
    5  * All Rights Reserved.  See COPYRIGHT.
    6  */
    7 
    8 /*
    9  * The following is the contents of the COPYRIGHT file from the
   10  * netatalk-1.4a2 distribution, from which this file is derived.
   11  */
   12 /*
   13  * Copyright (c) 1990,1996 Regents of The University of Michigan.
   14  *
   15  * All Rights Reserved.
   16  *
   17  *    Permission to use, copy, modify, and distribute this software and
   18  *    its documentation for any purpose and without fee is hereby granted,
   19  *    provided that the above copyright notice appears in all copies and
   20  *    that both that copyright notice and this permission notice appear
   21  *    in supporting documentation, and that the name of The University
   22  *    of Michigan not be used in advertising or publicity pertaining to
   23  *    distribution of the software without specific, written prior
   24  *    permission. This software is supplied as is without expressed or
   25  *    implied warranties of any kind.
   26  *
   27  * This product includes software developed by the University of
   28  * California, Berkeley and its contributors.
   29  *
   30  * Solaris code is encumbered by the following:
   31  *
   32  *     Copyright (C) 1996 by Sun Microsystems Computer Co.
   33  *
   34  *     Permission to use, copy, modify, and distribute this software and
   35  *     its documentation for any purpose and without fee is hereby
   36  *     granted, provided that the above copyright notice appear in all
   37  *     copies and that both that copyright notice and this permission
   38  *     notice appear in supporting documentation.  This software is
   39  *     provided "as is" without express or implied warranty.
   40  *
   41  * Research Systems Unix Group
   42  * The University of Michigan
   43  * c/o Wesley Craig
   44  * 535 W. William Street
   45  * Ann Arbor, Michigan
   46  * +1-313-764-2278
   47  * netatalk@umich.edu
   48  */
   49 /*
   50  * None of the Solaris code mentioned is included in OpenBSD.
   51  * This code also relies heavily on previous effort in FreeBSD and NetBSD.
   52  */
   53 
   54 #include <sys/param.h>
   55 #include <sys/systm.h>
   56 #include <sys/kernel.h>
   57 #include <sys/malloc.h>
   58 #include <sys/mbuf.h>
   59 #include <sys/protosw.h>
   60 #include <sys/socket.h>
   61 #include <sys/ioctl.h>
   62 #include <sys/errno.h>
   63 #include <sys/syslog.h>
   64 #include <sys/proc.h>
   65 #include <sys/socketvar.h>
   66 
   67 #include <net/if.h>
   68 #include <net/route.h>
   69 
   70 #include <machine/endian.h>
   71 
   72 #include <netatalk/at.h>
   73 #include <netatalk/at_var.h>
   74 #include <netatalk/ddp.h>
   75 #include <netatalk/ddp_var.h>
   76 #include <netatalk/at_extern.h>
   77 
   78 void atintr(void);
   79 void ddp_input(struct mbuf *, struct ifnet *,
   80                                 struct elaphdr *, int);
   81 #if 0
   82 static void m_printm(struct mbuf *);
   83 static void bprint( char *, int );
   84 #endif
   85 
   86 int             ddp_forward = 1;
   87 int             ddp_firewall = 0;
   88 extern int      ddp_cksum;
   89 
   90 /*
   91  * Could probably merge these two code segments a little better...
   92  */
   93 void
   94 atintr()
   95 {
   96     struct elaphdr      *elhp, elh;
   97     struct ifnet        *ifp;
   98     struct mbuf         *m;
   99     struct at_ifaddr    *aa;
  100     int                 s;
  101 
  102     for (;;) {
  103         s = splnet();
  104 
  105         IF_DEQUEUE( &atintrq2, m );
  106 
  107         splx( s );
  108 
  109         if ( m == 0 ) {                 /* no more queued packets */
  110             break;
  111         }
  112 
  113         ifp = m->m_pkthdr.rcvif;
  114         for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
  115             if ( aa->aa_ifp == ifp && ( aa->aa_flags & AFA_PHASE2 )) {
  116                 break;
  117             }
  118         }
  119         if ( aa == NULL ) {             /* ifp not an appletalk interface */
  120             m_freem( m );
  121             continue;
  122         }
  123 
  124         ddp_input( m, ifp, (struct elaphdr *)NULL, 2 );
  125     }
  126 
  127     for (;;) {
  128         s = splnet();
  129 
  130         IF_DEQUEUE( &atintrq1, m );
  131 
  132         splx( s );
  133 
  134         if ( m == 0 ) {                 /* no more queued packets */
  135             break;
  136         }
  137 
  138         ifp = m->m_pkthdr.rcvif;
  139         for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
  140             if ( aa->aa_ifp == ifp && ( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
  141                 break;
  142             }
  143         }
  144         if ( aa == NULL ) {             /* ifp not an appletalk interface */
  145             m_freem( m );
  146             continue;
  147         }
  148 
  149         if ( m->m_len < SZ_ELAPHDR &&
  150                 (( m = m_pullup( m, SZ_ELAPHDR )) == 0 )) {
  151             ddpstat.ddps_tooshort++;
  152             continue;
  153         }
  154 
  155         elhp = mtod( m, struct elaphdr *);
  156         m_adj( m, SZ_ELAPHDR );
  157 
  158         if ( elhp->el_type == ELAP_DDPEXTEND ) {
  159             ddp_input( m, ifp, (struct elaphdr *)NULL, 1 );
  160         } else {
  161             bcopy((caddr_t)elhp, (caddr_t)&elh, SZ_ELAPHDR );
  162             ddp_input( m, ifp, &elh, 1 );
  163         }
  164     }
  165     return;
  166 }
  167 
  168 struct route    forwro;
  169 
  170 void
  171 ddp_input( m, ifp, elh, phase )
  172     struct mbuf         *m;
  173     struct ifnet        *ifp;
  174     struct elaphdr      *elh;
  175     int                 phase;
  176 {
  177     struct sockaddr_at  from, to;
  178     struct ddpshdr      *dsh, ddps;
  179     struct at_ifaddr    *aa;
  180     struct ddpehdr      *deh, ddpe;
  181     struct ddpcb        *ddp;
  182     int                 dlen, mlen;
  183     u_int16_t           cksum;
  184 
  185     bzero( (caddr_t)&from, sizeof( struct sockaddr_at ));
  186     if ( elh ) {
  187         ddpstat.ddps_short++;
  188 
  189         if ( m->m_len < sizeof( struct ddpshdr ) &&
  190                 (( m = m_pullup( m, sizeof( struct ddpshdr ))) == 0 )) {
  191             ddpstat.ddps_tooshort++;
  192             return;
  193         }
  194 
  195         dsh = mtod( m, struct ddpshdr *);
  196         bcopy( (caddr_t)dsh, (caddr_t)&ddps, sizeof( struct ddpshdr ));
  197         ddps.dsh_bytes = ntohl( ddps.dsh_bytes );
  198         dlen = ddps.dsh_len;
  199 
  200         to.sat_addr.s_net = 0;
  201         to.sat_addr.s_node = elh->el_dnode;
  202         to.sat_port = ddps.dsh_dport;
  203         from.sat_addr.s_net = 0;
  204         from.sat_addr.s_node = elh->el_snode;
  205         from.sat_port = ddps.dsh_sport;
  206 
  207         for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
  208             if ( aa->aa_ifp == ifp && ( aa->aa_flags & AFA_PHASE2 ) == 0 &&
  209                     ( AA_SAT( aa )->sat_addr.s_node == to.sat_addr.s_node ||
  210                     to.sat_addr.s_node == ATADDR_BCAST )) {
  211                 break;
  212             }
  213         }
  214         if ( aa == NULL ) {
  215             m_freem( m );
  216             return;
  217         }
  218     } else {
  219         ddpstat.ddps_long++;
  220 
  221         if ( m->m_len < sizeof( struct ddpehdr ) &&
  222                 (( m = m_pullup( m, sizeof( struct ddpehdr ))) == 0 )) {
  223             ddpstat.ddps_tooshort++;
  224             return;
  225         }
  226 
  227         deh = mtod( m, struct ddpehdr *);
  228         bcopy( (caddr_t)deh, (caddr_t)&ddpe, sizeof( struct ddpehdr ));
  229         ddpe.deh_bytes = ntohl( ddpe.deh_bytes );
  230         dlen = ddpe.deh_len;
  231 
  232         if (( cksum = ddpe.deh_sum ) == 0 ) {
  233             ddpstat.ddps_nosum++;
  234         }
  235 
  236         from.sat_addr.s_net = ddpe.deh_snet;
  237         from.sat_addr.s_node = ddpe.deh_snode;
  238         from.sat_port = ddpe.deh_sport;
  239         to.sat_addr.s_net = ddpe.deh_dnet;
  240         to.sat_addr.s_node = ddpe.deh_dnode;
  241         to.sat_port = ddpe.deh_dport;
  242 
  243         if ( to.sat_addr.s_net == 0 ) {
  244             for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
  245                 if ( phase == 1 && ( aa->aa_flags & AFA_PHASE2 )) {
  246                     continue;
  247                 }
  248                 if ( phase == 2 && ( aa->aa_flags & AFA_PHASE2 ) == 0 ) {
  249                     continue;
  250                 }
  251                 if ( aa->aa_ifp == ifp &&
  252                         ( AA_SAT( aa )->sat_addr.s_node == to.sat_addr.s_node ||
  253                         to.sat_addr.s_node == ATADDR_BCAST ||
  254                         ( ifp->if_flags & IFF_LOOPBACK ))) {
  255                     break;
  256                 }
  257             }
  258         } else {
  259             for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
  260                 if ( to.sat_addr.s_net == aa->aa_firstnet &&
  261                         to.sat_addr.s_node == 0 ) {
  262                     break;
  263                 }
  264                 if (( ntohs( to.sat_addr.s_net ) < ntohs( aa->aa_firstnet ) ||
  265                         ntohs( to.sat_addr.s_net ) > ntohs( aa->aa_lastnet )) &&
  266                         ( ntohs( to.sat_addr.s_net ) < 0xff00 ||
  267                         ntohs( to.sat_addr.s_net ) > 0xfffe)) {
  268                     continue;
  269                 }
  270                 if ( to.sat_addr.s_node != AA_SAT( aa )->sat_addr.s_node &&
  271                         to.sat_addr.s_node != ATADDR_BCAST ) {
  272                     continue;
  273                 }
  274                 break;
  275             }
  276         }
  277     }
  278 
  279     /*
  280      * Adjust the length, removing any padding that may have been added
  281      * at a link layer.  We do this before we attempt to forward a packet,
  282      * possibly on a different media.
  283      */
  284     mlen = m->m_pkthdr.len;
  285     if ( mlen < dlen ) {
  286         ddpstat.ddps_toosmall++;
  287         m_freem( m );
  288         return;
  289     }
  290     if ( mlen > dlen ) {
  291         m_adj( m, dlen - mlen );
  292     }
  293 
  294     /*
  295      * XXX Should we deliver broadcasts locally, also, or rely on the
  296      * link layer to give us a copy?  For the moment, the latter.
  297      */
  298     if ( aa == NULL || ( to.sat_addr.s_node == ATADDR_BCAST &&
  299             aa->aa_ifp != ifp && ( ifp->if_flags & IFF_LOOPBACK ) == 0 )) {
  300         if ( ddp_forward == 0 ) {
  301             m_freem( m );
  302             return;
  303         }
  304         if ( forwro.ro_rt && ( satosat( &forwro.ro_dst )->sat_addr.s_net !=
  305                 to.sat_addr.s_net ||
  306                 satosat( &forwro.ro_dst )->sat_addr.s_node !=
  307                 to.sat_addr.s_node )) {
  308             RTFREE( forwro.ro_rt );
  309             forwro.ro_rt = (struct rtentry *)0;
  310         }
  311         if ( forwro.ro_rt == (struct rtentry *)0 ||
  312              forwro.ro_rt->rt_ifp == (struct ifnet *)0 ) {
  313             forwro.ro_dst.sa_len = sizeof( struct sockaddr_at );
  314             forwro.ro_dst.sa_family = AF_APPLETALK;
  315             satosat( &forwro.ro_dst )->sat_addr.s_net = to.sat_addr.s_net;
  316             satosat( &forwro.ro_dst )->sat_addr.s_node = to.sat_addr.s_node;
  317             rtalloc( &forwro );
  318         }
  319 
  320         if ( to.sat_addr.s_net != satosat( &forwro.ro_dst )->sat_addr.s_net &&
  321                 ddpe.deh_hops == DDP_MAXHOPS ) {
  322             m_freem( m );
  323             return;
  324         }
  325 
  326         /* XXX FreeBSD doesn't have this */
  327         if ( ddp_firewall &&
  328                 ( forwro.ro_rt == NULL || ( forwro.ro_rt->rt_ifp != ifp &&
  329                 forwro.ro_rt->rt_ifp != at_ifaddr->aa_ifp ))) {
  330             m_freem( m );
  331             return;
  332         }
  333 
  334         ddpe.deh_hops++;
  335         ddpe.deh_bytes = htonl( ddpe.deh_bytes );
  336         bcopy( (caddr_t)&ddpe, (caddr_t)deh, sizeof( u_int16_t ));
  337         if ( ddp_route( m, &forwro )) {
  338             ddpstat.ddps_cantforward++;
  339         } else {
  340             ddpstat.ddps_forward++;
  341         }
  342         return;
  343     }
  344 
  345     from.sat_len = sizeof( struct sockaddr_at );
  346     from.sat_family = AF_APPLETALK;
  347 
  348     if ( elh ) {
  349         m_adj( m, sizeof( struct ddpshdr ));
  350     } else {
  351         /*
  352          * XXX I've always hated this about the TCP checksum, and here it
  353          * is again. ddp_cksum determines whether we compute checksums on
  354          * outgoing packets. Why is it used to disable checkumming on
  355          * incoming packets as well? If the remote node went to the
  356          * trouble of computing the checksum, shouldn't we check it?
  357          */
  358         if ( ddp_cksum && cksum && cksum != at_cksum( m, sizeof( int ))) {
  359             ddpstat.ddps_badsum++;
  360             m_freem( m );
  361             return;
  362         }
  363         m_adj( m, sizeof( struct ddpehdr ));
  364     }
  365 
  366     if (( ddp = ddp_search( &from, &to, aa )) == NULL ) {
  367         m_freem( m );
  368         return;
  369     }
  370 
  371     if ( sbappendaddr( &ddp->ddp_socket->so_rcv, (struct sockaddr *)&from,
  372             m, (struct mbuf *)0 ) == 0 ) {
  373         ddpstat.ddps_nosockspace++;
  374         m_freem( m );
  375         return;
  376     }
  377     sorwakeup( ddp->ddp_socket );
  378 }
  379 
  380 #if 0
  381 static void
  382 m_printm( m )
  383     struct mbuf *m;
  384 {
  385     for (; m; m = m->m_next ) {
  386         bprint( mtod( m, char * ), m->m_len );
  387     }
  388 }
  389 
  390 #define BPXLEN  48
  391 #define BPALEN  16
  392 char    hexdig[] = "0123456789ABCDEF";
  393 
  394 static void
  395 bprint( data, len )
  396     char        *data;
  397     int         len;
  398 {
  399     char        xout[ BPXLEN ], aout[ BPALEN ];
  400     int         i = 0;
  401 
  402     bzero( xout, BPXLEN );
  403     bzero( aout, BPALEN );
  404 
  405     for ( ;; ) {
  406         if ( len < 1 ) {
  407             if ( i != 0 ) {
  408                 printf( "%s\t%s\n", xout, aout );
  409             }
  410             printf( "%s\n", "(end)" );
  411             break;
  412         }
  413 
  414         xout[ (i*3) ] = hexdig[ ( *data & 0xf0 ) >> 4 ];
  415         xout[ (i*3) + 1 ] = hexdig[ *data & 0x0f ];
  416 
  417         if ( (u_char)*data < 0x7f && (u_char)*data > 0x20 ) {
  418             aout[ i ] = *data;
  419         } else {
  420             aout[ i ] = '.';
  421         }
  422 
  423         xout[ (i*3) + 2 ] = ' ';
  424 
  425         i++;
  426         len--;
  427         data++;
  428 
  429         if ( i > BPALEN - 2 ) {
  430             printf( "%s\t%s\n", xout, aout );
  431             bzero( xout, BPXLEN );
  432             bzero( aout, BPALEN );
  433             i = 0;
  434             continue;
  435         }
  436     }
  437 }
  438 #endif

/* [<][>][^][v][top][bottom][index][help] */