Annotation of kernel/bsd/netat/ddp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /*
                     26:  *     Copyright (c) 1987, 1988, 1989 Apple Computer, Inc. 
                     27:  *
                     28:  *     The information contained herein is subject to change without
                     29:  *     notice and  should not be  construed as a commitment by Apple
                     30:  *     Computer, Inc. Apple Computer, Inc. assumes no responsibility
                     31:  *     for any errors that may appear.
                     32:  *
                     33:  *     Confidential and Proprietary to Apple Computer, Inc.
                     34:  *
                     35:  *
                     36:  *
                     37:  */
                     38: 
                     39: 
                     40: #define RESOLVE_DBG                    /* define debug globals in debug.h */
                     41: 
                     42: #include <sysglue.h>
                     43: #include <at/appletalk.h>
                     44: #include <lap.h>
                     45: #include <llap.h>
                     46: #include <at/elap.h>
                     47: #include <at/ddp.h>
                     48: #include <at/ep.h>
                     49: #include <nbp.h>
                     50: #include <rtmp.h>
                     51: #include <at/zip.h>
                     52: #include <at/at_lap.h>
                     53: #include <at_elap.h>
                     54: #include <at_ddp.h>
                     55: #include <adsp_local.h>
                     56: #include <at_ddp_brt.h>
                     57: #include <at_zip.h>
                     58: #include <routing_tables.h>
                     59: #include <atlog.h>
                     60: #include <at_snmp.h>
                     61: #include <at_aurp.h>
                     62: 
                     63: #include "at_kdebug.h"
                     64: 
                     65: /* globals */
                     66:        /* Queue of LAP interfaces which have registered themselves with DDP */
                     67: static at_if_t at_ifQueueHd = { &at_ifQueueHd, &at_ifQueueHd };
                     68: 
                     69:        /* Pointer to LAP interface which DDP addresses are tied to */
                     70: /*at_if_t              *at_ifDefault = 0; */
                     71: 
                     72:        /* DDP statistics */
                     73: static at_ddp_stats_t  at_ddp_stats;
                     74: snmpStats_t            snmpStats;                              /* snmp ddp & echo stats */
                     75: 
                     76:        /* DDP input queue */
                     77: static char    *InputQueue = NULL;
                     78: 
                     79:        /* DDP Socket Table */
                     80: ddp_socket_t   ddp_socket [DDP_SOCKET_LAST + 1];
                     81: 
                     82: at_if_t  *ifID_table[IF_TOTAL_MAX];
                     83:                        /* the table of ifID structures, one per 
                     84:                         * interface (not just ethernet)
                     85:                         * NOTE: for MH, entry 0 in this table is 
                     86:                         *       now defined to be the default I/F
                     87:                         */
                     88: 
                     89: /* Appletalk state */
                     90: extern at_state_t      *at_statep;
                     91: 
                     92:        /* routing mode special */
                     93: void (*ddp_AURPsendx)();
                     94: at_if_t *aurp_ifID = 0;
                     95: extern routing_needed();
                     96: extern pktsIn,pktsOut;
                     97: /* extern char ddp_off_flag; */
                     98: int pktsDropped,pktsHome;
                     99: atlock_t ddpall_lock;
                    100: atlock_t ddpinp_lock;
                    101: 
                    102: int ot_protoCnt = 0;
                    103: char ot_protoT[256];
                    104: char ot_atp_socketM[256];
                    105: char ot_adsp_socketM[256];
                    106: 
                    107: extern int *atp_pidM;
                    108: extern int *adsp_pidM;
                    109: extern gref_t *atp_inputQ[];
                    110: extern CCB *adsp_inputQ[];
                    111: 
                    112: at_if_t *forUs(at_ddp_t *);
                    113: 
                    114: extern void
                    115:   routershutdown(),
                    116:   ddp_brt_shutdown();
                    117: void ddp_notify_nbp();
                    118: 
                    119: #define MAX_NOTIFY_NBP 16
                    120: static struct {
                    121:        unsigned char socket;
                    122:        unsigned char ddptype;
                    123:        unsigned short filler;
                    124:        int pid;
                    125: } notify_nbp_tbl[MAX_NOTIFY_NBP];
                    126: 
                    127: void
                    128: Xddp_notify_nbp(id)
                    129: int    id;
                    130: {
                    131:        unsigned char socket;
                    132: 
                    133:        if ((socket = notify_nbp_tbl[id].socket) != 0) {
                    134:                notify_nbp_tbl[id].socket = 0;
                    135:                ddp_notify_nbp(
                    136:                        socket,
                    137:                        notify_nbp_tbl[id].pid,
                    138:                        notify_nbp_tbl[id].ddptype);
                    139:        }
                    140: }
                    141: 
                    142: int
                    143: ot_ddp_check_socket(socket, pid)
                    144: unsigned char socket;
                    145: int pid;
                    146: {
                    147:        extern ddp_dev_t ddp_devs[];
                    148:        int cnt;
                    149: 
                    150:        dPrintf(D_M_DDP, D_L_INFO, ("ot_ddp_check_socket: %d\n", socket));
                    151:        cnt = (DDP_SOCK_UPQ(socket) == NULL) ? 0 :
                    152:                ( (ddp_devs[socket].pid == pid) ? 1 : 0 );
                    153:        if (ot_protoT[3]) { /* ATP */
                    154:                if ((atp_inputQ[socket] != NULL)
                    155:                    && (atp_inputQ[socket] != (gref_t *)1)
                    156:                    && (atp_pidM[socket] == pid))
                    157:                        cnt++;
                    158:        }
                    159:        if (ot_protoT[DDP_ADSP]) {
                    160:                if ((adsp_inputQ[socket] != NULL) && (adsp_pidM[socket] == pid))
                    161:                        cnt++;
                    162:        }
                    163: 
                    164:        return(cnt);
                    165: }
                    166: 
                    167: /****************************************************************/
                    168: /*                                                             */
                    169: /*                                                             */
                    170: /*                     Support Routines                        */
                    171: /*                                                             */
                    172: /*                                                             */
                    173: /****************************************************************/
                    174: 
                    175: /*
                    176:  * Name:
                    177:  *     ddp_checksum
                    178:  *
                    179:  * Description:
                    180:  *     This procedure determines the checksum of an extended DDP datagram.
                    181:  *      Add the unsigned bytes into an unsigned 16-bit accumulator.
                    182:  *      After each add, rotate the sign bit into the low order bit of
                    183:  *      the accumulator. When done, if the checksum is 0, changed into 0xFFFF.
                    184:  *
                    185:  * Calling sequence:
                    186:  *     checksum = ddp_checksum(mp, offset)
                    187:  *
                    188:  * Parameters:
                    189:  *     mp              pointer to the datagram gbuf_t
                    190:  *     offset          offset to start at in first gbuf_t block
                    191:  *
                    192:  * Return value:
                    193:  *     The DDP checksum.
                    194:  *
                    195:  */
                    196: 
                    197: static u_short
                    198: ddp_checksum(mp, offset)
                    199: register gbuf_t        *mp;
                    200: register int   offset;
                    201: {
                    202:        register u_char *data;
                    203:        register int     length;
                    204:        register u_short checksum;
                    205: 
                    206:        checksum = 0;
                    207: 
                    208:        do {
                    209:                if (offset >= gbuf_len(mp))
                    210:                        offset -= gbuf_len(mp);
                    211:                else {
                    212:                        data = ((unsigned char *) gbuf_rptr(mp)) + offset;
                    213:                        length = gbuf_len(mp) - offset;
                    214:                        offset = 0;
                    215:                        /* Portable checksum from 3.0 */
                    216:                        while (length--) {
                    217:                                checksum += *data++;
                    218:                                checksum = (checksum & 0x8000) ?
                    219:                                        ((checksum << 1) | 1) : (checksum << 1);
                    220:                        }
                    221:                }
                    222:        } while ( (mp = gbuf_cont(mp)) );
                    223: 
                    224:        if (checksum == 0)
                    225:                checksum = 0xffff;
                    226: 
                    227:        return(checksum);
                    228: }
                    229: 
                    230: 
                    231: void ddp_shutdown()
                    232: {
                    233:        routershutdown();
                    234:        ddp_brt_shutdown();
                    235:        ddps_shutdown((gref_t *)InputQueue);
                    236:        InputQueue = NULL;
                    237:        dPrintf(D_M_DDP, D_L_VERBOSE, ("DDP shutdown completed"));
                    238:        return;
                    239: }
                    240: 
                    241: 
                    242: /*
                    243:  * Name:
                    244:  *     ddp_init
                    245:  *
                    246:  * Description:
                    247:  *     Initializes DDP.  The streams version allocates a new queue pair to
                    248:  *     be used as the input queue for incoming lap datagrams.  The write 
                    249:  *     queue of this pair is not used.
                    250:  *
                    251:  * Return value:
                    252:  *
                    253:  * Priority Level:
                    254:  *     This function is called by the stream head open routines, or
                    255:  *     by the lap layer's ONLINE function via ddp_add_if().
                    256:  */
                    257: static int
                    258: ddp_init()
                    259: {
                    260:        char            *q;
                    261:        char            *ddps_init();
                    262:        void            ddp_brt_init();
                    263:        at_socket       socket;
                    264: 
                    265:        typedef void    (*proc_ptr)();
                    266:        proc_ptr        handler;
                    267:        extern  void    sip_init();
                    268: 
                    269:        dPrintf(D_M_DDP, D_L_STARTUP, ("ddp_init starting\n"));
                    270:        /* If using streams, we may get called more than once */
                    271:        if (InputQueue == NULL) {
                    272:                bzero((char *)notify_nbp_tbl, sizeof(notify_nbp_tbl));
                    273:                if ((q = ddps_init()) == NULL)
                    274:                        return(ENOBUFS);
                    275:                else {
                    276:                        InputQueue = q;
                    277:                        /* initialize the ddp_socket table */
                    278:                        bzero(ddp_socket,sizeof(ddp_socket));
                    279:                        for (socket = DDP_SOCKET_1st_RESERVED; 
                    280:                                socket <= DDP_SOCKET_LAST; socket++)
                    281:                                ddp_socket[socket].number = socket;
                    282:                        bzero(&at_ddp_stats, sizeof(at_ddp_stats_t));
                    283:                        ddp_brt_init();
                    284: 
                    285:                        /* Initialize all the protocols implemented in 
                    286:                         * kernel
                    287:                         */
                    288:                        handler = (proc_ptr)ep_init();
                    289:                        ddp_socket[EP_SOCKET].number = EP_SOCKET;
                    290:                        ddp_socket[EP_SOCKET].flags |= DDP_CALL_HANDLER;
                    291:                        DDP_SOCK_HANDLER(EP_SOCKET) = handler;
                    292: 
                    293:                        handler = (proc_ptr)rtmp_init();
                    294:                        ddp_socket[RTMP_SOCKET].number= RTMP_SOCKET;
                    295:                        ddp_socket[RTMP_SOCKET].flags|=DDP_CALL_HANDLER;
                    296:                        DDP_SOCK_HANDLER(RTMP_SOCKET) = handler;
                    297: 
                    298:                        handler = (proc_ptr)zip_init();
                    299:                        ddp_socket[ZIP_SOCKET].flags|=DDP_CALL_HANDLER;
                    300:                        ddp_socket[ZIP_SOCKET].number = ZIP_SOCKET;
                    301:                        DDP_SOCK_HANDLER(ZIP_SOCKET) = handler;
                    302: 
                    303:                        handler = (proc_ptr)nbp_init();
                    304:                        ddp_socket[NBP_SOCKET].number = NBP_SOCKET;
                    305:                        ddp_socket[NBP_SOCKET].flags |= DDP_CALL_HANDLER;
                    306:                        DDP_SOCK_HANDLER(NBP_SOCKET) = handler;
                    307: 
                    308:                        bzero(ifID_table, sizeof(ifID_table));
                    309: 
                    310:                        sip_init();
                    311:                }
                    312:        }
                    313:        dPrintf(D_M_DDP, D_L_STARTUP, ("ddp_init OK\n"));
                    314: 
                    315:        return (0);
                    316: }
                    317: 
                    318: 
                    319: /*
                    320:  * ddp_add_if()
                    321:  *
                    322:  * Description:
                    323:  *     This procedure is called by each LAP interface when it wants to place
                    324:  *     itself online.  The LAP interfaces passes in a pointer to its at_if
                    325:  *     struct, which is added to DDP's list of active interfaces (at_ifQueueHd).
                    326:  *     When DDP wants to transmit a packet, it searches this list for the 
                    327:  *     interface to use.
                    328:  *     
                    329:  *     If AT_IFF_DEFAULT is set, then this interface is to be brought online
                    330:  *     as the interface DDP socket addresses are tied to.  Of course there can
                    331:  *     be only one default interface; we return an error if it's already set. 
                    332:  *
                    333:  * Calling Sequence:
                    334:  *     ret_status = ddp_add_if(ifID)
                    335:  *
                    336:  * Formal Parameters:
                    337:  *     ifID            pointer to LAP interface's at_if struct.
                    338:  *
                    339:  * Completion Status:
                    340:  *     0               Procedure successfully completed.
                    341:  *     EALREADY        This interface is already online, or there is
                    342:  *                     already a default interface.
                    343:  *     ENOBUFS         Cannot allocate input queue
                    344:  *
                    345:  * Side Effects:
                    346:  *     The global at_ifDefault may be set.
                    347:  */
                    348: int ddp_add_if(ifID)
                    349: register at_if_t       *ifID;
                    350: {
                    351:        int     status;
                    352:        int port = -1;
                    353: 
                    354:        dPrintf(D_M_DDP, D_L_STARTUP, ("ddp_add_if: called, ifID:0x%x\n", (u_int) ifID));
                    355:        /* Initialize some of the ddp data structures and protocol modules
                    356:         * like NBP and RTMP. 
                    357:         */
                    358:        if (!(at_statep->flags & AT_ST_DDP_INIT)) {
                    359:                
                    360:                if ((status = ddp_init()) != 0) {
                    361:                        ifID->ddpInputQueue = NULL;
                    362:                        return(status);
                    363:                }
                    364:                at_statep->flags |= AT_ST_DDP_INIT;
                    365:        }
                    366:        if (ifID->ifFlags & AT_IFF_DEFAULT) {
                    367:                if (ifID_table[IFID_HOME]) {
                    368:                        return(EEXIST);    /* home port already set */ 
                    369:                }
                    370:                else {
                    371:                        port = 0;
                    372:                        ifID_table[IFID_HOME] = ifID;
                    373:                }
                    374:        }
                    375:        else
                    376:                for (port=IFID_HOME+1; port<IF_TOTAL_MAX; port++) {     /* add i/f to port list */
                    377:                        if (!ifID_table[port]) {
                    378:                                ifID_table[port] = ifID;
                    379:                                ifID->ifPort = port;                                    /* set ddp port # in ifID */
                    380:                                break;
                    381:                        }
                    382:                }
                    383: 
                    384:        if (port == IF_TOTAL_MAX) {                                                     /* no space left */
                    385:                ifID->ddpInputQueue = NULL;
                    386:                return(ENOMEM);
                    387:        }
                    388:        dPrintf(D_M_DDP, D_L_STARTUP, ("ddp:adding ifID_table[%d]\n", port));
                    389:        
                    390:        /* Add this interface to the list of online interfaces */
                    391:        ddp_insque((LIB_QELEM_T *)ifID, (LIB_QELEM_T *)at_ifQueueHd.FwdLink);
                    392:        
                    393:        ifID->ddpInputQueue = InputQueue;
                    394:        ATALK_ASSIGN(ifID->ifARouter, 0, 0, 0);
                    395:                        at_statep->ifs_online++;
                    396: 
                    397:        return (0);
                    398: }
                    399: 
                    400: 
                    401: /*
                    402:  * ddp_rem_if()
                    403:  *
                    404:  * Description:
                    405:  *     This procedure is called by each LAP interface when it wants to take
                    406:  *     itself offline.  The LAP interfaces passes in a pointer to its at_if
                    407:  *     struct; DDP's list of active interfaces (at_ifQueueHd) is searched and
                    408:  *     this interface is removed from the list.  DDP can still transmit 
                    409:  *     packets as long as this interface is not the default interface; the
                    410:  *     sender will just get ENETUNREACH errors when it tries to send to an
                    411:  *     interface that went offline.  However, if the default interface is
                    412:  *     taken offline, we no longer have a node ID to use as a source address
                    413:  *     and DDP must return ENETDOWN when a caller tries to send a packet.
                    414:  *     
                    415:  * Calling Sequence:
                    416:  *     ret_status = ddp_rem_if(ifID)
                    417:  *
                    418:  * Formal Parameters:
                    419:  *     ifID            pointer to LAP interface's at_if struct.
                    420:  *
                    421:  * Completion Status:
                    422:  *     0               Procedure successfully completed.
                    423:  *     EALREADY        This interface is already offline.
                    424:  *
                    425:  * Side Effects:
                    426:  *     The global at_ifDefault may be reset.
                    427:  */
                    428: int ddp_rem_if(ifID)
                    429: register at_if_t       *ifID;
                    430: {
                    431:        register at_if_t        *ifQueuep;
                    432:        int s;
                    433: 
                    434:        ATDISABLE(s, ddpall_lock);
                    435:        ifQueuep = at_ifQueueHd.FwdLink;
                    436:        while (ifQueuep != &at_ifQueueHd) {
                    437:                if (ATALK_EQUAL(ifQueuep->ifThisNode, ifID->ifThisNode)){
                    438:                        trackrouter_rem_if(ifID);
                    439:                        ifID->ifARouterTimer = 0;
                    440:                        ddp_remque((LIB_QELEM_T *)ifQueuep);
                    441:                        if (at_statep->ifs_online == 1) {       /* if last interface */
                    442:                                ddp_shutdown();
                    443:                        }
                    444:                        ifID_table[ifID->ifPort] = NULL;
                    445:                        at_statep->ifs_online--;
                    446:                        ATENABLE(s, ddpall_lock);
                    447:                        return (0);
                    448:                }
                    449:                ifQueuep = ifQueuep->FwdLink;
                    450:        }
                    451:        ATENABLE(s, ddpall_lock);
                    452:        return (EALREADY);
                    453: }
                    454: 
                    455: /*
                    456:  * The user may have registered an NVE with the NBP on a socket.  When the
                    457:  * socket is closed, the NVE should be deleted from NBP's name table.  The
                    458:  * user should delete the NVE before the socket is shut down, but there
                    459:  * may be circumstances when he can't.  So, whenever a DDP socket is closed,
                    460:  * this routine is used to notify NBP of the socket closure.  This would
                    461:  * help NBP get rid of all NVE's registered on the socket.
                    462:  */
                    463: void ddp_notify_nbp(socket, pid, ddptype)
                    464:      unsigned char socket;
                    465:      int pid;
                    466:      unsigned char ddptype;
                    467: {
                    468:        register int            size;
                    469:        register gbuf_t         *mp;
                    470:        register at_ddp_t       *ddp;
                    471:        register at_nbp_t       *nbp;
                    472:        void            ddp_input();
                    473:        int id;
                    474: 
                    475:        /* *** do this only when the default interface is filled in? *** */
                    476:        if (DDP_SOCK_UPQ(NBP_SOCKET) && ifID_table[IFID_HOME]) {
                    477:                size = DDP_X_HDR_SIZE + 2; /* for NBP control fields */
                    478:                        
                    479:                if (!(mp = gbuf_alloc(size+8, PRI_HI))) {
                    480:                        dPrintf(D_M_DDP, D_L_ERROR, ("DDP: TROUBLE out of gbuf"));
                    481:                        /* *** find an empty entry? *** */
                    482:                        for (id = 0; id < MAX_NOTIFY_NBP; id++) {
                    483:                                if (notify_nbp_tbl[id].socket == 0) {
                    484:                                        notify_nbp_tbl[id].socket = socket;
                    485:                                        notify_nbp_tbl[id].ddptype = ddptype;
                    486:                                        notify_nbp_tbl[id].pid = pid;
                    487:                                        atalk_timeout(Xddp_notify_nbp, id, SYS_HZ/10);
                    488:                                        break;
                    489:                                }
                    490:                        }
                    491:                        return;
                    492:                }
                    493: 
                    494:                gbuf_wset(mp, size);
                    495:                ddp = (at_ddp_t *)gbuf_rptr(mp);
                    496:                nbp = (at_nbp_t *)ddp->data;
                    497: 
                    498:                nbp->control = NBP_CLOSE_NOTE;
                    499:                nbp->tuple_count = nbp->at_nbp_id = 0;
                    500:                ((int *)gbuf_wptr(mp))[0] = (int)pid;
                    501:                ((int *)gbuf_wptr(mp))[1] = (int)ddptype;
                    502:        
                    503:                ddp->type = NBP_DDP_TYPE;
                    504:                ddp->unused = ddp->hopcount = 0;
                    505:                DDPLEN_ASSIGN(ddp, size);
                    506:                UAS_ASSIGN(ddp->checksum, 0);
                    507:                NET_NET(ddp->src_net, ifID_table[IFID_HOME]->ifThisNode.atalk_net);
                    508:                ddp->src_node = ifID_table[IFID_HOME]->ifThisNode.atalk_node;
                    509:                ddp->src_socket = (at_socket)socket;
                    510:                NET_NET(ddp->dst_net, ifID_table[IFID_HOME]->ifThisNode.atalk_net);
                    511:                ddp->dst_node = ifID_table[IFID_HOME]->ifThisNode.atalk_node;
                    512:                ddp->dst_socket = NBP_SOCKET;
                    513:                ddp_input(mp, 0);  /* ifID 0 implies loopback */
                    514:        }
                    515: } /* ddp_notify_nbp */
                    516: 
                    517: 
                    518: /* This routine shrinks the ddp header from long to short, 
                    519:  * It also prepends ALAP header and fills up some of the
                    520:  * fields as appropriate.
                    521:  */
                    522: static at_ddp_short_t  *ddp_shrink_hdr (mp)
                    523: register gbuf_t        *mp;
                    524: {
                    525:        register at_ddp_t       *ddp;
                    526:        register at_ddp_short_t *ddp_short;
                    527:        register at_llap_hdr_t  *llap;
                    528:        gbuf_t *newmp;
                    529: 
                    530:        if ((newmp = (gbuf_t *)gbuf_copym((gbuf_t *) mp)) == (gbuf_t *)NULL)
                    531:            return ((at_ddp_short_t *)NULL);
                    532:        gbuf_freem(mp);
                    533:        mp = newmp;
                    534: 
                    535:        ddp = (at_ddp_t *)gbuf_rptr(mp);
                    536:        gbuf_rinc(mp,((DDP_X_HDR_SIZE - DDP_HDR_SIZE) - LLAP_HDR_SIZE));
                    537:        llap = (at_llap_hdr_t *)gbuf_rptr(mp);
                    538:        ddp_short = (at_ddp_short_t *)(gbuf_rptr(mp) + LLAP_HDR_SIZE);
                    539: 
                    540:        llap->destination = ddp->dst_node;
                    541:        llap->type = LLAP_TYPE_DDP;
                    542:        ddp_short->length = ddp->length - (DDP_X_HDR_SIZE - DDP_HDR_SIZE);
                    543:        ddp_short->unused = 0;
                    544:        return ((at_ddp_short_t *)mp);
                    545: }
                    546: 
                    547: 
                    548: /* mp points to message of the form {llap, short ddp, ...}.
                    549:  * Get rid of llap, extend ddp header to make it of the form
                    550:  * {extended ddp, ... }
                    551:  */
                    552: static gbuf_t  *ddp_extend_hdr (mp)
                    553: register gbuf_t        *mp;
                    554: {
                    555:        register at_llap_hdr_t  *llap;
                    556:        register at_ddp_short_t *ddp_short;
                    557:        register at_ddp_t       *ddp;
                    558:        char            buf[DDP_HDR_SIZE + LLAP_HDR_SIZE];
                    559:        gbuf_t          *m1, *m2;
                    560: 
                    561:        /* We need to remove the llap header from the packet and extend the
                    562:         * short DDP header in to a long one.  5 bytes of additional space
                    563:         * is required in effect, but we can not afford to put these 5 bytes
                    564:         * in a separate buffer, since the ddp buffer would end up being
                    565:         * fragmented into two pieces, which is a no-no.  So, we first get
                    566:         * rid of the llap and ddp short headers and then add the extended
                    567:         * header.
                    568:         */
                    569:        
                    570:        /* Assuming that the llap and ddp short headers are placed next
                    571:         * to each other in the same buffer
                    572:         */
                    573:        bcopy(gbuf_rptr(mp), buf, LLAP_HDR_SIZE + DDP_HDR_SIZE);
                    574:        m1 = ddp_adjmsg(mp, LLAP_HDR_SIZE+DDP_HDR_SIZE) ? mp : 0;
                    575: 
                    576:        /* If the message did not contain any ddp data bytes, then m would
                    577:         * be NULL at this point... and we can't just grow a NULL message, 
                    578:         * we need to ALLOC a new one.
                    579:         */
                    580:        if (m1) {
                    581:                if ((m2 = (gbuf_t *)ddp_growmsg(m1, -DDP_X_HDR_SIZE)) == NULL) {
                    582:                        dPrintf(D_M_DDP, D_L_WARNING,
                    583:                                ("Dropping packet - no bufs to extend hdr"));
                    584:                        at_ddp_stats.rcv_dropped_nobuf++;
                    585:                        gbuf_freem(m1);
                    586:                        return(NULL);
                    587:                }
                    588:        } else
                    589:                /* Original message mp has already been freed by ddp_adjmsg if we
                    590:                 * managed to arrive here... this case occurs only when the
                    591:                 * message mp did not contain any ddp data bytes, only lap and
                    592:                 * ddp headers
                    593:                 */
                    594:                if ((m2 = gbuf_alloc(AT_WR_OFFSET+DDP_X_HDR_SIZE, PRI_MED)) == NULL) {
                    595:                        dPrintf(D_M_DDP,D_L_WARNING,
                    596:                                ("Packet (no data) dropped - no bufs to extend hdr"));
                    597:                        at_ddp_stats.rcv_dropped_nobuf++;
                    598:                        return(NULL);
                    599:                } else {
                    600:                        gbuf_rinc(m2,AT_WR_OFFSET);
                    601:                        gbuf_wset(m2,DDP_X_HDR_SIZE);
                    602:                }
                    603:        
                    604:        /* By the time we arrive here, m2 points to message of the form
                    605:         * {Extended DDP, ... }
                    606:         * mp and m1 are either non-existent or irrelevant.
                    607:         */
                    608:        ddp = (at_ddp_t *)gbuf_rptr(m2);
                    609:        llap = (at_llap_hdr_t *)buf;
                    610:        ddp_short = (at_ddp_short_t *)(buf + LLAP_HDR_SIZE);
                    611: 
                    612:        ddp->unused = ddp->hopcount = 0;
                    613:        ddp->length = ddp_short->length + DDP_X_HDR_SIZE - DDP_HDR_SIZE;
                    614:        UAS_ASSIGN(ddp->checksum, 0);
                    615:        NET_NET(ddp->dst_net, ifID_table[IFID_HOME]->ifThisNode.atalk_net);
                    616:        NET_NET(ddp->src_net, ifID_table[IFID_HOME]->ifThisNode.atalk_net);
                    617:        ddp->src_node = llap->source;
                    618:        ddp->dst_node = llap->destination;
                    619:        ddp->dst_socket = ddp_short->dst_socket;
                    620:        ddp->src_socket = ddp_short->src_socket;
                    621:        ddp->type = ddp_short->type;
                    622:        return (m2);
                    623: }
                    624: 
                    625: 
                    626: int ddp_get_cfg(cfgp, src_socket)
                    627: register at_ddp_cfg_t  *cfgp;
                    628: at_socket src_socket;
                    629: {
                    630:        register at_if_t *ifID = ifID_table[IFID_HOME];
                    631: 
                    632:        dPrintf(D_M_DDP, D_L_VERBOSE, ("ddp_get_cfg() entry"));
                    633:        cfgp->network_up = (ifID != NULL);
                    634: 
                    635:        cfgp->flags = ifID? ifID->ifFlags : 0;
                    636: 
                    637:        if (ifID) {
                    638:                NET_NET(cfgp->node_addr.net, ifID->ifThisNode.atalk_net);
                    639:                cfgp->node_addr.node = ifID->ifThisNode.atalk_node;
                    640:                cfgp->node_addr.socket = src_socket;
                    641:                if (!ROUTING_MODE && (ifID->ifRouterState == NO_ROUTER)) {
                    642:                        NET_ASSIGN(cfgp->router_addr.net, 0);
                    643:                        cfgp->router_addr.node = 0;
                    644:                } else {
                    645:                        NET_NET(cfgp->router_addr.net, ifID->ifARouter.atalk_net);
                    646:                        cfgp->router_addr.node = ifID->ifARouter.atalk_node;
                    647:                }
                    648:                cfgp->netlo = ifID->ifThisCableStart;
                    649:                cfgp->nethi = ifID->ifThisCableEnd;
                    650:        }
                    651:        else {
                    652:                NET_ASSIGN(cfgp->node_addr.net, 64000);
                    653:                cfgp->node_addr.node = 128;
                    654:                NET_ASSIGN(cfgp->router_addr.net, 0);
                    655:                cfgp->router_addr.node = 0;
                    656:                cfgp->node_addr.socket = src_socket;
                    657:                cfgp->netlo = 1;
                    658:                cfgp->nethi = 64500;
                    659:        }
                    660:        
                    661:        return(0);
                    662: }
                    663: 
                    664: 
                    665: int ddp_get_stats(statsp)
                    666: at_ddp_stats_t *statsp;
                    667: {
                    668:        dPrintf(D_M_DDP, D_L_VERBOSE, ("ddp_get_cfg() entry"));
                    669:        bcopy(&at_ddp_stats, statsp, sizeof(at_ddp_stats));
                    670:        return(0);
                    671: }
                    672: 
                    673: 
                    674: /****************************************************************/
                    675: /*                                                             */
                    676: /*                                                             */
                    677: /*                     Module Code                             */
                    678: /*                                                             */
                    679: /*                                                             */
                    680: /****************************************************************/
                    681: 
                    682: /*
                    683:  * ddp_bind_socket()
                    684:  *
                    685:  * Description:
                    686:  *
                    687:  * Calling Sequence:
                    688:  *     ret_status = ddp_bind_socket(socketp)
                    689:  *
                    690:  * Formal Parameters:
                    691:  *     socketp         pointer to a socket table entry
                    692:  *
                    693:  * Completion Status:
                    694:  *     0               Procedure successfully completed.
                    695:  *     EINVAL          Invalid well-known socket supplied.
                    696:  *     EACCES          User is not super-user.
                    697:  *     ENETDOWN        There are no interfaces online.
                    698:  *
                    699:  * Side Effects:
                    700:  *     NONE
                    701:  */
                    702: 
                    703: int
                    704: ddp_bind_socket(socketp)
                    705: register ddp_socket_t  *socketp;
                    706: {
                    707:        register at_socket     socket;
                    708:        u_char proto;
                    709:        int s;
                    710: 
                    711:        ATDISABLE(s, ddpall_lock);
                    712:        if (socketp->dev == NULL)
                    713:                proto = 0;
                    714:        else
                    715:                proto = ((ddp_dev_t *)socketp->dev)->proto;
                    716: 
                    717:        /* Request for dynamic socket? */
                    718:        if (socketp->number == 0) {
                    719:                /* Search table for free one */
                    720:                for (socket = DDP_SOCKET_LAST-proto; 
                    721:                        socket >= DDP_SOCKET_1st_DYNAMIC; socket--)
                    722:                        if (DDP_SOCK_UPQ(socket) == 0) {
                    723:                                if ((proto == DDP_ATP) && atp_inputQ[socket])
                    724:                                        continue;
                    725:                                else if ((proto == DDP_ADSP) && adsp_inputQ[socket])
                    726:                                        continue;
                    727:                                break;
                    728:                        }
                    729:                if (socket < DDP_SOCKET_1st_DYNAMIC)
                    730:                {
                    731:                        ATENABLE(s, ddpall_lock);
                    732:                        return(EADDRNOTAVAIL);  /* Error if no free sockets */
                    733:                }
                    734:                else
                    735:                        socketp->number = ddp_socket[socket].number;
                    736:        } else {
                    737:                /* Asking to open a socket by its number.  Check if its legal & 
                    738:                 * free. 
                    739:                 */
                    740:                socket = socketp->number;
                    741:                if (socket > DDP_SOCKET_LAST) 
                    742:                {
                    743:                        ATENABLE(s, ddpall_lock);
                    744:                        return(EINVAL);
                    745:                }
                    746:                if (DDP_SOCK_UPQ(socket) || DDP_SOCK_HANDLER(socket))
                    747:                {
                    748:                        ATENABLE(s, ddpall_lock);
                    749:                        return(EISCONN);
                    750:                }
                    751:        }
                    752:        if (proto == DDP_ATP) {
                    753:                if (atp_inputQ[socket])
                    754:                {
                    755:                        ATENABLE(s, ddpall_lock);
                    756:                        return(EISCONN);
                    757:                }
                    758:                ot_atp_socketM[socket] = 1;
                    759:        } else if (proto == DDP_ADSP) {
                    760:                if (adsp_inputQ[socket])
                    761:                {
                    762:                        ATENABLE(s, ddpall_lock);
                    763:                        return(EISCONN);
                    764:                }
                    765:                ot_adsp_socketM[socket] = 1;
                    766:        }
                    767:        ddp_socket[socket].flags = socketp->flags;
                    768:        DDP_SOCK_UPQ(socket) = socketp->sock_u.gref;
                    769:        ATENABLE(s, ddpall_lock);
                    770: 
                    771:        dPrintf(D_M_DDP, D_L_VERBOSE,
                    772:                ("Socket 0x%x is opened", (u_char)socket));
                    773: 
                    774:        return(0);
                    775: }
                    776:       
                    777: 
                    778: /*
                    779:  * ddp_close_socket()
                    780:  *
                    781:  * Description:                  
                    782:  *     This procedure closes a DDP socket.
                    783:  *     NBP is notified that the socket is being closed so that it can 
                    784:  *     deregister any attached names.
                    785:  *
                    786:  * Calling Sequence:
                    787:  *     ret_status = ddp_close_socket(socketp)
                    788:  *
                    789:  * Formal Parameters:
                    790:  *     socketp         pointer to a socket table entry
                    791:  *
                    792:  * Completion Status:
                    793:  *     0               Procedure successfully completed.
                    794:  *     ENOTCONN        Socket was not open.
                    795:  *
                    796:  * Side Effects:
                    797:  *     NONE
                    798:  */
                    799: int ddp_close_socket(socketp)
                    800: register ddp_socket_t  *socketp;
                    801: {
                    802:        register at_socket      socket = socketp->number;
                    803: 
                    804:        /* Make sure socket was open, if not return error */
                    805:        if (!DDP_SOCK_UPQ(socket))
                    806:                return (ENOTCONN);
                    807: 
                    808:        /* Notify NBP that we are closing this DDP socket */
                    809:        ddp_notify_nbp(socket,
                    810:                ((ddp_dev_t *)socketp->dev)->pid, 0);
                    811: 
                    812:        /* mark socket as closed */
                    813:        if (socketp->flags & DDP_CALL_HANDLER)
                    814:                socketp->sock_u.handler = NULL;
                    815:        else
                    816:                socketp->sock_u.gref = NULL;
                    817:        socketp->flags = 0;
                    818:        
                    819:        if (((ddp_dev_t *)socketp->dev)->proto == DDP_ATP)
                    820:                ot_atp_socketM[socket] = 0;
                    821:        else if (((ddp_dev_t *)socketp->dev)->proto == DDP_ADSP)
                    822:                ot_adsp_socketM[socket] = 0;
                    823: 
                    824:        dPrintf(D_M_DDP, D_L_VERBOSE,
                    825:                ("Socket 0x%x is closed", (u_char)socket));
                    826: 
                    827:        return (0);
                    828: }
                    829: 
                    830: 
                    831: /* There are various ways a packet may go out.... it may be sent out
                    832:  * directly to destination node, or sent to a random router or sent
                    833:  * to a router whose entry exists in Best Router Cache.  Following are 
                    834:  * constants used WITHIN this routine to keep track of choice of destination
                    835:  */
                    836: #define DIRECT_ADDR    1
                    837: #define        BRT_ENTRY       2
                    838: #define        BRIDGE_ADDR     3
                    839: 
                    840: /* 
                    841:  * ddp_output()
                    842:  *
                    843:  * Remarks : 
                    844:  *     called to queue a atp/ddp data packet on the network interface.
                    845:  *     It returns 0 normally, and an errno in case of error.
                    846:  *
                    847:  */
                    848: int ddp_output(mp, src_socket, src_addr_included)
                    849:      register gbuf_t   **mp;
                    850:      at_socket src_socket;
                    851:      int src_addr_included;
                    852: {
                    853:        register at_if_t        *ifID, *ifIDTmp;
                    854:        register at_ddp_t       *ddp;
                    855:        register ddp_brt_t      *brt;
                    856:        register at_net_al      dst_net;
                    857:        register int            len;
                    858:        struct   atalk_addr     at_dest;
                    859:        at_if_t         *ARouterIf = NULL;
                    860:        at_ddp_short_t  *ddp_short = NULL;
                    861:        int             loop = 0;
                    862:        int             error;
                    863:        int             addr_type;
                    864:        void            ddp_input();
                    865:        u_char  addr_flag, ddp_type;
                    866:        char    *addr = NULL;
                    867:        register gbuf_t *m, *tmp_m;
                    868:        at_ddp_t        *tmp_ddp;
                    869: 
                    870:        snmpStats.dd_outReq++;
                    871:        if ((ifID = ifID_table[IFID_HOME]) == NULL)
                    872:                return (ENETDOWN);
                    873:        m = *mp;
                    874:        ddp = (at_ddp_t *)gbuf_rptr(m);
                    875:        if (MULTIHOME_MODE && (ifIDTmp = forUs(ddp))) {
                    876:                ifID = ifIDTmp;
                    877:                loop = TRUE;
                    878:            dPrintf(D_M_DDP_LOW, D_L_USR1,
                    879:                        ("ddp_out: for us if:%s\n", ifID->ifName));
                    880:        }
                    881: 
                    882:     if ((ddp->dst_socket > (unsigned) (DDP_SOCKET_LAST + 1)) || 
                    883:                (ddp->dst_socket < DDP_SOCKET_1st_RESERVED)) {
                    884:            dPrintf(D_M_DDP, D_L_ERROR,
                    885:                        ("Illegal destination socket on outgoing packet (0x%x)",
                    886:                        ddp->dst_socket));
                    887:                at_ddp_stats.xmit_bad_addr++;
                    888:                return (ENOTSOCK);
                    889:        }
                    890:        if ((len = gbuf_msgsize(*mp)) > DDP_DATAGRAM_SIZE) {
                    891:                /* the packet is too large */
                    892:                dPrintf(D_M_DDP, D_L_ERROR,
                    893:                        ("Outgoing packet too long (len=%d bytes)", len));
                    894:                at_ddp_stats.xmit_bad_length++;
                    895:                return (EMSGSIZE);
                    896:        }
                    897:        at_ddp_stats.xmit_bytes += len;
                    898:        at_ddp_stats.xmit_packets++;
                    899: 
                    900:        DDPLEN_ASSIGN(ddp, len);
                    901:        ddp->hopcount = ddp->unused = 0;
                    902: 
                    903:        /* If this packet is for the same node, loop it back
                    904:         * up...  Note that for LocalTalk, dst_net zero means "THIS_NET", so
                    905:         * address 0.nn is eligible for loopback.  For Extended EtherTalk,
                    906:         * dst_net 0 can be used only for cable-wide or zone-wide 
                    907:         * broadcasts (0.ff) and as such, address of the form 0.nn is NOT
                    908:         * eligible for loopback.
                    909:         */
                    910:        dst_net = NET_VALUE(ddp->dst_net);
                    911: 
                    912:        /* If our packet is destined for the 'virtual' bridge
                    913:         * address of NODE==0xFE, replace that address with a
                    914:         * real bridge address.
                    915:         */
                    916:        if ((ddp->dst_node == 0xfe) && 
                    917:            ((dst_net == 0) ||
                    918:             (dst_net >= ifID->ifThisCableStart &&
                    919:              dst_net <= ifID->ifThisCableEnd))) {
                    920:                NET_NET(ddp->dst_net, ifID->ifARouter.atalk_net);
                    921:                dst_net = NET_VALUE(ifID->ifARouter.atalk_net);
                    922:                ddp->dst_node = ifID->ifARouter.atalk_node;
                    923:        }
                    924:        loop = ((ddp->dst_node == ifID->ifThisNode.atalk_node) &&
                    925:                (dst_net == NET_VALUE(ifID->ifThisNode.atalk_net))
                    926:               );
                    927: 
                    928:        if (loop) {
                    929:                gbuf_t *mdata, *mdata_next;
                    930: 
                    931:                ddp_type = ddp->type;
                    932:                ddp->src_node = ifID->ifThisNode.atalk_node;
                    933:                ddp->src_socket = src_socket;
                    934:                NET_NET(ddp->src_net, ifID->ifThisNode.atalk_net);
                    935: 
                    936:                dPrintf(D_M_DDP_LOW, D_L_OUTPUT,
                    937:                        ("ddp_output: loop to %d:%d port=%d\n",
                    938:                          NET_VALUE(ddp->src_net),
                    939:                          ddp->src_node,
                    940:                          ifID->ifPort));
                    941: 
                    942:                if (UAS_VALUE(ddp->checksum)) {
                    943:                        u_short tmp;
                    944:                        tmp = ddp_checksum(*mp, 4);
                    945:                        UAS_ASSIGN(ddp->checksum, tmp);
                    946:                }
                    947:                tmp_m = *mp;
                    948:                for (tmp_m=gbuf_next(tmp_m); tmp_m; tmp_m=gbuf_next(tmp_m)) {
                    949:                        tmp_ddp = (at_ddp_t *)gbuf_rptr(tmp_m);
                    950:                        DDPLEN_ASSIGN(tmp_ddp, gbuf_msgsize(tmp_m));
                    951:                        tmp_ddp->hopcount = tmp_ddp->unused = 0;
                    952:                        tmp_ddp->src_node = ddp->src_node;
                    953:                        NET_NET(tmp_ddp->src_net, ddp->src_net);
                    954:                        if (UAS_VALUE(tmp_ddp->checksum)) {
                    955:                                u_short tmp;
                    956:                                tmp = ddp_checksum(tmp_m, 4);
                    957:                                UAS_ASSIGN(tmp_ddp->checksum, tmp);
                    958:                        }
                    959:                }
                    960:                dPrintf(D_M_DDP, D_L_VERBOSE,
                    961:                        ("Looping back a packet from socket 0x%x to socket 0x%x",
                    962:                        ddp->src_socket, ddp->dst_socket));
                    963: 
                    964:                for (mdata = *mp; mdata; mdata = mdata_next) {
                    965:                        mdata_next = gbuf_next(mdata);
                    966:                        gbuf_next(mdata) = 0;
                    967:                        ddp_input(mdata, ifID);
                    968:                }
                    969:                return (0);
                    970:        }
                    971:         if ((ddp->dst_socket == ZIP_SOCKET) &&
                    972:                     (zip_type_packet(*mp) == ZIP_GETMYZONE)) {
                    973:                ddp->src_socket = src_socket;
                    974:                if ((error = zip_handle_getmyzone(ifID, *mp)) != 0)
                    975:                        return(error);
                    976:                gbuf_freem(*mp);
                    977:                return (0);
                    978:        }
                    979:        /*
                    980:         * find out the interface on which the packet should go out
                    981:         */
                    982:        for (ifID = at_ifQueueHd.FwdLink; ifID != &at_ifQueueHd; ifID = ifID->FwdLink) {
                    983: 
                    984:                if ((NET_VALUE(ifID->ifThisNode.atalk_net) == dst_net) || (dst_net == 0))
                    985:                        /* the message is either going out (i) on the same 
                    986:                         * NETWORK in case of LocalTalk, or (ii) on the same
                    987:                         * CABLE in case of Extended AppleTalk (EtherTalk).
                    988:                         */
                    989:                        break;
                    990: 
                    991:                if ((ifID->ifThisCableStart <= dst_net) &&
                    992:                    (ifID->ifThisCableEnd   >= dst_net)
                    993:                   )
                    994:                        /* We're on EtherTalk and the message is going out to 
                    995:                         * some other network on the same cable.
                    996:                         */
                    997:                        break;
                    998:                
                    999:                if (ARouterIf == NULL && ATALK_VALUE(ifID->ifARouter))
                   1000:                        ARouterIf = ifID;
                   1001:        }
                   1002:        dPrintf(D_M_DDP_LOW, D_L_USR1,
                   1003:                        ("ddp_out: after search ifid:0x%x %s ifID0:0x%x\n",
                   1004:                        (u_int) ifID, ifID ? ifID->ifName : "",
                   1005:                        (u_int) ifID_table[0]));
                   1006: 
                   1007:        if (ifID != &at_ifQueueHd) {
                   1008:                /* located the interface where the packet should
                   1009:                 * go.... the "first-hop" destination address
                   1010:                 * must be the same as real destination address.
                   1011:                 */
                   1012:                addr_type = DIRECT_ADDR;
                   1013:        } else {
                   1014:                /* no, the destination network number does
                   1015:                 * not match known network numbers.  If we have
                   1016:                 * heard from this network recently, BRT table
                   1017:                 * may have address of a router we could use!
                   1018:                 */
                   1019:                if (!ROUTING_MODE && !MULTIHOME_MODE) {
                   1020:                
                   1021:                        BRT_LOOK (brt, dst_net);
                   1022:                        if (brt) {
                   1023:                                /* Bingo... BRT has an entry for this network. 
                   1024:                                 * Use the link address as is.
                   1025:                                 */
                   1026:                                dPrintf(D_M_DDP, D_L_VERBOSE,
                   1027:                                        ("Found BRT entry to send to net 0x%x", dst_net));
                   1028:                                at_ddp_stats.xmit_BRT_used++;
                   1029:                                addr_type = BRT_ENTRY;
                   1030:                                ifID = brt->ifID;
                   1031:                        } else {
                   1032:                                /* No BRT entry available for dest network... do we 
                   1033:                                 * know of any router at all??
                   1034:                                 */
                   1035:                                if ((ifID = ARouterIf) != NULL)
                   1036:                                        addr_type = BRIDGE_ADDR;
                   1037:                                else {
                   1038:                                dPrintf(D_M_DDP, D_L_WARNING,
                   1039:                                                ("Found no interface to send pkt"));
                   1040:                                        at_ddp_stats.xmit_bad_addr++;
                   1041:                                        return (ENETUNREACH);
                   1042:                                }
                   1043:                        }
                   1044:                }
                   1045:                else { /* We are in multiport mode,  so we can bypass all the rest 
                   1046:                            * and directly ask for the routing of the packet
                   1047:                                */ 
                   1048: 
                   1049:                        ddp->src_socket = src_socket;
                   1050:                        at_ddp_stats.xmit_BRT_used++;
                   1051:                        if (!MULTIPORT_MODE || ifID == &at_ifQueueHd) 
                   1052:                                ifID = ifID_table[IFID_HOME];
                   1053:                  if (!src_addr_included) {
                   1054:                        ddp->src_node = ifID->ifThisNode.atalk_node;
                   1055:                        NET_NET(ddp->src_net, ifID->ifThisNode.atalk_net); 
                   1056:                  }
                   1057:                        routing_needed(*mp, ifID, TRUE);
                   1058:                        return (0);
                   1059:                }
                   1060:        }
                   1061:        /* by the time we land here, we know the interface on 
                   1062:         * which this packet is going out....  ifID.  
                   1063:         */
                   1064:        
                   1065:                switch (addr_type) {
                   1066:                case DIRECT_ADDR :
                   1067:                        at_dest.atalk_unused = 0;
                   1068:                        NET_ASSIGN(at_dest.atalk_net, dst_net);
                   1069:                        at_dest.atalk_node = ddp->dst_node;
                   1070:                        addr_flag = AT_ADDR;
                   1071:                        addr = (char *)&at_dest;
                   1072:                        break;
                   1073:                case BRT_ENTRY :
                   1074:                        addr_flag = ET_ADDR;
                   1075:                        addr = (char *)&brt->et_addr;
                   1076:                        break;
                   1077:                case BRIDGE_ADDR :
                   1078:                        at_dest = ifID->ifARouter;
                   1079:                        addr_flag = AT_ADDR;
                   1080:                        addr = (char *)&at_dest;
                   1081:                        break;
                   1082: 
                   1083:                }
                   1084:                /* Irrespective of the interface on which 
                   1085:                 * the packet is going out, we always put the 
                   1086:                 * same source address on the packet (unless multihoming mode).
                   1087:                 */
                   1088:                if (MULTIPORT_MODE) {
                   1089:                  if (!src_addr_included) {
                   1090:                        ddp->src_node = ifID->ifThisNode.atalk_node;
                   1091:                        NET_NET(ddp->src_net, ifID->ifThisNode.atalk_net); 
                   1092:                  }
                   1093:                }
                   1094:                else {
                   1095:                        ddp->src_node = ifID_table[IFID_HOME]->ifThisNode.atalk_node;
                   1096:                        NET_NET(ddp->src_net, ifID_table[IFID_HOME]->ifThisNode.atalk_net);
                   1097:                }
                   1098: 
                   1099:                ddp->src_socket = src_socket;
                   1100:                if (UAS_VALUE(ddp->checksum)) {
                   1101:                        u_short tmp;
                   1102:                        tmp = ddp_checksum(*mp, 4);
                   1103:                        UAS_ASSIGN(ddp->checksum, tmp);
                   1104:                }
                   1105: 
                   1106:        dPrintf(D_M_DDP, D_L_VERBOSE,
                   1107:                ("Packet going out to : net 0x%x, node 0x%x, socket 0x%x on %s",
                   1108:                (ddp_short ? 0 : dst_net), 
                   1109:                (ddp_short ? 0 : ddp->dst_node),
                   1110:                (ddp_short ? ddp_short->dst_socket : ddp->dst_socket),ifID->ifName));
                   1111:         dPrintf(D_M_DDP_LOW, D_L_OUTPUT,
                   1112:                ("ddp_output: going out to %d:%d skt%d\n",
                   1113:                dst_net, ddp->dst_node, ddp->dst_socket));
                   1114: 
                   1115:        if (ifID->ifState != LAP_OFFLINE) {
                   1116:                        tmp_m = *mp;
                   1117:                        for (tmp_m=gbuf_next(tmp_m); tmp_m; tmp_m=gbuf_next(tmp_m)) {
                   1118:                                tmp_ddp = (at_ddp_t *)gbuf_rptr(tmp_m);
                   1119:                                DDPLEN_ASSIGN(tmp_ddp, gbuf_msgsize(tmp_m));
                   1120:                                tmp_ddp->hopcount = tmp_ddp->unused = 0;
                   1121:                                tmp_ddp->src_node = ddp->src_node;
                   1122:                                NET_NET(tmp_ddp->src_net, ddp->src_net);
                   1123:                                tmp_ddp->dst_node = ddp->dst_node;
                   1124:                                NET_NET(tmp_ddp->dst_net, ddp->dst_net);
                   1125:                                if (UAS_VALUE(tmp_ddp->checksum)) {
                   1126:                                        u_short tmp;
                   1127:                                        tmp = ddp_checksum(tmp_m, 4);
                   1128:                                        UAS_ASSIGN(tmp_ddp->checksum, tmp);
                   1129:                                }
                   1130:                        }
                   1131:        {
                   1132:        struct  etalk_addr      dest_addr;
                   1133:        struct  atalk_addr      dest_at_addr;
                   1134:        int             loop = TRUE;            /* flag to aarp to loopback (default) */
                   1135:        elap_specifics_t *elapp = (elap_specifics_t *)ifID->ifLapp;
                   1136: 
                   1137:        m = *mp;
                   1138: 
                   1139:        /* the incoming frame is of the form {flag, address, ddp...}
                   1140:         * where "flag" indicates whether the address is an 802.3
                   1141:         * (link) address, or an appletalk address.  If it's an
                   1142:         * 802.3 address, the packet can just go out to the network
                   1143:         * through PAT, if it's an appletalk address, AT->802.3 address
                   1144:         * resolution needs to be done.
                   1145:         * If 802.3 address is known, strip off the flag and 802.3
                   1146:         * address, and prepend 802.2 and 802.3 headers.
                   1147:         */
                   1148:        
                   1149:        if (addr == NULL) {
                   1150:                addr_flag = *(u_char *)gbuf_rptr(m);
                   1151:                gbuf_rinc(m,1);
                   1152:        }
                   1153:        
                   1154:        switch (addr_flag) {
                   1155:        case AT_ADDR_NO_LOOP :
                   1156:                loop = FALSE;
                   1157:                /* pass thru */
                   1158:        case AT_ADDR :
                   1159:        if (addr == NULL) {
                   1160:            dest_at_addr = *(struct atalk_addr *)gbuf_rptr(m);
                   1161:            gbuf_rinc(m,sizeof(struct atalk_addr));
                   1162:        } else
                   1163:            dest_at_addr = *(struct atalk_addr *)addr;
                   1164:            break;
                   1165:        case ET_ADDR :
                   1166:        if (addr == NULL) {
                   1167:            dest_addr = *(struct etalk_addr *)gbuf_rptr(m);
                   1168:            gbuf_rinc(m,sizeof(struct etalk_addr));
                   1169:        } else
                   1170:            dest_addr = *(struct etalk_addr *)addr;
                   1171:            break;
                   1172:        default :
                   1173:                dPrintf(D_M_DDP_LOW,D_L_ERROR,
                   1174:                    ("ddp_output: Unknown addr_flag = 0x%x\n", addr_flag));
                   1175:            gbuf_freel(m);              /* unknown address type, chuck it */
                   1176:            return 0;
                   1177:         }
                   1178: 
                   1179:        while (gbuf_len(m) == 0) {
                   1180:                tmp_m = m;
                   1181:                m = gbuf_cont(m);
                   1182:                gbuf_freeb(tmp_m); 
                   1183:        }
                   1184: 
                   1185:        /* At this point, rptr points to ddp header for sure */
                   1186: 
                   1187:        if (elapp->elap_if.ifState == LAP_OFFLINE) {
                   1188:            gbuf_freel(m);
                   1189:                return 0;
                   1190:        }
                   1191: 
                   1192:        if (elapp->elap_if.ifState == LAP_ONLINE_FOR_ZIP) {
                   1193:                /* see if this is a ZIP packet that we need
                   1194:                 * to let through even though network is
                   1195:                 * not yet alive!!
                   1196:                 */
                   1197:                if (zip_type_packet(m) == 0) {
                   1198:                gbuf_freel(m);
                   1199:                        return 0;
                   1200:                }
                   1201:        }
                   1202:        
                   1203:        elapp->stats.xmit_packets++;
                   1204:        elapp->stats.xmit_bytes += gbuf_msgsize(m);
                   1205:        snmpStats.dd_outLong++;
                   1206:        
                   1207:        switch (addr_flag) {
                   1208:        case AT_ADDR_NO_LOOP :
                   1209:        case AT_ADDR :
                   1210:            /*
                   1211:             * we don't want elap to be looking into ddp header, so
                   1212:             * it doesn't know net#, consequently can't do 
                   1213:             * AMT_LOOKUP.  That task left to aarp now.
                   1214:             */
                   1215:            aarp_send_data(m,elapp,&dest_at_addr, loop);
                   1216:            break;
                   1217:        case ET_ADDR :
                   1218:            pat_output(elapp->pat_id, m, &dest_addr, 0);
                   1219:            break;
                   1220:         }
                   1221:        }
                   1222:                        return(0);
                   1223:        } 
                   1224:        gbuf_freel(*mp);
                   1225:        return (0);
                   1226: } /* ddp_output */
                   1227: 
                   1228: void   ddp_input(mp, ifID)
                   1229: register gbuf_t   *mp;
                   1230: register at_if_t *ifID;
                   1231: {
                   1232:        register at_ddp_t *ddp;
                   1233:        register int       msgsize;
                   1234:        register at_socket socket;
                   1235:        register int       len;
                   1236:        register at_net_al dst_net;
                   1237:        extern volatile RoutingMix;
                   1238: 
                   1239:        KERNEL_DEBUG(DBG_AT_DDP_INPUT | DBG_FUNC_START, 0,0,0,0,0);
                   1240: 
                   1241:        /* Makes sure we know the default interface before starting to
                   1242:         * accept incomming packets. If we don't we may end up with a
                   1243:         * null ifID_table[0] and have impredicable results (specially
                   1244:         * in router mode. This is a transitory state (because we can
                   1245:         * begin to receive packet while we're not completly set up yet.
                   1246:         */
                   1247: 
                   1248:        if (ifID_table[IFID_HOME] == (at_if_t *)NULL) {
                   1249:                dPrintf(D_M_DDP, D_L_ERROR,
                   1250:                        ("dropped incoming packet ifID_home not set yet\n"));
                   1251:                gbuf_freem(mp);
                   1252:                goto out; /* return */
                   1253:        }
                   1254: 
                   1255:        /*
                   1256:         * if a DDP packet has been broadcast, we're going to get a copy of
                   1257:         * it here; if it originated at user level via a write on a DDP 
                   1258:         * socket; when it gets here, the first block in the chain will be
                   1259:         * empty since it only contained the lap level header which will be
                   1260:         * stripped in the lap level immediately below ddp
                   1261:         */
                   1262: 
                   1263:        if ((mp = (gbuf_t *)ddp_compress_msg(mp)) == NULL) {
                   1264:                dPrintf(D_M_DDP, D_L_ERROR,
                   1265:                        ("dropped short incoming ET packet (len %d)", 0));
                   1266:                snmpStats.dd_inTotal++;
                   1267:                at_ddp_stats.rcv_bad_length++;
                   1268:                goto out; /* return; */
                   1269:        }
                   1270:        msgsize = gbuf_msgsize(mp);
                   1271: 
                   1272:        at_ddp_stats.rcv_bytes += msgsize;
                   1273:        at_ddp_stats.rcv_packets++;
                   1274: 
                   1275:        /* if the interface pointer is 0, the packet has been 
                   1276:         * looped back by 'write' half of DDP.  It is of the
                   1277:         * form {extended ddp,...}.  The packet is meant to go
                   1278:         * up to some socket on the same node.
                   1279:         */
                   1280:        if (ifID == (at_if_t *)NULL)            /* if loop back is specified */
                   1281:                ifID = ifID_table[IFID_HOME];   /* that means the home port */
                   1282: 
                   1283:                /* the incoming datagram has extended DDP header and is of 
                   1284:                 * the form {ddp,...}.
                   1285:                 */
                   1286:                if (msgsize < DDP_X_HDR_SIZE) {
                   1287:                        dPrintf(D_M_DDP, D_L_ERROR,
                   1288:                                ("dropped short incoming ET packet (len %d)", 
                   1289:                                msgsize));
                   1290:                        at_ddp_stats.rcv_bad_length++;
                   1291:                        gbuf_freem(mp);
                   1292:                        goto out; /* return; */
                   1293:                }
                   1294:        /*
                   1295:         * At this point, the message is always of the form
                   1296:         * {extended ddp, ... }.
                   1297:         */
                   1298:        ddp = (at_ddp_t *)gbuf_rptr(mp);
                   1299:        len = DDPLEN_VALUE(ddp);
                   1300: 
                   1301:        if (msgsize != len) {
                   1302:                if ((unsigned) msgsize > len) {
                   1303:                        if (len < DDP_X_HDR_SIZE) {
                   1304:                                dPrintf(D_M_DDP, D_L_ERROR,
                   1305:                                       ("Length problems, ddp length %d, buffer length %d",
                   1306:                                       len, msgsize));
                   1307:                                snmpStats.dd_tooLong++;
                   1308:                                at_ddp_stats.rcv_bad_length++;
                   1309:                                gbuf_freem(mp);
                   1310:                                goto out; /* return; */
                   1311:                        }
                   1312:                        /*
                   1313:                         * shave off the extra bytes from the end of message
                   1314:                         */
                   1315:                        mp = ddp_adjmsg(mp, -(msgsize - len)) ? mp : 0;
                   1316:                        if (mp == 0)
                   1317:                                goto out; /* return; */
                   1318:                } else {
                   1319:                        dPrintf(D_M_DDP, D_L_ERROR,
                   1320:                                ("Length problems, ddp length %d, buffer length %d",
                   1321:                                len, msgsize));
                   1322:                                snmpStats.dd_tooShort++;
                   1323:                        at_ddp_stats.rcv_bad_length++;
                   1324:                        gbuf_freem(mp);
                   1325:                        goto out; /* return; */
                   1326:                }
                   1327:        }
                   1328:        socket = ddp->dst_socket;
                   1329: 
                   1330:        /*
                   1331:         * We want everything in router mode, specially socket 254 for nbp so we need
                   1332:         * to bypass this test when we are a router.
                   1333:         */
                   1334: 
                   1335:        if (!ROUTING_MODE && (socket > DDP_SOCKET_LAST ||
                   1336:                         socket < DDP_SOCKET_1st_RESERVED)) {
                   1337:                dPrintf(D_M_DDP, D_L_WARNING,
                   1338:                        ("Bad dst socket on incoming packet (0x%x)",
                   1339:                        ddp->dst_socket));
                   1340:                at_ddp_stats.rcv_bad_socket++;
                   1341:                gbuf_freem(mp);
                   1342:                goto out; /* return; */
                   1343:        }
                   1344:        /*
                   1345:         * if the checksum is true, then upstream wants us to calc
                   1346:         */
                   1347:        if (UAS_VALUE(ddp->checksum) && 
                   1348:            (UAS_VALUE(ddp->checksum) != ddp_checksum(mp, 4))) {
                   1349:                dPrintf(D_M_DDP, D_L_WARNING,
                   1350:                        ("Checksum error on incoming pkt, calc 0x%x, exp 0x%x",
                   1351:                        ddp_checksum(mp, 4), UAS_VALUE(ddp->checksum)));
                   1352:                snmpStats.dd_checkSum++;
                   1353:                at_ddp_stats.rcv_bad_checksum++;
                   1354:                gbuf_freem(mp);
                   1355:                goto out; /* return; */
                   1356:        }
                   1357: 
                   1358: /*############### routing input checking */
                   1359: 
                   1360: /* Router mode special: we send "up-stack" packets for this node or coming from any
                   1361:  * other ports, but for the reserved atalk sockets (RTMP, ZIP, NBP [and EP])
                   1362:  * BTW, the way we know it's for the router and not the home port is that the
                   1363:  * MAC (ethernet) address is always the one of the interface we're on, but
                   1364:  * the AppleTalk address must be the one of the home port. If it's a multicast
                   1365:  * or another AppleTalk address, this is the router job's to figure out where it's
                   1366:  * going to go.
                   1367:  */
                   1368:        dst_net = NET_VALUE(ddp->dst_net);
                   1369:        if (((ddp->dst_node == ifID_table[IFID_HOME]->ifThisNode.atalk_node) &&
                   1370:         (dst_net == NET_VALUE(ifID_table[IFID_HOME]->ifThisNode.atalk_net))) ||
                   1371:                ((ddp->dst_node == 255) && 
                   1372:                (((dst_net >= ifID_table[IFID_HOME]->ifThisCableStart) &&
                   1373:                (dst_net <= ifID_table[IFID_HOME]->ifThisCableEnd)) || dst_net == 0)) ||
                   1374:                (socket == RTMP_SOCKET) || (socket == NBP_SOCKET)  || (socket == EP_SOCKET) ||
                   1375:                (socket == ZIP_SOCKET) || (ifID->ifRoutingState < PORT_ONLINE) ||
                   1376:                ( MULTIPORT_MODE && forUs(ddp))
                   1377:      )
                   1378:         { 
                   1379: 
                   1380:            gref_t   *gref;
                   1381:                extern   ddp_dev_t ddp_devs[];
                   1382:                pktsHome++;
                   1383:                snmpStats.dd_inLocal++;
                   1384:        if (ot_protoT[ddp->type]) {
                   1385:                if (ddp->type == DDP_ATP) {
                   1386:                        if ((socket == ZIP_SOCKET) || (atp_inputQ[socket] == NULL)
                   1387:                            || (atp_inputQ[socket] == (gref_t *)1))
                   1388:                                goto l_continue;
                   1389:                        atp_input(mp);
                   1390:                } else if (ddp->type == DDP_ADSP) {
                   1391:                        if (adsp_inputQ[socket] == NULL)
                   1392:                                goto l_continue;
                   1393:                        adsp_input(mp);
                   1394:                }
                   1395:                goto out; /* return; */
                   1396:        }
                   1397:                /* 
                   1398:                 * Assure that this isn't for a shut-down socket
                   1399:                 */
                   1400: l_continue:
                   1401:                if ((ddp_devs[socket].flags&DDPF_SHUTDOWN) == 0 &&
                   1402:                    (gref = DDP_SOCK_UPQ(socket)) != NULL) {
                   1403:                        /* there is an upstream! either a queue or a handler routine */
                   1404:                        if (ddp_socket[socket].flags & DDP_CALL_HANDLER) {
                   1405:                                dPrintf(D_M_DDP,D_L_INPUT,
                   1406:                                        ("ddp_input: skt hndlr skt %d hdnlr:0x%x\n",
                   1407:                                        (u_int) socket,
                   1408:                                        DDP_SOCK_HANDLER(socket)));
                   1409:                                (*DDP_SOCK_HANDLER(socket))(mp, ifID);
                   1410:                        } else {
                   1411:                                dPrintf(D_M_DDP, D_L_INPUT, 
                   1412:                                        ("ddp_input: streamq, skt %d\n", socket));
                   1413:                        
                   1414:                                if (DDP_FLAGS(gref) & DDPF_SI) {
                   1415:                                        if (si_ddp_input(gref, mp)) {
                   1416:                                                at_ddp_stats.rcv_dropped_nobuf++;
                   1417:                                        }
                   1418:                                } else
                   1419:                                atalk_putnext(gref, mp);
                   1420:                        }
                   1421:                } else {
                   1422:                        dPrintf(D_M_DDP, D_L_VERBOSE,
                   1423:                                ("Dropping a packet -- dest socket closed"));
                   1424:                        at_ddp_stats.rcv_bad_socket++;
                   1425:                        gbuf_freem(mp);
                   1426:                        snmpStats.dd_noHandler++;
                   1427:                        dPrintf(D_M_DDP, D_L_WARNING, 
                   1428:                                ("ddp_input: dropped, hndlr socket %d unknown\n", socket));
                   1429:                }
                   1430:        }
                   1431: 
                   1432:        else { 
                   1433:                dPrintf(D_M_DDP, D_L_ROUTING, ("ddp_input: routing_needed from  port=%d sock=%d\n",
                   1434:                                        ifID->ifPort, ddp->dst_socket));
                   1435: 
                   1436:                snmpStats.dd_fwdReq++;
                   1437:                if (((pktsIn-pktsHome+200) >= RoutingMix) && ((++pktsDropped % 5) == 0)) {
                   1438:                        at_ddp_stats.rcv_dropped_nobuf++;
                   1439:                        gbuf_freem(mp);
                   1440:                }
                   1441:                else {
                   1442:                        routing_needed(mp, ifID, FALSE);
                   1443:                }
                   1444:        }
                   1445: out:
                   1446:        KERNEL_DEBUG(DBG_AT_DDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
                   1447: }
                   1448: 
                   1449: 
                   1450: /* 
                   1451:  * ddp_router_output()
                   1452:  *
                   1453:  * Remarks : 
                   1454:  *     This is a modified version of ddp_output for router use.
                   1455:  *     The main difference is that the interface on which the packet needs
                   1456:  *     to be sent is specified and a *destination* AppleTalk address is passed
                   1457:  *     as an argument, this address may or may not be the same as the destination
                   1458:  *     address found in the ddp packet... This is the trick about routing, the
                   1459:  *     AppleTalk destination of the packet may not be the same as the Enet address
                   1460:  *     we send the packet too (ie, we may pass the baby to another router).    
                   1461:  *
                   1462:  */
                   1463: int ddp_router_output(mp, ifID, addr_type, router_net, router_node, enet_addr)
                   1464: gbuf_t *mp;
                   1465: at_if_t *ifID;
                   1466: int addr_type;
                   1467: at_net_al router_net;
                   1468: at_node router_node;
                   1469: etalk_addr_t *enet_addr;
                   1470: {
                   1471:        register at_ddp_t       *ddp;
                   1472:        struct   atalk_addr     at_dest;
                   1473:        void            ddp_input();
                   1474:        int             addr_flag;
                   1475:        char    *addr = NULL;
                   1476:        register gbuf_t *m, *tmp_m;
                   1477:        at_ddp_t        *tmp_ddp;
                   1478: 
                   1479:     if (!ifID || ! IFID_VALID(ifID)) {
                   1480: 
                   1481:                dPrintf(D_M_DDP, D_L_WARNING, ("BAD BAD ifID\n"));
                   1482:                gbuf_freel(mp);
                   1483:                return(EPROTOTYPE);
                   1484:        }
                   1485:        ddp = (at_ddp_t *)gbuf_rptr(mp);
                   1486: 
                   1487:        if (ifID->ifFlags & AT_IFF_AURP) { /* AURP link? */
                   1488:                if (ddp_AURPsendx) {
                   1489:                        for (tmp_m=gbuf_next(mp); tmp_m; tmp_m=gbuf_next(tmp_m)) {
                   1490:                                tmp_ddp = (at_ddp_t *)gbuf_rptr(tmp_m);
                   1491:                                DDPLEN_ASSIGN(tmp_ddp, gbuf_msgsize(tmp_m));
                   1492:                                tmp_ddp->hopcount = tmp_ddp->unused = 0;
                   1493:                                tmp_ddp->src_node = ddp->src_node;
                   1494:                                NET_NET(tmp_ddp->src_net, ddp->src_net);
                   1495:                                tmp_ddp->dst_node = ddp->dst_node;
                   1496:                                NET_NET(tmp_ddp->dst_net, ddp->dst_net);
                   1497:                                if (UAS_VALUE(tmp_ddp->checksum)) {
                   1498:                                        u_short tmp;
                   1499:                                        tmp = ddp_checksum(tmp_m, 4);
                   1500:                                        UAS_ASSIGN(tmp_ddp->checksum, tmp);
                   1501:                                }
                   1502:                        }
                   1503:                        if (router_node == 255)
                   1504:                                router_node = 0;
                   1505:                        ddp_AURPsendx(AURPCODE_DATAPKT, mp, router_node);
                   1506:                        return 0;
                   1507:                } else {
                   1508:                        gbuf_freel(mp);
                   1509:                        return EPROTOTYPE;
                   1510:                }
                   1511:        }
                   1512: 
                   1513:        /* keep some of the tests for now ####### */
                   1514: 
                   1515:        if (gbuf_msgsize(mp) > DDP_DATAGRAM_SIZE) {
                   1516:                /* the packet is too large */
                   1517:                dPrintf(D_M_DDP, D_L_WARNING,
                   1518:                        ("ddp_router_output: Packet too large size=%d\n",
                   1519:                         gbuf_msgsize(mp)));
                   1520:                gbuf_freel(mp);
                   1521:                return (EMSGSIZE);
                   1522:        }
                   1523: 
                   1524:        switch (addr_type) {
                   1525: 
                   1526:                case AT_ADDR :
                   1527: 
                   1528:                        /*
                   1529:                         * Check for packet destined to the home stack
                   1530:                         */
                   1531: 
                   1532:                        if      ((ddp->dst_node == ifID->ifThisNode.atalk_node) &&
                   1533:                        (NET_VALUE(ddp->dst_net) == NET_VALUE(ifID->ifThisNode.atalk_net))) {
                   1534:                                        dPrintf(D_M_DDP_LOW, D_L_ROUTING, 
                   1535:                                                ("ddp_r_output: sending back home from port=%d socket=%d\n",
                   1536:                                                ifID->ifPort, ddp->dst_socket));
                   1537: 
                   1538:                                        UAS_ASSIGN(ddp->checksum, 0);
                   1539:                                        ddp_input(mp, ifID);    
                   1540:                                        return(0);
                   1541:                        }
                   1542: 
                   1543:                        NET_ASSIGN(at_dest.atalk_net, router_net);
                   1544:                        at_dest.atalk_node = router_node;
                   1545: 
                   1546:                        addr_flag = AT_ADDR_NO_LOOP;
                   1547:                        addr = (char *)&at_dest;
                   1548:                        dPrintf(D_M_DDP_LOW, D_L_ROUTING_AT,
                   1549:                                ("ddp_r_output: AT_ADDR out port=%d net %d:%d via rte %d:%d",
                   1550:                                ifID->ifPort, NET_VALUE(ddp->dst_net), ddp->dst_node, router_net,
                   1551:                                router_node));
                   1552:                        break;
                   1553: 
                   1554:                case ET_ADDR :
                   1555:                        addr_flag = ET_ADDR;
                   1556:                        addr = (char *)enet_addr;
                   1557:                        dPrintf(D_M_DDP_LOW, D_L_ROUTING,
                   1558:                                ("ddp_r_output: ET_ADDR out port=%d net %d:%d\n",
                   1559:                                ifID->ifPort, NET_VALUE(ddp->dst_net), ddp->dst_node));
                   1560:                        break;
                   1561:                }
                   1562: 
                   1563:                if (UAS_VALUE(ddp->checksum)) {
                   1564:                        u_short tmp;
                   1565:                        tmp = ddp_checksum(mp, 4);
                   1566:                        UAS_ASSIGN(ddp->checksum, tmp);
                   1567:                }
                   1568: 
                   1569: 
                   1570:        if (ifID->ifState != LAP_OFFLINE) {
                   1571:                        for (tmp_m=gbuf_next(mp); tmp_m; tmp_m=gbuf_next(tmp_m)) {
                   1572:                                tmp_ddp = (at_ddp_t *)gbuf_rptr(tmp_m);
                   1573:                                DDPLEN_ASSIGN(tmp_ddp, gbuf_msgsize(tmp_m));
                   1574:                                tmp_ddp->hopcount = tmp_ddp->unused = 0;
                   1575:                                tmp_ddp->src_node = ddp->src_node;
                   1576:                                NET_NET(tmp_ddp->src_net, ddp->src_net);
                   1577:                                tmp_ddp->dst_node = ddp->dst_node;
                   1578:                                NET_NET(tmp_ddp->dst_net, ddp->dst_net);
                   1579:                                if (UAS_VALUE(tmp_ddp->checksum)) {
                   1580:                                        u_short tmp;
                   1581:                                        tmp = ddp_checksum(tmp_m, 4);
                   1582:                                        UAS_ASSIGN(tmp_ddp->checksum, tmp);
                   1583:                                }
                   1584:                        }
                   1585:        {
                   1586:        struct  etalk_addr      dest_addr;
                   1587:        struct  atalk_addr      dest_at_addr;
                   1588:        int             loop = TRUE;            /* flag to aarp to loopback (default) */
                   1589:        elap_specifics_t *elapp = (elap_specifics_t *)ifID->ifLapp;
                   1590: 
                   1591:        m = mp;
                   1592: 
                   1593:        /* the incoming frame is of the form {flag, address, ddp...}
                   1594:         * where "flag" indicates whether the address is an 802.3
                   1595:         * (link) address, or an appletalk address.  If it's an
                   1596:         * 802.3 address, the packet can just go out to the network
                   1597:         * through PAT, if it's an appletalk address, AT->802.3 address
                   1598:         * resolution needs to be done.
                   1599:         * If 802.3 address is known, strip off the flag and 802.3
                   1600:         * address, and prepend 802.2 and 802.3 headers.
                   1601:         */
                   1602:        
                   1603:        if (addr == NULL) {
                   1604:                addr_flag = *(u_char *)gbuf_rptr(m);
                   1605:                gbuf_rinc(m,1);
                   1606:        }
                   1607:        
                   1608:        switch (addr_flag) {
                   1609:        case AT_ADDR_NO_LOOP :
                   1610:                loop = FALSE;
                   1611:                /* pass thru */
                   1612:        case AT_ADDR :
                   1613:        if (addr == NULL) {
                   1614:            dest_at_addr = *(struct atalk_addr *)gbuf_rptr(m);
                   1615:            gbuf_rinc(m,sizeof(struct atalk_addr));
                   1616:        } else
                   1617:            dest_at_addr = *(struct atalk_addr *)addr;
                   1618:            break;
                   1619:        case ET_ADDR :
                   1620:        if (addr == NULL) {
                   1621:            dest_addr = *(struct etalk_addr *)gbuf_rptr(m);
                   1622:            gbuf_rinc(m,sizeof(struct etalk_addr));
                   1623:        } else
                   1624:            dest_addr = *(struct etalk_addr *)addr;
                   1625:            break;
                   1626:        default :
                   1627:                dPrintf(D_M_DDP_LOW,D_L_ERROR,
                   1628:                    ("ddp_output: Unknown addr_flag = 0x%x\n", addr_flag));
                   1629: 
                   1630:            gbuf_freel(m);              /* unknown address type, chuck it */
                   1631:            return 0;
                   1632:         }
                   1633: 
                   1634:        while (gbuf_len(m) == 0) {
                   1635:                tmp_m = m;
                   1636:                m = gbuf_cont(m);
                   1637:                gbuf_freeb(tmp_m); 
                   1638:        }
                   1639: 
                   1640:        /* At this point, rptr points to ddp header for sure */
                   1641: 
                   1642:        if (elapp->elap_if.ifState == LAP_OFFLINE) {
                   1643:            gbuf_freel(m);
                   1644:                return 0;
                   1645:        }
                   1646: 
                   1647:        if (elapp->elap_if.ifState == LAP_ONLINE_FOR_ZIP) {
                   1648:                /* see if this is a ZIP packet that we need
                   1649:                 * to let through even though network is
                   1650:                 * not yet alive!!
                   1651:                 */
                   1652:                if (zip_type_packet(m) == 0) {
                   1653:                gbuf_freel(m);
                   1654:                        return 0;
                   1655:                }
                   1656:        }
                   1657:        
                   1658:        elapp->stats.xmit_packets++;
                   1659:        elapp->stats.xmit_bytes += gbuf_msgsize(m);
                   1660:        snmpStats.dd_outLong++;
                   1661:        
                   1662:        switch (addr_flag) {
                   1663:        case AT_ADDR_NO_LOOP :
                   1664:        case AT_ADDR :
                   1665:            /*
                   1666:             * we don't want elap to be looking into ddp header, so
                   1667:             * it doesn't know net#, consequently can't do 
                   1668:             * AMT_LOOKUP.  That task left to aarp now.
                   1669:             */
                   1670:            aarp_send_data(m,elapp,&dest_at_addr, loop);
                   1671:            break;
                   1672:        case ET_ADDR :
                   1673:            pat_output(elapp->pat_id, m, &dest_addr, 0);
                   1674:            break;
                   1675:         }
                   1676:        }
                   1677:                        return(0);
                   1678:        } 
                   1679:        gbuf_freel(mp);
                   1680:        return (0);
                   1681: }
                   1682: 
                   1683: int gbuf_freel(m)
                   1684:        gbuf_t *m;
                   1685: {
                   1686:        gbuf_t *tmp_m;
                   1687: 
                   1688:        while ((tmp_m = m) != 0) {
                   1689:                m = gbuf_next(m);
                   1690:                gbuf_next(tmp_m) = 0;
                   1691:                gbuf_freem(tmp_m);
                   1692:        }
                   1693:        return (0);
                   1694: }
                   1695: 
                   1696: /*****************************************/
                   1697: 
                   1698: void rt_delete(NetStop, NetStart)
                   1699:        unsigned short NetStop;
                   1700:        unsigned short NetStart;
                   1701: {
                   1702:        RT_entry *found;
                   1703:        int s;
                   1704: 
                   1705:        ATDISABLE(s, ddpinp_lock);
                   1706:        if ((found = rt_bdelete(NetStop, NetStart)) != 0) {
                   1707:                bzero(found, sizeof(RT_entry));
                   1708:                found->right = RT_table_freelist;
                   1709:                RT_table_freelist = found;
                   1710:        }
                   1711:        ATENABLE(s, ddpinp_lock);
                   1712: }
                   1713: 
                   1714: int ddp_AURPfuncx(code, param, node)
                   1715:        int code;
                   1716:        void *param;
                   1717:        unsigned char node;
                   1718: {
                   1719:        extern void zt_add_zonename();
                   1720:        extern void zt_set_zmap();
                   1721:        extern int  zt_ent_zindex();
                   1722:        extern void zt_remove_zones();
                   1723:        extern void rtmp_timeout();
                   1724:        extern void rtmp_send_port();
                   1725:        extern elap_specifics_t elap_specifics[];
                   1726:        aurp_rtinfo_t rtinfo;
                   1727:        elap_specifics_t *elapp;
                   1728:        int k;
                   1729: 
                   1730:        switch (code) {
                   1731:        case AURPCODE_DATAPKT: /* data packet */
                   1732:                if (aurp_ifID) {
                   1733:                        dPrintf(D_M_DDP, D_L_TRACE, ("ddp_AURPfuncx: data, 0x%x, %d\n",
                   1734:                                (u_int) aurp_ifID, node));
                   1735: 
                   1736:                        ddp_input((gbuf_t *)param, aurp_ifID);
                   1737:                } else
                   1738:                        gbuf_freem((gbuf_t *)param);
                   1739:                break;
                   1740: 
                   1741:        case AURPCODE_REG: /* register/deregister */
                   1742:                if (!ROUTING_MODE)
                   1743:                        return -1;
                   1744:                ddp_AURPsendx = (void(*)())param;
                   1745: 
                   1746:                if (param) {
                   1747:                        /* register AURP callback function */
                   1748:                        if (aurp_ifID)
                   1749:                                return 0;
                   1750:                        elapp = (elap_specifics_t *)&elap_specifics[1];
                   1751:                        for (k=1; k < IF_TOTAL_MAX; k++, elapp++) {
                   1752:                                if (elapp->pat_id == 0) {
                   1753:                                        /* assign a port */
                   1754:                                        elapp->pat_id = k;
                   1755:                                        aurp_ifID = (at_if_t *)&elapp->elap_if;
                   1756:                                        aurp_ifID->ifFlags = (AT_IFF_ETHERTALK|RTR_XNET_PORT);
                   1757:                                        ddp_add_if(aurp_ifID);
                   1758:                                        aurp_ifID->ifLapp = (void *)elapp;
                   1759:                                        aurp_ifID->ifState = LAP_ONLINE;
                   1760:                                        aurp_ifID->ifRoutingState = PORT_ONLINE;
                   1761:                                        dPrintf(D_M_DDP, D_L_TRACE,
                   1762:                                                ("ddp_AURPfuncx: on, 0x%x\n",
                   1763:                                                (u_int) aurp_ifID));
                   1764: 
                   1765:                                        ddp_AURPsendx(AURPCODE_DEBUGINFO,
                   1766:                                                        &dbgBits, aurp_ifID->ifPort);
                   1767:                                        return 0;
                   1768:                                }
                   1769:                        }
                   1770:                        return -1;
                   1771: 
                   1772:                } else {
                   1773:                        /* deregister AURP callback function */
                   1774:                        if (aurp_ifID) {
                   1775:                                rtmp_purge(aurp_ifID);
                   1776:                                elapp = (elap_specifics_t *)aurp_ifID->ifLapp;
                   1777:                                ddp_rem_if(aurp_ifID);
                   1778:                                elapp->pat_id = 0;
                   1779:                                aurp_ifID->ifLapp = (void *)0;
                   1780:                                aurp_ifID->ifState = LAP_OFFLINE;
                   1781:                                aurp_ifID->ifRoutingState = PORT_OFFLINE;
                   1782:                                dPrintf(D_M_DDP, D_L_TRACE,
                   1783:                                        ("ddp_AURPfuncx: off, 0x%x\n", (u_int) aurp_ifID));
                   1784:                                aurp_ifID = 0;
                   1785:                        }
                   1786:                }
                   1787:                break;
                   1788: 
                   1789:        case AURPCODE_AURPPROTO: /* proto type - AURP */
                   1790:                if (aurp_ifID) {
                   1791:                        aurp_ifID->ifFlags |= AT_IFF_AURP;
                   1792:                        rtinfo.RT_table = (void *)RT_table;
                   1793:                        rtinfo.ZT_table = (void *)ZT_table;
                   1794:                        rtinfo.RT_maxentry = RT_MAXENTRY;
                   1795:                        rtinfo.ZT_maxentry = ZT_MAXENTRY;
                   1796:                        rtinfo.rt_lock = (void *)&ddpinp_lock;
                   1797:                        rtinfo.rt_insert = (void *)rt_insert;
                   1798:                        rtinfo.rt_delete = (void *)rt_delete;
                   1799:                        rtinfo.rt_lookup = (void *)rt_blookup;
                   1800:                        rtinfo.zt_add_zname = (void *)zt_add_zonename;
                   1801:                        rtinfo.zt_set_zmap = (void *)zt_set_zmap;
                   1802:                        rtinfo.zt_get_zindex = (void *)zt_ent_zindex;
                   1803:                        rtinfo.zt_remove_zones = (void *)zt_remove_zones;
                   1804:                        ddp_AURPsendx(AURPCODE_RTINFO, &rtinfo, 0);
                   1805:                }
                   1806:                break;
                   1807:        }
                   1808: 
                   1809:        return 0;
                   1810: }
                   1811: 
                   1812: 
                   1813: at_if_t *forUs(ddp)
                   1814: register at_ddp_t *ddp;
                   1815: 
                   1816: /* checks to see if address of packet is for one of our interfaces
                   1817:    returns *ifID if it's for us, NULL if not
                   1818: */
                   1819: {
                   1820:        register at_if_t **ifID = &ifID_table[0];
                   1821:        int port;
                   1822: 
                   1823:        for (port=0; *ifID && port<IF_TOTAL_MAX; ifID++,port++) {       
                   1824:                if ((ddp->dst_node == (*ifID)->ifThisNode.atalk_node) &&
                   1825:                        (NET_EQUAL(ddp->dst_net, (*ifID)->ifThisNode.atalk_net))
                   1826:                   ) {
                   1827:                        dPrintf(D_M_DDP_LOW, D_L_ROUTING,
                   1828:                                ("pkt was for port %d\n", port));
                   1829: 
                   1830:                        return(*ifID);
                   1831:                }
                   1832:        }
                   1833:        return((at_if_t *)NULL);
                   1834: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.