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