root/netatalk/ddp_output.c

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

DEFINITIONS

This source file includes following definitions.
  1. ddp_output
  2. at_cksum
  3. ddp_route

    1 /*      $OpenBSD: ddp_output.c,v 1.6 2003/06/06 09:45:08 itojun Exp $   */
    2 
    3 /*
    4  * Copyright (c) 1990,1991 Regents of The University of Michigan.
    5  * All Rights Reserved.
    6  *
    7  * Permission to use, copy, modify, and distribute this software and
    8  * its documentation for any purpose and without fee is hereby granted,
    9  * provided that the above copyright notice appears in all copies and
   10  * that both that copyright notice and this permission notice appear
   11  * in supporting documentation, and that the name of The University
   12  * of Michigan not be used in advertising or publicity pertaining to
   13  * distribution of the software without specific, written prior
   14  * permission. This software is supplied as is without expressed or
   15  * implied warranties of any kind.
   16  *
   17  *      Research Systems Unix Group
   18  *      The University of Michigan
   19  *      c/o Mike Clark
   20  *      535 W. William Street
   21  *      Ann Arbor, Michigan
   22  *      +1-313-763-0525
   23  *      netatalk@itd.umich.edu
   24  */
   25 
   26 /*
   27  * The following is the contents of the COPYRIGHT file from the
   28  * netatalk-1.4a2 distribution, from which this file is derived.
   29  */
   30 /*
   31  * Copyright (c) 1990,1996 Regents of The University of Michigan.
   32  *
   33  * All Rights Reserved.
   34  *
   35  *    Permission to use, copy, modify, and distribute this software and
   36  *    its documentation for any purpose and without fee is hereby granted,
   37  *    provided that the above copyright notice appears in all copies and
   38  *    that both that copyright notice and this permission notice appear
   39  *    in supporting documentation, and that the name of The University
   40  *    of Michigan not be used in advertising or publicity pertaining to
   41  *    distribution of the software without specific, written prior
   42  *    permission. This software is supplied as is without expressed or
   43  *    implied warranties of any kind.
   44  *
   45  * This product includes software developed by the University of
   46  * California, Berkeley and its contributors.
   47  *
   48  * Solaris code is encumbered by the following:
   49  *
   50  *     Copyright (C) 1996 by Sun Microsystems Computer Co.
   51  *
   52  *     Permission to use, copy, modify, and distribute this software and
   53  *     its documentation for any purpose and without fee is hereby
   54  *     granted, provided that the above copyright notice appear in all
   55  *     copies and that both that copyright notice and this permission
   56  *     notice appear in supporting documentation.  This software is
   57  *     provided "as is" without express or implied warranty.
   58  *
   59  * Research Systems Unix Group
   60  * The University of Michigan
   61  * c/o Wesley Craig
   62  * 535 W. William Street
   63  * Ann Arbor, Michigan
   64  * +1-313-764-2278
   65  * netatalk@umich.edu
   66  */
   67 /*
   68  * None of the Solaris code mentioned is included in OpenBSD.
   69  * This code also relies heavily on previous effort in FreeBSD and NetBSD.
   70  */
   71 
   72 #include <sys/types.h>
   73 #include <sys/param.h>
   74 #include <sys/systm.h>
   75 #include <sys/mbuf.h>
   76 #include <sys/socket.h>
   77 #include <sys/errno.h>
   78 #include <sys/syslog.h>
   79 
   80 #include <net/if.h>
   81 #include <net/route.h>
   82 
   83 #include <netinet/in.h>
   84 #undef s_net
   85 #include <netinet/if_ether.h>
   86 
   87 #include <machine/endian.h>
   88 
   89 #include <netatalk/at.h>
   90 #include <netatalk/at_var.h>
   91 #include <netatalk/ddp.h>
   92 #include <netatalk/ddp_var.h>
   93 #include <netatalk/at_extern.h>
   94 
   95 int ddp_output( struct mbuf *, ... );
   96 u_int16_t at_cksum( struct mbuf *, int );
   97 int ddp_route(struct mbuf *, struct route * );
   98 
   99 int     ddp_cksum = 1;
  100 
  101 int
  102 ddp_output(struct mbuf *m, ...)
  103 {
  104     struct ddpcb        *ddp;
  105     struct ddpehdr      *deh;
  106     va_list             ap;
  107 
  108     va_start(ap, m);
  109     ddp = va_arg(ap, struct ddpcb *);
  110     va_end(ap);
  111 
  112     M_PREPEND( m, sizeof( struct ddpehdr ), M_DONTWAIT );
  113     if (!m)
  114         return (ENOBUFS);
  115 
  116     deh = mtod( m, struct ddpehdr *);
  117     deh->deh_pad = 0;
  118     deh->deh_hops = 0;
  119 
  120     deh->deh_len = m->m_pkthdr.len;
  121 
  122     deh->deh_dnet = ddp->ddp_fsat.sat_addr.s_net;
  123     deh->deh_dnode = ddp->ddp_fsat.sat_addr.s_node;
  124     deh->deh_dport = ddp->ddp_fsat.sat_port;
  125     deh->deh_snet = ddp->ddp_lsat.sat_addr.s_net;
  126     deh->deh_snode = ddp->ddp_lsat.sat_addr.s_node;
  127     deh->deh_sport = ddp->ddp_lsat.sat_port;
  128 
  129     /*
  130      * The checksum calculation is done after all of the other bytes have
  131      * been filled in.
  132      */
  133     if ( ddp_cksum ) {
  134         deh->deh_sum = at_cksum( m, sizeof( int ));
  135     } else {
  136         deh->deh_sum = 0;
  137     }
  138     deh->deh_bytes = htonl( deh->deh_bytes );
  139 
  140     return( ddp_route( m, &ddp->ddp_route ));
  141 }
  142 
  143 u_int16_t
  144 at_cksum( m, skip )
  145     struct mbuf *m;
  146     int         skip;
  147 {
  148     u_int8_t    *data, *end;
  149     u_long      cksum = 0;
  150 
  151     for (; m; m = m->m_next ) {
  152         for ( data = mtod( m, u_int8_t * ), end = data + m->m_len; data < end;
  153                 data++ ) {
  154             if ( skip ) {
  155                 skip--;
  156                 continue;
  157             }
  158             cksum = ( cksum + *data ) << 1;
  159             if ( cksum & 0x00010000 ) {
  160                 cksum++;
  161             }
  162             cksum &= 0x0000ffff;
  163         }
  164     }
  165 
  166     if ( cksum == 0 ) {
  167         cksum = 0x0000ffff;
  168     }
  169     return( (u_int16_t)cksum );
  170 }
  171 
  172 int
  173 ddp_route( m, ro )
  174     struct mbuf         *m;
  175     struct route        *ro;
  176 {
  177     struct sockaddr_at  gate;
  178     struct elaphdr      *elh;
  179     struct at_ifaddr    *aa = NULL;
  180     struct ifnet        *ifp;
  181     u_int16_t           net;
  182 
  183     if ( ro->ro_rt && ( ifp = ro->ro_rt->rt_ifp )) {
  184         net = satosat( ro->ro_rt->rt_gateway )->sat_addr.s_net;
  185         for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
  186             if ( aa->aa_ifp == ifp &&
  187                     ntohs( net ) >= ntohs( aa->aa_firstnet ) &&
  188                     ntohs( net ) <= ntohs( aa->aa_lastnet )) {
  189                 break;
  190             }
  191         }
  192     }
  193     if ( aa == NULL ) {
  194         m_freem( m );
  195         return( EINVAL );
  196     }
  197 
  198     /*
  199      * There are several places in the kernel where data is added to
  200      * an mbuf without ensuring that the mbuf pointer is aligned.
  201      * This is bad for transition routing, since phase 1 and phase 2
  202      * packets end up poorly aligned due to the three byte elap header.
  203      */
  204     if ( aa->aa_flags & AFA_PHASE2 ) {
  205         if (( m = m_pullup( m, MIN( MHLEN, m->m_pkthdr.len ))) == 0 ) {
  206             return( ENOBUFS );
  207         }
  208     } else {
  209         M_PREPEND(m, SZ_ELAPHDR, M_DONTWAIT);
  210         if (!m)
  211             return (ENOBUFS);
  212 
  213         elh = mtod( m, struct elaphdr *);
  214         elh->el_snode = satosat( &aa->aa_addr )->sat_addr.s_node;
  215         elh->el_type = ELAP_DDPEXTEND;
  216         if ( ntohs( satosat( &ro->ro_dst )->sat_addr.s_net ) >=
  217                 ntohs( aa->aa_firstnet ) &&
  218                 ntohs( satosat( &ro->ro_dst )->sat_addr.s_net ) <=
  219                 ntohs( aa->aa_lastnet )) {
  220             elh->el_dnode = satosat( &ro->ro_dst )->sat_addr.s_node;
  221         } else {
  222             elh->el_dnode = satosat( ro->ro_rt->rt_gateway )->sat_addr.s_node;
  223         }
  224     }
  225 
  226     if ( ntohs( satosat( &ro->ro_dst )->sat_addr.s_net ) >=
  227             ntohs( aa->aa_firstnet ) &&
  228             ntohs( satosat( &ro->ro_dst )->sat_addr.s_net ) <=
  229             ntohs( aa->aa_lastnet )) {
  230         gate = *satosat( &ro->ro_dst );
  231     } else {
  232         gate = *satosat( ro->ro_rt->rt_gateway );
  233     }
  234     ro->ro_rt->rt_use++;
  235 
  236     /* XXX The NULL should be a struct rtentry */
  237     return((*ifp->if_output)( ifp, m, (struct sockaddr *) &gate, NULL ));
  238 }

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