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