]> git.saurik.com Git - apple/xnu.git/blame - bsd/netat/adsp_Packet.c
xnu-792.12.6.tar.gz
[apple/xnu.git] / bsd / netat / adsp_Packet.c
CommitLineData
1c79356b 1/*
8ad349bb 2 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved.
1c79356b 3 *
8ad349bb 4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
1c79356b 5 *
8ad349bb
A
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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
1c79356b
A
29 */
30/*
31 * Packet.c
32 *
33 * v01.23 All incoming packets come here first 06/21/90 mbs
34 * Modified for MP, 1996 by Tuyen Nguyen
35 * Modified, April 9, 1997 by Tuyen Nguyen for MacOSX.
36 */
37
38#include <sys/errno.h>
39#include <sys/types.h>
40#include <sys/param.h>
41#include <machine/spl.h>
42#include <sys/systm.h>
43#include <sys/kernel.h>
44#include <sys/proc.h>
45#include <sys/filedesc.h>
46#include <sys/fcntl.h>
47#include <sys/mbuf.h>
48#include <sys/ioctl.h>
49#include <sys/malloc.h>
50#include <sys/socket.h>
51#include <sys/socketvar.h>
52#include <sys/time.h>
53
54#include <net/if.h>
55
56#include <netat/sysglue.h>
57#include <netat/appletalk.h>
58#include <netat/at_pcb.h>
59#include <netat/ddp.h>
60#include <netat/at_var.h>
61
62#include <netat/adsp.h>
63#include <netat/adsp_internal.h>
64
65extern at_ifaddr_t *ifID_home;
66
67/*
68 * GleanSession
69 *
70 * We just got a packet for this session, glean its address &
71 * reset probe timer
72 *
73 * INPUTS:
74 * Session
75 * OUTPUTS:
76 * none
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 */
403
404static boolean
405MatchStream(sp, m) /* (CCBPtr sp, MATCHPtr m) */
406 CCBPtr sp;
407 MATCHPtr m;
408{
409 unsigned char match;
410 struct adspcmd *opb;
411
412 if (sp->openState < O_STATE_LISTEN ||
413 sp->openState > O_STATE_OPEN)
414 return 0;
415
416
417 m->t = &tbl[sp->openState - O_STATE_LISTEN + m->idx];
418
419 match = m->t->match; /* Get match criteria */
420
421 if (match & M_IGNORE) /* Ignore this combination */
422 return 0;
423
424 if (match & M_LSOC) { /* Match on Local socket */
425 if (sp->localSocket != m->socket)
426 return 0;
427 }
428
429 if (match & M_ADDR) { /* Match on Address */
430 AddrUnion addr;
431 addr = m->addr; /* Make local copy for efficiency */
432 if (sp->remoteAddress.a.node != addr.a.node)
433 return 0;
434 if (sp->remoteAddress.a.socket != addr.a.socket)
435 return 0;
436 if (sp->remoteAddress.a.net && addr.a.net &&
437 (sp->remoteAddress.a.net != addr.a.net))
438 return 0;
439
440 /*
441 * Handle special case to reject self-sent open request
442 */
443 if ((m->srcCID == sp->locCID) &&
444 (addr.a.node == ifID_home->ifThisNode.s_node) &&
445 /* *** was (addr.a.node == ddpcfg.node_addr.node) && *** */
446 ((addr.a.net == 0) ||
447 (ifID_home->ifThisNode.s_net == 0) ||
448 (ifID_home->ifThisNode.s_net == addr.a.net)) )
449 /* *** was
450 (NET_VALUE(ddpcfg.node_addr.net) == 0) ||
451 (NET_VALUE(ddpcfg.node_addr.net) == NET_VALUE(addr.a.net))) )
452 *** */
453 /* CID's match, and */
454 /* If nodeID matches, and */
455 /* network matches, */
456 return 0; /* then came from us! */
457 }
458
459 if (match & M_DCID) { /* Match on DestCID */
460 if (sp->locCID != m->dstCID)
461 return 0;
462 }
463
464 if (match & M_SCID) { /* Match on SourceCID */
465 if (sp->remCID != m->srcCID)
466 return 0;
467 }
468
469 if (match & M_DCIDZERO) { /* Destination CID must be 0 */
470 if (m->dstCID != 0)
471 return 0;
472 }
473
474 if (match & M_SCIDZERO) /* Source CID must be 0 */
475 {
476 if (m->srcCID != 0)
477 return 0;
478 }
479
480 if (match & M_FILTER) { /* Check address filter? */
481 if ((opb = sp->opb)) /* There should be a param block... */
482 {
483 AddrUnion addr;
484 addr = m->addr; /* Make local copy for efficiency */
485 if ((opb->u.openParams.filterAddress.net &&
486 addr.a.net &&
487 opb->u.openParams.filterAddress.net != addr.a.net) ||
488 (opb->u.openParams.filterAddress.node != 0 &&
489 opb->u.openParams.filterAddress.node != addr.a.node)||
490 (opb->u.openParams.filterAddress.socket != 0 &&
491 opb->u.openParams.filterAddress.socket != addr.a.socket))
492 return 0;
493 }
494 }
495
496 return 1;
497}
498
499/*
500 * MatchListener
501 *
502 * Called by rx connection to see which connection listener (if any) should
503 * get this incoming open connection request.
504 *
505 */
506
507static boolean MatchListener(sp, m) /* (CCBPtr sp, MATCHPtr m) */
508 CCBPtr sp;
509 MATCHPtr m;
510{
511
512 if ((sp->state == (word)sListening) && /* This CCB is a listener */
513 (sp->localSocket == m->socket)) /* on the right socket */
514 return 1;
515
516 return 0;
517}
518
519/*
520 * RXConnection
521 *
522 * We just received one of the 4 Open Connection packets
523 * Interrupts are masked OFF at this point
524 *
525 * INPUTS:
526 * spPtr Place to put ptr to stream (if we found one -- not
527 * for listeners)
528 * f Pointer to ADSP header for packet, data follows behind it
529 * len # of byte in ADSP header + data
530 * addr Who sent the packet
531 * dsoc Where they sent it to
532 *
533 * OUTPUTS:
534 * Returns 1 if packet was ignored
535 */
536static int RXConnection(gref, spPtr, f, len, addr, dsoc)
537 /* (CCBPtr *spPtr, ADSP_FRAMEPtr f, word len, AddrUnion addr, byte dsoc) */
538 gref_t *gref; /* READ queue */
539 CCBPtr *spPtr;
540 ADSP_FRAMEPtr f;
541 int len;
542 AddrUnion addr;
543 unsigned char dsoc;
544{
545 CCBPtr sp;
546 ADSP_OPEN_DATAPtr op;
547 struct adspcmd *pb;
548 MATCH m;
549 gbuf_t *mp;
550 ADSP_FRAMEPtr adspp;
551 ADSP_OPEN_DATAPtr adspop;
8ad349bb 552 int s;
1c79356b
A
553
554 op = (ADSP_OPEN_DATAPtr)&f->data[0]; /* Point to Open-Connection parms */
555 len -= ADSP_FRAME_LEN;
556
557 if (len < (sizeof(ADSP_OPEN_DATA))) /* Packet too small */
558 return 1;
559
560
561 if (UAS_VALUE(op->version) != netw(0x0100)) { /* Check version num (on even-byte) */
562 /*
563 * The open request has been denied. Try to send him a denial.
564 */
565
566 mp = gbuf_alloc(AT_WR_OFFSET + DDPL_FRAME_LEN + ADSP_FRAME_LEN + ADSP_OPEN_FRAME_LEN,
567 PRI_LO);
568 gbuf_rinc(mp,AT_WR_OFFSET);
569 gbuf_wset(mp,DDPL_FRAME_LEN);
570 adspp = (ADSP_FRAMEPtr)gbuf_wptr(mp);
571 gbuf_winc(mp,ADSP_FRAME_LEN);
572 bzero((caddr_t) gbuf_rptr(mp),DDPL_FRAME_LEN + ADSP_FRAME_LEN +
573 ADSP_OPEN_FRAME_LEN);
574 adspp->descriptor = ADSP_CONTROL_BIT | ADSP_CTL_ODENY;
575 adspop = (ADSP_OPEN_DATAPtr)gbuf_wptr(mp);
576 gbuf_winc(mp,ADSP_OPEN_FRAME_LEN);
577 UAS_UAS(adspop->dstCID, f->CID);
8ad349bb 578 UAS_ASSIGN(adspop->version, 0x100);
1c79356b
A
579 adsp_sendddp(0, mp, DDPL_FRAME_LEN + ADSP_FRAME_LEN +
580 ADSP_OPEN_FRAME_LEN, &addr, DDP_ADSP);
581
582 return 0;
583 }
584 m.addr = addr;
585 m.socket = dsoc;
586 m.descriptor = f->descriptor;
8ad349bb
A
587 m.srcCID = UAS_VALUE(f->CID);
588 m.dstCID = UAS_VALUE(op->dstCID); /* On even-byte boundry */
1c79356b
A
589 m.idx = ((f->descriptor & ADSP_CONTROL_MASK) - 1) * 4;
590
591 /*
592 * See if we can find a stream that knows what to do with this packet
593 */
594 if ((sp = (CCBPtr)qfind_m(AT_ADSP_STREAMS, &m, (ProcPtr)MatchStream)) == 0)
595 {
596 struct adspcmd *p;
597 struct adspcmd *n;
598 /*
599 * No match, so look for connection listeners if this is an
600 * open request
601 */
602 if ((f->descriptor & ADSP_CONTROL_MASK) != (byte)ADSP_CTL_OREQ)
603 return 1;
604
605 if ((sp = (CCBPtr)qfind_m(AT_ADSP_STREAMS, &m,
606 (ProcPtr)MatchListener)) == 0)
607 return 1;
608
8ad349bb 609 ATDISABLE(s, sp->lock);
1c79356b
A
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;
8ad349bb
A
626 n->u.openParams.sendSeq = netdw(UAL_VALUE(f->pktNextRecvSeq));
627 n->u.openParams.sendWindow = netw(UAS_VALUE(f->pktRecvWdw));
628 n->u.openParams.attnSendSeq = netdw(UAL_VALUE(op->pktAttnRecvSeq));
1c79356b 629 n->ioResult = 0;
8ad349bb 630 ATENABLE(s, sp->lock);
1c79356b
A
631 completepb(sp, n); /* complete copy of request */
632 /* complete(n, 0); */
633 return 0;
634 } /* found CLListen */
635
636 p = n; /* down the list we go... */
637
638 } /* while */
639
8ad349bb 640 ATENABLE(s, sp->lock);
1c79356b
A
641 return 1;
642 }
643
644 *spPtr = sp; /* Save ptr to stream we just found */
645
8ad349bb 646 ATDISABLE(s, sp->lock);
1c79356b
A
647 sp->openState = m.t->openState; /* Move to next state (may be same) */
648 sp->state = m.t->state; /* Move to next state (may be same) */
649
650 if (m.t->action & A_SAVEPARMS) { /* Need to Save open-conn parms */
8ad349bb
A
651 sp->firstRtmtSeq = sp->sendSeq = netdw(UAL_VALUE(f->pktNextRecvSeq));
652 sp->sendWdwSeq = netdw(UAL_VALUE(f->pktNextRecvSeq)) + netw(UAS_VALUE(f->pktRecvWdw)) - 1;
653 sp->attnSendSeq = netdw(UAL_VALUE(op->pktAttnRecvSeq)); /* on even boundry */
1c79356b
A
654
655
8ad349bb 656 sp->remCID = UAS_VALUE(f->CID); /* Save Source CID as RemCID */
1c79356b
A
657 UAS_UAS(sp->of.dstCID, f->CID); /* Save CID in open ctl packet */
658
659 sp->remoteAddress = addr; /* Save his address */
660
661 }
8ad349bb 662 ATENABLE(s, sp->lock);
1c79356b
A
663
664 if (m.t->action & A_DENY) { /* We've been denied ! */
665 DoClose(sp, errOpenDenied, -1);
666 }
667
668 if (m.t->action & A_OREQACKOPEN) {
669 /* Special case for OREQACK */
670 /* on an open session */
671 RemoveTimerElem(&adspGlobal.fastTimers, &sp->RetryTimer);
672 sp->sendSeq = sp->firstRtmtSeq;
673 sp->pktSendCnt = 0;
674 sp->waitingAck = 0;
675 sp->callSend = 1;
676 }
677
678 if (m.t->send) { /* Need to send a response */
679 sp->sendCtl |= m.t->send;
680 sp->callSend = 1;
681 }
682
683 if (m.t->action & A_COMPLETE) { /* Need to complete open param blk */
684 RemoveTimerElem(&adspGlobal.slowTimers, &sp->ProbeTimer);
685
686 if (pb = sp->opb) {
687 sp->opb = 0;
688 pb->u.openParams.localCID = sp->locCID;
689 pb->u.openParams.remoteCID = sp->remCID;
690 pb->u.openParams.remoteAddress =
691 *((at_inet_t *)&sp->remoteAddress);
692 pb->u.openParams.sendSeq = sp->sendSeq;
693 pb->u.openParams.sendWindow = sp->sendWdwSeq - sp->sendSeq;
694 pb->u.openParams.attnSendSeq = sp->attnSendSeq;
695 pb->ioResult = 0;
696 completepb(sp, pb); /* complete(pb, 0); */
697 return 0;
698 }
699 /* Start probe timer */
700 InsertTimerElem(&adspGlobal.slowTimers, &sp->ProbeTimer,
701 sp->probeInterval);
702 }
703 return 0;
704}
705
706/*
707 * ADSPPacket
708 *
709 * When a packet is received by the protocol stack with DDP type equal
710 * to ADSP, then execution comes here
711 *
712 * DS is set to ATALK's DGROUP
713 *
714 * This routine, or one of its children MUST call glean packet
715 *
716 * INPUTS:
717 * Pointer to DDP header
718 * OUTPUTS:
719 * none
720 *
721 * Note that the incoming message block (mp) is usually discarded, either
722 * by the "ignored" path, or via the "checksend" path. The only case
723 * where the message is NOT freed is via the RxData case in the
724 * non control packet switch. I zero mp after the RxData case succeeds
725 * so that mp will not be freed.
726 */
727int adspPacket(gref, mp)
728 /* (bytePtr data, word len, AddrUnion a, byte dsoc) */
729 gref_t *gref;
730 gbuf_t *mp;
731{
732 unsigned char *bp;
733 int len;
734 AddrUnion a;
735 int dsoc;
8ad349bb 736 int s;
1c79356b
A
737 register DDPX_FRAME *ddp; /* DDP frame pointer */
738 register ADSP_FRAMEPtr f; /* Frame */
739 CCBPtr sp;
740
741 sp = 0; /* No stream */
742 bp = (unsigned char *)gbuf_rptr(mp);
743 ddp = (DDPX_FRAME *)bp;
744 if (ddp->ddpx_type != DDP_ADSP)
745 return -1;
746 f = (ADSP_FRAMEPtr)(bp + DDPL_FRAME_LEN);
747
8ad349bb 748 len = UAS_VALUE(ddp->ddpx_length) & 0x3ff; /* (ten bits of length) */
1c79356b
A
749 len -= DDPL_FRAME_LEN;
750 if (len < (sizeof(ADSP_FRAME) - 1)) /* Packet too small */
751 return -1; /* mark the failure */
752
753 a.a.net = NET_VALUE(ddp->ddpx_snet);
754 a.a.node = ddp->ddpx_snode;
755 a.a.socket = ddp->ddpx_source;
756
757 dsoc = ddp->ddpx_dest;
758
759 if (sp = (CCBPtr)FindSender(f, a))
760 GleanSession(sp);
761
762 if (f->descriptor & ADSP_ATTENTION_BIT) { /* ATTN packet */
763 if (sp && RXAttention(sp, mp, f, len))
764 goto ignore;
765 else
766 mp = 0; /* attention data is being held */
767 } /* ATTENTION BIT */
768
769 else if (f->descriptor & ADSP_CONTROL_BIT) { /* Control packet */
770 switch (f->descriptor & ADSP_CONTROL_MASK) {
771 case ADSP_CTL_PROBE: /* Probe or acknowledgement */
772 if (sp)
773 CheckRecvSeq(sp, f);
774 break;
775
776 case ADSP_CTL_OREQ: /* Open Connection Request */
777 case ADSP_CTL_OREQACK: /* Open Request and acknowledgement */
778 case ADSP_CTL_OACK: /* Open Request acknowledgment */
779 case ADSP_CTL_ODENY: /* Open Request denial */
780 if (RXConnection(gref, &sp, f, len, a, dsoc))
781 goto ignore;
782 break;
783
784 case ADSP_CTL_CLOSE: /* Close connection advice */
785 if (sp) {
786 /* This pkt may also ack some data we sent */
787 CheckRecvSeq(sp, f);
788 RxClose(sp);
789 sp = 0;
790 } else
791 goto ignore;
792 break;
793
794 case ADSP_CTL_FRESET: /* Forward Reset */
795 /* May I rot in hell for the code below... */
796 if (sp && (CheckRecvSeq(sp, f), RXFReset(sp, f)))
797 goto ignore;
798 break;
799
800 case ADSP_CTL_FRESET_ACK: /* Forward Reset Acknowledgement */
801 if (sp && (CheckRecvSeq(sp, f), RXFResetAck(sp, f)))
802 goto ignore;
803 break;
804
805 case ADSP_CTL_RETRANSMIT: /* Retransmit advice */
806 if (sp) {
807 /* This pkt may also ack some data we sent */
808 CheckRecvSeq(sp, f);
809 RemoveTimerElem(&adspGlobal.fastTimers, &sp->RetryTimer);
8ad349bb 810 ATDISABLE(s, sp->lock);
1c79356b
A
811 sp->sendSeq = sp->firstRtmtSeq;
812 sp->pktSendCnt = 0;
813 sp->waitingAck = 0;
814 sp->callSend = 1;
8ad349bb 815 ATENABLE(s, sp->lock);
1c79356b
A
816 } else
817 goto ignore;
818 break;
819
820 default:
821 goto ignore;
822 } /* switch */
823 } /* Control packet */
824
825 else { /* Data Packet */
826 if ((sp == 0) || RXData(sp, mp, f, len))
827 goto ignore;
828 else
829 mp = 0; /* RXData used up the data, DONT free it! */
830 } /* Data Packet */
831
832 if (mp)
833 gbuf_freem(mp);
834
835checksend: /* incoming data was not ignored */
836 if (sp && sp->callSend) /* If we have a stream & we need to send */
837 CheckSend(sp);
838
839 return 0;
840
841ignore:
842 gbuf_freem(mp);
843 return 0;
844}