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