|
|
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.