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

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  *     Copyright (c) 1987, 1988, 1989 Apple Computer, Inc. 
                     24:  *
                     25:  *
                     26:  *    Modified for MP, 1996 by Tuyen Nguyen
                     27:  *    Added AURP support, April 8, 1996 by Tuyen Nguyen
                     28:  *   Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
                     29:  */
                     30: 
                     31: #define RESOLVE_DBG                    /* define debug globals in debug.h */
                     32: 
                     33: #include <sys/errno.h>
                     34: #include <sys/types.h>
                     35: #include <sys/param.h>
                     36: #include <machine/spl.h>
                     37: #include <sys/systm.h>
                     38: #include <sys/kernel.h>
                     39: #include <sys/proc.h>
                     40: #include <sys/filedesc.h>
                     41: #include <sys/fcntl.h>
                     42: #include <sys/mbuf.h>
                     43: #include <sys/ioctl.h>
                     44: #include <sys/malloc.h>
                     45: #include <sys/socket.h>
                     46: #include <sys/socketvar.h>
                     47: #include <sys/protosw.h>
                     48: 
                     49: #include <net/if.h>
                     50: #include <net/dlil.h>
                     51: 
                     52: #include <netat/sysglue.h>
                     53: #include <netat/appletalk.h>
                     54: #include <netat/at_var.h>
                     55: #include <netat/ddp.h>
                     56: #include <netat/ep.h>
                     57: #include <netat/nbp.h>
                     58: #include <netat/rtmp.h>
                     59: #include <netat/zip.h>
                     60: #include <netat/at_pcb.h>
                     61: #include <netat/routing_tables.h>
                     62: #include <netat/at_snmp.h>
                     63: #include <netat/aurp.h>
                     64: #include <netat/at_config.h>
                     65: #include <netat/debug.h>
                     66: #include <netat/at_ddp_brt.h>
                     67: #include <netat/at_aarp.h>
                     68: #include <netat/adsp.h>
                     69: #include <netat/adsp_internal.h>
                     70: 
                     71: /* globals */
                     72: 
                     73: /* Queue of LAP interfaces which have registered themselves with DDP */
                     74: struct at_ifQueueHd at_ifQueueHd;
                     75: 
                     76: extern at_state_t at_state;
                     77: extern TAILQ_HEAD(name_registry, _nve_) name_registry;
                     78: 
                     79: at_ddp_stats_t at_ddp_stats;   /* DDP statistics */
                     80: snmpStats_t snmpStats;         /* snmp ddp & echo stats */
                     81: 
                     82: extern struct atpcb ddp_head;
                     83: extern at_ifaddr_t *ifID_home, *ifID_table[];
                     84: extern aarp_amt_array *aarp_table[];
                     85: extern at_ifaddr_t at_interfaces[];
                     86: 
                     87: /* routing mode special */
                     88: void (*ddp_AURPsendx)();
                     89: at_ifaddr_t *aurp_ifID = 0;
                     90: extern pktsIn,pktsOut;
                     91: int pktsDropped,pktsHome;
                     92: atlock_t ddpall_lock;
                     93: atlock_t ddpinp_lock;
                     94: 
                     95: char ot_atp_socketM[256];
                     96: char ot_adsp_socketM[256];
                     97: 
                     98: extern int *atp_pidM;
                     99: extern int *adsp_pidM;
                    100: extern struct atpcb *atp_inputQ[];
                    101: extern CCB *adsp_inputQ[];
                    102: 
                    103: at_ifaddr_t *forUs(at_ddp_t *);
                    104: 
                    105: void ddp_notify_nbp();
                    106: void ddp_input();
                    107: 
                    108: extern void routing_needed();
                    109: extern void ddp_brt_sweep();
                    110: 
                    111: struct {
                    112:        void (*func)();
                    113: } ddp_handler[256];
                    114: 
                    115: void init_ddp_handler()
                    116: {
                    117:        bzero(ddp_handler, sizeof(ddp_handler));
                    118: }
                    119: 
                    120: void add_ddp_handler(ddp_socket, input_func)
                    121:      u_char ddp_socket;
                    122:      void (*input_func)();
                    123: {
                    124:        ddp_handler[ddp_socket].func = input_func;
                    125: }
                    126: 
                    127: void
                    128: ddp_slowtimo()
                    129: {
                    130:        ddp_brt_sweep();
                    131: }
                    132: 
                    133: /*
                    134:  * Raw DDP socket option processing.
                    135:  */
                    136: int ddp_ctloutput(so, sopt)
                    137:      struct socket *so;
                    138:      struct sockopt *sopt;
                    139: {
                    140:        struct atpcb *at_pcb = sotoatpcb(so);
                    141:        int optval, error = 0;
                    142: 
                    143:        if (sopt->sopt_level != ATPROTO_NONE)
                    144:                return (EINVAL);
                    145: 
                    146:        switch (sopt->sopt_dir) {
                    147: 
                    148:        case SOPT_GET:
                    149:                switch (sopt->sopt_name) {
                    150:                case DDP_HDRINCL:
                    151:                        optval = at_pcb->ddp_flags & DDPFLG_HDRINCL;
                    152:                        error = sooptcopyout(sopt, &optval, sizeof optval);
                    153:                        break;
                    154:                case DDP_CHKSUM_ON:
                    155:                        optval = at_pcb->ddp_flags & DDPFLG_CHKSUM;
                    156:                        error = sooptcopyout(sopt, &optval, sizeof optval);
                    157:                        break;
                    158:                case DDP_STRIPHDR:
                    159:                        optval = at_pcb->ddp_flags & DDPFLG_STRIPHDR;
                    160:                        error = sooptcopyout(sopt, &optval, sizeof optval);
                    161:                        break;
                    162:                case DDP_SLFSNDOFF:
                    163:                        optval = at_pcb->ddp_flags & DDPFLG_SLFSNDOFF;
                    164:                        error = sooptcopyout(sopt, &optval, sizeof optval);
                    165:                        break;
                    166:                case DDP_GETSOCKNAME:
                    167:                  {
                    168:                        ddp_addr_t addr;
                    169:                        addr.inet.net = at_pcb->laddr.s_net;
                    170:                        addr.inet.node = at_pcb->laddr.s_node;
                    171:                        addr.inet.socket = at_pcb->lport;
                    172:                        addr.ddptype = at_pcb->ddptype;
                    173:                        error = sooptcopyout(sopt, &addr, sizeof addr);
                    174:                  }
                    175:                        break;
                    176:                 default:
                    177:                        error = ENOPROTOOPT;
                    178:                        break;
                    179:                }
                    180:                break;
                    181:        case SOPT_SET:
                    182:                switch (sopt->sopt_name) {
                    183:                case DDP_HDRINCL:
                    184:                        error = sooptcopyin(sopt, &optval, sizeof optval,
                    185:                                            sizeof optval);
                    186:                        if (error)
                    187:                                break;
                    188:                        if (optval)
                    189:                                at_pcb->ddp_flags |= DDPFLG_HDRINCL;
                    190:                        else
                    191:                                at_pcb->ddp_flags &= ~DDPFLG_HDRINCL;
                    192:                        break;
                    193:                case DDP_CHKSUM_ON:  /* *** not yet implemented *** */
                    194:                        error = sooptcopyin(sopt, &optval, sizeof optval,
                    195:                                            sizeof optval);
                    196:                        if (error)
                    197:                                break;
                    198:                        if (optval)
                    199:                                at_pcb->ddp_flags |= DDPFLG_CHKSUM;
                    200:                        else
                    201:                                at_pcb->ddp_flags &= ~DDPFLG_CHKSUM;
                    202:                        break;
                    203:                case DDP_STRIPHDR:
                    204:                        error = sooptcopyin(sopt, &optval, sizeof optval,
                    205:                                            sizeof optval);
                    206:                        if (error)
                    207:                                break;
                    208:                        if (optval)
                    209:                                at_pcb->ddp_flags |= DDPFLG_STRIPHDR;
                    210:                        else
                    211:                                at_pcb->ddp_flags &= ~DDPFLG_STRIPHDR;
                    212:                        break;
                    213:                case DDP_SLFSNDOFF:  /* *** not yet implemented *** */
                    214:                        error = sooptcopyin(sopt, &optval, sizeof optval,
                    215:                                            sizeof optval);
                    216:                        if (error)
                    217:                                break;
                    218:                        if (optval)
                    219:                                at_pcb->ddp_flags |= DDPFLG_SLFSNDOFF;
                    220:                        else
                    221:                                at_pcb->ddp_flags &= ~DDPFLG_SLFSNDOFF;
                    222:                        break;
                    223:                 default:
                    224:                        error = ENOPROTOOPT;
                    225:                        break;
                    226:                }
                    227:                break;
                    228:        }
                    229: 
                    230:        return(error);
                    231: } /* ddp_cloutput */
                    232: 
                    233: /****************************************************************/
                    234: /*                                                             */
                    235: /*                                                             */
                    236: /*                     Support Routines                        */
                    237: /*                                                             */
                    238: /*                                                             */
                    239: /****************************************************************/
                    240: 
                    241: /*
                    242:  * Name:
                    243:  *     ddp_checksum
                    244:  *
                    245:  * Description:
                    246:  *     This procedure determines the checksum of an extended DDP datagram.
                    247:  *      Add the unsigned bytes into an unsigned 16-bit accumulator.
                    248:  *      After each add, rotate the sign bit into the low order bit of
                    249:  *      the accumulator. When done, if the checksum is 0, changed into 0xFFFF.
                    250:  *
                    251:  * Calling sequence:
                    252:  *     checksum = ddp_checksum(mp, offset)
                    253:  *
                    254:  * Parameters:
                    255:  *     mp              pointer to the datagram gbuf_t
                    256:  *     offset          offset to start at in first gbuf_t block
                    257:  *
                    258:  * Return value:
                    259:  *     The DDP checksum.
                    260:  *
                    261:  */
                    262: 
                    263: static u_short ddp_checksum(mp, offset)
                    264:      register gbuf_t   *mp;
                    265:      register int      offset;
                    266: {
                    267:        register u_char *data;
                    268:        register int     length;
                    269:        register u_short checksum;
                    270: 
                    271:        checksum = 0;
                    272: 
                    273:        do {
                    274:                if (offset >= gbuf_len(mp))
                    275:                        offset -= gbuf_len(mp);
                    276:                else {
                    277:                        data = ((unsigned char *) gbuf_rptr(mp)) + offset;
                    278:                        length = gbuf_len(mp) - offset;
                    279:                        offset = 0;
                    280:                        /* Portable checksum from 3.0 */
                    281:                        while (length--) {
                    282:                                checksum += *data++;
                    283:                                checksum = (checksum & 0x8000) ?
                    284:                                        ((checksum << 1) | 1) : (checksum << 1);
                    285:                        }
                    286:                }
                    287:        } while ( (mp = gbuf_cont(mp)) );
                    288: 
                    289:        if (checksum == 0)
                    290:                checksum = 0xffff;
                    291: 
                    292:        return(checksum);
                    293: }
                    294: 
                    295: /*
                    296:  * ddp_add_if()
                    297:  *
                    298:  * Description:
                    299:  *     This procedure is called by each LAP interface when it wants to place
                    300:  *     itself online.  The LAP interfaces passes in a pointer to its at_if
                    301:  *     struct, which is added to DDP's list of active interfaces (at_ifQueueHd).
                    302:  *     When DDP wants to transmit a packet, it searches this list for the 
                    303:  *     interface to use.
                    304:  *     
                    305:  *     If AT_IFF_DEFAULT is set, then this interface is to be brought online
                    306:  *     as the interface DDP socket addresses are tied to.  Of course there can
                    307:  *     be only one default interface; we return an error if it's already set. 
                    308:  *
                    309:  * Calling Sequence:
                    310:  *     ret_status = ddp_add_if(ifID)
                    311:  *
                    312:  * Formal Parameters:
                    313:  *     ifID            pointer to LAP interface's at_if struct.
                    314:  *
                    315:  * Completion Status:
                    316:  *     0               Procedure successfully completed.
                    317:  *     EALREADY        This interface is already online, or there is
                    318:  *                     already a default interface.
                    319:  *     ENOBUFS         Cannot allocate input queue
                    320:  *
                    321:  */
                    322: int ddp_add_if(ifID)
                    323: register at_ifaddr_t   *ifID;
                    324: {
                    325:        int port = -1;
                    326: 
                    327:        dPrintf(D_M_DDP, D_L_STARTUP, 
                    328:                ("ddp_add_if: called, ifID:0x%x\n", (u_int) ifID));
                    329: 
                    330:        if (ifID->ifFlags & AT_IFF_DEFAULT) {
                    331:                if (ifID_home)
                    332:                        return(EEXIST);    /* home port already set */ 
                    333:                else {
                    334:                        port = IFID_HOME;
                    335:                        ifID_home = ifID;
                    336:                }
                    337:        } else {
                    338:                for (port=IFID_HOME+1; port<IF_TOTAL_MAX; port++)
                    339:                        if (!ifID_table[port]) {
                    340:                                break;
                    341:                }
                    342:                if (port == IF_TOTAL_MAX)       /* no space left */
                    343:                        return(ENOMEM);
                    344:        }
                    345: 
                    346:        /* allocate an et_aarp_amt structure */
                    347:        if ((aarp_table[port] = 
                    348:             (aarp_amt_array *)_MALLOC(sizeof(aarp_amt_array),
                    349:                                       M_RTABLE, M_NOWAIT)) == NULL)
                    350:                return(ENOMEM);
                    351: 
                    352:        dPrintf(D_M_DDP, D_L_STARTUP, ("ddp:adding ifID_table[%d]\n", port));
                    353:                
                    354:        /* add i/f to port list */
                    355:        ifID_table[port] = ifID;
                    356:        ifID->ifPort = port;    /* set ddp port # in ifID */
                    357: 
                    358:        /* Add this interface to the list of online interfaces */
                    359:        TAILQ_INSERT_TAIL(&at_ifQueueHd, ifID, aa_link);
                    360:        
                    361:        return (0);
                    362: } /* ddp_add_if */
                    363: 
                    364: /*
                    365:  * ddp_rem_if()
                    366:  *
                    367:  * Description:
                    368:  *     This procedure is called by each LAP interface when it wants to take
                    369:  *     itself offline.  The LAP interfaces passes in a pointer to its at_if
                    370:  *     struct; DDP's list of active interfaces (at_ifQueueHd) is searched and
                    371:  *     this interface is removed from the list.  DDP can still transmit 
                    372:  *     packets as long as this interface is not the default interface; the
                    373:  *     sender will just get ENETUNREACH errors when it tries to send to an
                    374:  *     interface that went offline.  However, if the default interface is
                    375:  *     taken offline, we no longer have a node ID to use as a source address
                    376:  *     and DDP must return ENETDOWN when a caller tries to send a packet.
                    377:  *     
                    378:  * Formal Parameters:
                    379:  *     ifID            pointer to LAP interface's at_if struct.
                    380:  */
                    381: 
                    382: void  ddp_rem_if(ifID)
                    383:      register at_ifaddr_t      *ifID;
                    384: {
                    385:        struct ifaddr *ifa = &ifID->aa_ifa;
                    386: 
                    387:        /* un-do processing done in SIOCSIFADDR */
                    388:        if (ifa->ifa_addr) {
                    389:                int s = splnet();
                    390:                TAILQ_REMOVE(&ifID->aa_ifp->if_addrhead, ifa, ifa_link);
                    391:                ifa->ifa_addr = NULL;
                    392:                splx(s);
                    393:        }
                    394:        if (ifID->at_dl_tag) {
                    395:                dlil_detach_protocol(ifID->at_dl_tag);
                    396:                ifID->at_dl_tag = 0;
                    397:        }
                    398: 
                    399:        /* un-do processing done in ddp_add_if() */
                    400:        if (ifID->ifPort) {
                    401:                if (aarp_table[ifID->ifPort]) {
                    402:                        FREE(aarp_table[ifID->ifPort], M_RTABLE);
                    403:                        aarp_table[ifID->ifPort] = NULL;
                    404:                }
                    405: 
                    406:                at_state.flags |= AT_ST_IF_CHANGED;
                    407:                ifID->aa_ifp = NULL;
                    408: 
                    409:                trackrouter_rem_if(ifID);
                    410:                TAILQ_REMOVE(&at_ifQueueHd, ifID, aa_link);
                    411:                ifID_table[ifID->ifPort] = NULL;
                    412:                ifID->ifName[0] = '\0';
                    413:                ifID->ifPort = 0;
                    414:        }
                    415: 
                    416:        /* *** deallocate ifID, eventually *** */
                    417: } /* ddp_rem_if */
                    418: 
                    419: /*
                    420:  * The user may have registered an NVE with the NBP on a socket.  When the
                    421:  * socket is closed, the NVE should be deleted from NBP's name table.  The
                    422:  * user should delete the NVE before the socket is shut down, but there
                    423:  * may be circumstances when he can't.  So, whenever a DDP socket is closed,
                    424:  * this routine is used to notify NBP of the socket closure.  This would
                    425:  * help NBP get rid of all NVE's registered on the socket.
                    426:  */
                    427: 
                    428: /* *** Do we still need to do this? *** */
                    429: int ot_ddp_check_socket(socket, pid)
                    430:      unsigned char socket;
                    431:      int pid;
                    432: {
                    433:        int cnt = 0;
                    434:        gref_t *gref;
                    435: 
                    436:        dPrintf(D_M_DDP, D_L_INFO, ("ot_ddp_check_socket: %d\n", socket));
                    437:        for (gref = ddp_head.atpcb_next; gref != &ddp_head; gref = gref->atpcb_next)
                    438:                if (gref->lport == socket && gref->pid == pid)
                    439:                     cnt++;
                    440:        if ((atp_inputQ[socket] != NULL) && (atp_inputQ[socket] != (gref_t *)1)
                    441:            && (atp_pidM[socket] == pid))
                    442:                cnt++;
                    443:        if ((adsp_inputQ[socket] != NULL) && (adsp_pidM[socket] == pid))
                    444:                cnt++;
                    445: 
                    446:        return(cnt);
                    447: }
                    448: 
                    449: void ddp_notify_nbp(socket, pid, ddptype)
                    450:      unsigned char socket;
                    451:      int pid;
                    452:      unsigned char ddptype; /* not used */
                    453: {
                    454:        extern int nve_lock;
                    455:        nve_entry_t *nve_entry;
                    456: 
                    457:        if (at_state.flags & AT_ST_STARTED) {
                    458:                /* *** NBP_CLOSE_NOTE processing (from ddp_nbp.c) *** */
                    459:                ATDISABLE(nve_lock, NVE_LOCK);
                    460:                TAILQ_FOREACH(nve_entry, &name_registry, nve_link) {
                    461:                        if ((at_socket)socket == nve_entry->address.socket &&
                    462:                            /* *** check complete address and ddptype here *** */
                    463:                            pid == nve_entry->pid &&
                    464:                            ot_ddp_check_socket(nve_entry->address.socket,
                    465:                                                nve_entry->pid) < 2) {
                    466:                                nbp_delete_entry(nve_entry);
                    467:                        }
                    468:                }
                    469:                ATENABLE(nve_lock, NVE_LOCK);
                    470:        }
                    471: } /* ddp_notify_nbp */
                    472: 
                    473: int ddp_get_stats(statsp)
                    474: at_ddp_stats_t *statsp;
                    475: {
                    476:        dPrintf(D_M_DDP, D_L_VERBOSE, ("ddp_get_stats() entry"));
                    477:        bcopy(&at_ddp_stats, statsp, sizeof(at_ddp_stats));
                    478:        return(0);
                    479: }
                    480:       
                    481: StaticProc void sum_pkt_chain(m)
                    482:      gbuf_t *m;
                    483: {
                    484:        gbuf_t *tmp_m = m;
                    485:        register at_ddp_t 
                    486:          *ddp = (at_ddp_t *)gbuf_rptr(m),
                    487:          *tmp_ddp;
                    488:        u_short tmp;
                    489: 
                    490:        if (UAS_VALUE(ddp->checksum)) {
                    491:                tmp = ddp_checksum(m, 4);
                    492:                UAS_ASSIGN(ddp->checksum, tmp);
                    493:        }
                    494: 
                    495:        for (tmp_m=gbuf_next(tmp_m); tmp_m; tmp_m=gbuf_next(tmp_m)) {
                    496:                tmp_ddp = (at_ddp_t *)gbuf_rptr(tmp_m);
                    497:                DDPLEN_ASSIGN(tmp_ddp, gbuf_msgsize(tmp_m));
                    498:                tmp_ddp->hopcount = tmp_ddp->unused = 0;
                    499:                NET_NET(tmp_ddp->src_net, ddp->src_net);
                    500:                tmp_ddp->src_node = ddp->src_node;
                    501:                tmp_ddp->src_socket = ddp->src_socket;
                    502:                if (UAS_VALUE(tmp_ddp->checksum)) {
                    503:                        tmp = ddp_checksum(tmp_m, 4);
                    504:                        UAS_ASSIGN(tmp_ddp->checksum, tmp);
                    505:                }
                    506:        }
                    507: }
                    508: 
                    509: /* There are various ways a packet may go out.... it may be sent out
                    510:  * directly to destination node, or sent to a random router or sent
                    511:  * to a router whose entry exists in Best Router Cache.  Following are 
                    512:  * constants used WITHIN this routine to keep track of choice of destination
                    513:  */
                    514: #define DIRECT_ADDR    1
                    515: #define        BRT_ENTRY       2
                    516: #define        BRIDGE_ADDR     3
                    517: 
                    518: /* 
                    519:  * ddp_output()
                    520:  *
                    521:  * Remarks : 
                    522:  *     Called to queue a atp/ddp data packet on the network interface.
                    523:  *     It returns 0 normally, and an errno in case of error.
                    524:  *     The mbuf chain pointed to by *mp is consumed on success, and
                    525:  *             freed in case of error.
                    526:  *
                    527:  */
                    528: int ddp_output(mp, src_socket, src_addr_included)
                    529:      register gbuf_t   **mp;
                    530:      at_socket src_socket;
                    531:      int src_addr_included;
                    532: {
                    533:        register at_ifaddr_t    *ifID, *ifIDTmp;
                    534:        register at_ddp_t       *ddp;
                    535:        register ddp_brt_t      *brt;
                    536:        register at_net_al      dst_net;
                    537:        register int            len;
                    538:        struct   atalk_addr     at_dest;
                    539:        at_ifaddr_t             *ARouterIf = NULL;
                    540:        int loop = 0;
                    541:        int error = 0;
                    542:        int addr_type;
                    543:        u_char  addr_flag;
                    544:        char    *addr = NULL;
                    545:        register gbuf_t *m;
                    546: 
                    547:        snmpStats.dd_outReq++;
                    548: 
                    549:        ifID = ifID_home;
                    550:        m = *mp;
                    551:        ddp = (at_ddp_t *)gbuf_rptr(m);
                    552:        KERNEL_DEBUG(DBG_AT_DDP_OUTPUT | DBG_FUNC_START, 0,
                    553:                     0,0,0,0);
                    554:        if (MULTIHOME_MODE && (ifIDTmp = forUs(ddp))) {
                    555:                ifID = ifIDTmp;
                    556:                loop = TRUE;
                    557:                dPrintf(D_M_DDP_LOW, D_L_USR1,
                    558:                        ("ddp_out: for us if:%s\n", ifID->ifName));
                    559:        }
                    560: 
                    561:        if ((ddp->dst_socket > (unsigned) (DDP_SOCKET_LAST + 1)) || 
                    562:            (ddp->dst_socket < DDP_SOCKET_1st_RESERVED)) {
                    563:                dPrintf(D_M_DDP, D_L_ERROR,
                    564:                        ("Illegal destination socket on outgoing packet (0x%x)",
                    565:                         ddp->dst_socket));
                    566:                at_ddp_stats.xmit_bad_addr++;
                    567:                error = ENOTSOCK;
                    568:                gbuf_freel(*mp);
                    569:                goto exit_ddp_output;
                    570:        }
                    571:        if ((len = gbuf_msgsize(*mp)) > DDP_DATAGRAM_SIZE) {
                    572:                /* the packet is too large */
                    573:                dPrintf(D_M_DDP, D_L_ERROR,
                    574:                        ("Outgoing packet too long (len=%d bytes)", len));
                    575:                at_ddp_stats.xmit_bad_length++;
                    576:                error = EMSGSIZE;
                    577:                gbuf_freel(*mp);
                    578:                goto exit_ddp_output;
                    579:        }
                    580:        at_ddp_stats.xmit_bytes += len;
                    581:        at_ddp_stats.xmit_packets++;
                    582: 
                    583:        DDPLEN_ASSIGN(ddp, len);
                    584:        ddp->hopcount = ddp->unused = 0;
                    585: 
                    586:        /* If this packet is for the same node, loop it back
                    587:         * up...  Note that for LocalTalk, dst_net zero means "THIS_NET", so
                    588:         * address 0.nn is eligible for loopback.  For Extended EtherTalk,
                    589:         * dst_net 0 can be used only for cable-wide or zone-wide 
                    590:         * broadcasts (0.ff) and as such, address of the form 0.nn is NOT
                    591:         * eligible for loopback.
                    592:         */
                    593:        dst_net = NET_VALUE(ddp->dst_net);
                    594: 
                    595:        /* If our packet is destined for the 'virtual' bridge
                    596:         * address of NODE==0xFE, replace that address with a
                    597:         * real bridge address.
                    598:         */
                    599:        if ((ddp->dst_node == 0xfe) && 
                    600:            ((dst_net == 0) ||
                    601:             (dst_net >= ifID->ifThisCableStart &&
                    602:              dst_net <= ifID->ifThisCableEnd))) {
                    603:                NET_ASSIGN(ddp->dst_net, ifID->ifARouter.s_net);
                    604:                dst_net = ifID->ifARouter.s_net;
                    605:                ddp->dst_node = ifID->ifARouter.s_node;
                    606:        }
                    607: 
                    608:        loop = ((ddp->dst_node == ifID->ifThisNode.s_node) &&
                    609:                (dst_net == ifID->ifThisNode.s_net)
                    610:               );
                    611:        if (loop) {
                    612:                gbuf_t *mdata, *mdata_next;
                    613: 
                    614:                NET_ASSIGN(ddp->src_net, ifID->ifThisNode.s_net);
                    615:                ddp->src_node = ifID->ifThisNode.s_node;
                    616:                ddp->src_socket = src_socket;
                    617: 
                    618:                dPrintf(D_M_DDP_LOW, D_L_OUTPUT,
                    619:                        ("ddp_output: loop to %d:%d port=%d\n",
                    620:                          NET_VALUE(ddp->src_net),
                    621:                          ddp->src_node,
                    622:                          ifID->ifPort));
                    623:                
                    624:                sum_pkt_chain(*mp);
                    625: 
                    626:                dPrintf(D_M_DDP, D_L_VERBOSE,
                    627:                        ("Looping back packet from skt 0x%x to skt 0x%x\n",
                    628:                        ddp->src_socket, ddp->dst_socket));
                    629: 
                    630:                for (mdata = *mp; mdata; mdata = mdata_next) {
                    631:                        mdata_next = gbuf_next(mdata);
                    632:                        gbuf_next(mdata) = 0;
                    633:                        ddp_input(mdata, ifID);
                    634:                }
                    635:                goto exit_ddp_output;
                    636:        }
                    637:         if ((ddp->dst_socket == ZIP_SOCKET) &&
                    638:            (zip_type_packet(*mp) == ZIP_GETMYZONE)) {
                    639:                ddp->src_socket = src_socket;
                    640:                error = zip_handle_getmyzone(ifID, *mp);
                    641:                gbuf_freel(*mp);
                    642:                goto exit_ddp_output;
                    643:        }
                    644:        /*
                    645:         * find out the interface on which the packet should go out
                    646:         */
                    647:        TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
                    648:                if ((ifID->ifThisNode.s_net == dst_net) || (dst_net == 0))
                    649:                        /* the message is either going out (i) on the same 
                    650:                         * NETWORK in case of LocalTalk, or (ii) on the same
                    651:                         * CABLE in case of Extended AppleTalk (EtherTalk).
                    652:                         */
                    653:                        break;
                    654: 
                    655:                if ((ifID->ifThisCableStart <= dst_net) &&
                    656:                    (ifID->ifThisCableEnd   >= dst_net)
                    657:                   )
                    658:                        /* We're on EtherTalk and the message is going out to 
                    659:                         * some other network on the same cable.
                    660:                         */
                    661:                        break;
                    662:                
                    663:                if (ARouterIf == NULL && ATALK_VALUE(ifID->ifARouter))
                    664:                        ARouterIf = ifID;
                    665:        }
                    666:        dPrintf(D_M_DDP_LOW, D_L_USR1,
                    667:                        ("ddp_output: after search ifid:0x%x %s ifID_home:0x%x\n",
                    668:                        (u_int)ifID, ifID ? ifID->ifName : "",
                    669:                        (u_int)ifID_home));
                    670: 
                    671:        if (ifID) {
                    672:                /* located the interface where the packet should
                    673:                 * go.... the "first-hop" destination address
                    674:                 * must be the same as real destination address.
                    675:                 */
                    676:                addr_type = DIRECT_ADDR;
                    677:        } else {
                    678:                /* no, the destination network number does
                    679:                 * not match known network numbers.  If we have
                    680:                 * heard from this network recently, BRT table
                    681:                 * may have address of a router we could use!
                    682:                 */
                    683:                if (!MULTIPORT_MODE) {
                    684:                        BRT_LOOK (brt, dst_net);
                    685:                        if (brt) {
                    686:                                /* Bingo... BRT has an entry for this network. 
                    687:                                 * Use the link address as is.
                    688:                                 */
                    689:                                dPrintf(D_M_DDP, D_L_VERBOSE,
                    690:                                        ("Found BRT entry to send to net 0x%x", dst_net));
                    691:                                at_ddp_stats.xmit_BRT_used++;
                    692:                                addr_type = BRT_ENTRY;
                    693:                                ifID = brt->ifID;
                    694:                        } else {
                    695:                                /* No BRT entry available for dest network... do we 
                    696:                                 * know of any router at all??
                    697:                                 */
                    698:                                if ((ifID = ARouterIf) != NULL)
                    699:                                        addr_type = BRIDGE_ADDR;
                    700:                                else {
                    701:                                dPrintf(D_M_DDP, D_L_WARNING,
                    702:                                                ("Found no interface to send pkt"));
                    703:                                        at_ddp_stats.xmit_bad_addr++;
                    704:                                        error = ENETUNREACH;
                    705:                                        gbuf_freel(*mp);
                    706:                                        goto exit_ddp_output;
                    707:                                }
                    708:                        }
                    709:                }
                    710:                else { /* We are in multiport mode,  so we can bypass all the rest 
                    711:                        * and directly ask for the routing of the packet
                    712:                        */ 
                    713:                        at_ddp_stats.xmit_BRT_used++;
                    714: 
                    715:                        ifID = ifID_home;
                    716:                        if (!src_addr_included) {
                    717:                          ddp->src_node = ifID->ifThisNode.s_node;
                    718:                          NET_ASSIGN(ddp->src_net, ifID->ifThisNode.s_net); 
                    719:                        }
                    720:                        ddp->src_socket = src_socket;
                    721:                        routing_needed(*mp, ifID, TRUE);
                    722: 
                    723:                        goto exit_ddp_output;
                    724:                }
                    725:        }
                    726:        /* by the time we land here, we know the interface on 
                    727:         * which this packet is going out....  ifID.  
                    728:         */
                    729:        if (ifID->ifState == LAP_OFFLINE) {
                    730:                gbuf_freel(*mp);
                    731:                goto exit_ddp_output;
                    732:        }               
                    733:        
                    734:        switch (addr_type) {
                    735:                case DIRECT_ADDR :
                    736: /*
                    737:                        at_dest.atalk_unused = 0;
                    738: */
                    739:                        NET_ASSIGN(at_dest.atalk_net, dst_net);
                    740:                        at_dest.atalk_node = ddp->dst_node;
                    741:                        addr_flag = AT_ADDR;
                    742:                        addr = (char *)&at_dest;
                    743:                        break;
                    744:                case BRT_ENTRY :
                    745:                        addr_flag = ET_ADDR;
                    746:                        addr = (char *)&brt->et_addr;
                    747:                        break;
                    748:                case BRIDGE_ADDR :
                    749:                        NET_ASSIGN(at_dest.atalk_net, ifID->ifARouter.s_net);
                    750:                        at_dest.atalk_node = ifID->ifARouter.s_node;
                    751:                        addr_flag = AT_ADDR;
                    752:                        addr = (char *)&at_dest;
                    753:                        break;
                    754: 
                    755:        }
                    756:        /* Irrespective of the interface on which 
                    757:         * the packet is going out, we always put the 
                    758:         * same source address on the packet (unless multihoming mode).
                    759:         */
                    760:        if (MULTIHOME_MODE) {
                    761:                if (!src_addr_included) {
                    762:                        ddp->src_node = ifID->ifThisNode.s_node;
                    763:                        NET_ASSIGN(ddp->src_net, ifID->ifThisNode.s_net); 
                    764:                }
                    765:        }
                    766:        else {
                    767:                ddp->src_node = ifID_home->ifThisNode.s_node;
                    768:                NET_ASSIGN(ddp->src_net, ifID_home->ifThisNode.s_net);
                    769:        }
                    770:        ddp->src_socket = src_socket;
                    771: 
                    772:        dPrintf(D_M_DDP_LOW, D_L_OUTPUT,
                    773:                ("ddp_output: going out to %d:%d skt%d on %s\n",
                    774:                dst_net, ddp->dst_node, ddp->dst_socket, ifID->ifName));
                    775: 
                    776:        sum_pkt_chain(*mp);
                    777: 
                    778:        { /* begin block */
                    779:        struct  etalk_addr      dest_addr;
                    780:        struct  atalk_addr      dest_at_addr;
                    781:        int             loop = TRUE;            /* flag to aarp to loopback (default) */
                    782: 
                    783:        m = *mp;
                    784: 
                    785:        /* the incoming frame is of the form {flag, address, ddp...}
                    786:         * where "flag" indicates whether the address is an 802.3
                    787:         * (link) address, or an appletalk address.  If it's an
                    788:         * 802.3 address, the packet can just go out to the network
                    789:         * through PAT, if it's an appletalk address, AT->802.3 address
                    790:         * resolution needs to be done.
                    791:         * If 802.3 address is known, strip off the flag and 802.3
                    792:         * address, and prepend 802.2 and 802.3 headers.
                    793:         */
                    794:        
                    795:        if (addr == NULL) {
                    796:                addr_flag = *(u_char *)gbuf_rptr(m);
                    797:                gbuf_rinc(m,1);
                    798:        }
                    799:        
                    800:        switch (addr_flag) {
                    801:        case AT_ADDR_NO_LOOP :
                    802:                loop = FALSE;
                    803:                /* pass thru */
                    804:        case AT_ADDR :
                    805:                if (addr == NULL) {
                    806:                    dest_at_addr = *(struct atalk_addr *)gbuf_rptr(m);
                    807:                    gbuf_rinc(m,sizeof(struct atalk_addr));
                    808:                } else
                    809:                    dest_at_addr = *(struct atalk_addr *)addr;
                    810:                break;
                    811:        case ET_ADDR :
                    812:                if (addr == NULL) {
                    813:                  dest_addr = *(struct etalk_addr *)gbuf_rptr(m);
                    814:                  gbuf_rinc(m,sizeof(struct etalk_addr));
                    815:                } else
                    816:                  dest_addr = *(struct etalk_addr *)addr;
                    817:                break;
                    818:        default :
                    819:                dPrintf(D_M_DDP_LOW,D_L_ERROR,
                    820:                    ("ddp_output: Unknown addr_flag = 0x%x\n", addr_flag));
                    821:                gbuf_freel(m);          /* unknown address type, chuck it */
                    822:                goto exit_ddp_output;
                    823:         }
                    824: 
                    825:        m = gbuf_strip(m);
                    826: 
                    827:        /* At this point, rptr points to ddp header for sure */
                    828:        if (ifID->ifState == LAP_ONLINE_FOR_ZIP) {
                    829:                /* see if this is a ZIP packet that we need
                    830:                 * to let through even though network is
                    831:                 * not yet alive!!
                    832:                 */
                    833:                if (zip_type_packet(m) == 0) {
                    834:                        gbuf_freel(m);
                    835:                        goto exit_ddp_output;
                    836:                }
                    837:        }
                    838:        
                    839:        ifID->stats.xmit_packets++;
                    840:        ifID->stats.xmit_bytes += gbuf_msgsize(m);
                    841:        snmpStats.dd_outLong++;
                    842:        
                    843:        switch (addr_flag) {
                    844:        case AT_ADDR_NO_LOOP :
                    845:        case AT_ADDR :
                    846:            /*
                    847:             * we don't want elap to be looking into ddp header, so
                    848:             * it doesn't know net#, consequently can't do 
                    849:             * AMT_LOOKUP.  That task left to aarp now.
                    850:             */
                    851:            aarp_send_data(m,ifID,&dest_at_addr, loop);
                    852:            break;
                    853:        case ET_ADDR :
                    854:            pat_output(ifID, m, &dest_addr, 0);
                    855:            break;
                    856:         }
                    857:        } /* end block */
                    858:  exit_ddp_output:
                    859:        KERNEL_DEBUG(DBG_AT_DDP_OUTPUT | DBG_FUNC_END, 0,
                    860:                     error, 0, 0, 0);
                    861:        return(error);
                    862: } /* ddp_output */
                    863: 
                    864: void ddp_input(mp, ifID)
                    865:      register gbuf_t   *mp;
                    866:      register at_ifaddr_t *ifID;
                    867: {
                    868:        register at_ddp_t *ddp;         /* DDP header */
                    869:        register int       msgsize;
                    870:        register at_socket socket;
                    871:        register int       len;
                    872:        register at_net_al dst_net;
                    873: 
                    874:        KERNEL_DEBUG(DBG_AT_DDP_INPUT | DBG_FUNC_START, 0,
                    875:                     ifID, mp, gbuf_len(mp),0);
                    876: 
                    877:        /* Makes sure we know the default interface before starting to
                    878:         * accept incomming packets. If we don't we may end up with a
                    879:         * null ifID_table[0] and have impredicable results (specially
                    880:         * in router mode. This is a transitory state (because we can
                    881:         * begin to receive packet while we're not completly set up yet.
                    882:         */
                    883: 
                    884:        if (ifID_home == (at_ifaddr_t *)NULL) {
                    885:                dPrintf(D_M_DDP, D_L_ERROR,
                    886:                        ("dropped incoming packet ifID_home not set yet\n"));
                    887:                gbuf_freem(mp);
                    888:                goto out; /* return */
                    889:        }
                    890: 
                    891:        /*
                    892:         * if a DDP packet has been broadcast, we're going to get a copy of
                    893:         * it here; if it originated at user level via a write on a DDP 
                    894:         * socket; when it gets here, the first block in the chain will be
                    895:         * empty since it only contained the lap level header which will be
                    896:         * stripped in the lap level immediately below ddp
                    897:         */
                    898: 
                    899:        if ((mp = (gbuf_t *)ddp_compress_msg(mp)) == NULL) {
                    900:                dPrintf(D_M_DDP, D_L_ERROR,
                    901:                        ("dropped short incoming ET packet (len %d)", 0));
                    902:                snmpStats.dd_inTotal++;
                    903:                at_ddp_stats.rcv_bad_length++;
                    904:                goto out; /* return; */
                    905:        }
                    906:        msgsize = gbuf_msgsize(mp);
                    907: 
                    908:        at_ddp_stats.rcv_bytes += msgsize;
                    909:        at_ddp_stats.rcv_packets++;
                    910: 
                    911:        /* if the interface pointer is 0, the packet has been 
                    912:         * looped back by 'write' half of DDP.  It is of the
                    913:         * form {extended ddp,...}.  The packet is meant to go
                    914:         * up to some socket on the same node.
                    915:         */
                    916:        if (!ifID)                      /* if loop back is specified */
                    917:                ifID = ifID_home;       /* that means the home port */
                    918: 
                    919:        /* the incoming datagram has extended DDP header and is of 
                    920:         * the form {ddp,...}.
                    921:         */
                    922:        if (msgsize < DDP_X_HDR_SIZE) {
                    923:                dPrintf(D_M_DDP, D_L_ERROR,
                    924:                        ("dropped short incoming ET packet (len %d)", msgsize));
                    925:                at_ddp_stats.rcv_bad_length++;
                    926:                gbuf_freem(mp);
                    927:                goto out; /* return; */
                    928:        }
                    929:        /*
                    930:         * At this point, the message is always of the form
                    931:         * {extended ddp, ... }.
                    932:         */
                    933:        ddp = (at_ddp_t *)gbuf_rptr(mp);
                    934:        len = DDPLEN_VALUE(ddp);
                    935: 
                    936:        if (msgsize != len) {
                    937:                if ((unsigned) msgsize > len) {
                    938:                        if (len < DDP_X_HDR_SIZE) {
                    939:                                dPrintf(D_M_DDP, D_L_ERROR,
                    940:                                       ("Length problems, ddp length %d, buffer length %d",
                    941:                                       len, msgsize));
                    942:                                snmpStats.dd_tooLong++;
                    943:                                at_ddp_stats.rcv_bad_length++;
                    944:                                gbuf_freem(mp);
                    945:                                goto out; /* return; */
                    946:                        }
                    947:                        /*
                    948:                         * shave off the extra bytes from the end of message
                    949:                         */
                    950:                        mp = ddp_adjmsg(mp, -(msgsize - len)) ? mp : 0;
                    951:                        if (mp == 0)
                    952:                                goto out; /* return; */
                    953:                } else {
                    954:                        dPrintf(D_M_DDP, D_L_ERROR,
                    955:                                ("Length problems, ddp length %d, buffer length %d",
                    956:                                len, msgsize));
                    957:                                snmpStats.dd_tooShort++;
                    958:                        at_ddp_stats.rcv_bad_length++;
                    959:                        gbuf_freem(mp);
                    960:                        goto out; /* return; */
                    961:                }
                    962:        }
                    963:        socket = ddp->dst_socket;
                    964: 
                    965:        /*
                    966:         * We want everything in router mode, specially socket 254 for nbp so we need
                    967:         * to bypass this test when we are a router.
                    968:         */
                    969: 
                    970:        if (!MULTIPORT_MODE && (socket > DDP_SOCKET_LAST ||
                    971:                         socket < DDP_SOCKET_1st_RESERVED)) {
                    972:                dPrintf(D_M_DDP, D_L_WARNING,
                    973:                        ("Bad dst socket on incoming packet (0x%x)",
                    974:                        ddp->dst_socket));
                    975:                at_ddp_stats.rcv_bad_socket++;
                    976:                gbuf_freem(mp);
                    977:                goto out; /* return; */
                    978:        }
                    979:        /*
                    980:         * if the checksum is true, then upstream wants us to calc
                    981:         */
                    982:        if (UAS_VALUE(ddp->checksum) && 
                    983:            (UAS_VALUE(ddp->checksum) != ddp_checksum(mp, 4))) {
                    984:                dPrintf(D_M_DDP, D_L_WARNING,
                    985:                        ("Checksum error on incoming pkt, calc 0x%x, exp 0x%x",
                    986:                        ddp_checksum(mp, 4), UAS_VALUE(ddp->checksum)));
                    987:                snmpStats.dd_checkSum++;
                    988:                at_ddp_stats.rcv_bad_checksum++;
                    989:                gbuf_freem(mp);
                    990:                goto out; /* return; */
                    991:        }
                    992: 
                    993: /*############### routing input checking */
                    994: 
                    995: /* Router mode special: we send "up-stack" packets for this node or coming from any
                    996:  * other ports, but for the reserved atalk sockets (RTMP, ZIP, NBP [and EP])
                    997:  * BTW, the way we know it's for the router and not the home port is that the
                    998:  * MAC (ethernet) address is always the one of the interface we're on, but
                    999:  * the AppleTalk address must be the one of the home port. If it's a multicast
                   1000:  * or another AppleTalk address, this is the router job's to figure out where it's
                   1001:  * going to go.
                   1002:  */
                   1003:        /* *** a duplicate should be sent to any other client that is listening
                   1004:           for packets of this type on a raw DDP socket *** */
                   1005:        if (ddp_handler[socket].func) {
                   1006:                dPrintf(D_M_DDP,D_L_INPUT,
                   1007:                        ("ddp_input: skt %d hdnlr:0x%x\n",
                   1008:                         (u_int) socket, ddp_handler[socket].func));
                   1009:                pktsHome++;
                   1010:                snmpStats.dd_inLocal++;
                   1011: 
                   1012:                (*ddp_handler[socket].func)(mp, ifID);
                   1013:                goto out; /* return; */
                   1014:        }
                   1015:        dst_net = NET_VALUE(ddp->dst_net);
                   1016:        if (
                   1017:            /* exact match */
                   1018:            forUs(ddp) ||
                   1019:            /* any node, wildcard or matching net */
                   1020:            ((ddp->dst_node == 255) && 
                   1021:             (((dst_net >= ifID_home->ifThisCableStart) &&
                   1022:               (dst_net <= ifID_home->ifThisCableEnd)) || 
                   1023:              dst_net == 0)) ||
                   1024:            /* this node is not online yet(?) */
                   1025:            (ifID->ifRoutingState < PORT_ONLINE)
                   1026:            ) { 
                   1027:                gref_t   *gref;
                   1028:                pktsHome++;
                   1029:                snmpStats.dd_inLocal++;
                   1030: 
                   1031:                if (ddp->type == DDP_ATP) {
                   1032:                  if (atp_inputQ[socket] && (atp_inputQ[socket] != (gref_t *)1)) {
                   1033:                        /* if there's an ATP pcb */
                   1034:                        atp_input(mp);
                   1035:                        goto out; /* return; */
                   1036:                  }
                   1037:                } else if (ddp->type == DDP_ADSP) {
                   1038:                  if (adsp_inputQ[socket]) {
                   1039:                        /* if there's an ADSP pcb */
                   1040:                        adsp_input(mp);
                   1041:                        goto out; /* return; */
                   1042:                  }
                   1043:                }
                   1044: 
                   1045:                /* otherwise look for a DDP pcb;
                   1046:                   ATP / raw-DDP and ADSP / raw-DDP are possible */
                   1047:                for (gref = ddp_head.atpcb_next; gref != &ddp_head; 
                   1048:                       gref = gref->atpcb_next)
                   1049:                    if (gref->lport == socket) {
                   1050:                        dPrintf(D_M_DDP, D_L_INPUT, 
                   1051:                                ("ddp_input: streamq, skt %d\n", socket));
                   1052:                        if (gref->atpcb_socket) {
                   1053:                                struct sockaddr_at ddp_in;
                   1054:                                ddp_in.sat_len = sizeof(ddp_in);
                   1055:                                ddp_in.sat_family = AF_APPLETALK;
                   1056:                                ddp_in.sat_addr.s_net = NET_VALUE(ddp->src_net);
                   1057:                                ddp_in.sat_addr.s_node = ddp->src_node;
                   1058:                                ddp_in.sat_port = ddp->src_socket;
                   1059: 
                   1060:                                /* strip off DDP header if so indicated by
                   1061:                                   sockopt */
                   1062:                                if (gref->ddp_flags & DDPFLG_STRIPHDR) {
                   1063:                                        mp = m_pullup((struct mbuf *)mp,
                   1064:                                                            DDP_X_HDR_SIZE);
                   1065:                                        if (mp) {
                   1066:                                                gbuf_rinc(mp, DDP_X_HDR_SIZE);
                   1067:                                        } else { 
                   1068:                                          /* this should never happen because 
                   1069:                                             msgsize was checked earlier */
                   1070:                                                at_ddp_stats.rcv_bad_length++;
                   1071:                                                goto out; /* return */
                   1072:                                        }
                   1073:                                }
                   1074: 
                   1075:                                if (sbappendaddr(&((gref->atpcb_socket)->so_rcv), 
                   1076:                                                 (struct sockaddr *)&ddp_in,
                   1077:                                                 mp, 0) == 0)
                   1078:                                        gbuf_freem(mp);
                   1079:                                else
                   1080:                                        sorwakeup(gref->atpcb_socket);
                   1081:                        } else {
                   1082:                                atalk_putnext(gref, mp);
                   1083:                        }
                   1084:                        goto out; /* return */
                   1085:                    } 
                   1086: 
                   1087:                at_ddp_stats.rcv_bad_socket++;
                   1088:                gbuf_freem(mp);
                   1089:                snmpStats.dd_noHandler++;
                   1090:                dPrintf(D_M_DDP, D_L_WARNING, 
                   1091:                        ("ddp_input: dropped pkt for socket %d\n", socket));
                   1092:        } else { 
                   1093:                dPrintf(D_M_DDP, D_L_ROUTING, 
                   1094:                        ("ddp_input: routing_needed from  port=%d sock=%d\n",
                   1095:                         ifID->ifPort, ddp->dst_socket));
                   1096: 
                   1097:                snmpStats.dd_fwdReq++;
                   1098:                if (((pktsIn-pktsHome+200) >= RouterMix) && ((++pktsDropped % 5) == 0)) {
                   1099:                        at_ddp_stats.rcv_dropped_nobuf++;
                   1100:                        gbuf_freem(mp);
                   1101:                }
                   1102:                else {
                   1103:                        routing_needed(mp, ifID, FALSE);
                   1104:                }
                   1105:        }
                   1106: out:
                   1107:        KERNEL_DEBUG(DBG_AT_DDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
                   1108: } /* ddp_input */
                   1109: 
                   1110: 
                   1111: /* 
                   1112:  * ddp_router_output()
                   1113:  *
                   1114:  * Remarks : 
                   1115:  *     This is a modified version of ddp_output for router use.
                   1116:  *     The main difference is that the interface on which the packet needs
                   1117:  *     to be sent is specified and a *destination* AppleTalk address is passed
                   1118:  *     as an argument, this address may or may not be the same as the destination
                   1119:  *     address found in the ddp packet... This is the trick about routing, the
                   1120:  *     AppleTalk destination of the packet may not be the same as the Enet address
                   1121:  *     we send the packet too (ie, we may pass the baby to another router).    
                   1122:  *
                   1123:  */
                   1124: int ddp_router_output(mp, ifID, addr_type, router_net, router_node, enet_addr)
                   1125:      gbuf_t    *mp;
                   1126:      at_ifaddr_t *ifID;
                   1127:      int addr_type;
                   1128:      at_net_al router_net;
                   1129:      at_node router_node;
                   1130:      etalk_addr_t *enet_addr;
                   1131: {
                   1132:        register at_ddp_t       *ddp;
                   1133:        struct   atalk_addr     at_dest;
                   1134:        int             addr_flag;
                   1135:        char    *addr = NULL;
                   1136:        register gbuf_t *m;
                   1137: 
                   1138:        if (!ifID) {
                   1139:                dPrintf(D_M_DDP, D_L_WARNING, ("BAD BAD ifID\n"));
                   1140:                gbuf_freel(mp);
                   1141:                return(EPROTOTYPE);
                   1142:        }
                   1143:        ddp = (at_ddp_t *)gbuf_rptr(mp);
                   1144: 
                   1145:        if (ifID->ifFlags & AT_IFF_AURP) { /* AURP link? */
                   1146:                if (ddp_AURPsendx) {
                   1147:                        sum_pkt_chain(mp);
                   1148:                        if (router_node == 255)
                   1149:                                router_node = 0;
                   1150:                        ddp_AURPsendx(AURPCODE_DATAPKT, mp, router_node);
                   1151:                        return 0;
                   1152:                } else {
                   1153:                        gbuf_freel(mp);
                   1154:                        return EPROTOTYPE;
                   1155:                }
                   1156:        }
                   1157: 
                   1158:        /* keep some of the tests for now ####### */
                   1159: 
                   1160:        if (gbuf_msgsize(mp) > DDP_DATAGRAM_SIZE) {
                   1161:                /* the packet is too large */
                   1162:                dPrintf(D_M_DDP, D_L_WARNING,
                   1163:                        ("ddp_router_output: Packet too large size=%d\n",
                   1164:                         gbuf_msgsize(mp)));
                   1165:                gbuf_freel(mp);
                   1166:                return (EMSGSIZE);
                   1167:        }
                   1168: 
                   1169:        switch (addr_type) {
                   1170: 
                   1171:                case AT_ADDR :
                   1172: 
                   1173:                        /*
                   1174:                         * Check for packet destined to the home stack
                   1175:                         */
                   1176: 
                   1177:                  if    ((ddp->dst_node == ifID->ifThisNode.s_node) &&
                   1178:                         (NET_VALUE(ddp->dst_net) == ifID->ifThisNode.s_net)) {
                   1179:                        dPrintf(D_M_DDP_LOW, D_L_ROUTING, 
                   1180:                                ("ddp_r_output: sending back home from port=%d socket=%d\n",
                   1181:                                 ifID->ifPort, ddp->dst_socket));
                   1182:                        
                   1183:                        UAS_ASSIGN(ddp->checksum, 0);
                   1184:                        ddp_input(mp, ifID);    
                   1185:                        return(0);
                   1186:                  }
                   1187: 
                   1188:                  NET_ASSIGN(at_dest.atalk_net, router_net);
                   1189:                  at_dest.atalk_node = router_node;
                   1190: 
                   1191:                  addr_flag = AT_ADDR_NO_LOOP;
                   1192:                  addr = (char *)&at_dest;
                   1193:                  dPrintf(D_M_DDP_LOW, D_L_ROUTING_AT,
                   1194:                          ("ddp_r_output: AT_ADDR out port=%d net %d:%d via rte %d:%d",
                   1195:                           ifID->ifPort, NET_VALUE(ddp->dst_net), ddp->dst_node, router_net,
                   1196:                           router_node));
                   1197:                  break;
                   1198: 
                   1199:                case ET_ADDR :
                   1200:                  addr_flag = ET_ADDR;
                   1201:                  addr = (char *)enet_addr;
                   1202:                  dPrintf(D_M_DDP_LOW, D_L_ROUTING,
                   1203:                          ("ddp_r_output: ET_ADDR out port=%d net %d:%d\n",
                   1204:                           ifID->ifPort, NET_VALUE(ddp->dst_net), ddp->dst_node));
                   1205:                  break;
                   1206:                }
                   1207: 
                   1208:        if (ifID->ifState == LAP_OFFLINE) {
                   1209:              gbuf_freel(mp);
                   1210:              return 0;
                   1211:        }
                   1212:        
                   1213:        sum_pkt_chain(mp);
                   1214: 
                   1215:        { /* begin block */
                   1216:            struct      etalk_addr      dest_addr;
                   1217:            struct      atalk_addr      dest_at_addr;
                   1218:            int loop = TRUE;            /* flag to aarp to loopback (default) */
                   1219: 
                   1220:            m = mp;
                   1221: 
                   1222:            /* the incoming frame is of the form {flag, address, ddp...}
                   1223:             * where "flag" indicates whether the address is an 802.3
                   1224:             * (link) address, or an appletalk address.  If it's an
                   1225:             * 802.3 address, the packet can just go out to the network
                   1226:             * through PAT, if it's an appletalk address, AT->802.3 address
                   1227:             * resolution needs to be done.
                   1228:             * If 802.3 address is known, strip off the flag and 802.3
                   1229:             * address, and prepend 802.2 and 802.3 headers.
                   1230:             */
                   1231:        
                   1232:            if (addr == NULL) {
                   1233:                addr_flag = *(u_char *)gbuf_rptr(m);
                   1234:                gbuf_rinc(m,1);
                   1235:            }
                   1236:        
                   1237:            switch (addr_flag) {
                   1238:            case AT_ADDR_NO_LOOP :
                   1239:              loop = FALSE;
                   1240:              /* pass thru */
                   1241:            case AT_ADDR :
                   1242:              if (addr == NULL) {
                   1243:                dest_at_addr = *(struct atalk_addr *)gbuf_rptr(m);
                   1244:                gbuf_rinc(m,sizeof(struct atalk_addr));
                   1245:              } else
                   1246:                dest_at_addr = *(struct atalk_addr *)addr;
                   1247:              break;
                   1248:            case ET_ADDR :
                   1249:              if (addr == NULL) {
                   1250:                dest_addr = *(struct etalk_addr *)gbuf_rptr(m);
                   1251:                gbuf_rinc(m,sizeof(struct etalk_addr));
                   1252:              } else
                   1253:                dest_addr = *(struct etalk_addr *)addr;
                   1254:              break;
                   1255:            default :
                   1256:              dPrintf(D_M_DDP_LOW,D_L_ERROR,
                   1257:                      ("ddp_router_output: Unknown addr_flag = 0x%x\n", addr_flag));
                   1258: 
                   1259:              gbuf_freel(m);            /* unknown address type, chuck it */
                   1260:              return 0;
                   1261:            }
                   1262: 
                   1263:            m = gbuf_strip(m);
                   1264: 
                   1265:            /* At this point, rptr points to ddp header for sure */
                   1266:            if (ifID->ifState == LAP_ONLINE_FOR_ZIP) {
                   1267:                      /* see if this is a ZIP packet that we need
                   1268:                       * to let through even though network is
                   1269:                       * not yet alive!!
                   1270:                       */
                   1271:                      if (zip_type_packet(m) == 0) {
                   1272:                        gbuf_freel(m);
                   1273:                        return 0;
                   1274:                      }
                   1275:            }
                   1276:        
                   1277:            ifID->stats.xmit_packets++;
                   1278:            ifID->stats.xmit_bytes += gbuf_msgsize(m);
                   1279:            snmpStats.dd_outLong++;
                   1280:            
                   1281:            switch (addr_flag) {
                   1282:            case AT_ADDR_NO_LOOP :
                   1283:            case AT_ADDR :
                   1284:              /*
                   1285:               * we don't want elap to be looking into ddp header, so
                   1286:               * it doesn't know net#, consequently can't do 
                   1287:               * AMT_LOOKUP.  That task left to aarp now.
                   1288:               */
                   1289:              aarp_send_data(m,ifID,&dest_at_addr, loop);
                   1290:              break;
                   1291:            case ET_ADDR :
                   1292:              pat_output(ifID, m, &dest_addr, 0);
                   1293:              break;
                   1294:            }
                   1295:        } /* end block */
                   1296: 
                   1297:        return(0);
                   1298: } /* ddp_router_output */
                   1299: 
                   1300: /*****************************************/
                   1301: 
                   1302: void rt_delete(NetStop, NetStart)
                   1303:        unsigned short NetStop;
                   1304:        unsigned short NetStart;
                   1305: {
                   1306:        RT_entry *found;
                   1307:        int s;
                   1308: 
                   1309:        ATDISABLE(s, ddpinp_lock);
                   1310:        if ((found = rt_bdelete(NetStop, NetStart)) != 0) {
                   1311:                bzero(found, sizeof(RT_entry));
                   1312:                found->right = RT_table_freelist;
                   1313:                RT_table_freelist = found;
                   1314:        }
                   1315:        ATENABLE(s, ddpinp_lock);
                   1316: }
                   1317: 
                   1318: int ddp_AURPfuncx(code, param, node)
                   1319:        int code;
                   1320:        void *param;
                   1321:        unsigned char node;
                   1322: {
                   1323:        extern void rtmp_timeout();
                   1324:        extern void rtmp_send_port();
                   1325:        at_ifaddr_t *ifID;
                   1326:        int k;
                   1327: 
                   1328:        switch (code) {
                   1329:        case AURPCODE_DATAPKT: /* data packet */
                   1330:                if (aurp_ifID) {
                   1331:                        dPrintf(D_M_DDP, D_L_TRACE, ("ddp_AURPfuncx: data, 0x%x, %d\n",
                   1332:                                (u_int) aurp_ifID, node));
                   1333: 
                   1334:                        ddp_input((gbuf_t *)param, aurp_ifID);
                   1335:                } else
                   1336:                        gbuf_freem((gbuf_t *)param);
                   1337:                break;
                   1338: 
                   1339:        case AURPCODE_REG: /* register/deregister */
                   1340:                if (!ROUTING_MODE)
                   1341:                        return -1;
                   1342:                ddp_AURPsendx = (void(*)())param;
                   1343: 
                   1344:                if (param) {
                   1345:                        /* register AURP callback function */
                   1346:                        if (aurp_ifID)
                   1347:                                return 0;
                   1348:                        for (k=(IFID_HOME+1); k < IF_TOTAL_MAX; k++) {
                   1349:                                if (ifID_table[k] == 0) {
                   1350:                                        aurp_ifID = &at_interfaces[k];
                   1351:                                        aurp_ifID->ifFlags = RTR_XNET_PORT;
                   1352:                                        ddp_add_if(aurp_ifID);
                   1353:                                        aurp_ifID->ifState = LAP_ONLINE;
                   1354:                                        aurp_ifID->ifRoutingState = PORT_ONLINE;
                   1355:                                        dPrintf(D_M_DDP, D_L_TRACE,
                   1356:                                                ("ddp_AURPfuncx: on, 0x%x\n",
                   1357:                                                (u_int) aurp_ifID));
                   1358: 
                   1359:                                        ddp_AURPsendx(AURPCODE_DEBUGINFO,
                   1360:                                                        &dbgBits, aurp_ifID->ifPort);
                   1361:                                        return 0;
                   1362:                                }
                   1363:                        }
                   1364:                        return -1;
                   1365: 
                   1366:                } else {
                   1367:                        /* deregister AURP callback function */
                   1368:                        if (aurp_ifID) {
                   1369:                                rtmp_purge(aurp_ifID);
                   1370:                                ddp_rem_if(aurp_ifID);
                   1371:                                aurp_ifID->ifState = LAP_OFFLINE;
                   1372:                                aurp_ifID->ifRoutingState = PORT_OFFLINE;
                   1373:                                dPrintf(D_M_DDP, D_L_TRACE,
                   1374:                                        ("ddp_AURPfuncx: off, 0x%x\n", (u_int) aurp_ifID));
                   1375:                                aurp_ifID = 0;
                   1376:                        }
                   1377:                }
                   1378:                break;
                   1379: 
                   1380:        case AURPCODE_AURPPROTO: /* proto type - AURP */
                   1381:                if (aurp_ifID) {
                   1382:                        aurp_ifID->ifFlags |= AT_IFF_AURP;
                   1383:                }
                   1384:                break;
                   1385:        }
                   1386: 
                   1387:        return 0;
                   1388: }
                   1389: 
                   1390: 
                   1391: /* checks to see if address of packet is for one of our interfaces
                   1392:    returns *ifID if it's for us, NULL if not
                   1393: */
                   1394: at_ifaddr_t *forUs(ddp)
                   1395:      register at_ddp_t *ddp;
                   1396: {
                   1397:        at_ifaddr_t *ifID;
                   1398: 
                   1399:        TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
                   1400:                if ((ddp->dst_node == ifID->ifThisNode.s_node) &&
                   1401:                        (NET_VALUE(ddp->dst_net) ==  ifID->ifThisNode.s_net)
                   1402:                   ) {
                   1403:                        dPrintf(D_M_DDP_LOW, D_L_ROUTING,
                   1404:                                ("pkt was for port %d\n", ifID->ifPort));
                   1405: 
                   1406:                        return(ifID);
                   1407:                }
                   1408:        }
                   1409: 
                   1410:        return((at_ifaddr_t *)NULL);
                   1411: } /* forUs */

unix.superglobalmegacorp.com

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