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

Annotation of sys/netatalk/ddp_usrreq.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: ddp_usrreq.c,v 1.8 2007/05/26 12:09:40 claudio 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/errno.h>
        !            55: #include <sys/types.h>
        !            56: #include <sys/param.h>
        !            57: #include <sys/systm.h>
        !            58: #include <sys/proc.h>
        !            59: #include <sys/user.h>
        !            60: #include <sys/mbuf.h>
        !            61: #include <sys/ioctl.h>
        !            62: #include <sys/socket.h>
        !            63: #include <sys/socketvar.h>
        !            64: #include <sys/protosw.h>
        !            65: #include <net/if.h>
        !            66: #include <net/route.h>
        !            67:
        !            68: #include <machine/endian.h>
        !            69:
        !            70: #include <netatalk/at.h>
        !            71: #include <netatalk/at_var.h>
        !            72: #include <netatalk/ddp_var.h>
        !            73: #include <netatalk/at_extern.h>
        !            74:
        !            75: int ddp_usrreq(struct socket *, int, struct mbuf *,
        !            76:                        struct mbuf *, struct mbuf * );
        !            77: static void at_sockaddr( struct ddpcb *, struct mbuf * );
        !            78: static int at_pcbsetaddr( struct ddpcb *, struct mbuf *,
        !            79:                        struct proc * );
        !            80: static int at_pcbconnect( struct ddpcb *, struct mbuf *,
        !            81:                        struct proc *);
        !            82: static void at_pcbdisconnect( struct ddpcb * );
        !            83: static int at_pcballoc( struct socket * );
        !            84: static void at_pcbdetach( struct socket *, struct ddpcb * );
        !            85: struct ddpcb *ddp_search( struct sockaddr_at *,
        !            86:                        struct sockaddr_at *, struct at_ifaddr * );
        !            87: void ddp_init(void);
        !            88:
        !            89: struct at_ifaddr       *at_ifaddr;
        !            90: struct ifqueue         atintrq1, atintrq2;
        !            91: int                    atdebug;
        !            92:
        !            93: struct ddpcb           *ddp_ports[ ATPORT_LAST ];
        !            94: struct ddpstat         ddpstat;
        !            95:
        !            96: struct ddpcb   *ddpcb = NULL;
        !            97: u_long         ddp_sendspace = DDP_MAXSZ; /* Max ddp size + 1 (ddp_type) */
        !            98: u_long         ddp_recvspace = 10 * ( 587 + sizeof( struct sockaddr_at ));
        !            99:
        !           100: /*ARGSUSED*/
        !           101: int
        !           102: ddp_usrreq( so, req, m, addr, rights )
        !           103:     struct socket      *so;
        !           104:     int                        req;
        !           105:     struct mbuf                *m, *addr, *rights;
        !           106: {
        !           107:     /* XXX Need to pass p into this routine */
        !           108:     struct proc *p = curproc;
        !           109:     struct ddpcb       *ddp;
        !           110:     int                        error = 0;
        !           111:
        !           112:     ddp = sotoddpcb( so );
        !           113:
        !           114:     if ( req == PRU_CONTROL ) {
        !           115:        return( at_control( (u_long) m, (caddr_t) addr,
        !           116:                (struct ifnet *) rights, p ));
        !           117:     }
        !           118:
        !           119:     if ( rights && rights->m_len ) {
        !           120:        error = EINVAL;
        !           121:        goto release;
        !           122:     }
        !           123:
        !           124:     if ( ddp == NULL && req != PRU_ATTACH ) {
        !           125:        error = EINVAL;
        !           126:        goto release;
        !           127:     }
        !           128:
        !           129:     switch ( req ) {
        !           130:     case PRU_ATTACH :
        !           131:        if ( ddp != NULL ) {
        !           132:            error = EINVAL;
        !           133:            break;
        !           134:        }
        !           135:        if (( error = at_pcballoc( so )) != 0 ) {
        !           136:            break;
        !           137:        }
        !           138:        error = soreserve( so, ddp_sendspace, ddp_recvspace );
        !           139:        break;
        !           140:
        !           141:     case PRU_DETACH :
        !           142:        at_pcbdetach( so, ddp );
        !           143:        break;
        !           144:
        !           145:     case PRU_BIND :
        !           146:        error = at_pcbsetaddr( ddp, addr, p );
        !           147:        break;
        !           148:
        !           149:     case PRU_SOCKADDR :
        !           150:        at_sockaddr( ddp, addr );
        !           151:        break;
        !           152:
        !           153:     case PRU_CONNECT:
        !           154:        if ( ddp->ddp_fsat.sat_port != ATADDR_ANYPORT ) {
        !           155:            error = EISCONN;
        !           156:            break;
        !           157:        }
        !           158:
        !           159:        error = at_pcbconnect( ddp, addr, p );
        !           160:        if ( error == 0 )
        !           161:            soisconnected( so );
        !           162:        break;
        !           163:
        !           164:     case PRU_DISCONNECT:
        !           165:        if ( ddp->ddp_fsat.sat_addr.s_node == ATADDR_ANYNODE ) {
        !           166:            error = ENOTCONN;
        !           167:            break;
        !           168:        }
        !           169:        at_pcbdisconnect( ddp );
        !           170:        soisdisconnected( so );
        !           171:        break;
        !           172:
        !           173:     case PRU_SHUTDOWN:
        !           174:        socantsendmore( so );
        !           175:        break;
        !           176:
        !           177:     case PRU_SEND: {
        !           178:        int     s;
        !           179:
        !           180:        if ( addr ) {
        !           181:            if ( ddp->ddp_fsat.sat_port != ATADDR_ANYPORT ) {
        !           182:                error = EISCONN;
        !           183:                break;
        !           184:            }
        !           185:
        !           186:            s = splnet();
        !           187:            error = at_pcbconnect( ddp, addr, p );
        !           188:            if ( error ) {
        !           189:                splx( s );
        !           190:                break;
        !           191:            }
        !           192:        } else {
        !           193:            if ( ddp->ddp_fsat.sat_port == ATADDR_ANYPORT ) {
        !           194:                error = ENOTCONN;
        !           195:                break;
        !           196:            }
        !           197:        }
        !           198:
        !           199:        error = ddp_output( m, ddp );
        !           200:        m = NULL;
        !           201:        if ( addr ) {
        !           202:            at_pcbdisconnect( ddp );
        !           203:            splx( s );
        !           204:        }
        !           205:        }
        !           206:        break;
        !           207:
        !           208:     case PRU_ABORT:
        !           209:        soisdisconnected( so );
        !           210:        at_pcbdetach( so, ddp );
        !           211:        break;
        !           212:
        !           213:     case PRU_LISTEN:
        !           214:     case PRU_CONNECT2:
        !           215:     case PRU_ACCEPT:
        !           216:     case PRU_SENDOOB:
        !           217:     case PRU_FASTTIMO:
        !           218:     case PRU_SLOWTIMO:
        !           219:     case PRU_PROTORCV:
        !           220:     case PRU_PROTOSEND:
        !           221:        error = EOPNOTSUPP;
        !           222:        break;
        !           223:
        !           224:     case PRU_RCVD:
        !           225:     case PRU_RCVOOB:
        !           226:        /*
        !           227:         * Don't mfree. Good architecture...
        !           228:         */
        !           229:        return( EOPNOTSUPP );
        !           230:
        !           231:     case PRU_SENSE:
        !           232:        /*
        !           233:         * 1. Don't return block size.
        !           234:         * 2. Don't mfree.
        !           235:         */
        !           236:        return( 0 );
        !           237:
        !           238:     default:
        !           239:        error = EOPNOTSUPP;
        !           240:     }
        !           241:
        !           242: release:
        !           243:     if ( m != NULL ) {
        !           244:        m_freem( m );
        !           245:     }
        !           246:     return( error );
        !           247: }
        !           248:
        !           249: static void
        !           250: at_sockaddr( ddp, addr )
        !           251:     struct ddpcb       *ddp;
        !           252:     struct mbuf                *addr;
        !           253: {
        !           254:     struct sockaddr_at *sat;
        !           255:
        !           256:     addr->m_len = sizeof( struct sockaddr_at );
        !           257:     sat = mtod( addr, struct sockaddr_at *);
        !           258:     *sat = ddp->ddp_lsat;
        !           259: }
        !           260:
        !           261: static int
        !           262: at_pcbsetaddr( ddp, addr, p )
        !           263:     struct ddpcb       *ddp;
        !           264:     struct mbuf                *addr;
        !           265:     struct proc                *p;
        !           266: {
        !           267:     struct sockaddr_at lsat, *sat;
        !           268:     struct at_ifaddr   *aa;
        !           269:     struct ddpcb       *ddpp;
        !           270:
        !           271:     if ( ddp->ddp_lsat.sat_port != ATADDR_ANYPORT ) { /* shouldn't be bound */
        !           272:        return( EINVAL );
        !           273:     }
        !           274:
        !           275:     if ( addr != 0 ) {                 /* validate passed address */
        !           276:        sat = mtod( addr, struct sockaddr_at *);
        !           277:        if ( addr->m_len != sizeof( *sat )) {
        !           278:            return( EINVAL );
        !           279:        }
        !           280:        if ( sat->sat_family != AF_APPLETALK ) {
        !           281:            return( EAFNOSUPPORT );
        !           282:        }
        !           283:
        !           284:        if ( sat->sat_addr.s_node != ATADDR_ANYNODE ||
        !           285:                sat->sat_addr.s_net != ATADDR_ANYNET ) {
        !           286:            for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
        !           287:                if (( sat->sat_addr.s_net == AA_SAT( aa )->sat_addr.s_net ) &&
        !           288:                 ( sat->sat_addr.s_node == AA_SAT( aa )->sat_addr.s_node )) {
        !           289:                    break;
        !           290:                }
        !           291:            }
        !           292:            if ( !aa ) {
        !           293:                return( EADDRNOTAVAIL );
        !           294:            }
        !           295:        }
        !           296:
        !           297:        if ( sat->sat_port != ATADDR_ANYPORT ) {
        !           298:            if ( sat->sat_port < ATPORT_FIRST ||
        !           299:                    sat->sat_port >= ATPORT_LAST ) {
        !           300:                return( EINVAL );
        !           301:            }
        !           302:            if ( sat->sat_port < ATPORT_RESERVED &&
        !           303:                    suser( p, 0 )) {
        !           304:                return( EACCES );
        !           305:            }
        !           306:        }
        !           307:     } else {
        !           308:        bzero( (caddr_t)&lsat, sizeof( struct sockaddr_at ));
        !           309:        lsat.sat_family = AF_APPLETALK;
        !           310:        sat = &lsat;
        !           311:     }
        !           312:
        !           313:     if ( sat->sat_addr.s_node == ATADDR_ANYNODE &&
        !           314:            sat->sat_addr.s_net == ATADDR_ANYNET ) {
        !           315:        if ( at_ifaddr == NULL ) {
        !           316:            return( EADDRNOTAVAIL );
        !           317:        }
        !           318:        sat->sat_addr = AA_SAT( at_ifaddr )->sat_addr;
        !           319:     }
        !           320:     ddp->ddp_lsat = *sat;
        !           321:
        !           322:     /*
        !           323:      * Choose port.
        !           324:      */
        !           325:     if ( sat->sat_port == ATADDR_ANYPORT ) {
        !           326:        for ( sat->sat_port = ATPORT_RESERVED;
        !           327:                sat->sat_port < ATPORT_LAST; sat->sat_port++ ) {
        !           328:            if ( ddp_ports[ sat->sat_port - 1 ] == 0 ) {
        !           329:                break;
        !           330:            }
        !           331:        }
        !           332:        if ( sat->sat_port == ATPORT_LAST ) {
        !           333:            return( EADDRNOTAVAIL );
        !           334:        }
        !           335:        ddp->ddp_lsat.sat_port = sat->sat_port;
        !           336:        ddp_ports[ sat->sat_port - 1 ] = ddp;
        !           337:     } else {
        !           338:        for ( ddpp = ddp_ports[ sat->sat_port - 1 ]; ddpp;
        !           339:                ddpp = ddpp->ddp_pnext ) {
        !           340:            if ( ddpp->ddp_lsat.sat_addr.s_net == sat->sat_addr.s_net &&
        !           341:                    ddpp->ddp_lsat.sat_addr.s_node == sat->sat_addr.s_node ) {
        !           342:                break;
        !           343:            }
        !           344:        }
        !           345:        if ( ddpp != NULL ) {
        !           346:            return( EADDRINUSE );
        !           347:        }
        !           348:        ddp->ddp_pnext = ddp_ports[ sat->sat_port - 1 ];
        !           349:        ddp_ports[ sat->sat_port - 1 ] = ddp;
        !           350:        if ( ddp->ddp_pnext ) {
        !           351:            ddp->ddp_pnext->ddp_pprev = ddp;
        !           352:        }
        !           353:     }
        !           354:
        !           355:     return( 0 );
        !           356: }
        !           357:
        !           358: static int
        !           359: at_pcbconnect( ddp, addr, p )
        !           360:     struct ddpcb       *ddp;
        !           361:     struct mbuf                *addr;
        !           362:     struct proc                *p;
        !           363: {
        !           364:     struct sockaddr_at *sat = mtod( addr, struct sockaddr_at *);
        !           365:     struct route       *ro;
        !           366:     struct at_ifaddr   *aa = 0;
        !           367:     struct ifnet       *ifp;
        !           368:     u_int16_t          hintnet = 0, net;
        !           369:
        !           370:     if ( addr->m_len != sizeof( *sat ))
        !           371:        return( EINVAL );
        !           372:     if ( sat->sat_family != AF_APPLETALK ) {
        !           373:        return( EAFNOSUPPORT );
        !           374:     }
        !           375:
        !           376:     /*
        !           377:      * Under phase 2, network 0 means "the network".  We take "the
        !           378:      * network" to mean the network the control block is bound to.
        !           379:      * If the control block is not bound, there is an error.
        !           380:      */
        !           381:     if ( sat->sat_addr.s_net == 0 && sat->sat_addr.s_node != ATADDR_ANYNODE ) {
        !           382:        if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) {
        !           383:            return( EADDRNOTAVAIL );
        !           384:        }
        !           385:        hintnet = ddp->ddp_lsat.sat_addr.s_net;
        !           386:     }
        !           387:
        !           388:     ro = &ddp->ddp_route;
        !           389:     /*
        !           390:      * If we've got an old route for this pcb, check that it is valid.
        !           391:      * If we've changed our address, we may have an old "good looking"
        !           392:      * route here.  Attempt to detect it.
        !           393:      */
        !           394:     if ( ro->ro_rt ) {
        !           395:        if ( hintnet ) {
        !           396:            net = hintnet;
        !           397:        } else {
        !           398:            net = sat->sat_addr.s_net;
        !           399:        }
        !           400:        aa = 0;
        !           401:        if ( (ifp = ro->ro_rt->rt_ifp) != NULL ) {
        !           402:            for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
        !           403:                if ( aa->aa_ifp == ifp &&
        !           404:                        ntohs( net ) >= ntohs( aa->aa_firstnet ) &&
        !           405:                        ntohs( net ) <= ntohs( aa->aa_lastnet )) {
        !           406:                    break;
        !           407:                }
        !           408:            }
        !           409:        }
        !           410:        if ( aa == NULL || ( satosat( &ro->ro_dst )->sat_addr.s_net !=
        !           411:                ( hintnet ? hintnet : sat->sat_addr.s_net ) ||
        !           412:                satosat( &ro->ro_dst )->sat_addr.s_node !=
        !           413:                sat->sat_addr.s_node )) {
        !           414:            RTFREE( ro->ro_rt );
        !           415:            ro->ro_rt = (struct rtentry *)0;
        !           416:        }
        !           417:     }
        !           418:
        !           419:     /*
        !           420:      * If we've got no route for this interface, try to find one.
        !           421:      */
        !           422:     if ( ro->ro_rt == (struct rtentry *)0 ||
        !           423:         ro->ro_rt->rt_ifp == (struct ifnet *)0 ) {
        !           424:        ro->ro_dst.sa_len = sizeof( struct sockaddr_at );
        !           425:        ro->ro_dst.sa_family = AF_APPLETALK;
        !           426:        if ( hintnet != 0 ) {
        !           427:            satosat( &ro->ro_dst )->sat_addr.s_net = hintnet;
        !           428:        } else {
        !           429:            satosat( &ro->ro_dst )->sat_addr.s_net = sat->sat_addr.s_net;
        !           430:        }
        !           431:        satosat( &ro->ro_dst )->sat_addr.s_node = sat->sat_addr.s_node;
        !           432:        rtalloc( ro );
        !           433:     }
        !           434:
        !           435:     /*
        !           436:      * Make sure any route that we have has a valid interface.
        !           437:      */
        !           438:     aa = 0;
        !           439:     if ( ro->ro_rt && ( ifp = ro->ro_rt->rt_ifp )) {
        !           440:        for ( aa = at_ifaddr; aa; aa = aa->aa_next ) {
        !           441:            if ( aa->aa_ifp == ifp ) {
        !           442:                break;
        !           443:            }
        !           444:        }
        !           445:     }
        !           446:     if ( aa == 0 ) {
        !           447:        return( ENETUNREACH );
        !           448:     }
        !           449:
        !           450:     ddp->ddp_fsat = *sat;
        !           451:     if ( ddp->ddp_lsat.sat_port == ATADDR_ANYPORT ) {
        !           452:        return( at_pcbsetaddr( ddp, (struct mbuf *)0, p ));
        !           453:     }
        !           454:     return( 0 );
        !           455: }
        !           456:
        !           457: static void
        !           458: at_pcbdisconnect( ddp )
        !           459:     struct ddpcb       *ddp;
        !           460: {
        !           461:     ddp->ddp_fsat.sat_addr.s_net = ATADDR_ANYNET;
        !           462:     ddp->ddp_fsat.sat_addr.s_node = ATADDR_ANYNODE;
        !           463:     ddp->ddp_fsat.sat_port = ATADDR_ANYPORT;
        !           464: }
        !           465:
        !           466: static int
        !           467: at_pcballoc( so )
        !           468:     struct socket      *so;
        !           469: {
        !           470:     struct ddpcb       *ddp;
        !           471:
        !           472:     MALLOC( ddp, struct ddpcb *, sizeof( *ddp ), M_PCB, M_NOWAIT );
        !           473:     if ( ddp == NULL ) {
        !           474:        return (ENOBUFS);
        !           475:     }
        !           476:     bzero( ddp, sizeof( *ddp ));
        !           477:
        !           478:     ddp->ddp_lsat.sat_port = ATADDR_ANYPORT;
        !           479:
        !           480:     ddp->ddp_next = ddpcb;
        !           481:     ddp->ddp_prev = NULL;
        !           482:     ddp->ddp_pprev = NULL;
        !           483:     ddp->ddp_pnext = NULL;
        !           484:     if ( ddpcb ) {
        !           485:        ddpcb->ddp_prev = ddp;
        !           486:     }
        !           487:     ddpcb = ddp;
        !           488:
        !           489:     ddp->ddp_socket = so;
        !           490:     so->so_pcb = (caddr_t)ddp;
        !           491:     return( 0 );
        !           492: }
        !           493:
        !           494: static void
        !           495: at_pcbdetach( so, ddp )
        !           496:     struct socket      *so;
        !           497:     struct ddpcb       *ddp;
        !           498: {
        !           499:     soisdisconnected( so );
        !           500:     so->so_pcb = 0;
        !           501:     sofree( so );
        !           502:
        !           503:     /* remove ddp from ddp_ports list */
        !           504:     if ( ddp->ddp_lsat.sat_port != ATADDR_ANYPORT &&
        !           505:            ddp_ports[ ddp->ddp_lsat.sat_port - 1 ] != NULL ) {
        !           506:        if ( ddp->ddp_pprev != NULL ) {
        !           507:            ddp->ddp_pprev->ddp_pnext = ddp->ddp_pnext;
        !           508:        } else {
        !           509:            ddp_ports[ ddp->ddp_lsat.sat_port - 1 ] = ddp->ddp_pnext;
        !           510:        }
        !           511:        if ( ddp->ddp_pnext != NULL ) {
        !           512:            ddp->ddp_pnext->ddp_pprev = ddp->ddp_pprev;
        !           513:        }
        !           514:     }
        !           515:
        !           516:     if ( ddp->ddp_route.ro_rt ) {
        !           517:        rtfree( ddp->ddp_route.ro_rt );
        !           518:     }
        !           519:
        !           520:     if ( ddp->ddp_prev ) {
        !           521:        ddp->ddp_prev->ddp_next = ddp->ddp_next;
        !           522:     } else {
        !           523:        ddpcb = ddp->ddp_next;
        !           524:     }
        !           525:     if ( ddp->ddp_next ) {
        !           526:        ddp->ddp_next->ddp_prev = ddp->ddp_prev;
        !           527:     }
        !           528:
        !           529:     FREE( ddp, M_PCB );
        !           530: }
        !           531:
        !           532: /*
        !           533:  * For the moment, this just find the pcb with the correct local address.
        !           534:  * In the future, this will actually do some real searching, so we can use
        !           535:  * the sender's address to do de-multiplexing on a single port to many
        !           536:  * sockets (pcbs).
        !           537:  */
        !           538: struct ddpcb *
        !           539: ddp_search( from, to, aa )
        !           540:     struct sockaddr_at *from, *to;
        !           541:     struct at_ifaddr   *aa;
        !           542: {
        !           543:     struct ddpcb       *ddp;
        !           544:
        !           545:     /*
        !           546:      * Check for bad ports.
        !           547:      */
        !           548:     if ( to->sat_port < ATPORT_FIRST || to->sat_port >= ATPORT_LAST ) {
        !           549:        return( NULL );
        !           550:     }
        !           551:
        !           552:     /*
        !           553:      * Make sure the local address matches the sent address.  What about
        !           554:      * the interface?
        !           555:      */
        !           556:     for ( ddp = ddp_ports[ to->sat_port - 1 ]; ddp; ddp = ddp->ddp_pnext ) {
        !           557:        /* XXX should we handle 0.YY? */
        !           558:
        !           559:        /* XXXX.YY to socket on destination interface */
        !           560:        if ( to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net &&
        !           561:                to->sat_addr.s_node == ddp->ddp_lsat.sat_addr.s_node ) {
        !           562:            break;
        !           563:        }
        !           564:
        !           565:        /* 0.255 to socket on receiving interface */
        !           566:        if ( to->sat_addr.s_node == ATADDR_BCAST && ( to->sat_addr.s_net == 0 ||
        !           567:                to->sat_addr.s_net == ddp->ddp_lsat.sat_addr.s_net ) &&
        !           568:                ddp->ddp_lsat.sat_addr.s_net == AA_SAT( aa )->sat_addr.s_net ) {
        !           569:            break;
        !           570:        }
        !           571:
        !           572:        /* XXXX.0 to socket on destination interface */
        !           573:        if ( to->sat_addr.s_net == aa->aa_firstnet &&
        !           574:                to->sat_addr.s_node == 0 &&
        !           575:                ntohs( ddp->ddp_lsat.sat_addr.s_net ) >=
        !           576:                ntohs( aa->aa_firstnet ) &&
        !           577:                ntohs( ddp->ddp_lsat.sat_addr.s_net ) <=
        !           578:                ntohs( aa->aa_lastnet )) {
        !           579:            break;
        !           580:        }
        !           581:     }
        !           582:     return( ddp );
        !           583: }
        !           584:
        !           585: void
        !           586: ddp_init()
        !           587: {
        !           588:     atintrq1.ifq_maxlen = IFQ_MAXLEN;
        !           589:     atintrq2.ifq_maxlen = IFQ_MAXLEN;
        !           590: }

CVSweb