|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /*-------------------------------------------------------------------------- ! 26: * Router RTMP protocol functions: ! 27: * ! 28: * This file contains Routing specifics to handle RTMP packets and ! 29: * the maintenance of the routing table through.... ! 30: * ! 31: * The entry point for the rtmp input in ddp is valid only when we're ! 32: * running in router mode. ! 33: * ! 34: * ! 35: *------------------------------------------------------------------------- ! 36: * ! 37: * Copyright (c) 1994, 1996-1998 Apple Computer, Inc. ! 38: * ! 39: * The information contained herein is subject to change without ! 40: * notice and should not be construed as a commitment by Apple ! 41: * Computer, Inc. Apple Computer, Inc. assumes no responsibility ! 42: * for any errors that may appear. ! 43: * ! 44: * Confidential and Proprietary to Apple Computer, Inc. ! 45: */ ! 46: ! 47: #include <sysglue.h> ! 48: #include <sys/malloc.h> ! 49: #include <at/appletalk.h> ! 50: #include <lap.h> ! 51: #include <llap.h> ! 52: #include <at/elap.h> ! 53: #include <at/ddp.h> ! 54: #include <rtmp.h> ! 55: #include <at/at_lap.h> ! 56: #include <at_elap.h> ! 57: #include <at_ddp.h> ! 58: #include <at_zip.h> ! 59: #include <routing_tables.h> ! 60: #include <at_aurp.h> ! 61: extern void (*ddp_AURPsendx)(); ! 62: extern at_if_t *aurp_ifID; ! 63: ! 64: /*DEBUG ONLY */ ! 65: static int dump_counter =0; ! 66: /*DEBUG ONLY */ ! 67: ! 68: static kern_err_t ke; ! 69: gbuf_t *rtmp_prep_new_packet(); ! 70: ! 71: void rtmp_timeout(); ! 72: void rtmp_send_port(); ! 73: void rtmp_dropper(); ! 74: extern RT_entry *rt_blookup (); ! 75: ! 76: extern at_if_t *ifID_table[]; ! 77: extern char errstr[]; /* formatting of Router Errors */ ! 78: extern at_state_t *at_statep; ! 79: ! 80: extern pktsIn,pktsOut,pktsDropped, pktsHome; ! 81: extern gref_t *at_delay_gref; ! 82: extern gbuf_t *at_delay_m; ! 83: extern int (*at_delay_func)(); ! 84: extern int at_delay_errno; ! 85: extern char at_delay_flag; ! 86: extern void *atalk_timeout(); ! 87: extern void atalk_untimeout(); ! 88: static void *dropper_tmo = 0; ! 89: ! 90: extern short ErrorRTMPoverflow; ! 91: extern short ErrorZIPoverflow; ! 92: extern atlock_t ddpinp_lock; ! 93: ! 94: static void rtmp_update(); ! 95: static void rtmp_request(); ! 96: ! 97: /* ddprunning_flag was used to make sure that shutdown did not occur ! 98: while a packet was being processed. However looping while waiting ! 99: for ddprunning_flag to be cleared has resulted in the system hanging. ! 100: Therefore this variable has been temporarily removed, until such time ! 101: as we can verify that there is no condition under which it will cause ! 102: trouble. ! 103: */ ! 104: #ifdef CHECK_DDPR_FLAG ! 105: int ddprunning_flag; /* temporarily removed using CHECK_DDPR_FLAG */ ! 106: #endif ! 107: ! 108: /* ! 109: * rtmp_router_input: function called by DDP (in router mode) to handle ! 110: * all incoming RTMP packets. Listen to the RTMP socket ! 111: * for all the connected ports. ! 112: * Switch to the relevant rtmp functions. ! 113: */ ! 114: ! 115: void ! 116: rtmp_router_input (mp, ifID) ! 117: register gbuf_t *mp; ! 118: register at_if_t *ifID; ! 119: { ! 120: register at_ddp_t *ddp = (at_ddp_t *)gbuf_rptr(mp); ! 121: /* NOTE: there is an assumption here that the ! 122: * DATA follows the header. */ ! 123: ! 124: register at_net_al OurNet; ! 125: register at_node OurNode; ! 126: register at_net_al DstNet; ! 127: register at_node DstNode; ! 128: short tuples; ! 129: RT_entry *Entry; ! 130: ! 131: if (!ifID || ! IFID_VALID(ifID) || (ifID->ifRoutingState < PORT_ACTIVATING)) { ! 132: gbuf_freem(mp); ! 133: return; ! 134: } ! 135: ! 136: ! 137: OurNet = NET_VALUE(ifID->ifThisNode.atalk_net); ! 138: OurNode =ifID->ifThisNode.atalk_node; ! 139: ! 140: ! 141: if (gbuf_type(mp) != MSG_DATA) { ! 142: ! 143: /* If this is a M_ERROR message, DDP is shutting down, ! 144: * nothing to do here...If it's something else, we don't ! 145: * understand what it is ! 146: */ ! 147: dPrintf(D_M_RTMP, D_L_WARNING, ("rtmp_router_input: Not an M_DATA type\n")); ! 148: gbuf_freem(mp); ! 149: return; ! 150: } ! 151: ! 152: DstNet = NET_VALUE(ddp->dst_net); ! 153: DstNode = ddp->dst_node; ! 154: ! 155: /* check the kind of RTMP packet we received */ ! 156: ! 157: switch (ddp->type) { ! 158: ! 159: case RTMP_DDP_TYPE: ! 160: ! 161: tuples = gbuf_len(mp) - DDP_X_HDR_SIZE - RTMP_IDLENGTH; ! 162: /* ! 163: * we need to make sure that the size of 'tuples' is ! 164: * not less than or equal to 0 due to a bad packet ! 165: */ ! 166: if (tuples <= 0) { ! 167: gbuf_freem(mp); ! 168: break; ! 169: } ! 170: ! 171: if (tuples % 3) {/* not a valid RTMP data packet */ ! 172: gbuf_freem(mp); ! 173: dPrintf(D_M_RTMP, D_L_WARNING, ! 174: ("rtmp_input: bad number of tuple in RTMP packet\n")); ! 175: return; ! 176: } ! 177: ! 178: tuples = tuples / 3; ! 179: ! 180: rtmp_update(ifID, (at_rtmp *)ddp->data, tuples); ! 181: gbuf_freem(mp); ! 182: ! 183: break; ! 184: ! 185: case RTMP_REQ: ! 186: ! 187: /* we should treat requests a bit differently. ! 188: * - if the request if not for the port, route it and also respond ! 189: * for this port if not locally connected. ! 190: * - if the request for this port, then just respond to it. ! 191: */ ! 192: ! 193: if (!ROUTING_MODE) { ! 194: gbuf_freem(mp); ! 195: return; ! 196: } ! 197: if (DstNode == 255) { ! 198: if (((DstNet >= CableStart) && (DstNet <= CableStop)) || ! 199: DstNet == 0) { ! 200: rtmp_request(ifID, ddp); ! 201: gbuf_freem(mp); ! 202: return; ! 203: } ! 204: else { ! 205: /* check if directly connected port */ ! 206: ! 207: if ((Entry = rt_blookup(DstNet)) && (Entry->NetDist == 0)) { ! 208: dPrintf(D_M_RTMP, D_L_WARNING, ! 209: ("rtmp_router_input: request for %d.%d, port %d\n", ! 210: DstNet, DstNode, Entry->NetPort)); ! 211: rtmp_request(ifID_table[Entry->NetPort], ddp); ! 212: gbuf_freem(mp); ! 213: return; ! 214: } ! 215: else { ! 216: dPrintf(D_M_RTMP, D_L_WARNING, ! 217: ("rtmp_router_input: RTMP packet received for %d.%d, also forward\n", ! 218: NET_VALUE(ddp->dst_net),ddp->dst_node)); ! 219: routing_needed(mp, ifID, TRUE); ! 220: return; ! 221: } ! 222: } ! 223: } ! 224: else { ! 225: ! 226: if ((DstNode == OurNode) && (DstNet == OurNet)) { ! 227: rtmp_request(ifID, ddp); ! 228: gbuf_freem(mp); ! 229: return; ! 230: } ! 231: else { ! 232: dPrintf(D_M_RTMP, D_L_WARNING, ! 233: ("rtmp_router_input: RTMP packet received for %d.%d, forward\n", ! 234: NET_VALUE(ddp->dst_net), ddp->dst_node)); ! 235: routing_needed(mp, ifID, TRUE); ! 236: } ! 237: } ! 238: ! 239: break; ! 240: ! 241: default: ! 242: ! 243: dPrintf(D_M_RTMP, D_L_WARNING, ! 244: ("rtmp_input: RTMP packet type=%d, route it\n", ddp->type)); ! 245: routing_needed(mp, ifID, TRUE); ! 246: break; ! 247: ! 248: } ! 249: ! 250: ! 251: } ! 252: ! 253: /* ! 254: * rtmp_update: ! 255: * ! 256: */ ! 257: ! 258: static ! 259: void rtmp_update(ifID, rtmp, tuple_nb) ! 260: register at_if_t *ifID; ! 261: register at_rtmp *rtmp; ! 262: register short tuple_nb; ! 263: { ! 264: register int PortFlags = ifID->ifFlags; ! 265: register at_rtmp_tuple *FirstTuple = (at_rtmp_tuple *)&rtmp->at_rtmp_id[1]; ! 266: register at_rtmp_tuple *SecondTuple = (at_rtmp_tuple *)&rtmp->at_rtmp_id[4]; ! 267: RT_entry NewRoute, *CurrentRoute; ! 268: ! 269: register u_char SenderNodeID = rtmp->at_rtmp_id[0]; ! 270: char *TuplePtr; ! 271: short state; ! 272: ! 273: ! 274: /* Make sure this an AppleTalk node sending us the RTMP packet */ ! 275: ! 276: if (rtmp->at_rtmp_id_length != 8) { ! 277: dPrintf(D_M_RTMP, D_L_WARNING, ! 278: ("rtmp_update : RTMP ID not as expected Net=%d L=x%x\n", ! 279: NET_VALUE(rtmp->at_rtmp_this_net), rtmp->at_rtmp_id_length)); ! 280: return; ! 281: } ! 282: ! 283: /* ! 284: * If the port is activating, only take the Network range from the ! 285: * the RTMP packet received. ! 286: * Check if there is a conflict with our seed infos. ! 287: */ ! 288: ! 289: if (ifID->ifRoutingState == PORT_ACTIVATING) { ! 290: if (PortFlags & RTR_XNET_PORT) { ! 291: if ((PortFlags & RTR_SEED_PORT) && ! 292: ((CableStart != TUPLENET(FirstTuple)) || ! 293: (CableStop != TUPLENET(SecondTuple)))) { ! 294: ifID->ifRoutingState = PORT_ERR_SEED; ! 295: ke.errno = KE_CONF_SEED_RNG; ! 296: ke.port1 = ifID->ifPort; ! 297: strncpy(ke.name1, ifID->ifName,IF_NAME_LEN); ! 298: ke.net = NET_VALUE(rtmp->at_rtmp_this_net); ! 299: ke.node = SenderNodeID; ! 300: ke.netr1b = TUPLENET(FirstTuple); ! 301: ke.netr1e = TUPLENET(SecondTuple); ! 302: ke.netr2b = CableStart; ! 303: ke.netr2e = CableStop; ! 304: RouterError(ifID->ifPort, ERTR_SEED_CONFLICT); ! 305: return; ! 306: } ! 307: CableStart = TUPLENET(FirstTuple); ! 308: CableStop = TUPLENET(SecondTuple); ! 309: /* ! 310: dPrintf(D_M_RTMP, D_L_INFO, ! 311: ("rtmp_update: Port #%d activating, set Cable %d-%d\n", ! 312: ifID->ifPort, CableStart, CableStop)); ! 313: */ ! 314: } ! 315: else { /* non extended cable */ ! 316: if ((PortFlags & RTR_SEED_PORT) && ! 317: (ifID->ifThisCableEnd != *(at_net_al*)&rtmp->at_rtmp_this_net)) { ! 318: ke.errno = KE_CONF_SEED1; ! 319: ke.port1 = ifID->ifPort; ! 320: strncpy(ke.name1, ifID->ifName,IF_NAME_LEN); ! 321: ke.net = NET_VALUE(rtmp->at_rtmp_this_net); ! 322: ke.node = SenderNodeID; ! 323: ke.netr1e = ifID->ifThisCableEnd; ! 324: ifID->ifRoutingState = PORT_ERR_SEED; ! 325: RouterError(ifID->ifPort, ERTR_SEED_CONFLICT); ! 326: return; ! 327: } ! 328: CableStop = *(at_net_al *)&rtmp->at_rtmp_this_net; ! 329: CableStart = 0; ! 330: dPrintf(D_M_RTMP, D_L_INFO, ! 331: ("rtmp_update: Port #%d NONX activating, set Cable %d-%d\n", ! 332: ifID->ifPort, CableStart, CableStop)); ! 333: } ! 334: ! 335: } ! 336: ! 337: /* ! 338: * Perform a few sanity checks on the received RTMP data packet ! 339: */ ! 340: ! 341: if ((PortFlags & RTR_XNET_PORT) && (tuple_nb >= 2)) { ! 342: ! 343: /* The first tuple must be extended */ ! 344: ! 345: if (! TUPLERANGE(FirstTuple)) { ! 346: dPrintf(D_M_RTMP, D_L_WARNING, ! 347: ("rtmp_update: bad range value in 1st tuple =%d\n", ! 348: TUPLERANGE(FirstTuple))); ! 349: return; ! 350: } ! 351: ! 352: if (PortFlags & RTR_SEED_PORT) ! 353: if ((TUPLENET(FirstTuple) != CableStart) || ! 354: (TUPLENET(SecondTuple) != CableStop)) { ! 355: dPrintf(D_M_RTMP, D_L_WARNING, ("rtmp_update: conflict on Seed Port\n")); ! 356: ifID->ifRoutingState = PORT_ERR_CABLER; ! 357: ke.errno = KE_CONF_SEED_NODE; ! 358: ke.port1 = ifID->ifPort; ! 359: strncpy(ke.name1, ifID->ifName,IF_NAME_LEN); ! 360: ke.net = NET_VALUE(rtmp->at_rtmp_this_net); ! 361: ke.node = SenderNodeID; ! 362: ke.netr1b = TUPLENET(FirstTuple); ! 363: ke.netr1e = TUPLENET(SecondTuple); ! 364: ke.netr2b = CableStart; ! 365: ke.netr2e = CableStop; ! 366: RouterError(ifID->ifPort, ERTR_CABLE_CONFLICT); ! 367: return; ! 368: } ! 369: ! 370: /* check that the tuple matches the range */ ! 371: ! 372: if ((TUPLENET(SecondTuple) < TUPLENET(FirstTuple)) || ! 373: (TUPLENET(FirstTuple) == 0) || ! 374: (TUPLENET(FirstTuple) >= DDP_STARTUP_LOW) || ! 375: (TUPLENET(SecondTuple) == 0) || ! 376: (TUPLENET(SecondTuple) >= DDP_STARTUP_LOW)) { ! 377: ! 378: /* ! 379: * IS THIS NON-FATAL????? ! 380: */ ! 381: dPrintf(D_M_RTMP, D_L_WARNING, ! 382: ("rtmp_update: STARTUP RANGE!!! 1st %d-%d\n", ! 383: TUPLENET(FirstTuple), TUPLENET(SecondTuple))); ! 384: ifID->ifRoutingState = PORT_ERR_STARTUP; ! 385: ke.errno = KE_SEED_STARTUP; ! 386: ke.port1 = ifID->ifPort; ! 387: strncpy(ke.name1, ifID->ifName,IF_NAME_LEN); ! 388: ke.net = NET_VALUE(rtmp->at_rtmp_this_net); ! 389: ke.node = SenderNodeID; ! 390: RouterError(ifID->ifPort, ERTR_CABLE_STARTUP); ! 391: return; ! 392: } ! 393: ! 394: if (TUPLEDIST(FirstTuple) != 0) { ! 395: dPrintf(D_M_RTMP, D_L_WARNING, ! 396: ("rtmp_update: Invalid distance in 1st tuple\n")); ! 397: return; ! 398: } ! 399: ! 400: if (rtmp->at_rtmp_id[6] != RTMP_VERSION_NUMBER) { ! 401: dPrintf(D_M_RTMP, D_L_WARNING, ! 402: ("rtmp_update: Invalid RTMP version = x%x\n", ! 403: rtmp->at_rtmp_id[6])); ! 404: return; ! 405: } ! 406: ! 407: ! 408: } ! 409: else { /* non extended interface or problem in tuple*/ ! 410: ! 411: if (PortFlags & RTR_XNET_PORT) { ! 412: dPrintf(D_M_RTMP, D_L_WARNING, ! 413: ("rtmp_update: invalid number of tuple for X-net\n")); ! 414: return; ! 415: } ! 416: ! 417: if (TUPLENET(FirstTuple) == 0) { /* non extended RTMP data */ ! 418: ! 419: if (rtmp->at_rtmp_id[3] > RTMP_VERSION_NUMBER) { ! 420: dPrintf(D_M_RTMP, D_L_WARNING, ! 421: ("rtmp_update: Invalid non extended RTMP version\n")); ! 422: return; ! 423: } ! 424: ! 425: } ! 426: else { ! 427: dPrintf(D_M_RTMP, D_L_WARNING, ! 428: ("rtmp_update: version 1.0 non Xtended net not supported\n")); ! 429: ifID->ifRoutingState = PORT_ERR_BADRTMP; ! 430: ke.errno = KE_BAD_VER; ! 431: ke.rtmp_id = rtmp->at_rtmp_id[6]; ! 432: ke.net = NET_VALUE(rtmp->at_rtmp_this_net); ! 433: ke.node = SenderNodeID; ! 434: RouterError(ifID->ifPort, ERTR_RTMP_BAD_VERSION); ! 435: return; ! 436: } ! 437: } ! 438: ! 439: ! 440: NewRoute.NextIRNet = NET_VALUE(rtmp->at_rtmp_this_net); ! 441: NewRoute.NextIRNode = SenderNodeID; ! 442: NewRoute.NetPort = ifID->ifPort; ! 443: ! 444: /* ! 445: * Process the case where a non-seed port needs to acquire the right ! 446: * information. ! 447: */ ! 448: ! 449: if (!(PortFlags & RTR_SEED_PORT) && (ifID->ifRoutingState == PORT_ACTIVATING)) { ! 450: dPrintf(D_M_RTMP_LOW, D_L_INFO, ! 451: ("rtmp_update: Port# %d, set non seed cable %d-%d\n", ! 452: ifID->ifPort, TUPLENET(FirstTuple), TUPLENET(SecondTuple))); ! 453: ! 454: if (PortFlags & RTR_XNET_PORT) { ! 455: NewRoute.NetStart = TUPLENET(FirstTuple); ! 456: NewRoute.NetStop = TUPLENET(SecondTuple); ! 457: ifID->ifThisCableStart = TUPLENET(FirstTuple); ! 458: ifID->ifThisCableEnd = TUPLENET(SecondTuple); ! 459: ! 460: ! 461: } ! 462: else { ! 463: ! 464: NewRoute.NetStart = 0; ! 465: NewRoute.NetStop = NET_VALUE(rtmp->at_rtmp_this_net); ! 466: ifID->ifThisCableStart = NET_VALUE(rtmp->at_rtmp_this_net); ! 467: ifID->ifThisCableEnd = NET_VALUE(rtmp->at_rtmp_this_net); ! 468: } ! 469: /* ! 470: * Now, check if we already know this route, or we need to add it ! 471: * (or modify it in the table accordingly) ! 472: */ ! 473: ! 474: if ((CurrentRoute = RT_LOOKUP(NewRoute)) && ! 475: (CurrentRoute->NetStop == NewRoute.NetStop) && ! 476: (CurrentRoute->NetStart == NewRoute.NetStart)) { ! 477: /*LD 7/31/95 tempo########*/ ! 478: if (NewRoute.NetPort != CurrentRoute->NetPort) { ! 479: dPrintf(D_M_RTMP, D_L_WARNING, ! 480: ("rtmp_update: port# %d, not the port we waited for %d\n", ! 481: ifID->ifPort, CurrentRoute->NetPort)); ! 482: /* propose to age the entry we know... */ ! 483: ! 484: state = CurrentRoute->EntryState & 0x0F; ! 485: /* if entry has been updated recently, just clear the UPDATED ! 486: bit. if bit not set, then we can age the entry */ ! 487: if (state) ! 488: if (CurrentRoute->EntryState & RTE_STATE_UPDATED) { ! 489: CurrentRoute->EntryState &= ~RTE_STATE_UPDATED; ! 490: } ! 491: else { ! 492: state = state >> 1 ; /* decrement state */ ! 493: } ! 494: ! 495: CurrentRoute->EntryState = (CurrentRoute->EntryState & 0xF0) | state; ! 496: } ! 497: } ! 498: ! 499: else { /* add the new route */ ! 500: ! 501: dPrintf(D_M_RTMP, D_L_INFO, ! 502: ("rtmp_update: P# %d, 1st tuple route not known, add %d-%d\n", ! 503: ifID->ifPort, NewRoute.NetStart, NewRoute.NetStop)); ! 504: ! 505: NewRoute.EntryState = RTE_STATE_GOOD|RTE_STATE_UPDATED; ! 506: NewRoute.NetDist = 0; ! 507: ! 508: if (rt_insert(NewRoute.NetStop, NewRoute.NetStart, 0, ! 509: 0, NewRoute.NetDist, NewRoute.NetPort, ! 510: NewRoute.EntryState) == (RT_entry *)NULL) ! 511: ! 512: ErrorRTMPoverflow = 1; ! 513: } ! 514: ! 515: } ! 516: ! 517: if (ifID->ifRoutingState == PORT_ACTIVATING) { ! 518: dPrintf(D_M_RTMP, D_L_INFO, ! 519: ("rtmp_update: port activating, ignoring remaining tuples\n")); ! 520: return; ! 521: } ! 522: ! 523: /* ! 524: * Process all the tuples against our routing table ! 525: */ ! 526: ! 527: TuplePtr = (char *)FirstTuple; ! 528: ! 529: ! 530: while (tuple_nb-- > 0) { ! 531: ! 532: ! 533: if (TUPLEDIST(TuplePtr) == NOTIFY_N_DIST) { ! 534: dPrintf(D_M_RTMP, D_L_INFO, ! 535: ("rtmp_update: Port# %d, Tuple with Notify Neighbour\n", ! 536: ifID->ifPort)); ! 537: NewRoute.NetDist = NOTIFY_N_DIST; ! 538: NewRoute.EntryState = RTE_STATE_BAD; ! 539: } ! 540: else { ! 541: NewRoute.NetDist = TUPLEDIST(TuplePtr) + 1; ! 542: NewRoute.EntryState = RTE_STATE_GOOD; ! 543: NewRoute.EntryState = RTE_STATE_GOOD|RTE_STATE_UPDATED; ! 544: } ! 545: ! 546: ! 547: if (TUPLERANGE(TuplePtr)) { /* Extended Tuple */ ! 548: ! 549: ! 550: NewRoute.NetStart = TUPLENET(TuplePtr); ! 551: TuplePtr += 3; ! 552: NewRoute.NetStop = TUPLENET((TuplePtr)); ! 553: TuplePtr += 3; ! 554: tuple_nb--; ! 555: ! 556: if ((NewRoute.NetDist == 0) || ! 557: (NewRoute.NetStart == 0) || ! 558: (NewRoute.NetStop == 0) || ! 559: (NewRoute.NetStop < NewRoute.NetStart) || ! 560: (NewRoute.NetStart >= DDP_STARTUP_LOW) || ! 561: (NewRoute.NetStop >= DDP_STARTUP_LOW)) { ! 562: ! 563: dPrintf(D_M_RTMP, D_L_WARNING, ! 564: ("rtmp_update: P# %d, non valid xtuple received [%d-%d]\n", ! 565: ifID->ifPort, NewRoute.NetStart, NewRoute.NetStop)); ! 566: ! 567: continue; ! 568: } ! 569: ! 570: } ! 571: else { /* Non Extended Tuple */ ! 572: ! 573: NewRoute.NetStart = 0; ! 574: NewRoute.NetStop = TUPLENET(TuplePtr); ! 575: ! 576: TuplePtr += 3; ! 577: ! 578: if ((NewRoute.NetDist == 0) || ! 579: (NewRoute.NetStop == 0) || ! 580: (NewRoute.NetStop >= DDP_STARTUP_LOW)) { ! 581: ! 582: dPrintf(D_M_RTMP, D_L_WARNING, ! 583: ("rtmp_update: P# %d, non valid tuple received [%d]\n", ! 584: ifID->ifPort, NewRoute.NetStop)); ! 585: ! 586: continue; ! 587: } ! 588: } ! 589: ! 590: if (CurrentRoute = RT_LOOKUP(NewRoute)) { /* found something... */ ! 591: ! 592: if (NewRoute.NetDist < 16 || NewRoute.NetDist == NOTIFY_N_DIST ) { ! 593: ! 594: /* ! 595: * Check if the definition of the route changed ! 596: */ ! 597: ! 598: if (NewRoute.NetStop != CurrentRoute->NetStop || ! 599: NewRoute.NetStart != CurrentRoute->NetStart) { ! 600: ! 601: if (NewRoute.NetStop == CurrentRoute->NetStop && ! 602: NewRoute.NetStop == CurrentRoute->NetStart && ! 603: NewRoute.NetStart == 0) ! 604: ! 605: NewRoute.NetStart = NewRoute.NetStop; ! 606: ! 607: else if (NewRoute.NetStop == CurrentRoute->NetStop && ! 608: NewRoute.NetStart == NewRoute.NetStop && ! 609: CurrentRoute->NetStart == 0) { ! 610: dPrintf(D_M_RTMP, D_L_WARNING, ! 611: ("rtmp_update: Range %d-%d has changed to %d-%d Dist=%d\n", ! 612: CurrentRoute->NetStart, CurrentRoute->NetStop, ! 613: NewRoute.NetStart, NewRoute.NetStop, NewRoute.NetDist)); ! 614: NewRoute.NetStart = 0; ! 615: } ! 616: ! 617: else { ! 618: dPrintf(D_M_RTMP, D_L_WARNING, ! 619: ("rtmp_update: Net Conflict Cur=%d, New=%d\n", ! 620: CurrentRoute->NetStop, NewRoute.NetStop)); ! 621: CurrentRoute->EntryState = ! 622: (CurrentRoute->EntryState & 0xF0) | RTE_STATE_BAD; ! 623: continue; ! 624: ! 625: } ! 626: } ! 627: ! 628: /* ! 629: * If we don't know the associated zones ! 630: */ ! 631: ! 632: if (!RT_ALL_ZONES_KNOWN(CurrentRoute)) { ! 633: ! 634: dPrintf(D_M_RTMP_LOW, D_L_INFO, ! 635: ("rtmp_update: Zone unknown for %d-%d state=0x%x\n", ! 636: CurrentRoute->NetStart, CurrentRoute->NetStop, ! 637: CurrentRoute->EntryState)); ! 638: ! 639: /* set the flag in the ifID structure telling ! 640: * that a scheduling of Zip Query is needed. ! 641: */ ! 642: ! 643: ifID->ifZipNeedQueries = 1; ! 644: continue; ! 645: } ! 646: ! 647: if (((CurrentRoute->EntryState & 0x0F) <= RTE_STATE_SUSPECT) && ! 648: NewRoute.NetDist != NOTIFY_N_DIST) { ! 649: ! 650: dPrintf(D_M_RTMP, D_L_INFO, ! 651: ("rtmp_update: update suspect entry %d-%d State=%d\n", ! 652: NewRoute.NetStart, NewRoute.NetStop, ! 653: (CurrentRoute->EntryState & 0x0F))); ! 654: ! 655: if (NewRoute.NetDist <= CurrentRoute->NetDist) { ! 656: CurrentRoute->NetDist = NewRoute.NetDist; ! 657: CurrentRoute->NetPort = NewRoute.NetPort; ! 658: CurrentRoute->NextIRNode = NewRoute.NextIRNode; ! 659: CurrentRoute->NextIRNet = NewRoute.NextIRNet; ! 660: CurrentRoute->EntryState = ! 661: (CurrentRoute->EntryState & 0xF0) | ! 662: (RTE_STATE_GOOD|RTE_STATE_UPDATED); ! 663: } ! 664: continue; ! 665: } ! 666: else { ! 667: ! 668: if (NewRoute.NetDist == NOTIFY_N_DIST) { ! 669: ! 670: CurrentRoute->EntryState = ! 671: (CurrentRoute->EntryState & 0xF0) | RTE_STATE_SUSPECT; ! 672: CurrentRoute->NetDist = NOTIFY_N_DIST; ! 673: continue; ! 674: } ! 675: } ! 676: ! 677: } ! 678: ! 679: ! 680: if ((NewRoute.NetDist <= CurrentRoute->NetDist) && (NewRoute.NetDist <16)) { ! 681: ! 682: /* Found a shorter or more recent Route, ! 683: * Replace with the New entryi ! 684: */ ! 685: ! 686: CurrentRoute->NetDist = NewRoute.NetDist; ! 687: CurrentRoute->NetPort = NewRoute.NetPort; ! 688: CurrentRoute->NextIRNode = NewRoute.NextIRNode; ! 689: CurrentRoute->NextIRNet = NewRoute.NextIRNet; ! 690: CurrentRoute->EntryState |= RTE_STATE_UPDATED; ! 691: ! 692: /* Can we consider now that the entry is updated? */ ! 693: dPrintf(D_M_RTMP_LOW, D_L_INFO, ! 694: ("rtmp_update: Shorter route found %d-%d, update\n", ! 695: NewRoute.NetStart, NewRoute.NetStop)); ! 696: ! 697: if (ddp_AURPsendx && (aurp_ifID->ifFlags & AT_IFF_AURP)) ! 698: ddp_AURPsendx(AURPCODE_RTUPDATE, ! 699: (void *)&NewRoute, AURPEV_NetDistChange); ! 700: } ! 701: } ! 702: else { /* no entry found */ ! 703: ! 704: if (NewRoute.NetDist < 16 && NewRoute.NetDist != NOTIFY_N_DIST && ! 705: NewRoute.NextIRNet >= ifID->ifThisCableStart && ! 706: NewRoute.NextIRNet <= ifID->ifThisCableEnd) { ! 707: ! 708: NewRoute.EntryState = (RTE_STATE_GOOD|RTE_STATE_UPDATED); ! 709: ! 710: dPrintf(D_M_RTMP_LOW, D_L_INFO, ! 711: ("rtmp_update: NewRoute %d-%d Tuple #%d\n", ! 712: NewRoute.NetStart, NewRoute.NetStop, tuple_nb)); ! 713: ! 714: ifID->ifZipNeedQueries = 1; ! 715: ! 716: if (rt_insert(NewRoute.NetStop, NewRoute.NetStart, NewRoute.NextIRNet, ! 717: NewRoute.NextIRNode, NewRoute.NetDist, NewRoute.NetPort, ! 718: NewRoute.EntryState) == (RT_entry *)NULL) ! 719: ErrorRTMPoverflow = 1; ! 720: ! 721: else if (ddp_AURPsendx && (aurp_ifID->ifFlags & AT_IFF_AURP)) ! 722: ddp_AURPsendx(AURPCODE_RTUPDATE, ! 723: (void *)&NewRoute, AURPEV_NetAdded); ! 724: } ! 725: } ! 726: ! 727: ! 728: ! 729: } /* end of main while */ ! 730: ifID->ifRouterState = ROUTER_UPDATED; ! 731: if (ifID->ifZipNeedQueries) ! 732: zip_send_queries(ifID, 0, 0xFF); ! 733: ! 734: /* ! 735: ifID->tmo_1 = atalk_timeout(rtmp_timeout, (caddr_t) ifID, 20*SYS_HZ); ! 736: */ ! 737: ! 738: } ! 739: /* The RTMP validity timer expired, we need to update the ! 740: * state of each routing entry in the table ! 741: * because there is only one validity timer and it is always running, ! 742: * we can't just age all the entries automatically, as we might be ! 743: * aging entries that were just updated. So, when an entry is updated, ! 744: * the RTE_STATE_UPDATED bit is set and when the aging routine is called ! 745: * it just resets this bit if it is set, only if it is not set will the ! 746: * route actually be aged. ! 747: * Note there are 4 states for an entry, the state is decremented until ! 748: * it reaches the bad state. At this point, the entry is removed ! 749: * ! 750: * RTE_STATE_GOOD : The entry was valid (will be SUSPECT) ! 751: * RTE_STATE_SUSPECT: The entry was suspect (can still be used for routing) ! 752: * RTE_STATE_BAD : The entry was bad and is now deleted ! 753: * RTE_STATE_UNUSED : Unused or removed entry in the table ! 754: */ ! 755: ! 756: void rtmp_timeout(ifID) ! 757: register at_if_t *ifID; ! 758: { ! 759: register u_char state; ! 760: register unsigned int s; ! 761: short i; ! 762: RT_entry *en = &RT_table[0]; ! 763: ! 764: if (ifID->ifRoutingState < PORT_ONLINE) ! 765: return; ! 766: ! 767: /* for multihoming mode, we use ifRouterState to tell if there ! 768: is a router out there, so we know when to use cable multicast */ ! 769: if (ifID->ifRouterState > NO_ROUTER) ! 770: ifID->ifRouterState--; ! 771: ! 772: ATDISABLE(s, ddpinp_lock); ! 773: for (i = 0 ; i < RT_MAXENTRY; i++,en++) { ! 774: ! 775: /* we want to age "learned" nets, not directly connected ones */ ! 776: state = en->EntryState & 0x0F; ! 777: ! 778: ! 779: if (state > RTE_STATE_UNUSED && ! 780: !(en->EntryState & RTE_STATE_PERMANENT) && en->NetStop && ! 781: en->NetDist && en->NetPort == ifID->ifPort) { ! 782: ! 783: /* if entry has been updated recently, just clear the UPDATED ! 784: bit. if bit not set, then we can age the entry */ ! 785: if (en->EntryState & RTE_STATE_UPDATED) { ! 786: en->EntryState &= ~RTE_STATE_UPDATED; ! 787: continue; ! 788: } ! 789: else ! 790: state = state >> 1 ; /* decrement state */ ! 791: ! 792: if (state == RTE_STATE_UNUSED) {/* was BAD, needs to delete */ ! 793: dPrintf(D_M_RTMP, D_L_INFO, ! 794: ("rtmp_timeout: Bad State for %d-%d (e#%d): remove\n", ! 795: en->NetStart, en->NetStop, i)); ! 796: ! 797: if (ddp_AURPsendx && (aurp_ifID->ifFlags & AT_IFF_AURP)) ! 798: ddp_AURPsendx(AURPCODE_RTUPDATE, ! 799: (void *)en, AURPEV_NetDeleted); ! 800: ! 801: /* then clear the bit in the table concerning this entry. ! 802: If the zone Count reaches zero, remove the entry */ ! 803: ! 804: zt_remove_zones(en->ZoneBitMap); ! 805: ! 806: RT_DELETE(en->NetStop, en->NetStart); ! 807: } ! 808: else { ! 809: en->EntryState = (en->EntryState & 0xF0) | state; ! 810: dPrintf(D_M_RTMP, D_L_INFO, ("Change State for %d-%d to %d (e#%d)\n", ! 811: en->NetStart, en->NetStop, state, i)); ! 812: } ! 813: } ! 814: } ! 815: ATENABLE(s, ddpinp_lock); ! 816: ifID->tmo_1 = atalk_timeout(rtmp_timeout, (caddr_t) ifID, 20*SYS_HZ); ! 817: ! 818: } ! 819: ! 820: /* ! 821: * rtmp_prep_new_packet: allocate a ddp packet for RTMP use (reply to a RTMP request or ! 822: * Route Data Request, or generation of RTMP data packets. ! 823: * The ddp header is filled with relevant information, as well as ! 824: * the beginning of the rtmp packet with the following info: ! 825: * Router's net number (2bytes) ! 826: * ID Length = 8 (1byte) ! 827: * Router's node ID (1byte) ! 828: * Extended Range Start (2bytes) ! 829: * Range + dist (0x80) (1byte) ! 830: * Extended Range End (2bytes) ! 831: * Rtmp version (0x82) (1byte) ! 832: * ! 833: */ ! 834: ! 835: gbuf_t *rtmp_prep_new_packet (ifID, DstNet, DstNode, socket) ! 836: register at_if_t *ifID; ! 837: register at_net DstNet; ! 838: register uchar DstNode; ! 839: register char socket; ! 840: ! 841: { ! 842: gbuf_t *m; ! 843: register at_ddp_t *ddp; ! 844: register char * rtmp_data; ! 845: ! 846: if ((m = gbuf_alloc(AT_WR_OFFSET+1024, PRI_HI)) == NULL) { ! 847: dPrintf(D_M_RTMP, D_L_WARNING, ("rtmp_new_packet: Can't allocate mblock\n")); ! 848: return ((gbuf_t *)NULL); ! 849: } ! 850: ! 851: gbuf_rinc(m,AT_WR_OFFSET); ! 852: gbuf_wset(m,DDP_X_HDR_SIZE + 10); ! 853: ddp = (at_ddp_t *)(gbuf_rptr(m)); ! 854: ! 855: /* ! 856: * Prepare the DDP header of the new packet ! 857: */ ! 858: ! 859: ! 860: ddp->unused = ddp->hopcount = 0; ! 861: ! 862: UAS_ASSIGN(ddp->checksum, 0); ! 863: ! 864: NET_NET(ddp->dst_net, DstNet); ! 865: ddp->dst_node = DstNode; ! 866: ddp->dst_socket = socket; ! 867: ! 868: NET_NET(ddp->src_net, ifID->ifThisNode.atalk_net); ! 869: ddp->src_node = ifID->ifThisNode.atalk_node; ! 870: ddp->src_socket = RTMP_SOCKET; ! 871: ddp->type = RTMP_DDP_TYPE; ! 872: ! 873: /* ! 874: * Prepare the RTMP header (Router Net, ID, Node and Net Tuple ! 875: * (this works only if we are on an extended net) ! 876: */ ! 877: ! 878: rtmp_data = ddp->data; ! 879: ! 880: *rtmp_data++ = (NET_VALUE(ifID->ifThisNode.atalk_net) & 0xff00) >> 8; ! 881: *rtmp_data++ = NET_VALUE(ifID->ifThisNode.atalk_net) & 0x00ff ; ! 882: *rtmp_data++ = 8; ! 883: *rtmp_data++ = (uchar)ifID->ifThisNode.atalk_node; ! 884: *rtmp_data++ = (CableStart & 0xff00) >> 8; ! 885: *rtmp_data++ = CableStart & 0x00ff ; ! 886: *rtmp_data++ = 0x80; /* first tuple, so distance is always zero */ ! 887: *rtmp_data++ = (CableStop & 0xff00) >> 8; ! 888: *rtmp_data++ = CableStop & 0x00ff ; ! 889: *rtmp_data++ = RTMP_VERSION_NUMBER; ! 890: ! 891: return (m); ! 892: ! 893: ! 894: } ! 895: int rtmp_r_find_bridge(ifID, orig_ddp) ! 896: register at_if_t *ifID; ! 897: register at_ddp_t *orig_ddp; ! 898: ! 899: { ! 900: gbuf_t *m; ! 901: register int size, status; ! 902: register at_ddp_t *ddp; ! 903: register char * rtmp_data; ! 904: RT_entry *Entry; ! 905: ! 906: ! 907: /* find the bridge for the querried net */ ! 908: ! 909: Entry = rt_blookup(NET_VALUE(orig_ddp->dst_net)); ! 910: ! 911: if (Entry == NULL) { ! 912: dPrintf(D_M_RTMP, D_L_WARNING, ("rtmp_r_find_bridge: no info for net %d\n", ! 913: NET_VALUE(orig_ddp->dst_net))); ! 914: return (1); ! 915: } ! 916: ! 917: ! 918: size = DDP_X_HDR_SIZE + 10 ; ! 919: if ((m = gbuf_alloc(AT_WR_OFFSET+size, PRI_HI)) == NULL) { ! 920: dPrintf(D_M_RTMP, D_L_WARNING, ("rtmp_r_find_bridge: Can't allocate mblock\n")); ! 921: return (ENOBUFS); ! 922: } ! 923: ! 924: gbuf_rinc(m,AT_WR_OFFSET); ! 925: gbuf_wset(m,size); ! 926: ddp = (at_ddp_t *)(gbuf_rptr(m)); ! 927: ! 928: /* ! 929: * Prepare the DDP header of the new packet ! 930: */ ! 931: ! 932: ddp->unused = ddp->hopcount = 0; ! 933: ! 934: DDPLEN_ASSIGN(ddp, size); ! 935: UAS_ASSIGN(ddp->checksum, 0); ! 936: ! 937: NET_NET(ddp->dst_net, orig_ddp->src_net); ! 938: ddp->dst_node = orig_ddp->src_node; ! 939: ddp->dst_socket = orig_ddp->src_socket; ! 940: ! 941: NET_ASSIGN(ddp->src_net, Entry->NextIRNet); ! 942: ddp->src_node = Entry->NextIRNode; ! 943: ddp->src_socket = RTMP_SOCKET; ! 944: ddp->type = RTMP_DDP_TYPE; ! 945: ! 946: /* ! 947: * Prepare the RTMP header (Router Net, ID, Node and Net Tuple ! 948: * (this works only if we are on an extended net) ! 949: */ ! 950: ! 951: rtmp_data = ddp->data; ! 952: ! 953: *rtmp_data++ = (Entry->NextIRNet & 0xff00) >> 8; ! 954: *rtmp_data++ = Entry->NextIRNet & 0x00ff ; ! 955: *rtmp_data++ = 8; ! 956: *rtmp_data++ = (uchar)Entry->NextIRNode; ! 957: *rtmp_data++ = (Entry->NetStart & 0xff00) >> 8; ! 958: *rtmp_data++ = Entry->NetStart & 0x00ff ; ! 959: *rtmp_data++ = 0x80; /* first tuple, so distance is always zero */ ! 960: *rtmp_data++ = (Entry->NetStop & 0xff00) >> 8; ! 961: *rtmp_data++ = Entry->NetStop & 0x00ff ; ! 962: *rtmp_data++ = RTMP_VERSION_NUMBER; ! 963: ! 964: ! 965: dPrintf(D_M_RTMP, D_L_INFO, ("rtmp_r_find_bridge: for net %d send back router %d.%d\n", ! 966: NET_VALUE(orig_ddp->dst_net), Entry->NextIRNet, Entry->NextIRNode)); ! 967: if (status = ddp_router_output(m, ifID, AT_ADDR, NET_VALUE(orig_ddp->src_net), ! 968: orig_ddp->src_node, 0)){ ! 969: dPrintf(D_M_RTMP, D_L_WARNING, ! 970: ("rtmp_r_find_bridge: ddp_router_output failed status=%d\n", status)); ! 971: return (status); ! 972: } ! 973: return (0); ! 974: } ! 975: ! 976: /* ! 977: * rtmp_send_table: ! 978: * Send the routing table entries in RTMP data packets. ! 979: * Use split horizon if specified. The Data packets are sent ! 980: * as full DDP packets, if the last packet is full an empty ! 981: * packet is sent to tell the recipients that this is the end of ! 982: * the table... ! 983: * ! 984: */ ! 985: static ! 986: int rtmp_send_table(ifID, DestNet, DestNode, split_hz, socket, n_neighbors) ! 987: register at_if_t *ifID; /* interface/port params */ ! 988: register at_net DestNet; /* net where to send the table */ ! 989: register uchar DestNode; /* node where to send to table */ ! 990: short split_hz; /* use split horizon */ ! 991: char socket; /* the destination socket to send to */ ! 992: short n_neighbors; /* used to send packets telling we are going down */ ! 993: { ! 994: ! 995: RT_entry *Entry; ! 996: char *Buff_ptr; ! 997: uchar NewDist; ! 998: gbuf_t *m; ! 999: short size,status ; ! 1000: register at_ddp_t *ddp; ! 1001: register short EntNb = 0, sent_tuple = 0; ! 1002: register unsigned int s; ! 1003: ! 1004: if (ifID->ifRoutingState < PORT_ONLINE) { ! 1005: dPrintf(D_M_RTMP, D_L_INFO, ! 1006: ("rtmp_send_table: port %d activating, we don't send anything!\n", ! 1007: ifID->ifPort)); ! 1008: return (0); ! 1009: } ! 1010: ! 1011: /* prerare tuples and packets for DDP*/ ! 1012: /* if split horizon, do not send tuples we can reach on the port we ! 1013: * want to send too ! 1014: */ ! 1015: ! 1016: Entry = &RT_table[0]; ! 1017: size = 0; ! 1018: if (!(m = rtmp_prep_new_packet(ifID, DestNet, DestNode, socket))) { ! 1019: dPrintf(D_M_RTMP, D_L_WARNING, ! 1020: ("rtmp_send_table: rtmp_prep_new_packet failed\n")); ! 1021: return(ENOBUFS); ! 1022: } ! 1023: ! 1024: ddp = (at_ddp_t *)(gbuf_rptr(m)); ! 1025: Buff_ptr = (char *)((char *)ddp + DDP_X_HDR_SIZE + 10); ! 1026: ! 1027: ATDISABLE(s, ddpinp_lock); ! 1028: while (EntNb < RT_MAXENTRY) { ! 1029: ! 1030: if (Entry->NetStop && ((Entry->EntryState & 0x0F) >= RTE_STATE_SUSPECT)) { ! 1031: if (!(split_hz && ifID->ifPort == Entry->NetPort)) { ! 1032: sent_tuple++; ! 1033: ! 1034: if (((Entry->EntryState & 0x0F) < RTE_STATE_SUSPECT) || n_neighbors) ! 1035: NewDist = NOTIFY_N_DIST; ! 1036: else ! 1037: NewDist = Entry->NetDist & 0x1F; ! 1038: ! 1039: if (Entry->NetStart) { /* Extended */ ! 1040: *Buff_ptr++ = (Entry->NetStart & 0xFF00) >> 8; ! 1041: *Buff_ptr++ = (Entry->NetStart & 0x00FF); ! 1042: *Buff_ptr++ = 0x80 | NewDist; ! 1043: *Buff_ptr++ = (Entry->NetStop & 0xFF00) >> 8; ! 1044: *Buff_ptr++ = (Entry->NetStop & 0x00FF); ! 1045: *Buff_ptr++ = RTMP_VERSION_NUMBER; ! 1046: size += 6; ! 1047: } ! 1048: else { /* non extended tuple */ ! 1049: *Buff_ptr++ = (Entry->NetStop & 0xFF00) >> 8; ! 1050: *Buff_ptr++ = (Entry->NetStop & 0x00FF); ! 1051: *Buff_ptr++ = NewDist; ! 1052: size += 3; ! 1053: } ! 1054: } ! 1055: } ! 1056: ! 1057: if (size > (DDP_MAX_DATA-20)) { ! 1058: DDPLEN_ASSIGN(ddp, size + DDP_X_HDR_SIZE + 10); ! 1059: gbuf_winc(m,size); ! 1060: ATENABLE(s, ddpinp_lock); ! 1061: if (status = ddp_router_output(m, ifID, AT_ADDR, ! 1062: NET_VALUE(DestNet),DestNode, 0)){ ! 1063: dPrintf(D_M_RTMP, D_L_WARNING, ! 1064: ("rtmp_send_table: ddp_router_output failed status=%d\n", ! 1065: status)); ! 1066: return (status); ! 1067: } ! 1068: if ((m = rtmp_prep_new_packet (ifID, DestNet, DestNode, socket)) == NULL){ ! 1069: dPrintf(D_M_RTMP, D_L_WARNING, ! 1070: ("rtmp_send_table: rtmp_prep_new_poacket failed status=%d\n", ! 1071: status)); ! 1072: return (ENOBUFS); ! 1073: } ! 1074: ddp = (at_ddp_t *)(gbuf_rptr(m)); ! 1075: Buff_ptr = (char *)((char *)ddp + DDP_X_HDR_SIZE + 10); ! 1076: ! 1077: dPrintf(D_M_RTMP_LOW, D_L_OUTPUT, ! 1078: ("rtmp_s_tble: Send %d tuples on port %d\n", ! 1079: sent_tuple, ifID->ifPort)); ! 1080: sent_tuple = 0; ! 1081: size = 0; ! 1082: ATDISABLE(s, ddpinp_lock); ! 1083: } ! 1084: ! 1085: Entry++; ! 1086: EntNb++; ! 1087: } ! 1088: ATENABLE(s, ddpinp_lock); ! 1089: ! 1090: /* ! 1091: * If we have some remaining entries to send, send them now. ! 1092: * otherwise, the last packet we sent was full, we need to send an empty one ! 1093: */ ! 1094: ! 1095: DDPLEN_ASSIGN(ddp, size + DDP_X_HDR_SIZE + 10); ! 1096: gbuf_winc(m,size); ! 1097: if (status = ddp_router_output(m, ifID, AT_ADDR, NET_VALUE(DestNet),DestNode, 0)){ ! 1098: dPrintf(D_M_RTMP, D_L_WARNING, ! 1099: ("rtmp_send_table: ddp_router_output failed status=%d\n", status)); ! 1100: return (status); ! 1101: } ! 1102: dPrintf(D_M_RTMP_LOW, D_L_OUTPUT, ! 1103: ("rtmp_s_tble: LAST Packet split=%d with %d tuples sent on port %d\n", ! 1104: split_hz, sent_tuple, ifID->ifPort)); ! 1105: ! 1106: return (0); ! 1107: } ! 1108: ! 1109: /* ! 1110: * rtmp_request: respond to the 3 types of RTMP requests RTMP may receive ! 1111: * RTMP func =1 : respond with an RTMP Reponse Packet ! 1112: * RTMP func =2 : respond with the routing table RTMP packet with split horizon ! 1113: * RTMP func =3 : respond with the routing table RTMP packet no split horizon ! 1114: * ! 1115: * see Inside AppleTalk around page 5-18 for "details" ! 1116: */ ! 1117: ! 1118: static ! 1119: void rtmp_request(ifID, ddp) ! 1120: register at_if_t *ifID; ! 1121: register at_ddp_t *ddp; ! 1122: { ! 1123: ! 1124: short split_horizon = FALSE; ! 1125: short code; ! 1126: short error; ! 1127: ! 1128: /* We ignore the request if we're activating on that port */ ! 1129: ! 1130: if (ifID->ifRoutingState < PORT_ONLINE) ! 1131: return; ! 1132: ! 1133: /* check RTMP function code */ ! 1134: ! 1135: code = ddp->data[0]; ! 1136: ! 1137: switch (code) { ! 1138: ! 1139: case RTMP_REQ_FUNC1: /* RTMP Find Bridge */ ! 1140: ! 1141: /* RTMP Request Packet: we send a response with the next IRrange */ ! 1142: dPrintf(D_M_RTMP, D_L_INPUT, ! 1143: ( "rtmp_request: find bridge for net %d port %d node %d.%d\n", ! 1144: NET_VALUE(ddp->dst_net), ifID->ifPort, ! 1145: NET_VALUE(ddp->src_net), ddp->src_node)); ! 1146: ! 1147: if (error = rtmp_r_find_bridge (ifID, ddp)) { ! 1148: dPrintf(D_M_RTMP, D_L_WARNING, ! 1149: ("rtmp_request: Code 1 ddp_r_output failed error=%d\n", ! 1150: error)); ! 1151: return; ! 1152: } ! 1153: ! 1154: break; ! 1155: ! 1156: case RTMP_REQ_FUNC2: ! 1157: ! 1158: split_horizon = TRUE; ! 1159: ! 1160: case RTMP_REQ_FUNC3: ! 1161: ! 1162: /* RTMP Route Request Packet */ ! 1163: ! 1164: dPrintf(D_M_RTMP, D_L_INPUT, ! 1165: ("rtmp_request: received code=%d from %d.%d for %d.%d\n", ! 1166: code, NET_VALUE(ddp->src_net), ddp->src_node, ! 1167: NET_VALUE(ddp->dst_net), ddp->dst_node)); ! 1168: ! 1169: rtmp_send_table(ifID, ddp->src_net, ddp->src_node, ! 1170: split_horizon, ddp->src_socket, 0); ! 1171: ! 1172: break; ! 1173: ! 1174: default: ! 1175: ! 1176: /* unknown type of request */ ! 1177: dPrintf(D_M_RTMP, D_L_WARNING, ! 1178: ("rtmp_request : invalid type of request =%d\n", ! 1179: code)); ! 1180: break; ! 1181: } ! 1182: ! 1183: } ! 1184: ! 1185: /* ! 1186: * rtmp_send_all_ports : send the routing table on all connected ports ! 1187: * check for the port status and if ok, send the ! 1188: * rtmp tuples to the broadcast address for the port ! 1189: * usually called on timeout every 10 seconds. ! 1190: */ ! 1191: ! 1192: void rtmp_send_port(ifID) ! 1193: register at_if_t *ifID; ! 1194: { ! 1195: at_net DestNet; ! 1196: ! 1197: NET_ASSIGN(DestNet, 0); ! 1198: ! 1199: if (ifID && IFID_VALID(ifID) && ifID->ifRoutingState == PORT_ONLINE) { ! 1200: dPrintf(D_M_RTMP_LOW, D_L_OUTPUT, ! 1201: ("rtmp_send_port: do stuff for port=%d\n", ! 1202: ifID->ifPort)); ! 1203: if (ifID->ifZipNeedQueries) ! 1204: zip_send_queries(ifID, 0, 0xFF); ! 1205: if (MULTIHOME_MODE) ! 1206: return(0); ! 1207: rtmp_send_table(ifID, DestNet, 0xFF, 1, RTMP_SOCKET, 0); ! 1208: } ! 1209: ! 1210: if (ifID == ifID_table[0]) ! 1211: dPrintf(D_M_RTMP_LOW, D_L_VERBOSE, ! 1212: ("I:%5d O:%5d H:%5d dropped:%d\n",pktsIn,pktsOut, pktsHome ,pktsDropped)); ! 1213: ! 1214: dPrintf(D_M_RTMP_LOW, D_L_TRACE, ! 1215: ("rtmp_send_port: func=0x%x, ifID=0x%x\n", (u_int) rtmp_send_port, (u_int) ifID)); ! 1216: ifID->tmo_2 = atalk_timeout (rtmp_send_port, (caddr_t)ifID, 10 * SYS_HZ); ! 1217: } ! 1218: ! 1219: /* rtmp_dropper: check the number of packet received every x secondes. ! 1220: * the actual packet dropping is done in ddp_input ! 1221: */ ! 1222: ! 1223: void rtmp_dropper() ! 1224: { ! 1225: pktsIn = pktsOut = pktsHome = pktsDropped = 0; ! 1226: dropper_tmo = atalk_timeout(rtmp_dropper, NULL, 2*SYS_HZ); ! 1227: } ! 1228: ! 1229: /* ! 1230: * rtmp_router_start: perform the sanity checks before declaring the router up ! 1231: * and running. This function looks for discrepency between the net infos ! 1232: * for the different ports and seed problems. ! 1233: * If everything is fine, the state of each port is brought to PORT_ONLINE.\ ! 1234: * ### LD 01/09/95 Changed to correct Zone problem on non seed ports. ! 1235: */ ! 1236: ! 1237: int rtmp_router_start(flag, m, gref) ! 1238: int flag; ! 1239: gbuf_t *m; ! 1240: gref_t *gref; ! 1241: { ! 1242: static short next_i = 0, next_router_starting_timer = 0; ! 1243: int err; ! 1244: register at_if_t *ifID, *ifID2; ! 1245: register short i,j,k, Index, router_starting_timer = 0; ! 1246: register RT_entry *Entry; ! 1247: register at_net_al netStart, netStop; ! 1248: ! 1249: switch (flag) { ! 1250: case 1: ! 1251: if ((m = at_delay_m) != NULL) { ! 1252: at_delay_m = NULL; ! 1253: at_delay_func = rtmp_router_start; ! 1254: at_delay_flag = 2; ! 1255: ioc_ack(ENOTREADY, m, at_delay_gref); ! 1256: } ! 1257: return (0); ! 1258: case 2: ! 1259: goto startZoneInfo; ! 1260: case 3: ! 1261: if ((m = at_delay_m) != NULL) { ! 1262: at_delay_m = NULL; ! 1263: at_delay_func = rtmp_router_start; ! 1264: at_delay_flag = 4; ! 1265: ioc_ack(ENOTREADY, m, at_delay_gref); ! 1266: } ! 1267: return (0); ! 1268: case 4: ! 1269: goto startZoneInfoCont; ! 1270: case 9: ! 1271: goto elap_onlineCont; ! 1272: default: ! 1273: break; ! 1274: } ! 1275: ! 1276: for (i= 0; i < IF_TOTAL_MAX; i++) { ! 1277: ifID = ifID_table[i]; ! 1278: ! 1279: if (!ifID || !IFID_VALID(ifID)) ! 1280: break; ! 1281: ! 1282: /* if non seed, need to acquire the right node address */ ! 1283: ! 1284: if ((ifID->ifFlags & RTR_SEED_PORT) == 0) { ! 1285: if ((ifID->ifThisCableStart == 0 && ifID->ifThisCableEnd == 0) || ! 1286: (ifID->ifThisCableStart >= DDP_STARTUP_LOW && ! 1287: ifID->ifThisCableEnd <= DDP_STARTUP_HIGH)) { ! 1288: ! 1289: if (ifID->ifThisCableEnd == 0) { ! 1290: ke.errno = KE_NO_SEED; ! 1291: ke.port1 = ifID->ifPort; ! 1292: strncpy(ke.name1, ifID->ifName,IF_NAME_LEN); ! 1293: } ! 1294: else { ! 1295: ke.errno = KE_INVAL_RANGE; ! 1296: ke.port1 = ifID->ifPort; ! 1297: strncpy(ke.name1, ifID->ifName,IF_NAME_LEN); ! 1298: ke.netr1b = ifID->ifThisCableStart; ! 1299: ke.netr1e = ifID->ifThisCableEnd; ! 1300: } ! 1301: ifID->ifRoutingState = PORT_ERR_STARTUP; ! 1302: RouterError(ifID->ifPort, ERTR_CABLE_STARTUP); ! 1303: ! 1304: goto error; ! 1305: } ! 1306: ! 1307: /* we are non seed, so try to acquire the zones for that guy */ ! 1308: ifID->ifZipNeedQueries = 1; ! 1309: ! 1310: dPrintf(D_M_RTMP, D_L_STARTUP, ! 1311: ("rtmp_router_start: call elap_online for Non Seed port #%d cable =%d-%d\n", ! 1312: ifID->ifPort, CableStart, CableStop)); ! 1313: at_delay_func = rtmp_router_start; ! 1314: at_delay_flag = 9; ! 1315: at_delay_errno = ENOTREADY; ! 1316: err = elap_online(gref, ifID->ifName, NULL, m); ! 1317: if (err != ENOTREADY) { ! 1318: at_delay_m = m; ! 1319: at_delay_gref = gref; ! 1320: goto error; ! 1321: } ! 1322: next_i = i; ! 1323: return (ENOTREADY); ! 1324: elap_onlineCont: ! 1325: i = next_i; ! 1326: } ! 1327: } ! 1328: next_i = 0; ! 1329: ! 1330: ! 1331: /* Check if we have a problem with the routing table size */ ! 1332: ! 1333: if (ErrorRTMPoverflow) { ! 1334: ke.errno = KE_RTMP_OVERFLOW; ! 1335: goto error; ! 1336: } ! 1337: ! 1338: ! 1339: /* Now, check that we don't have a conflict in between our interfaces */ ! 1340: ! 1341: for (i= 0; i < IF_TOTAL_MAX; i++) { ! 1342: ifID = ifID_table[i]; ! 1343: ! 1344: if (!ifID || !IFID_VALID(ifID)) ! 1345: break; ! 1346: ! 1347: /* check if the RoutingState != PORT_ONERROR */ ! 1348: ! 1349: if (ifID->ifRoutingState < PORT_ACTIVATING) { ! 1350: goto error; ! 1351: } ! 1352: ! 1353: if ((ifID->ifThisCableStart == 0 && ifID->ifThisCableEnd == 0) || ! 1354: (ifID->ifThisCableStart >= DDP_STARTUP_LOW && ! 1355: ifID->ifThisCableEnd <= DDP_STARTUP_HIGH)) { ! 1356: ! 1357: if (ifID->ifThisCableEnd == 0) { ! 1358: ke.errno = KE_NO_SEED; ! 1359: ke.port1 = ifID->ifPort; ! 1360: strncpy(ke.name1, ifID->ifName,IF_NAME_LEN); ! 1361: } ! 1362: else { ! 1363: ke.errno = KE_INVAL_RANGE; ! 1364: ke.port1 = ifID->ifPort; ! 1365: strncpy(ke.name1, ifID->ifName,IF_NAME_LEN); ! 1366: ke.netr1b = ifID->ifThisCableStart; ! 1367: ke.netr1e = ifID->ifThisCableEnd; ! 1368: } ! 1369: ! 1370: ifID->ifRoutingState = PORT_ERR_STARTUP; ! 1371: RouterError(ifID->ifPort, ERTR_CABLE_STARTUP); ! 1372: ! 1373: goto error; ! 1374: } ! 1375: ! 1376: /* check the interface address against all other ifs */ ! 1377: ! 1378: netStart = ifID->ifThisCableStart; ! 1379: netStop = ifID->ifThisCableEnd; ! 1380: ! 1381: for (j = i+1 ; j < IF_TOTAL_MAX ; j++) { ! 1382: ifID2 = ifID_table[j]; ! 1383: if (!ifID2 || !IFID_VALID(ifID2)) ! 1384: break; ! 1385: ! 1386: if (((netStart >= ifID2->ifThisCableStart) && ! 1387: (netStart <= ifID2->ifThisCableEnd)) || ! 1388: ((netStop >= ifID2->ifThisCableStart) && ! 1389: (netStop <= ifID2->ifThisCableEnd)) || ! 1390: ((ifID2->ifThisCableStart >= netStart) && ! 1391: (ifID2->ifThisCableStart <= netStop)) || ! 1392: ((ifID2->ifThisCableEnd >= netStart) && ! 1393: (ifID2->ifThisCableEnd <= netStop)) ) { ! 1394: ! 1395: ke.errno = KE_CONF_RANGE; ! 1396: ke.port1 = ifID->ifPort; ! 1397: strncpy(ke.name1, ifID->ifName,IF_NAME_LEN); ! 1398: ke.port2 = ifID2->ifPort; ! 1399: strncpy(ke.name2, ifID2->ifName,IF_NAME_LEN); ! 1400: ke.netr1b = ifID->ifThisCableStart; ! 1401: ke.netr1e = ifID->ifThisCableEnd; ! 1402: ifID->ifRoutingState = PORT_ERR_CABLER; ! 1403: RouterError(ifID->ifPort, ERTR_CABLE_CONFLICT); ! 1404: goto error; ! 1405: } ! 1406: ! 1407: } ! 1408: ! 1409: /* ### LD 01/04/94: We need to fill in the next IR info in the routing table */ ! 1410: Entry = rt_blookup(ifID->ifThisCableEnd); ! 1411: ! 1412: if (Entry == NULL) { ! 1413: dPrintf(D_M_RTMP, D_L_ERROR, ! 1414: ("rtmp_router_start: we don't know our cable range port=%d\n", ! 1415: ifID->ifPort)); ! 1416: ! 1417: goto error; ! 1418: } ! 1419: ! 1420: /* ! 1421: * Note: At this point, non seed ports may not be aware of their Default zone ! 1422: */ ! 1423: ! 1424: if (!(ifID->ifFlags & RTR_SEED_PORT)) { ! 1425: ifID->ifDefZone = 0; ! 1426: Entry->EntryState |= (RTE_STATE_GOOD|RTE_STATE_UPDATED); ! 1427: } ! 1428: ! 1429: ! 1430: ifID->ifRoutingState = PORT_ONLINE; ! 1431: ifID->ifState = LAP_ONLINE; ! 1432: ! 1433: /* set the right net and node for each port */ ! 1434: ! 1435: Entry->NextIRNet = NET_VALUE(ifID->ifThisNode.atalk_net); ! 1436: Entry->NextIRNode= ifID->ifThisNode.atalk_node; ! 1437: ! 1438: dPrintf(D_M_RTMP, D_L_STARTUP, ! 1439: ("rtmp_router_start: bring port=%d [%d.%d]... on line\n", ! 1440: ifID->ifPort, NET_VALUE(ifID->ifThisNode.atalk_net),ifID->ifThisNode.atalk_node)); ! 1441: ! 1442: } ! 1443: ! 1444: /* ! 1445: * Everything is fine, we can begin to babble on the net... ! 1446: */ ! 1447: ! 1448: for (k= 0; k < IF_TOTAL_MAX ; k++) { ! 1449: ifID = ifID_table[k]; ! 1450: if (ifID && IFID_VALID(ifID) && ifID->ifRoutingState == PORT_ONLINE) { ! 1451: rtmp_send_port(ifID); ! 1452: ifID->tmo_1 = atalk_timeout (rtmp_timeout, (caddr_t)ifID, (50+k) * SYS_HZ); ! 1453: if (ifID->ifRoutingState < PORT_ACTIVATING) { ! 1454: goto error; ! 1455: } ! 1456: } ! 1457: } ! 1458: ! 1459: /* Check if we have a problem with the routing or zip table size */ ! 1460: ! 1461: if (ErrorRTMPoverflow) { ! 1462: ke.errno = KE_RTMP_OVERFLOW; ! 1463: goto error; ! 1464: } ! 1465: if (ErrorZIPoverflow) { ! 1466: ke.errno = KE_ZIP_OVERFLOW; ! 1467: goto error; ! 1468: } ! 1469: ! 1470: at_delay_m = m; at_delay_gref = gref; ! 1471: atalk_timeout(rtmp_router_start, 1, 10 * SYS_HZ); ! 1472: return (ENOTREADY); ! 1473: ! 1474: startZoneInfo: ! 1475: for (i= 0; i < IF_TOTAL_MAX; i++) { ! 1476: ifID = ifID_table[i]; ! 1477: ! 1478: if (!ifID || !IFID_VALID(ifID)) ! 1479: break; ! 1480: ! 1481: if (ifID->ifRoutingState < PORT_ACTIVATING) { ! 1482: goto error; ! 1483: } ! 1484: ! 1485: if ((ifID->ifZipNeedQueries) ! 1486: && (ifID->ifFlags & RTR_SEED_PORT) == 0) { ! 1487: dPrintf(D_M_RTMP, D_L_STARTUP, ! 1488: ("rtmp_router_start: send Zip Queries for Port %d\n", ! 1489: ifID->ifPort)); ! 1490: zip_send_queries(ifID, 0, 0xFF); ! 1491: ! 1492: if (router_starting_timer >= 15) { ! 1493: dPrintf(D_M_RTMP, D_L_WARNING, ! 1494: ("rtmp_router_start: no received response to ZipNeedQueries\n")); ! 1495: ke.errno = KE_NO_ZONES_FOUND; ! 1496: ke.port1 = ifID->ifPort; ! 1497: strncpy(ke.name1, ifID->ifName,IF_NAME_LEN); ! 1498: ke.netr1b = ifID->ifThisCableStart; ! 1499: ke.netr1e = ifID->ifThisCableEnd; ! 1500: ifID->ifRoutingState = PORT_ERR_CABLER; ! 1501: RouterError(ifID->ifPort, ERTR_CABLE_CONFLICT); ! 1502: goto error; ! 1503: } ! 1504: ! 1505: dPrintf(D_M_RTMP, D_L_STARTUP, ! 1506: ("rtmp_router_start: waiting for zone info to complete\n")); ! 1507: at_delay_m = m; at_delay_gref = gref; ! 1508: atalk_timeout(rtmp_router_start, 3, 10 * SYS_HZ); ! 1509: next_router_starting_timer = router_starting_timer+1; ! 1510: return (ENOTREADY); ! 1511: startZoneInfoCont: ! 1512: router_starting_timer = next_router_starting_timer; ! 1513: i=0; ! 1514: goto startZoneInfo; ! 1515: } ! 1516: ! 1517: } ! 1518: next_router_starting_timer = 0; ! 1519: ! 1520: /* At This Point, check if we know the default zones for non seed port */ ! 1521: ! 1522: for (i= 0; i < IF_TOTAL_MAX; i++) { ! 1523: ifID = ifID_table[i]; ! 1524: ! 1525: if (!ifID || !IFID_VALID(ifID)) ! 1526: break; ! 1527: ! 1528: if (ifID->ifRoutingState < PORT_ACTIVATING){ ! 1529: goto error; ! 1530: } ! 1531: ! 1532: ! 1533: if (!(ifID->ifFlags & RTR_SEED_PORT)) { ! 1534: Entry = rt_blookup(ifID->ifThisCableEnd); ! 1535: ! 1536: if (Entry == NULL) { ! 1537: dPrintf(D_M_RTMP, D_L_ERROR, ! 1538: ("rtmp_router_start: (2)we don't know our cable range port=%d\n", ! 1539: ifID->ifPort)); ! 1540: goto error; ! 1541: } ! 1542: if (!(ifID->ifFlags & RTR_SEED_PORT)) { ! 1543: ! 1544: dPrintf(D_M_RTMP, D_L_STARTUP, ! 1545: ("rtmp_router_start: if %s set to permanent\n", ! 1546: ifID->ifName)); ! 1547: Entry->NetDist = 0; /* added 4-29-96 jjs, prevent direct ! 1548: nets from showing non-zero distance */ ! 1549: Entry->EntryState |= RTE_STATE_PERMANENT; /* upgrade the non seed ports. */ ! 1550: } ! 1551: ! 1552: Index = zt_ent_zindex(Entry->ZoneBitMap); ! 1553: if (Index <= 0) { ! 1554: dPrintf(D_M_RTMP, D_L_ERROR, ! 1555: ("rtmp_router_start: still don't know default zone for port %d\n", ! 1556: ifID->ifPort)); ! 1557: } ! 1558: else if (ROUTING_MODE) ! 1559: ifID->ifDefZone = Index; ! 1560: ! 1561: ! 1562: } ! 1563: ! 1564: } ! 1565: ! 1566: /* Check if we have a problem with the routing or zip table size */ ! 1567: ! 1568: if (ErrorRTMPoverflow) { ! 1569: ke.errno = KE_RTMP_OVERFLOW; ! 1570: goto error; ! 1571: } ! 1572: if (ErrorZIPoverflow) { ! 1573: ke.errno = KE_ZIP_OVERFLOW; ! 1574: goto error; ! 1575: } ! 1576: ! 1577: /* ! 1578: * Handle the Home Port specifics ! 1579: */ ! 1580: ! 1581: ifID = ifID_table[IFID_HOME]; ! 1582: ! 1583: /* set the router address as being us no matter what*/ ! 1584: ! 1585: NET_NET(ifID->ifARouter.atalk_net , ifID->ifThisNode.atalk_net); ! 1586: ifID->ifARouter.atalk_node = ifID->ifThisNode.atalk_node; ! 1587: ifID->ifRouterState = ROUTER_UPDATED; ! 1588: ! 1589: /* if we are non seed, take the first zone of the list as our home zone */ ! 1590: ! 1591: if ( 0 && !(ifID->ifFlags & RTR_SEED_PORT)) { ! 1592: Entry = rt_blookup(ifID->ifThisCableEnd); ! 1593: if (Entry != NULL) { ! 1594: Index = zt_ent_zindex(Entry->ZoneBitMap); ! 1595: ! 1596: ifID->ifDefZone = Index; ! 1597: dPrintf(D_M_RTMP, D_L_ERROR, ! 1598: ("rtmp_router_start: Index of default zone is: %d\n", ! 1599: Index)); ! 1600: ! 1601: ifID->ifZoneName.len = ZT_table[Index-1].Zone.len; ! 1602: ! 1603: dPrintf(D_M_RTMP, D_L_STARTUP, ! 1604: ("rtmp_router_start: Zone Name '%s' (#%d) set for non seed home port\n", ! 1605: ZT_table[Index-1].Zone.str, Index-1)); ! 1606: ! 1607: bcopy(&ZT_table[Index-1].Zone.str, &ifID->ifZoneName.str, ! 1608: ZT_table[Index-1].Zone.len); ! 1609: ! 1610: } ! 1611: } ! 1612: if (MULTIHOME_MODE) ! 1613: at_state.flags &= ~AT_ST_ROUTER; ! 1614: ! 1615: /* set the zone and stuffs for NBP */ ! 1616: ! 1617: zip_notify_nbp((int)ifID); ! 1618: ! 1619: if ((m = at_delay_m) != NULL) { ! 1620: at_delay_m = NULL; ! 1621: ioc_ack(0, m, at_delay_gref); ! 1622: } ! 1623: ! 1624: /* prepare the packet dropper timer */ ! 1625: ! 1626: dropper_tmo = atalk_timeout (rtmp_dropper, NULL, 1*SYS_HZ); ! 1627: return(0); ! 1628: ! 1629: error: ! 1630: dPrintf(D_M_RTMP,D_L_ERROR, ! 1631: ("rtmp_router_start: error type=%d occured on port %d\n", ! 1632: ifID->ifRoutingState, ifID->ifPort)); ! 1633: rtmp_shutdown(); ! 1634: if (m) { ! 1635: at_delay_m = m; ! 1636: at_delay_gref = gref; ! 1637: } ! 1638: if ((m = at_delay_m) != NULL) { ! 1639: at_delay_m = NULL; ! 1640: if ((gbuf_cont(m) = gbuf_alloc(sizeof(ke), PRI_HI)) == NULL) ! 1641: ioc_ack(ENOBUFS, m, gref); ! 1642: else { ! 1643: bcopy(&ke, gbuf_rptr(gbuf_cont(m)), sizeof(ke)); ! 1644: gbuf_wset(gbuf_cont(m),sizeof(ke)); ! 1645: ((ioc_t *)gbuf_rptr(m))->ioc_count = sizeof(ke); ! 1646: ioc_ack(0, m, at_delay_gref); ! 1647: } ! 1648: } ! 1649: next_i = 0; ! 1650: return(ENOTREADY); ! 1651: } ! 1652: ! 1653: ! 1654: void rtmp_shutdown() ! 1655: { ! 1656: register at_if_t *ifID; ! 1657: register short i; ! 1658: at_net DestNet; ! 1659: ! 1660: #ifdef CHECK_DDPR_FLAG ! 1661: while (ddprunning_flag) ! 1662: ; ! 1663: #endif ! 1664: NET_ASSIGN(DestNet, 0); ! 1665: ! 1666: dPrintf(D_M_RTMP, D_L_SHUTDN, ! 1667: ("rtmp_shutdown:stop sending to all ports\n")); ! 1668: ! 1669: untimeout(rtmp_dropper, (caddr_t)0); ! 1670: untimeout(rtmp_router_start, 1); /* added for 2225395 */ ! 1671: untimeout(rtmp_router_start, 3); /* added for 2225395 */ ! 1672: ! 1673: for (i= 0; i < IF_TOTAL_MAX; i++) { ! 1674: ifID = ifID_table[i]; ! 1675: if (ifID && IFID_VALID(ifID) && ifID->ifRoutingState > PORT_OFFLINE ) { ! 1676: if (ifID->ifRoutingState == PORT_ONLINE) { ! 1677: untimeout(rtmp_send_port, (caddr_t)ifID); ! 1678: untimeout(rtmp_timeout, (caddr_t) ifID); ! 1679: } ! 1680: /* ! 1681: * it's better to notify the neighbour routers that we are going down ! 1682: */ ! 1683: if (!MULTIHOME_MODE) ! 1684: rtmp_send_table(ifID, DestNet, 0xFF, TRUE, RTMP_SOCKET, TRUE); ! 1685: ! 1686: rtmp_send_table(ifID, DestNet, 0xFF, TRUE, RTMP_SOCKET, TRUE); ! 1687: ! 1688: ifID->ifRoutingState = PORT_OFFLINE; ! 1689: ! 1690: dPrintf(D_M_RTMP, D_L_SHUTDN, ! 1691: ("rtmp_shutdown: routing on port=%d... off line\nStats:\n", ! 1692: ifID->ifPort)); ! 1693: dPrintf(D_M_RTMP, D_L_SHUTDN, ! 1694: ("fwdBytes : %ld\nfwdPackets : %ld\ndroppedBytes : %ld\ndroppedPkts : %ld\n", ! 1695: ifID->ifStatistics.fwdBytes, ifID->ifStatistics.fwdPkts, ! 1696: ifID->ifStatistics.droppedBytes, ifID->ifStatistics.droppedPkts)); ! 1697: ! 1698: } ! 1699: } ! 1700: ! 1701: } ! 1702: ! 1703: /* ! 1704: * Remove all entries associated with the specified port. ! 1705: */ ! 1706: void rtmp_purge(ifID) ! 1707: at_if_t *ifID; ! 1708: { ! 1709: u_char state; ! 1710: int i, s; ! 1711: RT_entry *en = &RT_table[0]; ! 1712: ! 1713: ATDISABLE(s, ddpinp_lock); ! 1714: for (i=0; i < RT_MAXENTRY; i++) { ! 1715: state = en->EntryState & 0x0F; ! 1716: if ((state > RTE_STATE_UNUSED) && (state != RTE_STATE_PERMANENT) ! 1717: && en->NetStop && en->NetDist && (en->NetPort == ifID->ifPort)) { ! 1718: zt_remove_zones(en->ZoneBitMap); ! 1719: RT_DELETE(en->NetStop, en->NetStart); ! 1720: } ! 1721: en++; ! 1722: } ! 1723: ATENABLE(s, ddpinp_lock); ! 1724: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.