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