]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netat/ddp.c
xnu-2422.1.72.tar.gz
[apple/xnu.git] / bsd / netat / ddp.c
diff --git a/bsd/netat/ddp.c b/bsd/netat/ddp.c
deleted file mode 100644 (file)
index 0e2ebea..0000000
+++ /dev/null
@@ -1,1420 +0,0 @@
-/*
- * Copyright (c) 2000-2010 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- * 
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-/*
- *    Modified for MP, 1996 by Tuyen Nguyen
- *    Added AURP support, April 8, 1996 by Tuyen Nguyen
- *   Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
- */
-
-#define RESOLVE_DBG                    /* define debug globals in debug.h */
-
-#include <sys/errno.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <machine/spl.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/proc.h>
-#include <sys/filedesc.h>
-#include <sys/fcntl.h>
-#include <sys/mbuf.h>
-#include <sys/ioctl.h>
-#include <sys/malloc.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/protosw.h>
-
-#include <net/if.h>
-#include <net/dlil.h>
-
-#include <netat/sysglue.h>
-#include <netat/appletalk.h>
-#include <netat/at_pcb.h>
-#include <netat/at_var.h>
-#include <netat/ddp.h>
-#include <netat/ep.h>
-#include <netat/nbp.h>
-#include <netat/rtmp.h>
-#include <netat/zip.h>
-#include <netat/routing_tables.h>
-#include <netat/at_snmp.h>
-#include <netat/aurp.h>
-#include <netat/debug.h>
-#include <netat/at_ddp_brt.h>
-#include <netat/at_aarp.h>
-#include <netat/adsp.h>
-#include <netat/adsp_internal.h>
-#include <netat/at_pat.h>
-#include <netat/atp.h>
-
-#include <net/kpi_protocol.h>
-
-/* globals */
-
-/* Queue of LAP interfaces which have registered themselves with DDP */
-struct at_ifQueueHd at_ifQueueHd;
-
-extern TAILQ_HEAD(name_registry, _nve_) name_registry;
-
-snmpStats_t snmpStats;         /* snmp ddp & echo stats */
-
-extern at_ddp_stats_t at_ddp_stats;    /* DDP statistics */
-extern struct atpcb ddp_head;
-extern at_ifaddr_t *ifID_home, *ifID_table[];
-extern aarp_amt_array *aarp_table[];
-extern at_ifaddr_t at_interfaces[];
-
-/* routing mode special */
-void (*ddp_AURPsendx)(void) = NULL;
-at_ifaddr_t *aurp_ifID = 0;
-
-int pktsIn = 0;
-int pktsOut = 0;
-int pktsDropped = 0;
-int pktsHome = 0;
-
-extern int *atp_pidM;
-extern int *adsp_pidM;
-extern struct atpcb *atp_inputQ[];
-extern CCB *adsp_inputQ[];
-
-static void fillin_pkt_chain(gbuf_t *);
-static int ot_ddp_check_socket(unsigned char ,int pid);
-
-
-struct {
-       ddp_handler_func func;
-} ddp_handler[256];
-
-void init_ddp_handler(void)
-{
-       bzero(ddp_handler, sizeof(ddp_handler));
-}
-
-void add_ddp_handler(ddp_socket, input_func)
-     u_char ddp_socket;
-     ddp_handler_func input_func;
-{
-       ddp_handler[ddp_socket].func = input_func;
-}
-
-void
-ddp_slowtimo()
-{
-       ddp_brt_sweep();
-}
-
-/*
- * Raw DDP socket option processing.
- */
-int ddp_ctloutput(so, sopt)
-     struct socket *so;
-     struct sockopt *sopt;
-{
-       struct atpcb *at_pcb = sotoatpcb(so);
-       int optval, error = 0;
-
-       if (sopt->sopt_level != ATPROTO_NONE)
-               return (EINVAL);
-
-       switch (sopt->sopt_dir) {
-
-       case SOPT_GET:
-               switch (sopt->sopt_name) {
-               case DDP_HDRINCL:
-                       optval = at_pcb->ddp_flags & DDPFLG_HDRINCL;
-                       error = sooptcopyout(sopt, &optval, sizeof optval);
-                       break;
-               case DDP_CHKSUM_ON:
-                       optval = at_pcb->ddp_flags & DDPFLG_CHKSUM;
-                       error = sooptcopyout(sopt, &optval, sizeof optval);
-                       break;
-               case DDP_STRIPHDR:
-                       optval = at_pcb->ddp_flags & DDPFLG_STRIPHDR;
-                       error = sooptcopyout(sopt, &optval, sizeof optval);
-                       break;
-               case DDP_SLFSND_ON:
-                       optval = at_pcb->ddp_flags & DDPFLG_SLFSND;
-                       error = sooptcopyout(sopt, &optval, sizeof optval);
-                       break;
-               case DDP_GETSOCKNAME:
-                 {
-                       ddp_addr_t addr;
-                       addr.inet.net = at_pcb->laddr.s_net;
-                       addr.inet.node = at_pcb->laddr.s_node;
-                       addr.inet.socket = at_pcb->lport;
-                       addr.ddptype = at_pcb->ddptype;
-                       error = sooptcopyout(sopt, &addr, sizeof addr);
-                 }
-                       break;
-                default:
-                       error = ENOPROTOOPT;
-                       break;
-               }
-               break;
-       case SOPT_SET:
-               switch (sopt->sopt_name) {
-               case DDP_HDRINCL:
-                       error = sooptcopyin(sopt, &optval, sizeof optval,
-                                           sizeof optval);
-                       if (error)
-                               break;
-                       if (optval)
-                               at_pcb->ddp_flags |= DDPFLG_HDRINCL;
-                       else
-                               at_pcb->ddp_flags &= ~DDPFLG_HDRINCL;
-                       break;
-               case DDP_CHKSUM_ON:
-                       error = sooptcopyin(sopt, &optval, sizeof optval,
-                                           sizeof optval);
-                       if (error)
-                               break;
-                       if (optval)
-                               at_pcb->ddp_flags |= DDPFLG_CHKSUM;
-                       else
-                               at_pcb->ddp_flags &= ~DDPFLG_CHKSUM;
-                       break;
-               case DDP_STRIPHDR:
-                       error = sooptcopyin(sopt, &optval, sizeof optval,
-                                           sizeof optval);
-                       if (error)
-                               break;
-                       if (optval)
-                               at_pcb->ddp_flags |= DDPFLG_STRIPHDR;
-                       else
-                               at_pcb->ddp_flags &= ~DDPFLG_STRIPHDR;
-                       break;
-               case DDP_SLFSND_ON:
-                       error = sooptcopyin(sopt, &optval, sizeof optval,
-                                           sizeof optval);
-                       if (error)
-                               break;
-                       if (optval)
-                               at_pcb->ddp_flags |= DDPFLG_SLFSND;
-                       else
-                               at_pcb->ddp_flags &= ~DDPFLG_SLFSND;
-                       break;
-                default:
-                       error = ENOPROTOOPT;
-                       break;
-               }
-               break;
-       }
-
-       return(error);
-} /* ddp_cloutput */
-
-/****************************************************************/
-/*                                                             */
-/*                                                             */
-/*                     Support Routines                        */
-/*                                                             */
-/*                                                             */
-/****************************************************************/
-
-/*
- * Name:
- *     ddp_checksum
- *
- * Description:
- *     This procedure determines the checksum of an extended DDP datagram.
- *      Add the unsigned bytes into an unsigned 16-bit accumulator.
- *      After each add, rotate the sign bit into the low order bit of
- *      the accumulator. When done, if the checksum is 0, changed into 0xFFFF.
- *
- * Calling sequence:
- *     checksum = ddp_checksum(mp, offset)
- *
- * Parameters:
- *     mp              pointer to the datagram gbuf_t
- *     offset          offset to start at in first gbuf_t block
- *
- * Return value:
- *     The DDP checksum.
- *
- */
-
-u_short ddp_checksum(mp, offset)
-     register gbuf_t   *mp;
-     register int      offset;
-{
-       register u_char *data;
-       register int     length;
-       register u_short checksum;
-
-       checksum = 0;
-
-       do {
-               if (offset >= gbuf_len(mp))
-                       offset -= gbuf_len(mp);
-               else {
-                       data = ((unsigned char *) gbuf_rptr(mp)) + offset;
-                       length = gbuf_len(mp) - offset;
-                       offset = 0;
-                       /* Portable checksum from 3.0 */
-                       while (length--) {
-                               checksum += *data++;
-                               checksum = (checksum & 0x8000) ?
-                                       ((checksum << 1) | 1) : (checksum << 1);
-                       }
-               }
-       } while ( (mp = gbuf_cont(mp)) );
-
-       if (checksum == 0)
-               checksum = 0xffff;
-
-       return(checksum);
-}
-
-/*
- * ddp_add_if()
- *
- * Description:
- *     This procedure is called by each LAP interface when it wants to place
- *     itself online.  The LAP interfaces passes in a pointer to its at_if
- *     struct, which is added to DDP's list of active interfaces (at_ifQueueHd).
- *     When DDP wants to transmit a packet, it searches this list for the 
- *     interface to use.
- *     
- *     If AT_IFF_DEFAULT is set, then this interface is to be brought online
- *     as the interface DDP socket addresses are tied to.  Of course there can
- *     be only one default interface; we return an error if it's already set. 
- *
- * Calling Sequence:
- *     ret_status = ddp_add_if(ifID)
- *
- * Formal Parameters:
- *     ifID            pointer to LAP interface's at_if struct.
- *
- * Completion Status:
- *     0               Procedure successfully completed.
- *     EALREADY        This interface is already online, or there is
- *                     already a default interface.
- *     ENOBUFS         Cannot allocate input queue
- *
- */
-int ddp_add_if(ifID)
-register at_ifaddr_t   *ifID;
-{
-       int port = -1;
-
-       dPrintf(D_M_DDP, D_L_STARTUP, 
-               ("ddp_add_if: called, ifID:0x%x\n", (u_int) ifID));
-
-       if (ifID->ifFlags & AT_IFF_DEFAULT) {
-               if (ifID_home)
-                       return(EEXIST);    /* home port already set */ 
-               else {
-                       port = IFID_HOME;
-                       ifID_home = ifID;
-               }
-       } else {
-               for (port=IFID_HOME+1; port<IF_TOTAL_MAX; port++)
-                       if (!ifID_table[port]) {
-                               break;
-               }
-               if (port == IF_TOTAL_MAX)       /* no space left */
-                       return(ENOMEM);
-       }
-
-       /* allocate an et_aarp_amt structure */
-       if ((aarp_table[port] = 
-            (aarp_amt_array *)_MALLOC(sizeof(aarp_amt_array),
-                                      M_RTABLE, M_WAITOK)) == NULL)
-               return(ENOMEM);
-
-       dPrintf(D_M_DDP, D_L_STARTUP, ("ddp:adding ifID_table[%d]\n", port));
-               
-       /* add i/f to port list */
-       ifID_table[port] = ifID;
-       ifID->ifPort = port;    /* set ddp port # in ifID */
-
-       /* Add this interface to the list of online interfaces */
-       TAILQ_INSERT_TAIL(&at_ifQueueHd, ifID, aa_link);
-       
-       return (0);
-} /* ddp_add_if */
-
-/*
- * ddp_rem_if()
- *
- * Description:
- *     This procedure is called by each LAP interface when it wants to take
- *     itself offline.  The LAP interfaces passes in a pointer to its at_if
- *     struct; DDP's list of active interfaces (at_ifQueueHd) is searched and
- *     this interface is removed from the list.  DDP can still transmit 
- *     packets as long as this interface is not the default interface; the
- *     sender will just get ENETUNREACH errors when it tries to send to an
- *     interface that went offline.  However, if the default interface is
- *     taken offline, we no longer have a node ID to use as a source address
- *     and DDP must return ENETDOWN when a caller tries to send a packet.
- *     
- * Formal Parameters:
- *     ifID            pointer to LAP interface's at_if struct.
- */
-
-void  ddp_rem_if(ifID)
-     register at_ifaddr_t      *ifID;
-{
-       struct ifaddr *ifa = &ifID->aa_ifa;
-
-       /* un-do processing done in SIOCSIFADDR */
-       ifnet_lock_exclusive(ifID->aa_ifp);
-       IFA_LOCK(ifa);
-       if (ifa->ifa_debug & IFD_ATTACHED) {
-               if_detach_ifa(ifID->aa_ifp, ifa);
-               ifa->ifa_addr = NULL;
-       }
-       IFA_UNLOCK(ifa);
-       /* release reference held for at_interfaces[] */
-       IFA_REMREF(ifa);
-       ifnet_lock_done(ifID->aa_ifp);
-
-       if (ifID->at_was_attached == 0 && ifID->aa_ifp != NULL) {
-               (void)proto_unplumb(PF_APPLETALK, ifID->aa_ifp);
-       }
-
-       /* un-do processing done in ddp_add_if() */
-       if (ifID->ifPort) {
-               if (aarp_table[ifID->ifPort]) {
-                       FREE(aarp_table[ifID->ifPort], M_RTABLE);
-                       aarp_table[ifID->ifPort] = NULL;
-               }
-
-               at_state.flags |= AT_ST_IF_CHANGED;
-               ifID->aa_ifp = NULL;
-
-               trackrouter_rem_if(ifID);
-               TAILQ_REMOVE(&at_ifQueueHd, ifID, aa_link);
-               ifID_table[ifID->ifPort] = NULL;
-               ifID->ifName[0] = '\0';
-               ifID->ifPort = 0;
-       }
-
-       /* *** deallocate ifID, eventually *** */
-} /* ddp_rem_if */
-
-/*
- * The user may have registered an NVE with the NBP on a socket.  When the
- * socket is closed, the NVE should be deleted from NBP's name table.  The
- * user should delete the NVE before the socket is shut down, but there
- * may be circumstances when he can't.  So, whenever a DDP socket is closed,
- * this routine is used to notify NBP of the socket closure.  This would
- * help NBP get rid of all NVE's registered on the socket.
- */
-
-/* *** Do we still need to do this? *** */
-static int ot_ddp_check_socket(socket, pid)
-     unsigned char socket;
-     int pid;
-{
-       int cnt = 0;
-       gref_t *gref;
-
-       dPrintf(D_M_DDP, D_L_INFO, ("ot_ddp_check_socket: %d\n", socket));
-       for (gref = ddp_head.atpcb_next; gref != &ddp_head; gref = gref->atpcb_next)
-               if (gref->lport == socket && gref->pid == pid)
-                    cnt++;
-       if ((atp_inputQ[socket] != NULL) && (atp_inputQ[socket] != (gref_t *)1)
-           && (atp_pidM[socket] == pid))
-               cnt++;
-       if ((adsp_inputQ[socket] != NULL) && (adsp_pidM[socket] == pid))
-               cnt++;
-
-       return(cnt);
-}
-
-void ddp_notify_nbp(
-     unsigned char socket,
-     int pid,
-     __unused unsigned char ddptype)
-{
-       nve_entry_t *nve_entry, *nve_next;
-
-       if (at_state.flags & AT_ST_STARTED) {
-               /* *** NBP_CLOSE_NOTE processing (from ddp_nbp.c) *** */
-                for ((nve_entry = TAILQ_FIRST(&name_registry)); nve_entry; nve_entry = nve_next) {
-                        nve_next = TAILQ_NEXT(nve_entry, nve_link);
-                       if ((at_socket)socket == nve_entry->address.socket &&
-                           /* *** check complete address and ddptype here *** */
-                           pid == nve_entry->pid &&
-                           ot_ddp_check_socket(nve_entry->address.socket,
-                                               nve_entry->pid) < 2) {
-                                /* NB: nbp_delete_entry calls TAILQ_REMOVE */
-                               nbp_delete_entry(nve_entry);
-                       }
-               }
-       }
-} /* ddp_notify_nbp */
-
-static void fillin_pkt_chain(m)
-     gbuf_t *m;
-{
-       gbuf_t *tmp_m = m;
-       register at_ddp_t 
-         *ddp = (at_ddp_t *)gbuf_rptr(m),
-         *tmp_ddp;
-       u_short tmp;
-
-       if (UAS_VALUE(ddp->checksum)) {
-               tmp = ddp_checksum(m, 4);
-               UAS_ASSIGN_HTON(ddp->checksum, tmp);
-       }
-
-       for (tmp_m=gbuf_next(tmp_m); tmp_m; tmp_m=gbuf_next(tmp_m)) {
-               tmp_ddp = (at_ddp_t *)gbuf_rptr(tmp_m);
-               DDPLEN_ASSIGN(tmp_ddp, gbuf_msgsize(tmp_m));
-               tmp_ddp->hopcount = 
-                 tmp_ddp->unused = 0;
-               NET_NET(tmp_ddp->src_net, ddp->src_net);
-               tmp_ddp->src_node = ddp->src_node;
-               tmp_ddp->src_socket = ddp->src_socket;
-               if (UAS_VALUE(tmp_ddp->checksum)) {
-                       tmp = ddp_checksum(tmp_m, 4);
-                       UAS_ASSIGN_HTON(ddp->checksum, tmp);
-               }
-       }
-}
-
-/* There are various ways a packet may go out.... it may be sent out
- * directly to destination node, or sent to a random router or sent
- * to a router whose entry exists in Best Router Cache.  Following are 
- * constants used WITHIN this routine to keep track of choice of destination
- */
-#define DIRECT_ADDR    1
-#define        BRT_ENTRY       2
-#define        BRIDGE_ADDR     3
-
-/* 
- * ddp_output()
- *
- * Remarks : 
- *     Called to queue a atp/ddp data packet on the network interface.
- *     It returns 0 normally, and an errno in case of error.
- *     The mbuf chain pointed to by *mp is consumed on success, and
- *             freed in case of error.
- *
- */
-int ddp_output(mp, src_socket, src_addr_included)
-     register gbuf_t   **mp;
-     at_socket src_socket;
-     int src_addr_included;
-{
-       register at_ifaddr_t    *ifID = ifID_home, *ifIDTmp = NULL;
-       register at_ddp_t       *ddp;
-       register ddp_brt_t      *brt = NULL;
-       register at_net_al      dst_net;
-       register int            len;
-       struct   atalk_addr     at_dest;
-       at_ifaddr_t             *ARouterIf = NULL;
-       int loop = 0;
-       int error = 0;
-       int addr_type;
-       u_char  addr_flag = 0;
-       char    *addr = NULL;
-       register gbuf_t *m;
-
-       KERNEL_DEBUG(DBG_AT_DDP_OUTPUT | DBG_FUNC_START, 0,
-                    0,0,0,0);
-
-       snmpStats.dd_outReq++;
-
-       m = *mp;
-       ddp = (at_ddp_t *)gbuf_rptr(m);
-       
-       if (!ifID) {
-               /* Device/Interface not configured */
-               dPrintf(D_M_DDP, D_L_ERROR, ("Device/Interface not configured"));
-               error = ENXIO;
-               gbuf_freel(*mp);
-               goto exit_ddp_output;
-       }
-
-       if ((ddp->dst_socket > (unsigned) (DDP_SOCKET_LAST + 1)) || 
-           (ddp->dst_socket < DDP_SOCKET_1st_RESERVED)) {
-               dPrintf(D_M_DDP, D_L_ERROR,
-                       ("Illegal destination socket on outgoing packet (0x%x)",
-                        ddp->dst_socket));
-               at_ddp_stats.xmit_bad_addr++;
-               error = ENOTSOCK;
-               gbuf_freel(*mp);
-               goto exit_ddp_output;
-       }
-       if ((len = gbuf_msgsize(*mp)) > DDP_DATAGRAM_SIZE) {
-               /* the packet is too large */
-               dPrintf(D_M_DDP, D_L_ERROR,
-                       ("Outgoing packet too long (len=%d bytes)", len));
-               at_ddp_stats.xmit_bad_length++;
-               error = EMSGSIZE;
-               gbuf_freel(*mp);
-               goto exit_ddp_output;
-       }
-       at_ddp_stats.xmit_bytes += len;
-       at_ddp_stats.xmit_packets++;
-
-       DDPLEN_ASSIGN(ddp, len);
-       ddp->hopcount = 
-         ddp->unused = 0;
-
-       /* If this packet is for the same node, loop it back
-        * up...  Note that for LocalTalk, dst_net zero means "THIS_NET", so
-        * address 0.nn is eligible for loopback.  For Extended EtherTalk,
-        * dst_net 0 can be used only for cable-wide or zone-wide 
-        * broadcasts (0.ff) and as such, address of the form 0.nn is NOT
-        * eligible for loopback.
-        */
-       dst_net = NET_VALUE(ddp->dst_net);
-
-       /* If our packet is destined for the 'virtual' bridge
-        * address of NODE==0xFE, replace that address with a
-        * real bridge address.
-        */
-       if ((ddp->dst_node == 0xfe) && 
-           ((dst_net == ATADDR_ANYNET) ||
-            (dst_net >= ifID_home->ifThisCableStart &&
-             dst_net <= ifID_home->ifThisCableEnd))) {
-               /* if there's a router that's not us, it's in ifID_home */
-               NET_ASSIGN(ddp->dst_net, ifID_home->ifARouter.s_net);
-               dst_net = ifID_home->ifARouter.s_net;
-               ddp->dst_node = ifID_home->ifARouter.s_node;
-       }
-
-       if (MULTIHOME_MODE && (ifIDTmp = forUs(ddp))) {
-               ifID = ifIDTmp;
-               loop = TRUE;
-               dPrintf(D_M_DDP_LOW, D_L_USR1,
-                       ("ddp_out: for us if:%s\n", ifIDTmp->ifName));
-       }
-
-       if (!loop)
-               loop = ((ddp->dst_node == ifID->ifThisNode.s_node) &&
-                       (dst_net == ifID->ifThisNode.s_net)
-                       );
-       if (loop) {
-               gbuf_t *mdata, *mdata_next;
-
-               if (!MULTIHOME_MODE || !src_addr_included) {
-                       NET_ASSIGN(ddp->src_net, ifID->ifThisNode.s_net);
-                       ddp->src_node = ifID->ifThisNode.s_node;
-               }
-               ddp->src_socket = src_socket;
-
-               dPrintf(D_M_DDP_LOW, D_L_OUTPUT,
-                       ("ddp_output: loop to %d:%d port=%d\n",
-                         NET_VALUE(ddp->dst_net),
-                         ddp->dst_node,
-                         ifID->ifPort));
-               
-               fillin_pkt_chain(*mp);
-
-               dPrintf(D_M_DDP, D_L_VERBOSE,
-                       ("Looping back packet from skt 0x%x to skt 0x%x\n",
-                       ddp->src_socket, ddp->dst_socket));
-
-               for (mdata = *mp; mdata; mdata = mdata_next) {
-                       mdata_next = gbuf_next(mdata);
-                       gbuf_next(mdata) = 0;
-                       ddp_input(mdata, ifID);
-               }
-               goto exit_ddp_output;
-       }
-        if ((ddp->dst_socket == ZIP_SOCKET) &&
-           (zip_type_packet(*mp) == ZIP_GETMYZONE)) {
-               ddp->src_socket = src_socket;
-               error = zip_handle_getmyzone(ifID, *mp);
-               gbuf_freel(*mp);
-               goto exit_ddp_output;
-       }
-       /*
-        * find out the interface on which the packet should go out
-        */
-       TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
-               if ((ifID->ifThisNode.s_net == dst_net) || (dst_net == 0))
-                       /* the message is either going out (i) on the same 
-                        * NETWORK in case of LocalTalk, or (ii) on the same
-                        * CABLE in case of Extended AppleTalk (EtherTalk).
-                        */
-                       break;
-
-               if ((ifID->ifThisCableStart <= dst_net) &&
-                   (ifID->ifThisCableEnd   >= dst_net)
-                  )
-                       /* We're on EtherTalk and the message is going out to 
-                        * some other network on the same cable.
-                        */
-                       break;
-               
-               if (ARouterIf == NULL && ATALK_VALUE(ifID->ifARouter))
-                       ARouterIf = ifID;
-       }
-       dPrintf(D_M_DDP_LOW, D_L_USR1,
-                       ("ddp_output: after search ifid:0x%x %s ifID_home:0x%x\n",
-                       (u_int)ifID, ifID ? ifID->ifName : "",
-                       (u_int)ifID_home));
-
-       if (ifID) {
-               /* located the interface where the packet should
-                * go.... the "first-hop" destination address
-                * must be the same as real destination address.
-                */
-               addr_type = DIRECT_ADDR;
-       } else {
-               /* no, the destination network number does
-                * not match known network numbers.  If we have
-                * heard from this network recently, BRT table
-                * may have address of a router we could use!
-                */
-               if (!MULTIPORT_MODE) {
-                       BRT_LOOK (brt, dst_net);
-                       if (brt) {
-                               /* Bingo... BRT has an entry for this network. 
-                                * Use the link address as is.
-                                */
-                               dPrintf(D_M_DDP, D_L_VERBOSE,
-                                       ("Found BRT entry to send to net 0x%x", dst_net));
-                               at_ddp_stats.xmit_BRT_used++;
-                               addr_type = BRT_ENTRY;
-                               ifID = brt->ifID;
-                       } else {
-                               /* No BRT entry available for dest network... do we 
-                                * know of any router at all??
-                                */
-                               if ((ifID = ARouterIf) != NULL)
-                                       addr_type = BRIDGE_ADDR;
-                               else {
-                               dPrintf(D_M_DDP, D_L_WARNING,
-                                               ("Found no interface to send pkt"));
-                                       at_ddp_stats.xmit_bad_addr++;
-                                       error = ENETUNREACH;
-                                       gbuf_freel(*mp);
-                                       goto exit_ddp_output;
-                               }
-                       }
-               }
-               else { /* We are in multiport mode,  so we can bypass all the rest 
-                       * and directly ask for the routing of the packet
-                       */ 
-                       at_ddp_stats.xmit_BRT_used++;
-
-                       ifID = ifID_home;
-                       if (!src_addr_included) {
-                         ddp->src_node = ifID->ifThisNode.s_node;
-                         NET_ASSIGN(ddp->src_net, ifID->ifThisNode.s_net); 
-                       }
-                       ddp->src_socket = src_socket;
-                       routing_needed(*mp, ifID, TRUE);
-
-                       goto exit_ddp_output;
-               }
-       }
-       /* by the time we land here, we know the interface on 
-        * which this packet is going out....  ifID.  
-        */
-       if (ifID->ifState == LAP_OFFLINE) {
-               gbuf_freel(*mp);
-               goto exit_ddp_output;
-       }               
-       
-       switch (addr_type) {
-               case DIRECT_ADDR :
-/*
-                       at_dest.atalk_unused = 0;
-*/
-                       NET_ASSIGN(at_dest.atalk_net, dst_net);
-                       at_dest.atalk_node = ddp->dst_node;
-                       addr_flag = AT_ADDR;
-                       addr = (char *)&at_dest;
-                       break;
-               case BRT_ENTRY :
-                       addr_flag = ET_ADDR;
-                       addr = (char *)&brt->et_addr;
-                       break;
-               case BRIDGE_ADDR :
-                       NET_ASSIGN(at_dest.atalk_net, ifID->ifARouter.s_net);
-                       at_dest.atalk_node = ifID->ifARouter.s_node;
-                       addr_flag = AT_ADDR;
-                       addr = (char *)&at_dest;
-                       break;
-
-       }
-       /* Irrespective of the interface on which 
-        * the packet is going out, we always put the 
-        * same source address on the packet (unless multihoming mode).
-        */
-       if (MULTIHOME_MODE) {
-               if (!src_addr_included) {
-                       ddp->src_node = ifID->ifThisNode.s_node;
-                       NET_ASSIGN(ddp->src_net, ifID->ifThisNode.s_net); 
-               }
-       }
-       else {
-               ddp->src_node = ifID_home->ifThisNode.s_node;
-               NET_ASSIGN(ddp->src_net, ifID_home->ifThisNode.s_net);
-       }
-       ddp->src_socket = src_socket;
-
-       dPrintf(D_M_DDP_LOW, D_L_OUTPUT,
-               ("ddp_output: going out to %d:%d skt%d on %s\n",
-               dst_net, ddp->dst_node, ddp->dst_socket, ifID->ifName));
-
-       fillin_pkt_chain(*mp);
-
-       { /* begin block */
-       struct  etalk_addr      dest_addr;
-       struct  atalk_addr      dest_at_addr;
-       
-       loop = TRUE;            /* flag to aarp to loopback (default) */
-
-       m = *mp;
-
-       /* the incoming frame is of the form {flag, address, ddp...}
-        * where "flag" indicates whether the address is an 802.3
-        * (link) address, or an appletalk address.  If it's an
-        * 802.3 address, the packet can just go out to the network
-        * through PAT, if it's an appletalk address, AT->802.3 address
-        * resolution needs to be done.
-        * If 802.3 address is known, strip off the flag and 802.3
-        * address, and prepend 802.2 and 802.3 headers.
-        */
-       
-       if (addr == NULL) {
-               addr_flag = *(u_char *)gbuf_rptr(m);
-               gbuf_rinc(m,1);
-       }
-       
-       switch (addr_flag) {
-       case AT_ADDR_NO_LOOP :
-               loop = FALSE;
-               /* pass thru */
-       case AT_ADDR :
-               if (addr == NULL) {
-                   dest_at_addr = *(struct atalk_addr *)gbuf_rptr(m);
-                   gbuf_rinc(m,sizeof(struct atalk_addr));
-               } else
-                   dest_at_addr = *(struct atalk_addr *)addr;
-               break;
-       case ET_ADDR :
-               if (addr == NULL) {
-                 dest_addr = *(struct etalk_addr *)gbuf_rptr(m);
-                 gbuf_rinc(m,sizeof(struct etalk_addr));
-               } else
-                 dest_addr = *(struct etalk_addr *)addr;
-               break;
-       default :
-               dPrintf(D_M_DDP_LOW,D_L_ERROR,
-                   ("ddp_output: Unknown addr_flag = 0x%x\n", addr_flag));
-               gbuf_freel(m);          /* unknown address type, chuck it */
-               goto exit_ddp_output;
-        }
-
-       m = gbuf_strip(m);
-
-       /* At this point, rptr points to ddp header for sure */
-       if (ifID->ifState == LAP_ONLINE_FOR_ZIP) {
-               /* see if this is a ZIP packet that we need
-                * to let through even though network is
-                * not yet alive!!
-                */
-               if (zip_type_packet(m) == 0) {
-                       gbuf_freel(m);
-                       goto exit_ddp_output;
-               }
-       }
-       
-       ifID->stats.xmit_packets++;
-       ifID->stats.xmit_bytes += gbuf_msgsize(m);
-       snmpStats.dd_outLong++;
-       
-       switch (addr_flag) {
-       case AT_ADDR_NO_LOOP :
-       case AT_ADDR :
-           /*
-            * we don't want elap to be looking into ddp header, so
-            * it doesn't know net#, consequently can't do 
-            * AMT_LOOKUP.  That task left to aarp now.
-            */
-           aarp_send_data(m,ifID, &dest_at_addr, loop);
-           break;
-       case ET_ADDR :
-           pat_output(ifID, m, (unsigned char *)&dest_addr, 0);
-           break;
-        }
-       } /* end block */
- exit_ddp_output:
-       KERNEL_DEBUG(DBG_AT_DDP_OUTPUT | DBG_FUNC_END, 0,
-                    error, 0, 0, 0);
-       return(error);
-} /* ddp_output */
-
-void ddp_input(mp, ifID)
-     register gbuf_t   *mp;
-     register at_ifaddr_t *ifID;
-{
-       register at_ddp_t *ddp;         /* DDP header */
-       register int       msgsize;
-       register at_socket socket;
-       register int       len;
-       register at_net_al dst_net;
-
-       KERNEL_DEBUG(DBG_AT_DDP_INPUT | DBG_FUNC_START, 0,
-                    ifID, mp, gbuf_len(mp),0);
-
-       /* Makes sure we know the default interface before starting to
-        * accept incomming packets. If we don't we may end up with a
-        * null ifID_table[0] and have impredicable results (specially
-        * in router mode. This is a transitory state (because we can
-        * begin to receive packet while we're not completly set up yet.
-        */
-
-       if (ifID_home == (at_ifaddr_t *)NULL) {
-               dPrintf(D_M_DDP, D_L_ERROR,
-                       ("dropped incoming packet ifID_home not set yet\n"));
-               gbuf_freem(mp);
-               goto out; /* return */
-       }
-
-       /*
-        * if a DDP packet has been broadcast, we're going to get a copy of
-        * it here; if it originated at user level via a write on a DDP 
-        * socket; when it gets here, the first block in the chain will be
-        * empty since it only contained the lap level header which will be
-        * stripped in the lap level immediately below ddp
-        */
-
-       if ((mp = (gbuf_t *)ddp_compress_msg(mp)) == NULL) {
-               dPrintf(D_M_DDP, D_L_ERROR,
-                       ("dropped short incoming ET packet (len %d)", 0));
-               snmpStats.dd_inTotal++;
-               at_ddp_stats.rcv_bad_length++;
-               goto out; /* return; */
-       }
-       msgsize = gbuf_msgsize(mp);
-
-       at_ddp_stats.rcv_bytes += msgsize;
-       at_ddp_stats.rcv_packets++;
-
-       /* if the interface pointer is 0, the packet has been 
-        * looped back by 'write' half of DDP.  It is of the
-        * form {extended ddp,...}.  The packet is meant to go
-        * up to some socket on the same node.
-        */
-       if (!ifID)                      /* if loop back is specified */
-               ifID = ifID_home;       /* that means the home port */
-
-       /* the incoming datagram has extended DDP header and is of 
-        * the form {ddp,...}.
-        */
-       if (msgsize < DDP_X_HDR_SIZE) {
-               dPrintf(D_M_DDP, D_L_ERROR,
-                       ("dropped short incoming ET packet (len %d)", msgsize));
-               at_ddp_stats.rcv_bad_length++;
-               gbuf_freem(mp);
-               goto out; /* return; */
-       }
-       /*
-        * At this point, the message is always of the form
-        * {extended ddp, ... }.
-        */
-       ddp = (at_ddp_t *)gbuf_rptr(mp);
-       len = DDPLEN_VALUE(ddp);
-
-       if (msgsize != len) {
-               if (msgsize > len) {
-                       if (len < DDP_X_HDR_SIZE) {
-                               dPrintf(D_M_DDP, D_L_ERROR,
-                                      ("Length problems, ddp length %d, buffer length %d",
-                                      len, msgsize));
-                               snmpStats.dd_tooLong++;
-                               at_ddp_stats.rcv_bad_length++;
-                               gbuf_freem(mp);
-                               goto out; /* return; */
-                       }
-                       /*
-                        * shave off the extra bytes from the end of message
-                        */
-                       mp = ddp_adjmsg(mp, -(msgsize - len)) ? mp : 0;
-                       if (mp == 0)
-                               goto out; /* return; */
-               } else {
-                       dPrintf(D_M_DDP, D_L_ERROR,
-                               ("Length problems, ddp length %d, buffer length %d",
-                               len, msgsize));
-                               snmpStats.dd_tooShort++;
-                       at_ddp_stats.rcv_bad_length++;
-                       gbuf_freem(mp);
-                       goto out; /* return; */
-               }
-       }
-       socket = ddp->dst_socket;
-
-       /*
-        * We want everything in router mode, specially socket 254 for nbp so we need
-        * to bypass this test when we are a router.
-        */
-
-       if (!MULTIPORT_MODE && (socket > DDP_SOCKET_LAST ||
-                        socket < DDP_SOCKET_1st_RESERVED)) {
-               dPrintf(D_M_DDP, D_L_WARNING,
-                       ("Bad dst socket on incoming packet (0x%x)",
-                       ddp->dst_socket));
-               at_ddp_stats.rcv_bad_socket++;
-               gbuf_freem(mp);
-               goto out; /* return; */
-       }
-       /*
-        * if the checksum is true, then upstream wants us to calc
-        */
-       if (UAS_VALUE(ddp->checksum) && 
-           (UAS_VALUE_NTOH(ddp->checksum) != ddp_checksum(mp, 4))) {
-               dPrintf(D_M_DDP, D_L_WARNING,
-                       ("Checksum error on incoming pkt, calc 0x%x, exp 0x%x",
-                       ddp_checksum(mp, 4), UAS_VALUE_NTOH(ddp->checksum)));
-               snmpStats.dd_checkSum++;
-               at_ddp_stats.rcv_bad_checksum++;
-               gbuf_freem(mp);
-               goto out; /* return; */
-       }
-
-/*############### routing input checking */
-
-/* Router mode special: we send "up-stack" packets for this node or coming from any
- * other ports, but for the reserved atalk sockets (RTMP, ZIP, NBP [and EP])
- * BTW, the way we know it's for the router and not the home port is that the
- * MAC (ethernet) address is always the one of the interface we're on, but
- * the AppleTalk address must be the one of the home port. If it's a multicast
- * or another AppleTalk address, this is the router job's to figure out where it's
- * going to go.
- */
-       /* *** a duplicate should be sent to any other client that is listening
-          for packets of this type on a raw DDP socket *** */
-       if (ddp_handler[socket].func) {
-               dPrintf(D_M_DDP,D_L_INPUT,
-                       ("ddp_input: skt %u hdnlr:0x%p\n",
-                        (u_int) socket, ddp_handler[socket].func));
-               pktsHome++;
-               snmpStats.dd_inLocal++;
-
-               (*ddp_handler[socket].func)(mp, ifID);
-               goto out; /* return; */
-       }
-       dst_net = NET_VALUE(ddp->dst_net);
-       if (
-           /* exact match */
-           forUs(ddp) ||
-           /* any node, wildcard or matching net */
-           ((ddp->dst_node == 255) && 
-            (((dst_net >= ifID_home->ifThisCableStart) &&
-              (dst_net <= ifID_home->ifThisCableEnd)) || 
-             dst_net == 0)) ||
-           /* this node is not online yet(?) */
-           (ifID->ifRoutingState < PORT_ONLINE)
-           ) { 
-               gref_t   *gref;
-               pktsHome++;
-               snmpStats.dd_inLocal++;
-
-               if (ddp->type == DDP_ATP) {
-                 if (atp_inputQ[socket] && (atp_inputQ[socket] != (gref_t *)1)) {
-                       /* if there's an ATP pcb */
-                       atp_input(mp);
-                       goto out; /* return; */
-                 }
-               } else if (ddp->type == DDP_ADSP) {
-                 if (adsp_inputQ[socket]) {
-                       /* if there's an ADSP pcb */
-                       adsp_input(mp);
-                       goto out; /* return; */
-                 }
-               }
-
-               /* otherwise look for a DDP pcb;
-                  ATP / raw-DDP and ADSP / raw-DDP are possible */
-               for (gref = ddp_head.atpcb_next; gref != &ddp_head; 
-                      gref = gref->atpcb_next)
-                   if (gref->lport == socket &&
-                       (gref->ddptype == 0 || gref->ddptype == ddp->type)) {
-                                       dPrintf(D_M_DDP, D_L_INPUT, 
-                                       ("ddp_input: streamq, skt %d\n", socket));
-                       if (gref->atpcb_socket) {
-                               struct sockaddr_at ddp_in;
-                               ddp_in.sat_len = sizeof(ddp_in);
-                               ddp_in.sat_family = AF_APPLETALK;
-                               ddp_in.sat_addr.s_net = NET_VALUE(ddp->src_net);
-                               ddp_in.sat_addr.s_node = ddp->src_node;
-                               ddp_in.sat_port = ddp->src_socket;
-
-                               /* strip off DDP header if so indicated by
-                                  sockopt */
-                               if (gref->ddp_flags & DDPFLG_STRIPHDR) {
-                                       mp = m_pullup((struct mbuf *)mp,
-                                                           DDP_X_HDR_SIZE);
-                                       if (mp) {
-                                               gbuf_rinc(mp, DDP_X_HDR_SIZE);
-                                       } else { 
-                                         /* this should never happen because 
-                                            msgsize was checked earlier */
-                                               at_ddp_stats.rcv_bad_length++;
-                                               goto out; /* return */
-                                       }
-                               }
-
-                               if (sbappendaddr(&((gref->atpcb_socket)->so_rcv), 
-                                                (struct sockaddr *)&ddp_in,
-                                                mp, 0, NULL) != 0) {
-                                       sorwakeup(gref->atpcb_socket);
-                                }
-                       } else {
-                               atalk_putnext(gref, mp);
-                       }
-                       goto out; /* return */
-                   } 
-
-               at_ddp_stats.rcv_bad_socket++;
-               gbuf_freem(mp);
-               snmpStats.dd_noHandler++;
-               dPrintf(D_M_DDP, D_L_WARNING, 
-                       ("ddp_input: dropped pkt for socket %d\n", socket));
-       } else { 
-               dPrintf(D_M_DDP, D_L_ROUTING, 
-                       ("ddp_input: routing_needed from  port=%d sock=%d\n",
-                        ifID->ifPort, ddp->dst_socket));
-
-               snmpStats.dd_fwdReq++;
-               if (((pktsIn-pktsHome+200) >= RouterMix) && ((++pktsDropped % 5) == 0)) {
-                       at_ddp_stats.rcv_dropped_nobuf++;
-                       gbuf_freem(mp);
-               }
-               else {
-                       routing_needed(mp, ifID, FALSE);
-               }
-       }
-out:
-       KERNEL_DEBUG(DBG_AT_DDP_INPUT | DBG_FUNC_END, 0,0,0,0,0);
-} /* ddp_input */
-
-
-/* 
- * ddp_router_output()
- *
- * Remarks : 
- *     This is a modified version of ddp_output for router use.
- *     The main difference is that the interface on which the packet needs
- *     to be sent is specified and a *destination* AppleTalk address is passed
- *     as an argument, this address may or may not be the same as the destination
- *     address found in the ddp packet... This is the trick about routing, the
- *     AppleTalk destination of the packet may not be the same as the Enet address
- *     we send the packet too (ie, we may pass the baby to another router).    
- *
- */
-int ddp_router_output(mp, ifID, addr_type, router_net, router_node, enet_addr)
-     gbuf_t    *mp;
-     at_ifaddr_t *ifID;
-     int addr_type;
-     at_net_al router_net;
-     at_node router_node;
-     etalk_addr_t *enet_addr;
-{
-       register at_ddp_t       *ddp;
-       struct   atalk_addr     at_dest;
-       int             addr_flag = 0;
-       char    *addr = NULL;
-       register gbuf_t *m;
-
-       if (!ifID) {
-               dPrintf(D_M_DDP, D_L_WARNING, ("BAD BAD ifID\n"));
-               gbuf_freel(mp);
-               return(EPROTOTYPE);
-       }
-       ddp = (at_ddp_t *)gbuf_rptr(mp);
-
-#ifdef AURP_SUPPORT
-       if (ifID->ifFlags & AT_IFF_AURP) { /* AURP link? */
-               if (ddp_AURPsendx) {
-                       fillin_pkt_chain(mp);
-                       if (router_node == 255)
-                               router_node = 0;
-                       ddp_AURPsendx(AURPCODE_DATAPKT, mp, router_node);
-                       return 0;
-               } else {
-                       gbuf_freel(mp);
-                       return EPROTOTYPE;
-               }
-       }
-#endif
-
-       /* keep some of the tests for now ####### */
-
-       if (gbuf_msgsize(mp) > DDP_DATAGRAM_SIZE) {
-               /* the packet is too large */
-               dPrintf(D_M_DDP, D_L_WARNING,
-                       ("ddp_router_output: Packet too large size=%d\n",
-                        gbuf_msgsize(mp)));
-               gbuf_freel(mp);
-               return (EMSGSIZE);
-       }
-
-       switch (addr_type) {
-
-               case AT_ADDR :
-
-                       /*
-                        * Check for packet destined to the home stack
-                        */
-
-                 if    ((ddp->dst_node == ifID->ifThisNode.s_node) &&
-                        (NET_VALUE(ddp->dst_net) == ifID->ifThisNode.s_net)) {
-                       dPrintf(D_M_DDP_LOW, D_L_ROUTING, 
-                               ("ddp_r_output: sending back home from port=%d socket=%d\n",
-                                ifID->ifPort, ddp->dst_socket));
-                       
-                       UAS_ASSIGN(ddp->checksum, 0);
-                       ddp_input(mp, ifID);    
-                       return(0);
-                 }
-
-                 NET_ASSIGN(at_dest.atalk_net, router_net);
-                 at_dest.atalk_node = router_node;
-
-                 addr_flag = AT_ADDR_NO_LOOP;
-                 addr = (char *)&at_dest;
-                 dPrintf(D_M_DDP_LOW, D_L_ROUTING_AT,
-                         ("ddp_r_output: AT_ADDR out port=%d net %d:%d via rte %d:%d",
-                          ifID->ifPort, NET_VALUE(ddp->dst_net), ddp->dst_node, router_net,
-                          router_node));
-                 break;
-
-               case ET_ADDR :
-                 addr_flag = ET_ADDR;
-                 addr = (char *)enet_addr;
-                 dPrintf(D_M_DDP_LOW, D_L_ROUTING,
-                         ("ddp_r_output: ET_ADDR out port=%d net %d:%d\n",
-                          ifID->ifPort, NET_VALUE(ddp->dst_net), ddp->dst_node));
-                 break;
-               }
-
-       if (ifID->ifState == LAP_OFFLINE) {
-             gbuf_freel(mp);
-             return 0;
-       }
-       
-       fillin_pkt_chain(mp);
-
-       { /* begin block */
-           struct      etalk_addr      dest_addr;
-           struct      atalk_addr      dest_at_addr;
-           int loop = TRUE;            /* flag to aarp to loopback (default) */
-
-           m = mp;
-
-           /* the incoming frame is of the form {flag, address, ddp...}
-            * where "flag" indicates whether the address is an 802.3
-            * (link) address, or an appletalk address.  If it's an
-            * 802.3 address, the packet can just go out to the network
-            * through PAT, if it's an appletalk address, AT->802.3 address
-            * resolution needs to be done.
-            * If 802.3 address is known, strip off the flag and 802.3
-            * address, and prepend 802.2 and 802.3 headers.
-            */
-       
-           if (addr == NULL) {
-               addr_flag = *(u_char *)gbuf_rptr(m);
-               gbuf_rinc(m,1);
-           }
-       
-           switch (addr_flag) {
-           case AT_ADDR_NO_LOOP :
-             loop = FALSE;
-             /* pass thru */
-           case AT_ADDR :
-             if (addr == NULL) {
-               dest_at_addr = *(struct atalk_addr *)gbuf_rptr(m);
-               gbuf_rinc(m,sizeof(struct atalk_addr));
-             } else
-               dest_at_addr = *(struct atalk_addr *)addr;
-             break;
-           case ET_ADDR :
-             if (addr == NULL) {
-               dest_addr = *(struct etalk_addr *)gbuf_rptr(m);
-               gbuf_rinc(m,sizeof(struct etalk_addr));
-             } else
-               dest_addr = *(struct etalk_addr *)addr;
-             break;
-           default :
-             dPrintf(D_M_DDP_LOW,D_L_ERROR,
-                     ("ddp_router_output: Unknown addr_flag = 0x%x\n", addr_flag));
-
-             gbuf_freel(m);            /* unknown address type, chuck it */
-             return 0;
-           }
-
-           m = gbuf_strip(m);
-
-           /* At this point, rptr points to ddp header for sure */
-           if (ifID->ifState == LAP_ONLINE_FOR_ZIP) {
-                     /* see if this is a ZIP packet that we need
-                      * to let through even though network is
-                      * not yet alive!!
-                      */
-                     if (zip_type_packet(m) == 0) {
-                       gbuf_freel(m);
-                       return 0;
-                     }
-           }
-       
-           ifID->stats.xmit_packets++;
-           ifID->stats.xmit_bytes += gbuf_msgsize(m);
-           snmpStats.dd_outLong++;
-           
-           switch (addr_flag) {
-           case AT_ADDR_NO_LOOP :
-           case AT_ADDR :
-             /*
-              * we don't want elap to be looking into ddp header, so
-              * it doesn't know net#, consequently can't do 
-              * AMT_LOOKUP.  That task left to aarp now.
-              */
-             aarp_send_data(m,ifID,&dest_at_addr, loop);
-             break;
-           case ET_ADDR :
-             pat_output(ifID, m, (unsigned char *)&dest_addr, 0);
-             break;
-           }
-       } /* end block */
-
-       return(0);
-} /* ddp_router_output */
-
-/*****************************************/
-
-#ifdef AURP_SUPPORT
-
-void rt_delete(NetStop, NetStart)
-       unsigned short NetStop;
-       unsigned short NetStart;
-{
-       RT_entry *found;
-
-       if ((found = rt_bdelete(NetStop, NetStart)) != 0) {
-               bzero(found, sizeof(RT_entry));
-               found->right = RT_table_freelist;
-               RT_table_freelist = found;
-       }
-}
-
-int ddp_AURPfuncx(code, param, node)
-       int code;
-       void *param;
-       unsigned char node;
-{
-       at_ifaddr_t *ifID;
-       int k;
-
-       switch (code) {
-       case AURPCODE_DATAPKT: /* data packet */
-               if (aurp_ifID) {
-                       dPrintf(D_M_DDP, D_L_TRACE, ("ddp_AURPfuncx: data, 0x%x, %d\n",
-                               (u_int) aurp_ifID, node));
-
-                       ddp_input((gbuf_t *)param, aurp_ifID);
-               } else
-                       gbuf_freem((gbuf_t *)param);
-               break;
-
-       case AURPCODE_REG: /* register/deregister */
-               if (!ROUTING_MODE)
-                       return -1;
-               ddp_AURPsendx = (void(*)())param;
-
-               if (param) {
-                       /* register AURP callback function */
-                       if (aurp_ifID)
-                               return 0;
-                       for (k=(IFID_HOME+1); k < IF_TOTAL_MAX; k++) {
-                               if (ifID_table[k] == 0) {
-                                       aurp_ifID = &at_interfaces[k];
-                                       aurp_ifID->ifFlags = RTR_XNET_PORT;
-                                       ddp_add_if(aurp_ifID);
-                                       aurp_ifID->ifState = LAP_ONLINE;
-                                       aurp_ifID->ifRoutingState = PORT_ONLINE;
-                                       dPrintf(D_M_DDP, D_L_TRACE,
-                                               ("ddp_AURPfuncx: on, 0x%x\n",
-                                               (u_int) aurp_ifID));
-
-                                       ddp_AURPsendx(AURPCODE_DEBUGINFO,
-                                                       &dbgBits, aurp_ifID->ifPort);
-                                       return 0;
-                               }
-                       }
-                       return -1;
-
-               } else {
-                       /* deregister AURP callback function */
-                       if (aurp_ifID) {
-                               rtmp_purge(aurp_ifID);
-                               ddp_rem_if(aurp_ifID);
-                               aurp_ifID->ifState = LAP_OFFLINE;
-                               aurp_ifID->ifRoutingState = PORT_OFFLINE;
-                               dPrintf(D_M_DDP, D_L_TRACE,
-                                       ("ddp_AURPfuncx: off, 0x%x\n", (u_int) aurp_ifID));
-                               aurp_ifID = 0;
-                       }
-               }
-               break;
-
-       case AURPCODE_AURPPROTO: /* proto type - AURP */
-               if (aurp_ifID) {
-                       aurp_ifID->ifFlags |= AT_IFF_AURP;
-               }
-               break;
-       }
-
-       return 0;
-}
-#endif
-
-/* checks to see if address of packet is for one of our interfaces
-   returns *ifID if it's for us, NULL if not
-*/
-at_ifaddr_t *forUs(ddp)
-     register at_ddp_t *ddp;
-{
-       at_ifaddr_t *ifID;
-
-       TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) {
-               if ((ddp->dst_node == ifID->ifThisNode.s_node) &&
-                   (NET_VALUE(ddp->dst_net) ==  ifID->ifThisNode.s_net)
-                  ) {
-                       dPrintf(D_M_DDP_LOW, D_L_ROUTING,
-                               ("pkt was for port %d\n", ifID->ifPort));
-
-                       return(ifID);
-               }
-       }
-
-       return((at_ifaddr_t *)NULL);
-} /* forUs */