X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/bd504ef0e0b883cdd7917b73b3574eb9ce669905..39236c6e673c41db228275375ab7fdb0f837b292:/bsd/netat/ddp_r_rtmp.c diff --git a/bsd/netat/ddp_r_rtmp.c b/bsd/netat/ddp_r_rtmp.c deleted file mode 100644 index bc21d5b40..000000000 --- a/bsd/netat/ddp_r_rtmp.c +++ /dev/null @@ -1,1659 +0,0 @@ -/* - * Copyright (c) 1994, 1996-2000 Apple Computer, 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@ - */ -/*-------------------------------------------------------------------------- - * Router RTMP protocol functions: - * - * This file contains Routing specifics to handle RTMP packets and - * the maintenance of the routing table through.... - * - * The entry point for the rtmp input in ddp is valid only when we're - * running in router mode. - * - * - * 0.01 03/22/94 Laurent Dumont Creation - * 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. - * - *------------------------------------------------------------------------- - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -extern void (*ddp_AURPsendx)(void); -extern at_ifaddr_t *aurp_ifID; -extern at_ifaddr_t *ifID_table[]; -extern at_ifaddr_t *ifID_home; - - -int rtmp_router_start(at_kern_err_t *); -void rtmp_router_start_tmo(void *); - - - -static at_kern_err_t ke; - /* Used to record error discovered in rtmp_update() */ - -void rtmp_timeout(void *arg); -void rtmp_send_port(at_ifaddr_t *); -void rtmp_send_port_locked(void *); -void rtmp_dropper(void *); -static void rtmp_update(at_ifaddr_t *, at_rtmp *, short); -static void rtmp_request(at_ifaddr_t *, at_ddp_t *); -int elap_online3(at_ifaddr_t *); - -extern short ErrorRTMPoverflow, ErrorZIPoverflow; -extern lck_mtx_t * atalk_mutex; - -extern int pktsIn, pktsOut, pktsDropped, pktsHome; - - -/* - * rtmp_router_input: function called by DDP (in router mode) to handle - * all incoming RTMP packets. Listen to the RTMP socket - * for all the connected ports. - * Switch to the relevant rtmp functions. - */ - -void rtmp_router_input(mp, ifID) - register gbuf_t *mp; - register at_ifaddr_t *ifID; -{ - register at_ddp_t *ddp = (at_ddp_t *)gbuf_rptr(mp); - /* NOTE: there is an assumption here that the - * DATA follows the header. */ - - register at_net_al OurNet; - register at_node OurNode; - register at_net_al DstNet; - register at_node DstNode; - short tuples; - RT_entry *Entry; - - if (!ifID || (ifID->ifRoutingState < PORT_ACTIVATING)) { - gbuf_freem(mp); - return; - } - - - OurNet = ifID->ifThisNode.s_net; - OurNode = ifID->ifThisNode.s_node; - - - if (gbuf_type(mp) != MSG_DATA) { - - /* If this is a M_ERROR message, DDP is shutting down, - * nothing to do here...If it's something else, we don't - * understand what it is - */ - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_router_input: Not an M_DATA type\n")); - gbuf_freem(mp); - return; - } - - DstNet = NET_VALUE(ddp->dst_net); - DstNode = ddp->dst_node; - - /* check the kind of RTMP packet we received */ - - switch (ddp->type) { - - case DDP_RTMP: - - tuples = gbuf_len(mp) - DDP_X_HDR_SIZE - RTMP_IDLENGTH; - /* - * we need to make sure that the size of 'tuples' is - * not less than or equal to 0 due to a bad packet - */ - if (tuples <= 0) { - gbuf_freem(mp); - break; - } - - if (tuples % 3) {/* not a valid RTMP data packet */ - gbuf_freem(mp); - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_input: bad number of tuple in RTMP packet\n")); - return; - } - - tuples = tuples / 3; - - rtmp_update(ifID, (at_rtmp *)ddp->data, tuples); - gbuf_freem(mp); - - break; - - case DDP_RTMP_REQ: - - /* we should treat requests a bit differently. - * - if the request if not for the port, route it and also respond - * for this port if not locally connected. - * - if the request for this port, then just respond to it. - */ - - if (!ROUTING_MODE) { - gbuf_freem(mp); - return; - } - if (DstNode == 255) { - if (((DstNet >= CableStart) && (DstNet <= CableStop)) || - DstNet == 0) { - rtmp_request(ifID, ddp); - gbuf_freem(mp); - return; - } - else { - /* check if directly connected port */ - if ((Entry = rt_blookup(DstNet)) && - (Entry->NetDist == 0)) { - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_router_input: request for %d.%d, port %d\n", - DstNet, DstNode, Entry->NetPort)); - rtmp_request(ifID_table[Entry->NetPort], ddp); - gbuf_freem(mp); - return; - } - else { - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_router_input: RTMP packet received for %d.%d, also forward\n", - NET_VALUE(ddp->dst_net),ddp->dst_node)); - routing_needed(mp, ifID, TRUE); - return; - } - } - } - else { - - if ((DstNode == OurNode) && (DstNet == OurNet)) { - rtmp_request(ifID, ddp); - gbuf_freem(mp); - return; - } - else { - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_router_input: RTMP packet received for %d.%d, forward\n", - NET_VALUE(ddp->dst_net), ddp->dst_node)); - routing_needed(mp, ifID, TRUE); - } - } - - break; - - default: - - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_input: RTMP packet type=%d, route it\n", ddp->type)); - routing_needed(mp, ifID, TRUE); - break; - - } -} /* rtmp_router_input */ - -/* - * rtmp_update: - * - */ - -static void rtmp_update(ifID, rtmp, tuple_nb) - register at_ifaddr_t *ifID; - register at_rtmp *rtmp; - register short tuple_nb; -{ - register int PortFlags = ifID->ifFlags; - register at_rtmp_tuple *FirstTuple = (at_rtmp_tuple *)&rtmp->at_rtmp_id[1]; - register at_rtmp_tuple *SecondTuple = (at_rtmp_tuple *)&rtmp->at_rtmp_id[4]; - RT_entry NewRoute, *CurrentRoute; - register u_char SenderNodeID = rtmp->at_rtmp_id[0]; - char *TuplePtr; - short state; - - bzero(&NewRoute, sizeof(RT_entry)); - - /* Make sure this an AppleTalk node sending us the RTMP packet */ - - if (rtmp->at_rtmp_id_length != 8) { - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_update : RTMP ID not as expected Net=%d L=x%x\n", - NET_VALUE(rtmp->at_rtmp_this_net), rtmp->at_rtmp_id_length)); - return; - } - - /* - * If the port is activating, only take the Network range from the - * the RTMP packet received. - * Check if there is a conflict with our seed infos. - */ - - if (ifID->ifRoutingState == PORT_ACTIVATING) { - if (PortFlags & RTR_XNET_PORT) { - if ((PortFlags & RTR_SEED_PORT) && - ((CableStart != TUPLENET(FirstTuple)) || - (CableStop != TUPLENET(SecondTuple)))) { - ifID->ifRoutingState = PORT_ERR_SEED; - ke.error = KE_CONF_SEED_RNG; - ke.port1 = ifID->ifPort; - strlcpy(ke.name1, ifID->ifName, sizeof(ke.name1)); - ke.net = NET_VALUE(rtmp->at_rtmp_this_net); - ke.node = SenderNodeID; - ke.netr1b = TUPLENET(FirstTuple); - ke.netr1e = TUPLENET(SecondTuple); - ke.netr2b = CableStart; - ke.netr2e = CableStop; - RouterError(ifID->ifPort, ERTR_SEED_CONFLICT); - return; - } - CableStart = TUPLENET(FirstTuple); - CableStop = TUPLENET(SecondTuple); -/* - dPrintf(D_M_RTMP, D_L_INFO, - ("rtmp_update: Port #%d activating, set Cable %d-%d\n", - ifID->ifPort, CableStart, CableStop)); -*/ - } - else { /* non extended cable */ - if ((PortFlags & RTR_SEED_PORT) && - (ifID->ifThisCableEnd != NET_VALUE(rtmp->at_rtmp_this_net))) { - ke.error = KE_CONF_SEED1; - ke.port1 = ifID->ifPort; - strlcpy(ke.name1, ifID->ifName,sizeof(ke.name1)); - ke.net = NET_VALUE(rtmp->at_rtmp_this_net); - ke.node = SenderNodeID; - ke.netr1e = ifID->ifThisCableEnd; - ifID->ifRoutingState = PORT_ERR_SEED; - RouterError(ifID->ifPort, ERTR_SEED_CONFLICT); - return; - } - CableStop = NET_VALUE(rtmp->at_rtmp_this_net); - CableStart = 0; - dPrintf(D_M_RTMP, D_L_INFO, - ("rtmp_update: Port #%d NONX activating, set Cable %d-%d\n", - ifID->ifPort, CableStart, CableStop)); - } - } - - /* - * Perform a few sanity checks on the received RTMP data packet - */ - - if ((PortFlags & RTR_XNET_PORT) && (tuple_nb >= 2)) { - - /* The first tuple must be extended */ - - if (! TUPLERANGE(FirstTuple)) { - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_update: bad range value in 1st tuple =%d\n", - TUPLERANGE(FirstTuple))); - return; - } - - if (PortFlags & RTR_SEED_PORT) - if ((TUPLENET(FirstTuple) != CableStart) || - (TUPLENET(SecondTuple) != CableStop)) { - dPrintf(D_M_RTMP, D_L_WARNING, ("rtmp_update: conflict on Seed Port\n")); - ifID->ifRoutingState = PORT_ERR_CABLER; - ke.error = KE_CONF_SEED_NODE; - ke.port1 = ifID->ifPort; - strlcpy(ke.name1, ifID->ifName,sizeof(ke.name1)); - ke.net = NET_VALUE(rtmp->at_rtmp_this_net); - ke.node = SenderNodeID; - ke.netr1b = TUPLENET(FirstTuple); - ke.netr1e = TUPLENET(SecondTuple); - ke.netr2b = CableStart; - ke.netr2e = CableStop; - RouterError(ifID->ifPort, ERTR_CABLE_CONFLICT); - return; - } - - /* check that the tuple matches the range */ - - if ((TUPLENET(SecondTuple) < TUPLENET(FirstTuple)) || - (TUPLENET(FirstTuple) == 0) || - (TUPLENET(FirstTuple) >= DDP_STARTUP_LOW) || - (TUPLENET(SecondTuple) == 0) || - (TUPLENET(SecondTuple) >= DDP_STARTUP_LOW)) { - - /* - * IS THIS NON-FATAL????? - */ - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_update: STARTUP RANGE!!! 1st %d-%d\n", - TUPLENET(FirstTuple), TUPLENET(SecondTuple))); - ifID->ifRoutingState = PORT_ERR_STARTUP; - ke.error = KE_SEED_STARTUP; - ke.port1 = ifID->ifPort; - strlcpy(ke.name1, ifID->ifName,sizeof(ke.name1)); - ke.net = NET_VALUE(rtmp->at_rtmp_this_net); - ke.node = SenderNodeID; - RouterError(ifID->ifPort, ERTR_CABLE_STARTUP); - return; - } - - if (TUPLEDIST(FirstTuple) != 0) { - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_update: Invalid distance in 1st tuple\n")); - return; - } - - if (rtmp->at_rtmp_id[6] != RTMP_VERSION_NUMBER) { - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_update: Invalid RTMP version = x%x\n", - rtmp->at_rtmp_id[6])); - return; - } - - } - else { /* non extended interface or problem in tuple*/ - - if (PortFlags & RTR_XNET_PORT) { - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_update: invalid number of tuple for X-net\n")); - return; - } - - if (TUPLENET(FirstTuple) == 0) { /* non extended RTMP data */ - - if (rtmp->at_rtmp_id[3] > RTMP_VERSION_NUMBER) { - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_update: Invalid non extended RTMP version\n")); - return; - } - - } - else { - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_update: version 1.0 non Xtended net not supported\n")); - ifID->ifRoutingState = PORT_ERR_BADRTMP; - ke.error = KE_BAD_VER; - ke.rtmp_id = rtmp->at_rtmp_id[6]; - ke.net = NET_VALUE(rtmp->at_rtmp_this_net); - ke.node = SenderNodeID; - RouterError(ifID->ifPort, ERTR_RTMP_BAD_VERSION); - return; - } - } - - NewRoute.NextIRNet = NET_VALUE(rtmp->at_rtmp_this_net); - NewRoute.NextIRNode = SenderNodeID; - NewRoute.NetPort = ifID->ifPort; - - /* - * Process the case where a non-seed port needs to acquire the right - * information. - */ - - if (!(PortFlags & RTR_SEED_PORT) && (ifID->ifRoutingState == PORT_ACTIVATING)) { - dPrintf(D_M_RTMP_LOW, D_L_INFO, - ("rtmp_update: Port# %d, set non seed cable %d-%d\n", - ifID->ifPort, TUPLENET(FirstTuple), TUPLENET(SecondTuple))); - - if (PortFlags & RTR_XNET_PORT) { - NewRoute.NetStart = TUPLENET(FirstTuple); - NewRoute.NetStop = TUPLENET(SecondTuple); - ifID->ifThisCableStart = TUPLENET(FirstTuple); - ifID->ifThisCableEnd = TUPLENET(SecondTuple); - - } - else { - - NewRoute.NetStart = 0; - NewRoute.NetStop = NET_VALUE(rtmp->at_rtmp_this_net); - ifID->ifThisCableStart = NET_VALUE(rtmp->at_rtmp_this_net); - ifID->ifThisCableEnd = NET_VALUE(rtmp->at_rtmp_this_net); - } - /* - * Now, check if we already know this route, or we need to add it - * (or modify it in the table accordingly) - */ - - if ((CurrentRoute = rt_blookup(NewRoute.NetStop)) && - (CurrentRoute->NetStop == NewRoute.NetStop) && - (CurrentRoute->NetStart == NewRoute.NetStart)) { -/*LD 7/31/95 tempo########*/ - if (NewRoute.NetPort != CurrentRoute->NetPort) { - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_update: port# %d, not the port we waited for %d\n", - ifID->ifPort, CurrentRoute->NetPort)); - /* propose to age the entry we know... */ - - state = CurrentRoute->EntryState & 0x0F; - /* if entry has been updated recently, just clear the UPDATED - bit. if bit not set, then we can age the entry */ - if (state) { - if (CurrentRoute->EntryState & RTE_STATE_UPDATED) { - CurrentRoute->EntryState &= ~RTE_STATE_UPDATED; - } - else { - state = state >> 1 ; /* decrement state */ - } - } - CurrentRoute->EntryState = (CurrentRoute->EntryState & 0xF0) | state; - } - } - - else { /* add the new route */ - - dPrintf(D_M_RTMP, D_L_INFO, - ("rtmp_update: P# %d, 1st tuple route not known, add %d-%d\n", - ifID->ifPort, NewRoute.NetStart, NewRoute.NetStop)); - - NewRoute.EntryState = RTE_STATE_GOOD|RTE_STATE_UPDATED; - NewRoute.NetDist = 0; - - if (rt_insert(NewRoute.NetStop, NewRoute.NetStart, 0, - 0, NewRoute.NetDist, NewRoute.NetPort, - NewRoute.EntryState) == (RT_entry *)NULL) - - ErrorRTMPoverflow = 1; - } - - } - - if (ifID->ifRoutingState == PORT_ACTIVATING) { - dPrintf(D_M_RTMP, D_L_INFO, - ("rtmp_update: port activating, ignoring remaining tuples\n")); - return; - } - - /* - * Process all the tuples against our routing table - */ - - TuplePtr = (char *)FirstTuple; - - while (tuple_nb-- > 0) { - - if (TUPLEDIST(TuplePtr) == NOTIFY_N_DIST) { - dPrintf(D_M_RTMP, D_L_INFO, - ("rtmp_update: Port# %d, Tuple with Notify Neighbour\n", - ifID->ifPort)); - NewRoute.NetDist = NOTIFY_N_DIST; - NewRoute.EntryState = RTE_STATE_BAD; - } - else { - NewRoute.NetDist = TUPLEDIST(TuplePtr) + 1; - NewRoute.EntryState = RTE_STATE_GOOD; - NewRoute.EntryState = RTE_STATE_GOOD|RTE_STATE_UPDATED; - } - - - if (TUPLERANGE(TuplePtr)) { /* Extended Tuple */ - - - NewRoute.NetStart = TUPLENET(TuplePtr); - TuplePtr += 3; - NewRoute.NetStop = TUPLENET((TuplePtr)); - TuplePtr += 3; - tuple_nb--; - - if ((NewRoute.NetDist == 0) || - (NewRoute.NetStart == 0) || - (NewRoute.NetStop == 0) || - (NewRoute.NetStop < NewRoute.NetStart) || - (NewRoute.NetStart >= DDP_STARTUP_LOW) || - (NewRoute.NetStop >= DDP_STARTUP_LOW)) { - - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_update: P# %d, non valid xtuple received [%d-%d]\n", - ifID->ifPort, NewRoute.NetStart, NewRoute.NetStop)); - - continue; - } - - } - else { /* Non Extended Tuple */ - - NewRoute.NetStart = 0; - NewRoute.NetStop = TUPLENET(TuplePtr); - - TuplePtr += 3; - - if ((NewRoute.NetDist == 0) || - (NewRoute.NetStop == 0) || - (NewRoute.NetStop >= DDP_STARTUP_LOW)) { - - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_update: P# %d, non valid tuple received [%d]\n", - ifID->ifPort, NewRoute.NetStop)); - - continue; - } - } - - if ((CurrentRoute = rt_blookup(NewRoute.NetStop))) { - /* found something... */ - - if (NewRoute.NetDist < 16 || - NewRoute.NetDist == NOTIFY_N_DIST ) { - - /* - * Check if the definition of the route changed - */ - - if (NewRoute.NetStop != CurrentRoute->NetStop || - NewRoute.NetStart != CurrentRoute->NetStart) { - - if (NewRoute.NetStop == CurrentRoute->NetStop && - NewRoute.NetStop == CurrentRoute->NetStart && - NewRoute.NetStart == 0) - - NewRoute.NetStart = NewRoute.NetStop; - - else if (NewRoute.NetStop == CurrentRoute->NetStop && - NewRoute.NetStart == NewRoute.NetStop && - CurrentRoute->NetStart == 0) { - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_update: Range %d-%d has changed to %d-%d Dist=%d\n", - CurrentRoute->NetStart, CurrentRoute->NetStop, - NewRoute.NetStart, NewRoute.NetStop, NewRoute.NetDist)); - NewRoute.NetStart = 0; - } - - else { - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_update: Net Conflict Cur=%d, New=%d\n", - CurrentRoute->NetStop, NewRoute.NetStop)); - CurrentRoute->EntryState = - (CurrentRoute->EntryState & 0xF0) | RTE_STATE_BAD; - continue; - - } - } - - /* - * If we don't know the associated zones - */ - - if (!RT_ALL_ZONES_KNOWN(CurrentRoute)) { - - dPrintf(D_M_RTMP_LOW, D_L_INFO, - ("rtmp_update: Zone unknown for %d-%d state=0x%x\n", - CurrentRoute->NetStart, CurrentRoute->NetStop, - CurrentRoute->EntryState)); - - /* set the flag in the ifID structure telling - * that a scheduling of Zip Query is needed. - */ - - ifID->ifZipNeedQueries = 1; - continue; - } - - if (((CurrentRoute->EntryState & 0x0F) <= RTE_STATE_SUSPECT) && - NewRoute.NetDist != NOTIFY_N_DIST) { - - dPrintf(D_M_RTMP, D_L_INFO, - ("rtmp_update: update suspect entry %d-%d State=%d\n", - NewRoute.NetStart, NewRoute.NetStop, - (CurrentRoute->EntryState & 0x0F))); - - if (NewRoute.NetDist <= CurrentRoute->NetDist) { - CurrentRoute->NetDist = NewRoute.NetDist; - CurrentRoute->NetPort = NewRoute.NetPort; - CurrentRoute->NextIRNode = NewRoute.NextIRNode; - CurrentRoute->NextIRNet = NewRoute.NextIRNet; - CurrentRoute->EntryState = - (CurrentRoute->EntryState & 0xF0) | - (RTE_STATE_GOOD|RTE_STATE_UPDATED); - } - continue; - } - else { - - if (NewRoute.NetDist == NOTIFY_N_DIST) { - - CurrentRoute->EntryState = - (CurrentRoute->EntryState & 0xF0) | RTE_STATE_SUSPECT; - CurrentRoute->NetDist = NOTIFY_N_DIST; - continue; - } - } - - } - - - if ((NewRoute.NetDist <= CurrentRoute->NetDist) && (NewRoute.NetDist <16)) { - - /* Found a shorter or more recent Route, - * Replace with the New entryi - */ - - CurrentRoute->NetDist = NewRoute.NetDist; - CurrentRoute->NetPort = NewRoute.NetPort; - CurrentRoute->NextIRNode = NewRoute.NextIRNode; - CurrentRoute->NextIRNet = NewRoute.NextIRNet; - CurrentRoute->EntryState |= RTE_STATE_UPDATED; - - /* Can we consider now that the entry is updated? */ - dPrintf(D_M_RTMP_LOW, D_L_INFO, - ("rtmp_update: Shorter route found %d-%d, update\n", - NewRoute.NetStart, NewRoute.NetStop)); - -#ifdef AURP_SUPPORT - if (ddp_AURPsendx && (aurp_ifID->ifFlags & AT_IFF_AURP)) - ddp_AURPsendx(AURPCODE_RTUPDATE, - (void *)&NewRoute, AURPEV_NetDistChange); -#endif - } - } - else { /* no entry found */ - - if (NewRoute.NetDist < 16 && NewRoute.NetDist != NOTIFY_N_DIST && - NewRoute.NextIRNet >= ifID->ifThisCableStart && - NewRoute.NextIRNet <= ifID->ifThisCableEnd) { - - NewRoute.EntryState = (RTE_STATE_GOOD|RTE_STATE_UPDATED); - - dPrintf(D_M_RTMP_LOW, D_L_INFO, - ("rtmp_update: NewRoute %d-%d Tuple #%d\n", - NewRoute.NetStart, NewRoute.NetStop, tuple_nb)); - - ifID->ifZipNeedQueries = 1; - - if (rt_insert(NewRoute.NetStop, NewRoute.NetStart, NewRoute.NextIRNet, - NewRoute.NextIRNode, NewRoute.NetDist, NewRoute.NetPort, - NewRoute.EntryState) == (RT_entry *)NULL) - ErrorRTMPoverflow = 1; -#ifdef AURP_SUPPORT - else if (ddp_AURPsendx && (aurp_ifID->ifFlags & AT_IFF_AURP)) - ddp_AURPsendx(AURPCODE_RTUPDATE, - (void *)&NewRoute, AURPEV_NetAdded); -#endif - } - } - - } /* end of main while */ - ifID->ifRouterState = ROUTER_UPDATED; - if (ifID->ifZipNeedQueries) - zip_send_queries(ifID, 0, 0xFF); - -/* - timeout(rtmp_timeout, (caddr_t) ifID, 20*SYS_HZ); -*/ -} /* rtmp_update */ - -/* The RTMP validity timer expired, we need to update the - * state of each routing entry in the table - * because there is only one validity timer and it is always running, - * we can't just age all the entries automatically, as we might be - * aging entries that were just updated. So, when an entry is updated, - * the RTE_STATE_UPDATED bit is set and when the aging routine is called - * it just resets this bit if it is set, only if it is not set will the - * route actually be aged. - * Note there are 4 states for an entry, the state is decremented until - * it reaches the bad state. At this point, the entry is removed - * - * RTE_STATE_GOOD : The entry was valid (will be SUSPECT) - * RTE_STATE_SUSPECT: The entry was suspect (can still be used for routing) - * RTE_STATE_BAD : The entry was bad and is now deleted - * RTE_STATE_UNUSED : Unused or removed entry in the table - */ - -void rtmp_timeout(void *arg) -{ - at_ifaddr_t *ifID = (at_ifaddr_t *)arg; - register u_char state; - short i; - RT_entry *en = &RT_table[0]; - - atalk_lock(); - - if (ifID->ifRoutingState < PORT_ONLINE) { - atalk_unlock(); - return; - } - - /* for multihoming mode, we use ifRouterState to tell if there - is a router out there, so we know when to use cable multicast */ - if (ifID->ifRouterState > NO_ROUTER) - ifID->ifRouterState--; - - for (i = 0 ; i < RT_maxentry; i++,en++) { - - /* we want to age "learned" nets, not directly connected ones */ - state = en->EntryState & 0x0F; - - - if (state > RTE_STATE_UNUSED && - !(en->EntryState & RTE_STATE_PERMANENT) && en->NetStop && - en->NetDist && en->NetPort == ifID->ifPort) { - - /* if entry has been updated recently, just clear the UPDATED - bit. if bit not set, then we can age the entry */ - if (en->EntryState & RTE_STATE_UPDATED) { - en->EntryState &= ~RTE_STATE_UPDATED; - continue; - } - else - state = state >> 1 ; /* decrement state */ - - if (state == RTE_STATE_UNUSED) {/* was BAD, needs to delete */ - dPrintf(D_M_RTMP, D_L_INFO, - ("rtmp_timeout: Bad State for %d-%d (e#%d): remove\n", - en->NetStart, en->NetStop, i)); -#ifdef AURP_SUPPORT - if (ddp_AURPsendx && (aurp_ifID->ifFlags & AT_IFF_AURP)) - ddp_AURPsendx(AURPCODE_RTUPDATE, - (void *)en, AURPEV_NetDeleted); -#endif - - /* then clear the bit in the table concerning this entry. - If the zone Count reaches zero, remove the entry */ - - zt_remove_zones(en->ZoneBitMap); - - RT_DELETE(en->NetStop, en->NetStart); - } - else { - en->EntryState = (en->EntryState & 0xF0) | state; - dPrintf(D_M_RTMP, D_L_INFO, ("Change State for %d-%d to %d (e#%d)\n", - en->NetStart, en->NetStop, state, i)); - } - } - } - timeout(rtmp_timeout, (caddr_t) ifID, 20*SYS_HZ); - - atalk_unlock(); -} - -/* - * rtmp_prep_new_packet: allocate a ddp packet for RTMP use (reply to a RTMP request or - * Route Data Request, or generation of RTMP data packets. - * The ddp header is filled with relevant information, as well as - * the beginning of the rtmp packet with the following info: - * Router's net number (2bytes) - * ID Length = 8 (1byte) - * Router's node ID (1byte) - * Extended Range Start (2bytes) - * Range + dist (0x80) (1byte) - * Extended Range End (2bytes) - * Rtmp version (0x82) (1byte) - * - */ - -gbuf_t *rtmp_prep_new_packet (at_ifaddr_t *, at_net, u_char, char); - -gbuf_t *rtmp_prep_new_packet (ifID, DstNet, DstNode, socket) -register at_ifaddr_t *ifID; -register at_net DstNet; -register u_char DstNode; -register char socket; - -{ - gbuf_t *m; - register at_ddp_t *ddp; - register char * rtmp_data; - - if ((m = gbuf_alloc(AT_WR_OFFSET+1024, PRI_HI)) == NULL) { - dPrintf(D_M_RTMP, D_L_WARNING, ("rtmp_new_packet: Can't allocate mblock\n")); - return ((gbuf_t *)NULL); - } - - gbuf_rinc(m,AT_WR_OFFSET); - gbuf_wset(m,DDP_X_HDR_SIZE + 10); - ddp = (at_ddp_t *)(gbuf_rptr(m)); - - /* - * Prepare the DDP header of the new packet - */ - - - ddp->unused = ddp->hopcount = 0; - - UAS_ASSIGN(ddp->checksum, 0); - - NET_NET(ddp->dst_net, DstNet); - ddp->dst_node = DstNode; - ddp->dst_socket = socket; - - NET_ASSIGN(ddp->src_net, ifID->ifThisNode.s_net); - ddp->src_node = ifID->ifThisNode.s_node; - ddp->src_socket = RTMP_SOCKET; - ddp->type = DDP_RTMP; - - /* - * Prepare the RTMP header (Router Net, ID, Node and Net Tuple - * (this works only if we are on an extended net) - */ - - rtmp_data = ddp->data; - - *rtmp_data++ = (ifID->ifThisNode.s_net & 0xff00) >> 8; - *rtmp_data++ = ifID->ifThisNode.s_net & 0x00ff ; - *rtmp_data++ = 8; - *rtmp_data++ = (u_char)ifID->ifThisNode.s_node; - *rtmp_data++ = (CableStart & 0xff00) >> 8; - *rtmp_data++ = CableStart & 0x00ff ; - *rtmp_data++ = 0x80; /* first tuple, so distance is always zero */ - *rtmp_data++ = (CableStop & 0xff00) >> 8; - *rtmp_data++ = CableStop & 0x00ff ; - *rtmp_data++ = RTMP_VERSION_NUMBER; - - return (m); - - -} -int rtmp_r_find_bridge(at_ifaddr_t *, at_ddp_t *); - -int rtmp_r_find_bridge(ifID, orig_ddp) -register at_ifaddr_t *ifID; -register at_ddp_t *orig_ddp; - -{ - gbuf_t *m; - register int size, status; - register at_ddp_t *ddp; - register char * rtmp_data; - RT_entry *Entry; - - - /* find the bridge for the querried net */ - - Entry = rt_blookup(NET_VALUE(orig_ddp->dst_net)); - - if (Entry == NULL) { - dPrintf(D_M_RTMP, D_L_WARNING, ("rtmp_r_find_bridge: no info for net %d\n", - NET_VALUE(orig_ddp->dst_net))); - return (1); - } - - - size = DDP_X_HDR_SIZE + 10 ; - if ((m = gbuf_alloc(AT_WR_OFFSET+size, PRI_HI)) == NULL) { - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_r_find_bridge: Can't allocate mblock\n")); - return (ENOBUFS); - } - - gbuf_rinc(m,AT_WR_OFFSET); - gbuf_wset(m,size); - ddp = (at_ddp_t *)(gbuf_rptr(m)); - - /* - * Prepare the DDP header of the new packet - */ - - ddp->unused = ddp->hopcount = 0; - - DDPLEN_ASSIGN(ddp, size); - UAS_ASSIGN(ddp->checksum, 0); - - NET_NET(ddp->dst_net, orig_ddp->src_net); - ddp->dst_node = orig_ddp->src_node; - ddp->dst_socket = orig_ddp->src_socket; - - NET_ASSIGN(ddp->src_net, Entry->NextIRNet); - ddp->src_node = Entry->NextIRNode; - ddp->src_socket = RTMP_SOCKET; - ddp->type = DDP_RTMP; - - /* - * Prepare the RTMP header (Router Net, ID, Node and Net Tuple - * (this works only if we are on an extended net) - */ - - rtmp_data = ddp->data; - - *rtmp_data++ = (Entry->NextIRNet & 0xff00) >> 8; - *rtmp_data++ = Entry->NextIRNet & 0x00ff ; - *rtmp_data++ = 8; - *rtmp_data++ = (u_char)Entry->NextIRNode; - *rtmp_data++ = (Entry->NetStart & 0xff00) >> 8; - *rtmp_data++ = Entry->NetStart & 0x00ff ; - *rtmp_data++ = 0x80; /* first tuple, so distance is always zero */ - *rtmp_data++ = (Entry->NetStop & 0xff00) >> 8; - *rtmp_data++ = Entry->NetStop & 0x00ff ; - *rtmp_data++ = RTMP_VERSION_NUMBER; - - - dPrintf(D_M_RTMP, D_L_INFO, ("rtmp_r_find_bridge: for net %d send back router %d.%d\n", - NET_VALUE(orig_ddp->dst_net), Entry->NextIRNet, Entry->NextIRNode)); - if ((status = ddp_router_output(m, ifID, AT_ADDR, NET_VALUE(orig_ddp->src_net), - orig_ddp->src_node, 0))){ - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_r_find_bridge: ddp_router_output failed status=%d\n", status)); - return (status); - } - return (0); -} - -/* - * rtmp_send_table: - * Send the routing table entries in RTMP data packets. - * Use split horizon if specified. The Data packets are sent - * as full DDP packets, if the last packet is full an empty - * packet is sent to tell the recipients that this is the end of - * the table... - * - */ -static int rtmp_send_table(at_ifaddr_t *, at_net, u_char, short, char, short); - -static int rtmp_send_table(ifID, DestNet, DestNode, split_hz, socket, - n_neighbors) - register at_ifaddr_t *ifID; /* interface/port params */ - register at_net DestNet; /* net where to send the table */ - register u_char DestNode; /* node where to send to table */ - short split_hz; /* use split horizon */ - char socket; /* the destination socket to send to */ - short n_neighbors; /* used to send packets telling we are going down */ -{ - - RT_entry *Entry; - char *Buff_ptr; - u_char NewDist; - gbuf_t *m; - short size,status ; - register at_ddp_t *ddp; - register short EntNb = 0, sent_tuple = 0; - - if (ifID->ifRoutingState < PORT_ONLINE) { - dPrintf(D_M_RTMP, D_L_INFO, - ("rtmp_send_table: port %d activating, we don't send anything!\n", - ifID->ifPort)); - return (0); - } - - /* prerare tuples and packets for DDP*/ - /* if split horizon, do not send tuples we can reach on the port we - * want to send too - */ - - Entry = &RT_table[0]; - size = 0; - if (!(m = rtmp_prep_new_packet(ifID, DestNet, DestNode, socket))) { - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_send_table: rtmp_prep_new_packet failed\n")); - return(ENOBUFS); - } - - ddp = (at_ddp_t *)(gbuf_rptr(m)); - Buff_ptr = (char *)((char *)ddp + DDP_X_HDR_SIZE + 10); - - while (EntNb < RT_maxentry) { - - if (Entry->NetStop && ((Entry->EntryState & 0x0F) >= RTE_STATE_SUSPECT)) { - if (!(split_hz && ifID->ifPort == Entry->NetPort)) { - sent_tuple++; - - if (((Entry->EntryState & 0x0F) < RTE_STATE_SUSPECT) || n_neighbors) - NewDist = NOTIFY_N_DIST; - else - NewDist = Entry->NetDist & 0x1F; - - if (Entry->NetStart) { /* Extended */ - *Buff_ptr++ = (Entry->NetStart & 0xFF00) >> 8; - *Buff_ptr++ = (Entry->NetStart & 0x00FF); - *Buff_ptr++ = 0x80 | NewDist; - *Buff_ptr++ = (Entry->NetStop & 0xFF00) >> 8; - *Buff_ptr++ = (Entry->NetStop & 0x00FF); - *Buff_ptr++ = RTMP_VERSION_NUMBER; - size += 6; - } - else { /* non extended tuple */ - *Buff_ptr++ = (Entry->NetStop & 0xFF00) >> 8; - *Buff_ptr++ = (Entry->NetStop & 0x00FF); - *Buff_ptr++ = NewDist; - size += 3; - } - } - } - - if (size > (DDP_DATA_SIZE-20)) { - DDPLEN_ASSIGN(ddp, (size + DDP_X_HDR_SIZE + 10)); - gbuf_winc(m,size); - if ((status = ddp_router_output(m, ifID, AT_ADDR, - NET_VALUE(DestNet),DestNode, 0))){ - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_send_table: ddp_router_output failed status=%d\n", - status)); - return (status); - } - if ((m = rtmp_prep_new_packet (ifID, DestNet, DestNode, socket)) == NULL){ - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_send_table: rtmp_prep_new_poacket failed status=%d\n", - status)); - return (ENOBUFS); - } - ddp = (at_ddp_t *)(gbuf_rptr(m)); - Buff_ptr = (char *)((char *)ddp + DDP_X_HDR_SIZE + 10); - - dPrintf(D_M_RTMP_LOW, D_L_OUTPUT, - ("rtmp_s_tble: Send %d tuples on port %d\n", - sent_tuple, ifID->ifPort)); - sent_tuple = 0; - size = 0; - } - - Entry++; - EntNb++; - } - - /* - * If we have some remaining entries to send, send them now. - * otherwise, the last packet we sent was full, we need to send an empty one - */ - - DDPLEN_ASSIGN(ddp, (size + DDP_X_HDR_SIZE + 10)); - gbuf_winc(m,size); - if ((status = - ddp_router_output(m, ifID, AT_ADDR, NET_VALUE(DestNet),DestNode, 0))){ - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_send_table: ddp_router_output failed status=%d\n", status)); - return (status); - } - dPrintf(D_M_RTMP_LOW, D_L_OUTPUT, - ("rtmp_s_tble: LAST Packet split=%d with %d tuples sent on port %d\n", - split_hz, sent_tuple, ifID->ifPort)); - - return (0); -} - -/* - * rtmp_request: respond to the 3 types of RTMP requests RTMP may receive - * RTMP func =1 : respond with an RTMP Reponse Packet - * RTMP func =2 : respond with the routing table RTMP packet with split horizon - * RTMP func =3 : respond with the routing table RTMP packet no split horizon - * - * see Inside AppleTalk around page 5-18 for "details" - */ - -static void rtmp_request(ifID, ddp) - register at_ifaddr_t *ifID; - register at_ddp_t *ddp; -{ - - short split_horizon = FALSE; - short code; - short error; - - /* We ignore the request if we're activating on that port */ - - if (ifID->ifRoutingState < PORT_ONLINE) - return; - - /* check RTMP function code */ - - code = ddp->data[0]; - - switch (code) { - - case RTMP_REQ_FUNC1: /* RTMP Find Bridge */ - - /* RTMP Request Packet: we send a response with the next IRrange */ - dPrintf(D_M_RTMP, D_L_INPUT, - ( "rtmp_request: find bridge for net %d port %d node %d.%d\n", - NET_VALUE(ddp->dst_net), ifID->ifPort, - NET_VALUE(ddp->src_net), ddp->src_node)); - - if ((error = rtmp_r_find_bridge (ifID, ddp))) { - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_request: Code 1 ddp_r_output failed error=%d\n", - error)); - return; - } - - break; - - case RTMP_REQ_FUNC2: - - split_horizon = TRUE; - - case RTMP_REQ_FUNC3: - - /* RTMP Route Request Packet */ - - dPrintf(D_M_RTMP, D_L_INPUT, - ("rtmp_request: received code=%d from %d.%d for %d.%d\n", - code, NET_VALUE(ddp->src_net), ddp->src_node, - NET_VALUE(ddp->dst_net), ddp->dst_node)); - - rtmp_send_table(ifID, ddp->src_net, ddp->src_node, - split_horizon, ddp->src_socket, 0); - - break; - - default: - - /* unknown type of request */ - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_request : invalid type of request =%d\n", - code)); - break; - } - -} - -/* locked version of rtmp_send_port */ -void rtmp_send_port_locked(void *arg) -{ - at_ifaddr_t *ifID = (at_ifaddr_t *)arg; - atalk_lock(); - rtmp_send_port(ifID); - atalk_unlock(); -} - - -/* - * rtmp_send_all_ports : send the routing table on all connected ports - * check for the port status and if ok, send the - * rtmp tuples to the broadcast address for the port - * usually called on timeout every 10 seconds. - */ - -void rtmp_send_port(ifID) - register at_ifaddr_t *ifID; -{ - at_net DestNet; - - NET_ASSIGN(DestNet, 0); - - if (ifID && ifID->ifRoutingState == PORT_ONLINE) { - dPrintf(D_M_RTMP_LOW, D_L_OUTPUT, - ("rtmp_send_port: do stuff for port=%d\n", - ifID->ifPort)); - if (ifID->ifZipNeedQueries) - zip_send_queries(ifID, 0, 0xFF); - if (!ROUTING_MODE) { - return; - } - rtmp_send_table(ifID, DestNet, 0xFF, 1, RTMP_SOCKET, 0); - } - -#if DEBUG - if (ifID == ifID_home) - dPrintf(D_M_RTMP_LOW, D_L_VERBOSE, - ("I:%5d O:%5d H:%5d dropped:%d\n", - pktsIn, pktsOut, pktsHome, pktsDropped)); - - dPrintf(D_M_RTMP_LOW, D_L_TRACE, - ("rtmp_send_port: func=0x%x, ifID=0x%x\n", - (u_int) rtmp_send_port, (u_int) ifID)); -#endif - - timeout (rtmp_send_port_locked, (caddr_t)ifID, 10 * SYS_HZ); - -} - -/* rtmp_dropper: check the number of packet received every x secondes. - * the actual packet dropping is done in ddp_input - */ - -void rtmp_dropper(__unused void *arg) -{ - - atalk_lock(); - - pktsIn = pktsOut = pktsHome = pktsDropped = 0; - timeout(rtmp_dropper, NULL, 2*SYS_HZ); - - atalk_unlock(); -} - -/* - * rtmp_router_start: perform the sanity checks before declaring the router up - * and running. This function looks for discrepency between the net infos - * for the different ports and seed problems. - * If everything is fine, the state of each port is brought to PORT_ONLINE.\ - * ### LD 01/09/95 Changed to correct Zone problem on non seed ports. - */ - -int rtmp_router_start(at_kern_err_t *keP) -{ - int err = 0; - register at_ifaddr_t *ifID, *ifID2; - register short Index, router_starting_timer = 0; - register RT_entry *Entry; - register at_net_al netStart, netStop; - struct timespec ts; - - - /* clear the static structure used to record routing errors */ - bzero(&ke, sizeof(ke)); - - TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) { - - /* if non seed, need to acquire the right node address */ - - if ((ifID->ifFlags & RTR_SEED_PORT) == 0) { - if ((ifID->ifThisCableStart == 0 && ifID->ifThisCableEnd == 0) || - (ifID->ifThisCableStart >= DDP_STARTUP_LOW && - ifID->ifThisCableEnd <= DDP_STARTUP_HIGH)) { - - if (ifID->ifThisCableEnd == 0) { - keP->error = KE_NO_SEED; - keP->port1 = ifID->ifPort; - strlcpy(keP->name1, ifID->ifName,sizeof(keP->name1)); - } - else { - keP->error = KE_INVAL_RANGE; - keP->port1 = ifID->ifPort; - strlcpy(keP->name1, ifID->ifName,sizeof(keP->name1)); - keP->netr1b = ifID->ifThisCableStart; - keP->netr1e = ifID->ifThisCableEnd; - } - ifID->ifRoutingState = PORT_ERR_STARTUP; - RouterError(ifID->ifPort, ERTR_CABLE_STARTUP); - - goto error; - } - - /* we are non seed, so try to acquire the zones for that guy */ - ifID->ifZipNeedQueries = 1; - - dPrintf(D_M_RTMP, D_L_STARTUP, - ("rtmp_router_start: call elap_online for Non Seed port #%d cable =%d-%d\n", - ifID->ifPort, CableStart, CableStop)); - if ((err = elap_online3(ifID))) - goto error; - } - } - - /* Check if we have a problem with the routing table size */ - - if (ErrorRTMPoverflow) { - keP->error = KE_RTMP_OVERFLOW; - goto error; - } - - - /* Now, check that we don't have a conflict in between our interfaces */ - TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) { - - /* check if the RoutingState != PORT_ONERROR */ - if (ifID->ifRoutingState < PORT_ACTIVATING) { - goto error; - } - - if ((ifID->ifThisCableStart == 0 && ifID->ifThisCableEnd == 0) || - (ifID->ifThisCableStart >= DDP_STARTUP_LOW && - ifID->ifThisCableEnd <= DDP_STARTUP_HIGH)) { - - if (ifID->ifThisCableEnd == 0) { - keP->error = KE_NO_SEED; - keP->port1 = ifID->ifPort; - strlcpy(keP->name1, ifID->ifName,sizeof(keP->name1)); - } - else { - keP->error = KE_INVAL_RANGE; - keP->port1 = ifID->ifPort; - strlcpy(keP->name1, ifID->ifName,sizeof(keP->name1)); - keP->netr1b = ifID->ifThisCableStart; - keP->netr1e = ifID->ifThisCableEnd; - } - - ifID->ifRoutingState = PORT_ERR_STARTUP; - RouterError(ifID->ifPort, ERTR_CABLE_STARTUP); - - goto error; - } - - /* check the interface address against all other ifs */ - - netStart = ifID->ifThisCableStart; - netStop = ifID->ifThisCableEnd; - - for (ifID2 = TAILQ_NEXT(ifID, aa_link); ifID2; - ifID2 = TAILQ_NEXT(ifID2, aa_link)) { - - if (((netStart >= ifID2->ifThisCableStart) && - (netStart <= ifID2->ifThisCableEnd)) || - ((netStop >= ifID2->ifThisCableStart) && - (netStop <= ifID2->ifThisCableEnd)) || - ((ifID2->ifThisCableStart >= netStart) && - (ifID2->ifThisCableStart <= netStop)) || - ((ifID2->ifThisCableEnd >= netStart) && - (ifID2->ifThisCableEnd <= netStop)) ) { - - keP->error = KE_CONF_RANGE; - keP->port1 = ifID->ifPort; - strlcpy(keP->name1, ifID->ifName,sizeof(keP->name1)); - keP->port2 = ifID2->ifPort; - strlcpy(keP->name2, ifID2->ifName,sizeof(keP->name2)); - keP->netr1b = ifID->ifThisCableStart; - keP->netr1e = ifID->ifThisCableEnd; - ifID->ifRoutingState = PORT_ERR_CABLER; - RouterError(ifID->ifPort, ERTR_CABLE_CONFLICT); - goto error; - } - - } - - /* ### LD 01/04/94: We need to fill in the next IR info in the routing table */ - Entry = rt_blookup(ifID->ifThisCableEnd); - - if (Entry == NULL) { - dPrintf(D_M_RTMP, D_L_ERROR, - ("rtmp_router_start: we don't know our cable range port=%d\n", - ifID->ifPort)); - - goto error; - } - - /* - * Note: At this point, non seed ports may not be aware of their Default zone - */ - - if (!(ifID->ifFlags & RTR_SEED_PORT)) { - ifID->ifDefZone = 0; - Entry->EntryState |= (RTE_STATE_GOOD|RTE_STATE_UPDATED); - } - - ifID->ifRoutingState = PORT_ONLINE; - ifID->ifState = LAP_ONLINE; - - /* set the right net and node for each port */ - Entry->NextIRNet = ifID->ifThisNode.s_net; - Entry->NextIRNode= ifID->ifThisNode.s_node; - - dPrintf(D_M_RTMP, D_L_STARTUP, - ("rtmp_router_start: bring port=%d [%d.%d]... on line\n", - ifID->ifPort, ifID->ifThisNode.s_net, - ifID->ifThisNode.s_node)); - - } - - /* - * Everything is fine, we can begin to babble on the net... - */ - - TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) { - if (ifID->ifRoutingState == PORT_ONLINE) { - rtmp_send_port(ifID); - timeout(rtmp_timeout, (caddr_t)ifID, (50+ifID->ifPort) * SYS_HZ); - if (ifID->ifRoutingState < PORT_ACTIVATING) { - goto error; - } - } - } - - /* Check if we have a problem with the routing or zip table size */ - - if (ErrorRTMPoverflow) { - keP->error = KE_RTMP_OVERFLOW; - goto error; - } - if (ErrorZIPoverflow) { - keP->error = KE_ZIP_OVERFLOW; - goto error; - } - - /* sleep for 11 seconds */ - ts.tv_sec = 11; - ts.tv_nsec = 0; - if ((err = - /* *** eventually this will be the ifID for the interface - being brought up in router mode *** */ - /* *** router sends rtmp packets every 10 seconds *** */ - msleep(&ifID_home->startup_inprogress, atalk_mutex, - PSOCK | PCATCH, "router_start1", &ts)) - != EWOULDBLOCK) { - goto error; - } - - /* Is the stack still up ? */ - if (!(at_state.flags & AT_ST_STARTED) || !ifID_home) { - err = ECONNABORTED; - goto error; - } - -startZoneInfo: - err = 0; - TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) { - - if (ifID->ifRoutingState < PORT_ACTIVATING) { - goto error; - } - - if ((ifID->ifZipNeedQueries) - && (ifID->ifFlags & RTR_SEED_PORT) == 0) { - dPrintf(D_M_RTMP, D_L_STARTUP, - ("rtmp_router_start: send Zip Queries for Port %d\n", - ifID->ifPort)); - zip_send_queries(ifID, 0, 0xFF); - - if (router_starting_timer >= 10) { - dPrintf(D_M_RTMP, D_L_WARNING, - ("rtmp_router_start: no received response to ZipNeedQueries\n")); - keP->error = KE_NO_ZONES_FOUND; - keP->port1 = ifID->ifPort; - strlcpy(keP->name1, ifID->ifName,sizeof(keP->name1)); - keP->netr1b = ifID->ifThisCableStart; - keP->netr1e = ifID->ifThisCableEnd; - ifID->ifRoutingState = PORT_ERR_CABLER; - RouterError(ifID->ifPort, ERTR_CABLE_CONFLICT); - goto error; - } - - dPrintf(D_M_RTMP, D_L_STARTUP, - ("rtmp_router_start: waiting for zone info to complete\n")); - /* sleep for 10 seconds */ - ts.tv_sec = 10; - ts.tv_nsec = 0; - if ((err = - /* *** eventually this will be the ifID for the - interface being brought up in router mode *** */ - msleep(&ifID_home->startup_inprogress, atalk_mutex, - PSOCK | PCATCH, "router_start2", &ts)) - != EWOULDBLOCK) { - goto error; - } - - /* Is the stack still up ? */ - if (!(at_state.flags & AT_ST_STARTED) || !ifID_home) { - err = ECONNABORTED; - goto error; - } - - err = 0; - router_starting_timer++; - goto startZoneInfo; - } - - } - - /* At This Point, check if we know the default zones for non seed port */ - - TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) { - - if (ifID->ifRoutingState < PORT_ACTIVATING) - goto error; - - if (!(ifID->ifFlags & RTR_SEED_PORT)) { - Entry = rt_blookup(ifID->ifThisCableEnd); - - if (Entry == NULL) { - dPrintf(D_M_RTMP, D_L_ERROR, - ("rtmp_router_start: (2)we don't know our cable range port=%d\n", - ifID->ifPort)); - goto error; - } - - dPrintf(D_M_RTMP, D_L_STARTUP, - ("rtmp_router_start: if %s set to permanent\n", - ifID->ifName)); - Entry->NetDist = 0; /* added 4-29-96 jjs, prevent direct - nets from showing non-zero - distance */ - /* upgrade the non seed ports. */ - Entry->EntryState |= RTE_STATE_PERMANENT; - - Index = zt_ent_zindex(Entry->ZoneBitMap); - if (Index <= 0) { - dPrintf(D_M_RTMP, D_L_ERROR, - ("rtmp_router_start: still don't know default zone for port %d\n", - ifID->ifPort)); - } else { - ifID->ifDefZone = Index; - if ((ifID == ifID_home) || MULTIHOME_MODE) { - ifID->ifZoneName = ZT_table[Index-1].Zone; - (void)regDefaultZone(ifID); - - /* Send zone change event */ - atalk_post_msg(ifID->aa_ifp, KEV_ATALK_ZONEUPDATED, 0, &(ifID->ifZoneName)); - } - } - } - } - - /* Check if we have a problem with the routing or zip table size */ - - if (ErrorRTMPoverflow) { - keP->error = KE_RTMP_OVERFLOW; - goto error; - } - if (ErrorZIPoverflow) { - keP->error = KE_ZIP_OVERFLOW; - goto error; - } - - /* - * Handle the Home Port specifics - */ - - /* set the router address as being us no matter what*/ - ifID_home->ifARouter = ifID_home->ifThisNode; - ifID_home->ifRouterState = ROUTER_UPDATED; - - /* prepare the packet dropper timer */ - timeout (rtmp_dropper, NULL, 1*SYS_HZ); - - return(0); - -error: - dPrintf(D_M_RTMP,D_L_ERROR, - ("rtmp_router_start: error type=%d occurred on port %d\n", - ifID->ifRoutingState, ifID->ifPort)); - - /* if there's no keP->error, copy the local ke structure, - since the error occurred asyncronously */ - if ((!keP->error) && ke.error) - bcopy(&ke, keP, sizeof(ke)); - rtmp_shutdown(); - - /* to return the error in keP, the ioctl has to return 0 */ - - return((keP->error)? 0: err); -} /* rtmp_router_start */ - -void rtmp_router_start_tmo(void *arg) -{ - (void)rtmp_router_start_tmo((at_kern_err_t*)arg); -} - -void rtmp_shutdown(void) -{ - register at_ifaddr_t *ifID; - at_net DestNet; - - NET_ASSIGN(DestNet, 0); - - dPrintf(D_M_RTMP, D_L_SHUTDN, - ("rtmp_shutdown:stop sending to all ports\n")); - - untimeout(rtmp_dropper, (void *)0); - untimeout(rtmp_router_start_tmo, (void *)1); /* added for 2225395 */ - untimeout(rtmp_router_start_tmo, (void *)3); /* added for 2225395 */ - - TAILQ_FOREACH(ifID, &at_ifQueueHd, aa_link) { - if (ifID->ifRoutingState > PORT_OFFLINE ) { - if (ifID->ifRoutingState == PORT_ONLINE) { - untimeout(rtmp_send_port_locked, (caddr_t)ifID); - untimeout(rtmp_timeout, (caddr_t) ifID); - } - /* - * it's better to notify the neighbour routers that we are going down - */ - if (ROUTING_MODE) - rtmp_send_table(ifID, DestNet, 0xFF, TRUE, - RTMP_SOCKET, TRUE); - - ifID->ifRoutingState = PORT_OFFLINE; - - dPrintf(D_M_RTMP, D_L_SHUTDN, - ("rtmp_shutdown: routing on port=%d... off line\nStats:\n", - ifID->ifPort)); - dPrintf(D_M_RTMP, D_L_SHUTDN, - ("fwdBytes : %ld\nfwdPackets : %ld\ndroppedBytes : %ld\ndroppedPkts : %ld\n", - ifID->ifStatistics.fwdBytes, ifID->ifStatistics.fwdPkts, - ifID->ifStatistics.droppedBytes, ifID->ifStatistics.droppedPkts)); - - } - } - -} - -/* - * Remove all entries associated with the specified port. - */ -void rtmp_purge(ifID) - at_ifaddr_t *ifID; -{ - u_char state; - int i; - RT_entry *en = &RT_table[0]; - - for (i=0; i < RT_maxentry; i++) { - state = en->EntryState & 0x0F; - if ((state > RTE_STATE_UNUSED) && (state != RTE_STATE_PERMANENT) - && en->NetStop && en->NetDist && (en->NetPort == ifID->ifPort)) { - zt_remove_zones(en->ZoneBitMap); - RT_DELETE(en->NetStop, en->NetStart); - } - en++; - } -}