[BACK]Return to ddp_input.c CVS log [TXT][DIR] Up to [local] / sys / netatalk

Annotation of sys/netatalk/ddp_input.c, Revision 1.1.1.1

1.1       nbrk        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

CVSweb