|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Packet.c ! 24: * ! 25: * v01.23 All incoming packets come here first 06/21/90 mbs ! 26: * Modified for MP, 1996 by Tuyen Nguyen ! 27: * Modified, April 9, 1997 by Tuyen Nguyen for MacOSX. ! 28: */ ! 29: ! 30: #include <sys/errno.h> ! 31: #include <sys/types.h> ! 32: #include <sys/param.h> ! 33: #include <machine/spl.h> ! 34: #include <sys/systm.h> ! 35: #include <sys/kernel.h> ! 36: #include <sys/proc.h> ! 37: #include <sys/filedesc.h> ! 38: #include <sys/fcntl.h> ! 39: #include <sys/mbuf.h> ! 40: #include <sys/ioctl.h> ! 41: #include <sys/malloc.h> ! 42: #include <sys/socket.h> ! 43: #include <sys/socketvar.h> ! 44: #include <sys/time.h> ! 45: ! 46: #include <net/if.h> ! 47: ! 48: #include <netat/sysglue.h> ! 49: #include <netat/appletalk.h> ! 50: #include <netat/at_pcb.h> ! 51: #include <netat/ddp.h> ! 52: #include <netat/at_var.h> ! 53: ! 54: #include <netat/adsp.h> ! 55: #include <netat/adsp_internal.h> ! 56: ! 57: extern at_ifaddr_t *ifID_home; ! 58: ! 59: /* ! 60: * GleanSession ! 61: * ! 62: * We just got a packet for this session, glean its address & ! 63: * reset probe timer ! 64: * ! 65: * INPUTS: ! 66: * Session ! 67: * OUTPUTS: ! 68: * none ! 69: */ ! 70: static void GleanSession(sp) /* (CCBPtr sp) */ ! 71: CCBPtr sp; ! 72: { ! 73: if (sp->openState == O_STATE_OPEN) { ! 74: /* This is true for both state = sOpen & sClosing */ ! 75: RemoveTimerElem(&adspGlobal.slowTimers, &sp->ProbeTimer); ! 76: InsertTimerElem(&adspGlobal.slowTimers, &sp->ProbeTimer, ! 77: sp->probeInterval); ! 78: sp->probeCntr = 4; ! 79: } ! 80: ! 81: } ! 82: ! 83: ! 84: /* ! 85: * The same code handles incoming Open Connection Request, ! 86: * Open Request + Ack, Open Connection Ack, Open Connection Denial ! 87: * ! 88: * We could be in four different states, LISTEN, OPENWAIT, ESTABLISHED, ! 89: * OPEN. ! 90: */ ! 91: ! 92: /* ! 93: * ! 94: * Ok, there are 16 combinations. 8 are do-nothings, 2 have to be ! 95: * special cased (Open Deny and Req+Ack on Open session) ! 96: * ! 97: * Build a table of actions: ! 98: * Ignore? ! 99: * What to match on (local socket, whole address, DestCID, SrcCID) ! 100: * What to send (Ack or Req+Ack) ! 101: * Next State (both the ccb state and the open state) ! 102: */ ! 103: ! 104: /* ! 105: * ! 106: */ ! 107: typedef struct { ! 108: u_char match; /* Characteristics that have to match ! 109: * (Bit-Mapped, see below) */ ! 110: char action; /* What to do if CCB matches */ ! 111: char send; /* What to send in response ! 112: * (Bit mapped, same as sendCtl field of ! 113: * CCB) */ ! 114: char openState; /* Next Open state */ ! 115: char state; /* Next ccb state. */ ! 116: char pad; /* Too bad we need this to make structure ! 117: * even size */ ! 118: } TBL, *TBLPtr; ! 119: ! 120: #define M_LSOC 0x01 /* bit 0 - Match on local socket */ ! 121: #define M_ADDR 0x02 /* bit 1 - Match on whole address */ ! 122: #define M_DCID 0x04 /* bit 2 - Match on DestCID */ ! 123: #define M_SCID 0x08 /* bit 3 - Match SrcCID */ ! 124: #define M_DCIDZERO 0x10 /* bit 4 - Dest CID must be 0 */ ! 125: #define M_SCIDZERO 0x20 /* bit 5 - Src CID must be 0 */ ! 126: #define M_FILTER 0x40 /* bit 6 - Match address filter */ ! 127: #define M_IGNORE 0x80 /* bit 7 - Ignore */ ! 128: ! 129: #define A_COMPLETE 0x01 /* Complete open parameter block */ ! 130: #define A_SAVEPARMS 0x02 /* Save connection parameters */ ! 131: #define A_OREQACKOPEN 0x04 /* special case for open Req+Ack on ! 132: * OPEN session */ ! 133: #define A_GLEAN 0x08 /* We'll be talking back to this guy */ ! 134: #define A_DENY 0x10 /* We've been denied! */ ! 135: ! 136: ! 137: /* ! 138: * So here's our table ! 139: */ ! 140: ! 141: static TBL tbl[16] = { ! 142: ! 143: /* ! 144: * For Open Request ($81) ! 145: * ! 146: * LISTENING ! 147: * Match on destination socket ! 148: * Match on address filter ! 149: * Dest CID must be 0 ! 150: * Glean connection ! 151: * Save Open Connection parameters ! 152: * Send OREQACK ! 153: * Change state to ESTABLISHED ! 154: */ ! 155: { M_LSOC + M_DCIDZERO + M_FILTER, ! 156: A_SAVEPARMS + A_GLEAN, ! 157: B_CTL_OREQACK, ! 158: O_STATE_ESTABLISHED, ! 159: sOpening, ! 160: 0 ! 161: }, ! 162: ! 163: /* ! 164: * ! 165: * OPENWAIT ! 166: * Match on Remote Address & destination socket ! 167: * Dest CID must be 0 ! 168: * Save Open Connection parameters ! 169: * Send Ack ! 170: * Change state to ESTABLISHED ! 171: */ ! 172: { M_LSOC + M_ADDR + M_DCIDZERO, ! 173: A_SAVEPARMS + A_GLEAN, ! 174: B_CTL_OACK, ! 175: O_STATE_ESTABLISHED, ! 176: sOpening, ! 177: 0 ! 178: }, ! 179: /* ! 180: * ! 181: * ESTABLISHED ! 182: * Match on Remote Address & SrcCID ! 183: * Dest CID must be 0 ! 184: * Send Req + Ack ! 185: */ ! 186: { M_ADDR + M_SCID + M_DCIDZERO, ! 187: A_GLEAN, ! 188: B_CTL_OACK, ! 189: O_STATE_ESTABLISHED, ! 190: sOpening, ! 191: 0 ! 192: }, ! 193: /* ! 194: * OPEN ! 195: * Ignore ! 196: */ ! 197: { M_IGNORE, ! 198: 0, ! 199: 0, ! 200: 0, ! 201: 0, ! 202: 0 ! 203: }, ! 204: ! 205: /* ! 206: * ! 207: * For Open Ack ($82) ! 208: * ! 209: * LISTENING ! 210: * Ignore ! 211: */ ! 212: { M_IGNORE, ! 213: 0, ! 214: 0, ! 215: 0, ! 216: 0, ! 217: 0 ! 218: }, ! 219: /* ! 220: * ! 221: * OPENWAIT ! 222: * Ignore ! 223: */ ! 224: { M_IGNORE, ! 225: 0, ! 226: 0, ! 227: 0, ! 228: 0, ! 229: 0 ! 230: }, ! 231: /* ! 232: * ! 233: * ESTABLISHED ! 234: * Match on SrcCID & DestCID & Address & Local Socket ! 235: * Complete Listen or Connect PB ! 236: * OPEN ! 237: */ ! 238: { M_ADDR + M_DCID + M_SCID + M_LSOC, ! 239: A_COMPLETE + A_GLEAN, ! 240: 0, ! 241: O_STATE_OPEN, ! 242: sOpen, ! 243: 0 ! 244: }, ! 245: /* ! 246: * ! 247: * OPEN ! 248: * Ignore ! 249: */ ! 250: { M_IGNORE, ! 251: 0, ! 252: 0, ! 253: 0, ! 254: 0, ! 255: 0 ! 256: }, ! 257: ! 258: /* ! 259: * ! 260: * For Open Request + Ack ($83) ! 261: * ! 262: * LISTENING ! 263: * Ignore ! 264: */ ! 265: { M_IGNORE, ! 266: 0, ! 267: 0, ! 268: 0, ! 269: 0, ! 270: 0 ! 271: }, ! 272: /* ! 273: * ! 274: * OPENWAIT ! 275: * Match on DestCID & socket ! 276: * Do not test remote address -- our open req could have ! 277: * been passed to another address by a connection server ! 278: * Save Open Connection parameters ! 279: * Complete Connect parameter block ! 280: * Send Ack ! 281: * OPEN ! 282: */ ! 283: { M_DCID + M_LSOC, ! 284: A_COMPLETE + A_SAVEPARMS + A_GLEAN, ! 285: B_CTL_OACK, ! 286: O_STATE_OPEN, ! 287: sOpen, ! 288: 0 ! 289: }, ! 290: /* ! 291: * ! 292: * ESTABLISHED ! 293: * Ignore ! 294: */ ! 295: { M_IGNORE, ! 296: 0, ! 297: 0, ! 298: 0, ! 299: 0, ! 300: 0 ! 301: }, ! 302: /* ! 303: * ! 304: * OPEN ! 305: * Match on Remote Address & SrcCID & DestCID & Local Socket ! 306: * If we've never gotten any data ! 307: * Send Ack & Retransmit ! 308: */ ! 309: { M_ADDR + M_DCID + M_SCID + M_LSOC, ! 310: A_OREQACKOPEN + A_GLEAN, ! 311: B_CTL_OACK, ! 312: O_STATE_OPEN, ! 313: sOpen, ! 314: 0 ! 315: }, ! 316: ! 317: /* ! 318: * ! 319: * ! 320: * For Open Deny ($84) ! 321: * ! 322: * LISTENING ! 323: * Ignore ! 324: */ ! 325: { M_IGNORE, ! 326: 0, ! 327: 0, ! 328: 0, ! 329: 0, ! 330: 0 ! 331: }, ! 332: /* ! 333: * ! 334: * OPENWAIT ! 335: * Match on DestCID & Address ! 336: * Source CID must be 0 ! 337: * Complete with error ! 338: */ ! 339: { M_SCIDZERO + M_DCID + M_ADDR, ! 340: A_DENY, ! 341: 0, ! 342: O_STATE_NOTHING, ! 343: sClosed, ! 344: 0 ! 345: }, ! 346: /* ! 347: * ! 348: * ESTABLISHED ! 349: * Ignore ! 350: */ ! 351: { M_IGNORE, ! 352: 0, ! 353: 0, ! 354: 0, ! 355: 0, ! 356: 0 ! 357: }, /* %%% No we probably don't want to ignore in this case */ ! 358: /* ! 359: * ! 360: * OPEN ! 361: * Ignore ! 362: */ ! 363: { M_IGNORE, ! 364: 0, ! 365: 0, ! 366: 0, ! 367: 0, ! 368: 0 ! 369: } ! 370: }; ! 371: ! 372: extern at_ifaddr_t *ifID_table[]; ! 373: ! 374: /* ! 375: * Used to search down queue of sessions for a session waiting for an ! 376: * open request. ! 377: */ ! 378: typedef struct { ! 379: AddrUnion addr; ! 380: word dstCID; ! 381: word srcCID; ! 382: byte socket; ! 383: byte descriptor; ! 384: byte idx; /* Index into state tables */ ! 385: TBLPtr t; /* Ptr to entry in table above */ ! 386: } MATCH, *MATCHPtr; ! 387: ! 388: /* ! 389: * MatchStream ! 390: * ! 391: * Called by Rx connection to find which stream (if any) should get this open ! 392: * request/ack/req+ack/deny packet. ! 393: * ! 394: */ ! 395: ! 396: static boolean ! 397: MatchStream(sp, m) /* (CCBPtr sp, MATCHPtr m) */ ! 398: CCBPtr sp; ! 399: MATCHPtr m; ! 400: { ! 401: unsigned char match; ! 402: struct adspcmd *opb; ! 403: ! 404: if (sp->openState < O_STATE_LISTEN || ! 405: sp->openState > O_STATE_OPEN) ! 406: return 0; ! 407: ! 408: ! 409: m->t = &tbl[sp->openState - O_STATE_LISTEN + m->idx]; ! 410: ! 411: match = m->t->match; /* Get match criteria */ ! 412: ! 413: if (match & M_IGNORE) /* Ignore this combination */ ! 414: return 0; ! 415: ! 416: if (match & M_LSOC) { /* Match on Local socket */ ! 417: if (sp->localSocket != m->socket) ! 418: return 0; ! 419: } ! 420: ! 421: if (match & M_ADDR) { /* Match on Address */ ! 422: AddrUnion addr; ! 423: addr = m->addr; /* Make local copy for efficiency */ ! 424: if (sp->remoteAddress.a.node != addr.a.node) ! 425: return 0; ! 426: if (sp->remoteAddress.a.socket != addr.a.socket) ! 427: return 0; ! 428: if (sp->remoteAddress.a.net && addr.a.net && ! 429: (sp->remoteAddress.a.net != addr.a.net)) ! 430: return 0; ! 431: ! 432: /* ! 433: * Handle special case to reject self-sent open request ! 434: */ ! 435: if ((m->srcCID == sp->locCID) && ! 436: (addr.a.node == ifID_home->ifThisNode.s_node) && ! 437: /* *** was (addr.a.node == ddpcfg.node_addr.node) && *** */ ! 438: ((addr.a.net == 0) || ! 439: (ifID_home->ifThisNode.s_net == 0) || ! 440: (ifID_home->ifThisNode.s_net == addr.a.net)) ) ! 441: /* *** was ! 442: (NET_VALUE(ddpcfg.node_addr.net) == 0) || ! 443: (NET_VALUE(ddpcfg.node_addr.net) == NET_VALUE(addr.a.net))) ) ! 444: *** */ ! 445: /* CID's match, and */ ! 446: /* If nodeID matches, and */ ! 447: /* network matches, */ ! 448: return 0; /* then came from us! */ ! 449: } ! 450: ! 451: if (match & M_DCID) { /* Match on DestCID */ ! 452: if (sp->locCID != m->dstCID) ! 453: return 0; ! 454: } ! 455: ! 456: if (match & M_SCID) { /* Match on SourceCID */ ! 457: if (sp->remCID != m->srcCID) ! 458: return 0; ! 459: } ! 460: ! 461: if (match & M_DCIDZERO) { /* Destination CID must be 0 */ ! 462: if (m->dstCID != 0) ! 463: return 0; ! 464: } ! 465: ! 466: if (match & M_SCIDZERO) /* Source CID must be 0 */ ! 467: { ! 468: if (m->srcCID != 0) ! 469: return 0; ! 470: } ! 471: ! 472: if (match & M_FILTER) { /* Check address filter? */ ! 473: if ((opb = sp->opb)) /* There should be a param block... */ ! 474: { ! 475: AddrUnion addr; ! 476: addr = m->addr; /* Make local copy for efficiency */ ! 477: if ((opb->u.openParams.filterAddress.net && ! 478: addr.a.net && ! 479: opb->u.openParams.filterAddress.net != addr.a.net) || ! 480: (opb->u.openParams.filterAddress.node != 0 && ! 481: opb->u.openParams.filterAddress.node != addr.a.node)|| ! 482: (opb->u.openParams.filterAddress.socket != 0 && ! 483: opb->u.openParams.filterAddress.socket != addr.a.socket)) ! 484: return 0; ! 485: } ! 486: } ! 487: ! 488: return 1; ! 489: } ! 490: ! 491: /* ! 492: * MatchListener ! 493: * ! 494: * Called by rx connection to see which connection listener (if any) should ! 495: * get this incoming open connection request. ! 496: * ! 497: */ ! 498: ! 499: static boolean MatchListener(sp, m) /* (CCBPtr sp, MATCHPtr m) */ ! 500: CCBPtr sp; ! 501: MATCHPtr m; ! 502: { ! 503: ! 504: if ((sp->state == (word)sListening) && /* This CCB is a listener */ ! 505: (sp->localSocket == m->socket)) /* on the right socket */ ! 506: return 1; ! 507: ! 508: return 0; ! 509: } ! 510: ! 511: /* ! 512: * RXConnection ! 513: * ! 514: * We just received one of the 4 Open Connection packets ! 515: * Interrupts are masked OFF at this point ! 516: * ! 517: * INPUTS: ! 518: * spPtr Place to put ptr to stream (if we found one -- not ! 519: * for listeners) ! 520: * f Pointer to ADSP header for packet, data follows behind it ! 521: * len # of byte in ADSP header + data ! 522: * addr Who sent the packet ! 523: * dsoc Where they sent it to ! 524: * ! 525: * OUTPUTS: ! 526: * Returns 1 if packet was ignored ! 527: */ ! 528: static int RXConnection(gref, spPtr, f, len, addr, dsoc) ! 529: /* (CCBPtr *spPtr, ADSP_FRAMEPtr f, word len, AddrUnion addr, byte dsoc) */ ! 530: gref_t *gref; /* READ queue */ ! 531: CCBPtr *spPtr; ! 532: ADSP_FRAMEPtr f; ! 533: int len; ! 534: AddrUnion addr; ! 535: unsigned char dsoc; ! 536: { ! 537: CCBPtr sp; ! 538: ADSP_OPEN_DATAPtr op; ! 539: struct adspcmd *pb; ! 540: MATCH m; ! 541: gbuf_t *mp; ! 542: ADSP_FRAMEPtr adspp; ! 543: ADSP_OPEN_DATAPtr adspop; ! 544: int s; ! 545: ! 546: op = (ADSP_OPEN_DATAPtr)&f->data[0]; /* Point to Open-Connection parms */ ! 547: len -= ADSP_FRAME_LEN; ! 548: ! 549: if (len < (sizeof(ADSP_OPEN_DATA))) /* Packet too small */ ! 550: return 1; ! 551: ! 552: ! 553: if (UAS_VALUE(op->version) != netw(0x0100)) { /* Check version num (on even-byte) */ ! 554: /* ! 555: * The open request has been denied. Try to send him a denial. ! 556: */ ! 557: ! 558: mp = gbuf_alloc(AT_WR_OFFSET + DDPL_FRAME_LEN + ADSP_FRAME_LEN + ADSP_OPEN_FRAME_LEN, ! 559: PRI_LO); ! 560: gbuf_rinc(mp,AT_WR_OFFSET); ! 561: gbuf_wset(mp,DDPL_FRAME_LEN); ! 562: adspp = (ADSP_FRAMEPtr)gbuf_wptr(mp); ! 563: gbuf_winc(mp,ADSP_FRAME_LEN); ! 564: bzero((caddr_t) gbuf_rptr(mp),DDPL_FRAME_LEN + ADSP_FRAME_LEN + ! 565: ADSP_OPEN_FRAME_LEN); ! 566: adspp->descriptor = ADSP_CONTROL_BIT | ADSP_CTL_ODENY; ! 567: adspop = (ADSP_OPEN_DATAPtr)gbuf_wptr(mp); ! 568: gbuf_winc(mp,ADSP_OPEN_FRAME_LEN); ! 569: UAS_UAS(adspop->dstCID, f->CID); ! 570: UAS_ASSIGN(adspop->version, 0x100); ! 571: adsp_sendddp(0, mp, DDPL_FRAME_LEN + ADSP_FRAME_LEN + ! 572: ADSP_OPEN_FRAME_LEN, &addr, DDP_ADSP); ! 573: ! 574: return 0; ! 575: } ! 576: m.addr = addr; ! 577: m.socket = dsoc; ! 578: m.descriptor = f->descriptor; ! 579: m.srcCID = UAS_VALUE(f->CID); ! 580: m.dstCID = UAS_VALUE(op->dstCID); /* On even-byte boundry */ ! 581: m.idx = ((f->descriptor & ADSP_CONTROL_MASK) - 1) * 4; ! 582: ! 583: /* ! 584: * See if we can find a stream that knows what to do with this packet ! 585: */ ! 586: if ((sp = (CCBPtr)qfind_m(AT_ADSP_STREAMS, &m, (ProcPtr)MatchStream)) == 0) ! 587: { ! 588: struct adspcmd *p; ! 589: struct adspcmd *n; ! 590: /* ! 591: * No match, so look for connection listeners if this is an ! 592: * open request ! 593: */ ! 594: if ((f->descriptor & ADSP_CONTROL_MASK) != (byte)ADSP_CTL_OREQ) ! 595: return 1; ! 596: ! 597: if ((sp = (CCBPtr)qfind_m(AT_ADSP_STREAMS, &m, ! 598: (ProcPtr)MatchListener)) == 0) ! 599: return 1; ! 600: ! 601: ATDISABLE(s, sp->lock); ! 602: p = (struct adspcmd *)&sp->opb; ! 603: while (n = (struct adspcmd *)p->qLink) /* Hunt down list of listens */ ! 604: { ! 605: /* Check address filter */ ! 606: if (((n->u.openParams.filterAddress.net == 0) || ! 607: (addr.a.net == 0) || ! 608: (n->u.openParams.filterAddress.net == addr.a.net)) && ! 609: ! 610: ((n->u.openParams.filterAddress.node == 0) || ! 611: (n->u.openParams.filterAddress.node == addr.a.node)) && ! 612: ! 613: ((n->u.openParams.filterAddress.socket == 0) || ! 614: (n->u.openParams.filterAddress.socket == addr.a.socket))) { ! 615: p->qLink = n->qLink; /* Unlink this param block */ ! 616: n->u.openParams.remoteCID = m.srcCID; ! 617: *((AddrUnionPtr)&n->u.openParams.remoteAddress) = addr; ! 618: n->u.openParams.sendSeq = netdw(UAL_VALUE(f->pktNextRecvSeq)); ! 619: n->u.openParams.sendWindow = netw(UAS_VALUE(f->pktRecvWdw)); ! 620: n->u.openParams.attnSendSeq = netdw(UAL_VALUE(op->pktAttnRecvSeq)); ! 621: n->ioResult = 0; ! 622: ATENABLE(s, sp->lock); ! 623: completepb(sp, n); /* complete copy of request */ ! 624: /* complete(n, 0); */ ! 625: return 0; ! 626: } /* found CLListen */ ! 627: ! 628: p = n; /* down the list we go... */ ! 629: ! 630: } /* while */ ! 631: ! 632: ATENABLE(s, sp->lock); ! 633: return 1; ! 634: } ! 635: ! 636: *spPtr = sp; /* Save ptr to stream we just found */ ! 637: ! 638: ATDISABLE(s, sp->lock); ! 639: sp->openState = m.t->openState; /* Move to next state (may be same) */ ! 640: sp->state = m.t->state; /* Move to next state (may be same) */ ! 641: ! 642: if (m.t->action & A_SAVEPARMS) { /* Need to Save open-conn parms */ ! 643: sp->firstRtmtSeq = sp->sendSeq = netdw(UAL_VALUE(f->pktNextRecvSeq)); ! 644: sp->sendWdwSeq = netdw(UAL_VALUE(f->pktNextRecvSeq)) + netw(UAS_VALUE(f->pktRecvWdw)) - 1; ! 645: sp->attnSendSeq = netdw(UAL_VALUE(op->pktAttnRecvSeq)); /* on even boundry */ ! 646: ! 647: ! 648: sp->remCID = UAS_VALUE(f->CID); /* Save Source CID as RemCID */ ! 649: UAS_UAS(sp->of.dstCID, f->CID); /* Save CID in open ctl packet */ ! 650: ! 651: sp->remoteAddress = addr; /* Save his address */ ! 652: ! 653: } ! 654: ATENABLE(s, sp->lock); ! 655: ! 656: if (m.t->action & A_DENY) { /* We've been denied ! */ ! 657: DoClose(sp, errOpenDenied, -1); ! 658: } ! 659: ! 660: if (m.t->action & A_OREQACKOPEN) { ! 661: /* Special case for OREQACK */ ! 662: /* on an open session */ ! 663: RemoveTimerElem(&adspGlobal.fastTimers, &sp->RetryTimer); ! 664: sp->sendSeq = sp->firstRtmtSeq; ! 665: sp->pktSendCnt = 0; ! 666: sp->waitingAck = 0; ! 667: sp->callSend = 1; ! 668: } ! 669: ! 670: if (m.t->send) { /* Need to send a response */ ! 671: sp->sendCtl |= m.t->send; ! 672: sp->callSend = 1; ! 673: } ! 674: ! 675: if (m.t->action & A_COMPLETE) { /* Need to complete open param blk */ ! 676: RemoveTimerElem(&adspGlobal.slowTimers, &sp->ProbeTimer); ! 677: ! 678: if (pb = sp->opb) { ! 679: sp->opb = 0; ! 680: pb->u.openParams.localCID = sp->locCID; ! 681: pb->u.openParams.remoteCID = sp->remCID; ! 682: pb->u.openParams.remoteAddress = ! 683: *((at_inet_t *)&sp->remoteAddress); ! 684: pb->u.openParams.sendSeq = sp->sendSeq; ! 685: pb->u.openParams.sendWindow = sp->sendWdwSeq - sp->sendSeq; ! 686: pb->u.openParams.attnSendSeq = sp->attnSendSeq; ! 687: pb->ioResult = 0; ! 688: completepb(sp, pb); /* complete(pb, 0); */ ! 689: return 0; ! 690: } ! 691: /* Start probe timer */ ! 692: InsertTimerElem(&adspGlobal.slowTimers, &sp->ProbeTimer, ! 693: sp->probeInterval); ! 694: } ! 695: return 0; ! 696: } ! 697: ! 698: /* ! 699: * ADSPPacket ! 700: * ! 701: * When a packet is received by the protocol stack with DDP type equal ! 702: * to ADSP, then execution comes here ! 703: * ! 704: * DS is set to ATALK's DGROUP ! 705: * ! 706: * This routine, or one of its children MUST call glean packet ! 707: * ! 708: * INPUTS: ! 709: * Pointer to DDP header ! 710: * OUTPUTS: ! 711: * none ! 712: * ! 713: * Note that the incoming message block (mp) is usually discarded, either ! 714: * by the "ignored" path, or via the "checksend" path. The only case ! 715: * where the message is NOT freed is via the RxData case in the ! 716: * non control packet switch. I zero mp after the RxData case succeeds ! 717: * so that mp will not be freed. ! 718: */ ! 719: int adspPacket(gref, mp) ! 720: /* (bytePtr data, word len, AddrUnion a, byte dsoc) */ ! 721: gref_t *gref; ! 722: gbuf_t *mp; ! 723: { ! 724: unsigned char *bp; ! 725: int len; ! 726: AddrUnion a; ! 727: int dsoc; ! 728: int s; ! 729: register DDPX_FRAME *ddp; /* DDP frame pointer */ ! 730: register ADSP_FRAMEPtr f; /* Frame */ ! 731: CCBPtr sp; ! 732: ! 733: sp = 0; /* No stream */ ! 734: bp = (unsigned char *)gbuf_rptr(mp); ! 735: ddp = (DDPX_FRAME *)bp; ! 736: if (ddp->ddpx_type != DDP_ADSP) ! 737: return -1; ! 738: f = (ADSP_FRAMEPtr)(bp + DDPL_FRAME_LEN); ! 739: ! 740: len = UAS_VALUE(ddp->ddpx_length) & 0x3ff; /* (ten bits of length) */ ! 741: len -= DDPL_FRAME_LEN; ! 742: if (len < (sizeof(ADSP_FRAME) - 1)) /* Packet too small */ ! 743: return -1; /* mark the failure */ ! 744: ! 745: a.a.net = NET_VALUE(ddp->ddpx_snet); ! 746: a.a.node = ddp->ddpx_snode; ! 747: a.a.socket = ddp->ddpx_source; ! 748: ! 749: dsoc = ddp->ddpx_dest; ! 750: ! 751: if (sp = (CCBPtr)FindSender(f, a)) ! 752: GleanSession(sp); ! 753: ! 754: if (f->descriptor & ADSP_ATTENTION_BIT) { /* ATTN packet */ ! 755: if (sp && RXAttention(sp, mp, f, len)) ! 756: goto ignore; ! 757: else ! 758: mp = 0; /* attention data is being held */ ! 759: } /* ATTENTION BIT */ ! 760: ! 761: else if (f->descriptor & ADSP_CONTROL_BIT) { /* Control packet */ ! 762: switch (f->descriptor & ADSP_CONTROL_MASK) { ! 763: case ADSP_CTL_PROBE: /* Probe or acknowledgement */ ! 764: if (sp) ! 765: CheckRecvSeq(sp, f); ! 766: break; ! 767: ! 768: case ADSP_CTL_OREQ: /* Open Connection Request */ ! 769: case ADSP_CTL_OREQACK: /* Open Request and acknowledgement */ ! 770: case ADSP_CTL_OACK: /* Open Request acknowledgment */ ! 771: case ADSP_CTL_ODENY: /* Open Request denial */ ! 772: if (RXConnection(gref, &sp, f, len, a, dsoc)) ! 773: goto ignore; ! 774: break; ! 775: ! 776: case ADSP_CTL_CLOSE: /* Close connection advice */ ! 777: if (sp) { ! 778: /* This pkt may also ack some data we sent */ ! 779: CheckRecvSeq(sp, f); ! 780: RxClose(sp); ! 781: sp = 0; ! 782: } else ! 783: goto ignore; ! 784: break; ! 785: ! 786: case ADSP_CTL_FRESET: /* Forward Reset */ ! 787: /* May I rot in hell for the code below... */ ! 788: if (sp && (CheckRecvSeq(sp, f), RXFReset(sp, f))) ! 789: goto ignore; ! 790: break; ! 791: ! 792: case ADSP_CTL_FRESET_ACK: /* Forward Reset Acknowledgement */ ! 793: if (sp && (CheckRecvSeq(sp, f), RXFResetAck(sp, f))) ! 794: goto ignore; ! 795: break; ! 796: ! 797: case ADSP_CTL_RETRANSMIT: /* Retransmit advice */ ! 798: if (sp) { ! 799: /* This pkt may also ack some data we sent */ ! 800: CheckRecvSeq(sp, f); ! 801: RemoveTimerElem(&adspGlobal.fastTimers, &sp->RetryTimer); ! 802: ATDISABLE(s, sp->lock); ! 803: sp->sendSeq = sp->firstRtmtSeq; ! 804: sp->pktSendCnt = 0; ! 805: sp->waitingAck = 0; ! 806: sp->callSend = 1; ! 807: ATENABLE(s, sp->lock); ! 808: } else ! 809: goto ignore; ! 810: break; ! 811: ! 812: default: ! 813: goto ignore; ! 814: } /* switch */ ! 815: } /* Control packet */ ! 816: ! 817: else { /* Data Packet */ ! 818: if ((sp == 0) || RXData(sp, mp, f, len)) ! 819: goto ignore; ! 820: else ! 821: mp = 0; /* RXData used up the data, DONT free it! */ ! 822: } /* Data Packet */ ! 823: ! 824: if (mp) ! 825: gbuf_freem(mp); ! 826: ! 827: checksend: /* incoming data was not ignored */ ! 828: if (sp && sp->callSend) /* If we have a stream & we need to send */ ! 829: CheckSend(sp); ! 830: ! 831: return 0; ! 832: ! 833: ignore: ! 834: gbuf_freem(mp); ! 835: return 0; ! 836: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.