Annotation of sys/netatalk/ddp_output.c, Revision 1.1
1.1 ! nbrk 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: }
CVSweb