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