|
|
1.1 root 1: /* ssaprovider.c - implement the session protocol */
2:
3: #ifndef lint
4: static char *rcsid = "$Header: /f/osi/ssap/RCS/ssaprovider.c,v 7.1 89/11/30 23:51:19 mrose Exp $";
5: #endif
6:
7: /*
8: * $Header: /f/osi/ssap/RCS/ssaprovider.c,v 7.1 89/11/30 23:51:19 mrose Exp $
9: *
10: *
11: * $Log: ssaprovider.c,v $
12: * Revision 7.1 89/11/30 23:51:19 mrose
13: * touch-up
14: *
15: * Revision 7.0 89/11/23 22:25:45 mrose
16: * Release 6.0
17: *
18: */
19:
20: /*
21: * NOTICE
22: *
23: * Acquisition, use, and distribution of this module and related
24: * materials are subject to the restrictions of a license agreement.
25: * Consult the Preface in the User's Manual for the full terms of
26: * this agreement.
27: *
28: */
29:
30:
31: /* LINTLIBRARY */
32:
33: #include <stdio.h>
34: #include <signal.h>
35: #include "spkt.h"
36: #include "tailor.h"
37:
38: /* DATA */
39:
40: static int once_only = 0;
41: static struct ssapblk ssapque;
42: static struct ssapblk *SHead = &ssapque;
43:
44:
45: int TDATAser (), TDISCser ();
46:
47:
48: /* S-DATA.REQUEST */
49:
50: int SDataRequest (sd, data, cc, si)
51: int sd;
52: char *data;
53: int cc;
54: struct SSAPindication *si;
55: {
56: SBV smask;
57: int result;
58: struct udvec uvs[2];
59: register struct udvec *uv = uvs;
60: register struct ssapblk *sb;
61:
62: missingP (data);
63: if (cc <= 0)
64: return ssaplose (si, SC_PARAMETER, NULLCP,
65: "illegal value for SSDU length (%d)", cc);
66: missingP (si);
67:
68: smask = sigioblock ();
69:
70: ssapPsig (sb, sd);
71:
72: uv -> uv_base = data, uv -> uv_len = cc, uv++;
73: uv -> uv_base = NULL;
74:
75: result = SDataRequestAux (sb, SPDU_DT, uvs, si);
76:
77: (void) sigiomask (smask);
78:
79: return result;
80: }
81:
82: /* S-WRITE.REQUEST (pseudo; write user data vectors) */
83:
84: int SWriteRequest (sd, typed, uv, si)
85: int sd;
86: int typed;
87: struct udvec *uv;
88: struct SSAPindication *si;
89: {
90: SBV smask;
91: int result;
92: register struct ssapblk *sb;
93:
94: missingP (uv);
95: missingP (si);
96:
97: smask = sigioblock ();
98:
99: ssapPsig (sb, sd);
100:
101: result = SDataRequestAux (sb, typed ? SPDU_TD : SPDU_DT, uv, si);
102:
103: (void) sigiomask (smask);
104:
105: return result;
106: }
107:
108: /* */
109:
110: #define NSPUV 12 /* really should be MSG_MAXIOVLEN - 4 */
111:
112:
113: int SDataRequestAux (sb, code, uv, si)
114: register struct ssapblk *sb;
115: int code;
116: register struct udvec *uv;
117: struct SSAPindication *si;
118: {
119: int begin,
120: cc,
121: j,
122: len,
123: n,
124: result;
125: register char *bp,
126: *ep;
127: register struct ssapkt *s;
128: struct TSAPdisconnect tds;
129: register struct TSAPdisconnect *td = &tds;
130: struct udvec vvs[NSPUV];
131: register struct udvec *vv,
132: *wv;
133: struct udvec *xv;
134:
135: switch (code) {
136: case SPDU_DT:
137: if ((sb -> sb_requirements & SR_DAT_EXISTS)
138: && !(sb -> sb_owned & ST_DAT_TOKEN))
139: return ssaplose (si, SC_OPERATION, NULLCP,
140: "data token not owned by you");
141: break;
142:
143: case SPDU_TD:
144: if (!(sb -> sb_requirements & SR_TYPEDATA))
145: return ssaplose (si, SC_OPERATION, NULLCP,
146: "typed data service unavailable");
147: break;
148: }
149:
150: n = 0;
151: for (vv = uv; vv -> uv_base; vv++)
152: n += vv -> uv_len;
153: if (n == 0)
154: return ssaplose (si, SC_PARAMETER, NULLCP, "zero-length SSDU");
155:
156: ep = (bp = uv -> uv_base) + (cc = uv -> uv_len);
157: begin = 1;
158: while (uv -> uv_base) {
159: len = sb -> sb_tsdu_us ? min (n, sb -> sb_tsdu_us - SSDU_MAGIC) : n;
160: vv = vvs;
161: vvs[0].uv_base = vvs[1].uv_base = NULL;
162: vvs[1].uv_inline = 0;
163:
164: if (code == SPDU_DT) {
165: if ((s = newspkt (SPDU_GT)) == NULL)
166: return ssaplose (si, SC_CONGEST, NULLCP, "out of memory");
167: s -> s_mask |= SMASK_SPDU_GT;
168:
169: if (spkt2tsdu (s, &vv -> uv_base, &vv -> uv_len) == NOTOK) {
170: (void) ssaplose (si, s -> s_errno, NULLCP, NULLCP);
171: goto out1;
172: }
173: freespkt (s);
174: s = NULL;
175: vv++;
176: }
177:
178: xv = vv++;
179:
180: wv = vvs + NSPUV - 1;
181: for (; len > 0 && vv < wv; len -= j) {
182: j = min (cc, len);
183: vv -> uv_base = bp, vv -> uv_len = j, vv -> uv_inline = 1, vv++;
184: bp += j, cc -= j, n -= j;
185:
186: if (bp >= ep) {
187: if ((bp = (++uv) -> uv_base) == NULL)
188: break;
189: ep = bp + (cc = uv -> uv_len);
190: }
191: }
192: if (!sb -> sb_tsdu_us && uv -> uv_base) {
193: (void) ssaplose (si, SC_PARAMETER, NULLCP,
194: "too many vector entries in SDU");
195: goto out2;
196: }
197: vv -> uv_base = NULL;
198:
199: vv = xv;
200: if ((s = newspkt (code)) == NULL) {
201: (void) ssaplose (si, SC_CONGEST, NULLCP, "out of memory");
202: goto out2;
203: }
204: if (sb -> sb_tsdu_us) {
205: s -> s_mask |= SMASK_ENCLOSE;
206: if (begin) {
207: s -> s_enclose |= ENCL_BEGIN;
208: begin = 0;
209: }
210: if (uv -> uv_base == NULL)
211: s -> s_enclose |= ENCL_END;
212: }
213: if (spkt2tsdu (s, &vv -> uv_base, &vv -> uv_len) == NOTOK) {
214: (void) ssaplose (si, s -> s_errno, NULLCP, NULLCP);
215: goto out3;
216: }
217: freespkt (s);
218: s = NULL;
219:
220: if ((result = TWriteRequest (sb -> sb_fd, vvs, td)) == NOTOK)
221: (void) ts2sslose (si, "TWriteRequest", td);
222:
223: free (vvs[0].uv_base);
224: if (code == SPDU_DT)
225: free (vvs[1].uv_base);
226:
227: if (result == NOTOK)
228: return NOTOK;
229: }
230: return OK;
231:
232: out3: ;
233: if (vvs[1].uv_base && !vvs[1].uv_inline)
234: free (vvs[1].uv_base);
235: out2: ;
236: if (vvs[0].uv_base)
237: free (vvs[0].uv_base);
238: out1: ;
239: freespkt (s);
240:
241: return NOTOK;
242: }
243:
244: /* S-READ.REQUEST (pseudo; synchronous read) */
245:
246: int SReadRequest (sd, sx, secs, si)
247: int sd;
248: struct SSAPdata *sx;
249: int secs;
250: struct SSAPindication *si;
251: {
252: SBV smask;
253: int result;
254: register struct ssapblk *sb;
255:
256: missingP (sx);
257: missingP (si);
258:
259: smask = sigioblock ();
260:
261: if ((sb = findsblk (sd)) == NULL) {
262: (void) sigiomask (smask);
263: return ssaplose (si, SC_PARAMETER, NULLCP, "invalid session descriptor");
264: }
265: if (!(sb -> sb_flags & SB_CONN)) {
266: (void) sigiomask (smask);
267: return ssaplose (si, SC_PARAMETER, NULLCP,
268: "session descriptor not connected");
269: }
270: if (sb -> sb_flags & SB_FINN) {
271: (void) sigiomask (smask);
272: return ssaplose (si, SC_OPERATION, NULLCP,
273: "session descriptor finishing");
274: }
275:
276: result = SReadRequestAux (sb, sx, secs, si, 0, NULLTX);
277:
278: (void) sigiomask (smask);
279:
280: return result;
281: }
282:
283: /* */
284:
285: static int SReadRequestAux (sb, sx, secs, si, async, tx)
286: register struct ssapblk *sb;
287: register struct SSAPdata *sx;
288: int secs;
289: struct SSAPindication *si;
290: int async;
291: struct TSAPdata *tx;
292: {
293: int eot;
294: char tokens;
295: register struct ssapkt *s;
296:
297: bzero ((char *) sx, sizeof *sx);
298: sx -> sx_qbuf.qb_forw = sx -> sx_qbuf.qb_back = &sx -> sx_qbuf;
299: bzero ((char *) si, sizeof *si);
300:
301: for (; s = sb2spkt (sb, si, secs, tx); tx = NULLTX) {
302: if (!(s -> s_mask & SMASK_SPDU_EXPD))
303: switch (sb -> sb_pr) {
304: case SPDU_PR:
305: break;
306:
307: case SPDU_MAA:
308: if (s -> s_code == SPDU_MAA)
309: sb -> sb_pr = SPDU_PR;
310: break;
311:
312: case SPDU_RS:
313: switch (s -> s_code) {
314: case SPDU_AB:
315: #ifdef notdef
316: case SPDU_AI: /* aka SPDU_AB */
317: #endif
318: if (s -> s_mask & SMASK_SPDU_AB)
319: break; /* else fall */
320: case SPDU_AD:
321: case SPDU_RS:
322: sb -> sb_pr = SPDU_PR;
323: break;
324:
325: default:
326: goto drop_it;
327: }
328: break;
329:
330: case SPDU_RA:
331: switch (s -> s_code) {
332: case SPDU_AB:
333: break;
334:
335: case SPDU_AA:
336: #ifdef notdef
337: case SPDU_AIA: /* aka SPDU_AA */
338: #endif
339: if (s -> s_mask & SMASK_SPDU_AA)
340: break; /* else fall */
341: case SPDU_ADA:
342: case SPDU_RA:
343: sb -> sb_pr = SPDU_PR;
344: break;
345:
346: default:
347: drop_it: ;
348: SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
349: ("discarding 0x%x SPDU", s -> s_code));
350: freespkt (s);
351: goto spin;
352: }
353: break;
354:
355: case SPDU_AB:
356: if (s -> s_code != SPDU_AB)
357: goto drop_it;
358: sb -> sb_pr = SPDU_PR;
359: break;
360:
361: default:
362: break;
363: }
364:
365: if (sb -> sb_flags & (SB_RS | SB_AI))
366: switch (s -> s_code) {
367: case SPDU_PR:
368: switch (s -> s_pr_type) {
369: case PR_RS:
370: case PR_RA:
371: break;
372: default:
373: goto drop_it;
374: }
375: break;
376:
377: case SPDU_RS:
378: if (SDoCollideAux (sb -> sb_flags & SB_INIT ? 1 : 0,
379: sb -> sb_rs, sb -> sb_rsn,
380: (int) s -> s_rs_type, (long) s -> s_rs_serial)
381: != NOTOK)
382: goto drop_it;
383: break;
384:
385: case SPDU_RA:
386: break;
387:
388: case SPDU_AD:
389: if (SDoCollideAux (sb -> sb_flags & SB_INIT ? 1 : 0,
390: sb -> sb_rs, sb -> sb_rsn, SYNC_DISC, 0L)
391: != NOTOK)
392: goto drop_it;
393: break;
394:
395: case SPDU_AB:
396: #ifdef notdef
397: case SPDU_AI: /* aka SPDU_AB */
398: #endif
399: if (s -> s_mask & SMASK_SPDU_AB)
400: break;
401: if (SDoCollideAux (sb -> sb_flags & SB_INIT ? 1 : 0,
402: sb -> sb_rs, sb -> sb_rsn, SYNC_INTR, 0L)
403: != NOTOK)
404: goto drop_it;
405: break;
406: }
407:
408: if (sb -> sb_flags & (SB_ED | SB_ERACK))
409: switch (s -> s_code) {
410: case SPDU_AB:
411: break;
412:
413: case SPDU_MAP:
414: case SPDU_MIP:
415: if (sb -> sb_flags & SB_ED)
416: break;
417: goto drop_it;
418:
419: case SPDU_PR:
420: if (s -> s_pr_type == PR_RS)
421: break;
422: goto drop_it;
423:
424: case SPDU_GT:
425: if ((s -> s_mask & SMASK_SPDU_GT)
426: && (s -> s_mask & SMASK_GT_TOKEN)
427: && (s -> s_gt_token & ST_DAT_TOKEN))
428: break; /* else fall */
429:
430: default:
431: goto drop_it;
432: }
433:
434: if (sb -> sb_len > 0)
435: switch (s -> s_code) {
436: case SPDU_PT:
437: case SPDU_EX:
438: break;
439:
440: case SPDU_PR:
441: if (s -> s_pr_type != PR_RS)
442: break;
443: case SPDU_RS:
444: case SPDU_ER:
445: case SPDU_ED:
446: case SPDU_AD:
447: #ifdef notdef
448: case SPDU_AI: /* aka SPDU_AB */
449: #endif
450: case SPDU_AB:
451: SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
452: ("flush partially assembled (T))SSDU"));
453: QBFREE (&sb -> sb_qbuf);
454: sb -> sb_len = 0;
455: break;
456:
457: case SPDU_GT:
458: if (s -> s_mask & SMASK_SPDU_GT)
459: break; /* else SPDU_DT */
460: default:
461: if (sb -> sb_code == s -> s_code)
462: break;
463: (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
464: "session protocol mangled: expecting 0x%x, got 0x%x during segmentation",
465: sb -> sb_code, s -> s_code);
466: goto out;
467: }
468:
469: /* allows AB SPDUs to have 512, not 9, octets (which is fine by me) */
470: if (s -> s_ulen > CN_SIZE && sb -> sb_version < SB_VRSN2) {
471: (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
472: "too much user data (%d) in SPDU 0x%x",
473: s -> s_ulen, s -> s_code);
474: goto out;
475: }
476:
477: if ((s -> s_mask & SMASK_ENCLOSE)
478: && (s -> s_code != SPDU_DT || (s -> s_mask & SMASK_SPDU_GT))
479: && s -> s_code != SPDU_TD) {
480: if (sb -> sb_version < SB_VRSN2) {
481: (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
482: "unexpected segmentation for SPDU 0x%x",
483: s -> s_code);
484: goto out;
485: }
486:
487: /* XXX: in practice, I don't think this is unreasonable. It is
488: however not too restrictive */
489:
490: if (s -> s_enclose != ENCL_MASK) {
491: (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
492: "non-trivial segmentation (0x%x) for SPDU 0x%x",
493: s -> s_enclose, s -> s_code);
494: goto out;
495: }
496: }
497:
498: switch (s -> s_code) {
499: case SPDU_PT:
500: if (sb -> sb_flags & SB_GTC) {
501: freespkt (s);
502: goto spin;
503: }
504: tokens = 0;
505: if (s -> s_mask & SMASK_PT_TOKEN) {
506: #define dotoken(requires,shift,bit,type) \
507: { \
508: if ((sb -> sb_requirements & requires) \
509: && (s -> s_pt_token & bit)) \
510: tokens |= bit; \
511: }
512: dotokens ();
513: #undef dotoken
514: }
515: si -> si_type = SI_TOKEN;
516: {
517: register struct SSAPtoken *st = &si -> si_token;
518:
519: st -> st_type = ST_PLEASE;
520: st -> st_tokens = tokens;
521: st -> st_owned = sb -> sb_owned;
522: copySPKTdata (s, st);
523: }
524: freespkt (s);
525: return DONE;
526:
527: case SPDU_GT:
528: if (s -> s_mask & SMASK_SPDU_GT) {
529: if (sb -> sb_flags & SB_GTC) {
530: freespkt (s);
531: goto spin;
532: }
533: tokens = 0;
534: if (s -> s_mask & SMASK_GT_TOKEN) {
535: #define dotoken(requires,shift,bit,type) \
536: { \
537: if ((sb -> sb_requirements & requires) \
538: && (s -> s_gt_token & bit)) \
539: sb -> sb_owned |= bit, tokens |= bit; \
540: }
541: dotokens ();
542: #undef dotoken
543: }
544: freespkt (s);
545: if (tokens & ST_DAT_TOKEN)
546: sb -> sb_flags &= ~(SB_ED | SB_ERACK);
547: si -> si_type = SI_TOKEN;
548: {
549: register struct SSAPtoken *st = &si -> si_token;
550:
551: st -> st_type = ST_GIVE;
552: st -> st_tokens = tokens;
553: st -> st_owned = sb -> sb_owned;
554: }
555: return DONE;
556: } /* else fall for case SPDU_DT: */
557: #ifdef notdef
558: case SPDU_DT:
559: #endif
560: case SPDU_TD:
561: sb -> sb_code = s -> s_code;
562: if (sb -> sb_tsdu_them) {
563: if (!(s -> s_mask & SMASK_ENCLOSE)) {
564: (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
565: "no segmentation information");
566: break;
567: }
568: if ((s -> s_enclose & ENCL_BEGIN)
569: ? sb -> sb_len > 0 : sb -> sb_len == 0) {
570: (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
571: "segmentation mismatch");
572: break;
573: }
574: eot = s -> s_enclose & ENCL_END;
575: }
576: else
577: eot = 1;
578: if (s -> s_qbuf.qb_forw != &s -> s_qbuf) {
579: sb -> sb_qbuf.qb_back -> qb_forw = s -> s_qbuf.qb_forw;
580: s -> s_qbuf.qb_forw -> qb_back = sb -> sb_qbuf.qb_back;
581: s -> s_qbuf.qb_back -> qb_forw = &sb -> sb_qbuf;
582: sb -> sb_qbuf.qb_back = s -> s_qbuf.qb_back;
583: sb -> sb_len += s -> s_qlen;
584: s -> s_qbuf.qb_forw =
585: s -> s_qbuf.qb_back = &s -> s_qbuf;
586: s -> s_qlen = 0;
587: }
588: if (!eot && (s -> s_code == SPDU_DT) && sb -> sb_spdu) {
589: freespkt (sb -> sb_spdu);
590: sb -> sb_spdu = NULL;
591: }
592: freespkt (s);
593: if (!eot)
594: goto spin;
595: sx -> sx_type = sb -> sb_code == SPDU_DT ? SX_NORMAL
596: : SX_TYPED;
597: if (sb -> sb_qbuf.qb_forw != &sb -> sb_qbuf) {
598: sx -> sx_qbuf = sb -> sb_qbuf;/* struct copy */
599: sx -> sx_qbuf.qb_forw -> qb_back =
600: sx -> sx_qbuf.qb_back -> qb_forw = &sx -> sx_qbuf;
601: sx -> sx_cc = sb -> sb_len;
602: sb -> sb_qbuf.qb_forw =
603: sb -> sb_qbuf.qb_back = &sb -> sb_qbuf;
604: sb -> sb_len = 0;
605: }
606: return OK;
607:
608: case SPDU_EX:
609: if (sb -> sb_pr != SPDU_PR) {
610: SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
611: ("buffering XSDU during preparation"));
612: if (sb -> sb_xspdu) {
613: (void) spktlose (sb -> sb_fd, si, SC_CONGEST, NULLCP,
614: "unable to buffer second XSDU");
615: break;
616: }
617: sb -> sb_xspdu = s;
618: goto spin;
619: }
620: sx -> sx_type = SX_EXPEDITED;
621: if (s -> s_qbuf.qb_forw != &s -> s_qbuf) {
622: sx -> sx_qbuf = s -> s_qbuf;/* struct copy */
623: sx -> sx_qbuf.qb_forw -> qb_back =
624: sx -> sx_qbuf.qb_back -> qb_forw = &sx -> sx_qbuf;
625: sx -> sx_cc = s -> s_qlen;
626: s -> s_qbuf.qb_forw =
627: s -> s_qbuf.qb_back = &s -> s_qbuf;
628: s -> s_qlen = 0;
629: }
630: freespkt (s);
631: return OK;
632:
633: case SPDU_CD:
634: case SPDU_CDA:
635: if (s -> s_code == SPDU_CD) {
636: sb -> sb_flags |= SB_CDA;
637: sx -> sx_type = SX_CAPDIND;
638: }
639: else {
640: sb -> sb_flags &= ~SB_CD;
641: sx -> sx_type = SX_CAPDCNF;
642: }
643: if (s -> s_udata) {
644: register struct qbuf *qb;
645:
646: qb = (struct qbuf *)
647: malloc (sizeof *qb + (unsigned) s -> s_ulen);
648: if (qb == NULL) {
649: (void) spktlose (sb -> sb_fd, si, SC_CONGEST, NULLCP,
650: "out of memory");
651: break;
652: }
653: bcopy (s -> s_udata, qb -> qb_data = qb -> qb_base,
654: qb -> qb_len = s -> s_ulen);
655: insque (qb, &sx -> sx_qbuf);
656: sx -> sx_cc = s -> s_ulen;
657: }
658: freespkt (s);
659: return OK;
660:
661: case SPDU_GTC:
662: if (sb -> sb_flags & SB_Vact) {
663: freespkt (s);
664: goto spin;
665: }
666: #define dotoken(requires,shift,bit,type) \
667: { \
668: if (sb -> sb_requirements & requires) \
669: sb -> sb_owned |= bit; \
670: }
671: dotokens ();
672: #undef dotoken
673: freespkt (s);
674: if ((s = newspkt (SPDU_GTA)) == NULL) {
675: (void) spktlose (sb -> sb_fd, si, SC_CONGEST, NULLCP,
676: "out of memory");
677: break;
678: }
679: if (spkt2sd (s, sb -> sb_fd, 0, si) == NOTOK)
680: break;
681: freespkt (s);
682: si -> si_type = SI_TOKEN;
683: {
684: register struct SSAPtoken *st = &si -> si_token;
685:
686: st -> st_type = ST_CONTROL;
687: st -> st_tokens = st -> st_owned = sb -> sb_owned;
688: }
689: return DONE;
690:
691: case SPDU_GTA:
692: if (!(sb -> sb_flags & SB_GTC)) {
693: freespkt (s);
694: goto spin;
695: }
696: sb -> sb_flags &= ~SB_GTC;
697: spin: ;
698: if (!async || sb -> sb_spdu)
699: continue;
700: si -> si_type = SI_DATA;
701: {
702: register struct SSAPdata *sk = &si -> si_data;
703:
704: bzero ((char *) sk, sizeof *sk);
705: sk -> sx_qbuf.qb_forw = sk -> sx_qbuf.qb_back =
706: &sk -> sx_qbuf;
707: }
708: return DONE;
709:
710: case SPDU_MAP:
711: #ifdef notdef
712: case SPDU_AE: /* aka SPDU_MAP */
713: #endif
714: if (sb -> sb_V_M != s -> s_map_serial) {
715: freespkt (s);
716: goto spin;
717: }
718: if (!(s -> s_mask & SMASK_MAP_SYNC)
719: || !(s -> s_map_sync & MAP_SYNC_NOEND))
720: goto spdu_ae;
721: if (!(sb -> sb_flags & SB_Vsc))
722: sb -> sb_V_A = sb -> sb_V_M;
723: sb -> sb_V_M++;
724: if (sb -> sb_flags & (SB_ED | SB_ERACK)) {
725: freespkt (s);
726: goto spin;
727: }
728: if (sb -> sb_requirements & SR_ACTIVITY)
729: sb -> sb_flags |= SB_Vnextact;
730: sb -> sb_flags |= SB_MAA;
731: si -> si_type = SI_SYNC;
732: {
733: register struct SSAPsync *sn = &si -> si_sync;
734:
735: sn -> sn_type = SN_MAJORIND;
736: sn -> sn_ssn = s -> s_map_serial;
737: copySPKTdata (s, sn);
738: }
739: freespkt (s);
740: return DONE;
741:
742: case SPDU_MAA:
743: #ifdef notdef
744: case SPDU_AEA: /* aka SPDU_MAA */
745: #endif
746: if (sb -> sb_V_M != s -> s_maa_serial + 1) {
747: freespkt (s);
748: goto spin;
749: }
750: sb -> sb_V_A = sb -> sb_V_R = sb -> sb_V_M;
751: if (sb -> sb_requirements & SR_ACTIVITY)
752: if (sb -> sb_flags & SB_Vnextact)
753: sb -> sb_flags |= SB_Vact;
754: else
755: sb -> sb_flags &= ~SB_Vact;
756: sb -> sb_flags &= ~SB_MAP;
757: if (sb -> sb_flags & SB_AE) {
758: sb -> sb_flags &= ~SB_AE;
759: si -> si_type = SI_ACTIVITY;
760: {
761: register struct SSAPactivity *sv = &si -> si_activity;
762:
763: sv -> sv_type = SV_ENDCNF;
764: sv -> sv_ssn = s -> s_maa_serial;
765: copySPKTdata (s, sv);
766: }
767: }
768: else {
769: si -> si_type = SI_SYNC;
770: {
771: register struct SSAPsync *sn = &si -> si_sync;
772:
773: sn -> sn_type = SN_MAJORCNF;
774: sn -> sn_ssn = s -> s_maa_serial;
775: copySPKTdata (s, sn);
776: }
777: }
778: freespkt (s);
779: return DONE;
780:
781: case SPDU_MIP:
782: if (!(sb -> sb_flags & SB_Vsc)) {
783: sb -> sb_V_A = sb -> sb_V_M;
784: sb -> sb_flags |= SB_Vsc;
785: }
786: sb -> sb_V_M++;
787: if (sb -> sb_flags & (SB_ED | SB_ERACK)) {
788: freespkt (s);
789: goto spin;
790: }
791: si -> si_type = SI_SYNC;
792: {
793: register struct SSAPsync *sn = &si -> si_sync;
794:
795: sn -> sn_type = SN_MINORIND;
796: sn -> sn_options = (s -> s_mask & SMASK_MIP_SYNC)
797: && (s -> s_mip_sync & MIP_SYNC_NOEXPL)
798: ? SYNC_NOCONFIRM : SYNC_CONFIRM;
799: sn -> sn_ssn = s -> s_mip_serial;
800: copySPKTdata (s, sn);
801: }
802: freespkt (s);
803: return DONE;
804:
805: case SPDU_MIA:
806: if ((sb -> sb_flags & SB_Vsc)
807: || sb -> sb_V_A > s -> s_mia_serial
808: || s -> s_mia_serial >= sb -> sb_V_M) {
809: freespkt (s);
810: goto spin;
811: }
812: sb -> sb_V_A = s -> s_mia_serial;
813: si -> si_type = SI_SYNC;
814: {
815: register struct SSAPsync *sn = &si -> si_sync;
816:
817: sn -> sn_type = SN_MINORCNF;
818: sn -> sn_ssn = s -> s_mia_serial;
819: copySPKTdata (s, sn);
820: }
821: freespkt (s);
822: return DONE;
823:
824: case SPDU_RS:
825: if (s -> s_rs_type == SYNC_RESTART
826: && sb -> sb_V_R > s -> s_rs_serial) {
827: freespkt (s);
828: goto spin;
829: }
830: sb -> sb_flags &= ~SB_RS, sb -> sb_flags |= SB_RA;
831: sb -> sb_rs = s -> s_rs_type;
832: sb -> sb_rsn = s -> s_rs_serial;
833: if (s -> s_mask & SMASK_RS_SET)
834: sb -> sb_rsettings = s -> s_rs_settings;
835: else {
836: sb -> sb_rsettings = 0;
837: #define dotoken(requires,shift,bit,type) \
838: { \
839: if (sb -> sb_requirements & requires) \
840: if ((sb -> sb_owned & bit) \
841: && (sb -> sb_flags & SB_INIT)) \
842: sb -> sb_rsettings = ST_INIT_VALUE << shift; \
843: else \
844: sb -> sb_rsettings = ST_RESP_VALUE << shift; \
845: }
846: dotokens ();
847: #undef dotoken
848: }
849: si -> si_type = SI_SYNC;
850: {
851: register struct SSAPsync *sn = &si -> si_sync;
852:
853: sn -> sn_type = SN_RESETIND;
854: sn -> sn_options = sb -> sb_rs;
855: sn -> sn_ssn = sb -> sb_rsn;
856: sn -> sn_settings = sb -> sb_rsettings;
857: copySPKTdata (s, sn);
858: }
859: freespkt (s);
860: return DONE;
861:
862: case SPDU_RA:
863: sb -> sb_flags &= ~SB_RS;
864: sb -> sb_V_A = sb -> sb_V_M = s -> s_ra_serial;
865: if (sb -> sb_rs != SYNC_RESTART)
866: sb -> sb_V_R = 0;
867: if (s -> s_mask & SMASK_RA_SET)
868: sb -> sb_rsettings = s -> s_ra_settings;
869: #define dotoken(requires,shift,bit,type) \
870: { \
871: if (sb -> sb_requirements & requires) \
872: switch (sb -> sb_rsettings & (ST_MASK << shift)) { \
873: dotoken1 (requires,shift,bit,type); \
874: \
875: dotoken2 (requires,shift,bit,type); \
876: } \
877: }
878: #define dotoken1(requires,shift,bit,type) \
879: case ST_CALL_VALUE << shift: \
880: switch (s -> s_ra_settings & (ST_MASK << shift)) { \
881: case ST_INIT_VALUE: \
882: if (sb -> sb_flags & SB_INIT) \
883: sb -> sb_owned |= bit; \
884: else \
885: sb -> sb_owned &= ~bit; \
886: break; \
887: \
888: case ST_RESP_VALUE: \
889: if (!(sb -> sb_flags & SB_INIT)) \
890: sb -> sb_owned |= bit; \
891: else \
892: sb -> sb_owned &= ~bit; \
893: break; \
894: } \
895: break;
896: #define dotoken2(requires,shift,bit,type) \
897: case ST_INIT_VALUE << shift: \
898: if (sb -> sb_flags & SB_INIT) \
899: sb -> sb_owned |= bit; \
900: else \
901: sb -> sb_owned &= ~bit; \
902: break; \
903: \
904: case ST_RESP_VALUE << shift: \
905: if (!(sb -> sb_flags & SB_INIT)) \
906: sb -> sb_owned |= bit; \
907: else \
908: sb -> sb_owned &= ~bit; \
909: break;
910: dotokens ();
911: #undef dotoken
912: #undef dotoken1
913: #undef dotoken2
914: si -> si_type = SI_SYNC;
915: {
916: register struct SSAPsync *sn = &si -> si_sync;
917:
918: sn -> sn_type = SN_RESETCNF;
919: sn -> sn_ssn = sb -> sb_V_M;
920: sn -> sn_settings = sb -> sb_rsettings;
921: copySPKTdata (s, sn);
922: }
923: freespkt (s);
924: return DONE;
925:
926: case SPDU_PR:
927: switch (s -> s_pr_type) {
928: case PR_MAA:
929: sb -> sb_pr = SPDU_MAA;
930: break;
931: case PR_RS:
932: sb -> sb_flags &= ~(SB_ED | SB_ERACK);
933: sb -> sb_pr = SPDU_RS;
934: break;
935: case PR_RA:
936: sb -> sb_pr = SPDU_RA;
937: break;
938: case PR_AB:
939: sb -> sb_pr = SPDU_AB;
940: break;
941: }
942: freespkt (s);
943: goto spin;
944:
945: case SPDU_ER: /* this implementation never generates these */
946: sb -> sb_flags |= SB_ERACK;
947: si -> si_type = SI_REPORT;
948: {
949: register struct SSAPreport *sp = &si -> si_report;
950:
951: sp -> sp_peer = 0;
952: sp -> sp_reason = SP_PROTOCOL;
953: }
954: freespkt (s);
955: return DONE;
956:
957: case SPDU_ED:
958: if (sb -> sb_owned & ST_DAT_TOKEN)
959: sb -> sb_flags |= SB_EDACK;
960: si -> si_type = SI_REPORT;
961: {
962: register struct SSAPreport *sp = &si -> si_report;
963:
964: sp -> sp_peer = 1;
965: sp -> sp_reason = s -> s_ed_reason;
966: copySPKTdata (s, sp);
967: }
968: freespkt (s);
969: return DONE;
970:
971: case SPDU_AS:
972: if (sb -> sb_flags & SB_Vact) {
973: freespkt (s);
974: goto spin;
975: }
976: sb -> sb_V_A = sb -> sb_V_M = sb -> sb_V_R = 1;
977: sb -> sb_flags |= SB_Vact;
978: si -> si_type = SI_ACTIVITY;
979: {
980: register struct SSAPactivity *sv = &si -> si_activity;
981:
982: sv -> sv_type = SV_START;
983: sv -> sv_id = s -> s_as_id; /* struct copy */
984: copySPKTdata (s, sv);
985: }
986: freespkt (s);
987: return DONE;
988:
989: case SPDU_AR:
990: if (sb -> sb_flags & SB_Vact) {
991: freespkt (s);
992: goto spin;
993: }
994: sb -> sb_V_A = sb -> sb_V_M = s -> s_ar_serial + 1;
995: sb -> sb_V_R = 1;
996: sb -> sb_flags |= SB_Vact;
997: si -> si_type = SI_ACTIVITY;
998: {
999: register struct SSAPactivity *sv = &si -> si_activity;
1000:
1001: sv -> sv_type = SV_RESUME;
1002: sv -> sv_id = s -> s_ar_id; /* struct copy */
1003: sv -> sv_oid = s -> s_ar_oid; /* struct copy */
1004: if (s -> s_mask & SMASK_AR_REF) /* struct copy */
1005: sv -> sv_connect = s -> s_ar_reference;
1006: sv -> sv_ssn = s -> s_ar_serial;
1007: copySPKTdata (s, sv);
1008: }
1009: freespkt (s);
1010: return DONE;
1011:
1012: case SPDU_AD:
1013: spdu_ai: ;
1014: if (!(sb -> sb_flags & SB_Vact)) {
1015: freespkt (s);
1016: goto spin;
1017: }
1018: sb -> sb_flags &= ~(SB_RS | SB_RA), sb -> sb_flags |= SB_AIA;
1019: sb -> sb_rs = SYNC_INTR;
1020: si -> si_type = SI_ACTIVITY;
1021: {
1022: register struct SSAPactivity *sv = &si -> si_activity;
1023:
1024: sv -> sv_type = s -> s_code == SPDU_AI ? SV_INTRIND
1025: : SV_DISCIND;
1026: sv -> sv_reason = s -> s_ai_reason;
1027: }
1028: freespkt (s);
1029: return DONE;
1030:
1031: case SPDU_AA:
1032: #ifdef notdef
1033: case SPDU_AIA: /* aka SPDU_AA */
1034: #endif
1035: if (s -> s_mask & SMASK_SPDU_AA) {
1036: freespkt (s);
1037: goto spin;
1038: } /* else fall */
1039: case SPDU_ADA:
1040: if (!(sb -> sb_flags & SB_Vact)) {
1041: freespkt (s);
1042: goto spin;
1043: }
1044: sb -> sb_flags &= ~(SB_AI | SB_Vact);
1045: #define dotoken(requires,shift,bit,type) \
1046: { \
1047: if (sb -> sb_requirements & requires) \
1048: sb -> sb_owned |= bit; \
1049: }
1050: dotokens ();
1051: #undef dotoken
1052: si -> si_type = SI_ACTIVITY;
1053: {
1054: register struct SSAPactivity *sv = &si -> si_activity;
1055:
1056: sv -> sv_type = s -> s_code == SPDU_AIA ? SV_INTRCNF
1057: : SV_DISCCNF;
1058: }
1059: freespkt (s);
1060: return DONE;
1061:
1062: spdu_ae: ;
1063: if (!(sb -> sb_flags & SB_Vsc))
1064: sb -> sb_V_A = sb -> sb_V_M;
1065: sb -> sb_V_M++;
1066: sb -> sb_flags &= ~SB_Vnextact;
1067: sb -> sb_flags |= SB_MAA | SB_AE;
1068: si -> si_type = SI_ACTIVITY;
1069: {
1070: register struct SSAPactivity *sv = &si -> si_activity;
1071:
1072: sv -> sv_type = SV_ENDIND;
1073: sv -> sv_ssn = s -> s_map_serial;
1074: copySPKTdata (s, sv);
1075: }
1076: freespkt (s);
1077: return DONE;
1078:
1079: case SPDU_FN:
1080: sb -> sb_flags |= SB_FINN;
1081: si -> si_type = SI_FINISH;
1082: {
1083: register struct SSAPfinish *sf = &si -> si_finish;
1084:
1085: copySPKTdata (s, sf);
1086: }
1087: freespkt (s);
1088: return DONE;
1089:
1090: case SPDU_AB:
1091: if (!(s -> s_mask & SMASK_SPDU_AB))
1092: goto spdu_ai;
1093: sb -> sb_flags &= ~(SB_ED | SB_EDACK | SB_ERACK);
1094: si -> si_type = SI_ABORT;
1095: {
1096: register struct SSAPabort *sa = &si -> si_abort;
1097:
1098: if (!(sa -> sa_peer = (s -> s_ab_disconnect & AB_DISC_USER)
1099: ? 1 : 0))
1100: sa -> sa_reason = SC_ABORT;
1101: sa -> sa_info = s -> s_udata, sa -> sa_cc = s -> s_ulen;
1102: sa -> sa_realinfo = s -> s_udata, s -> s_udata = NULL;
1103: }
1104: #ifdef notdef /* only if transport connection is to be re-used */
1105: freespkt (s);
1106: if (s = newspkt (SPDU_AA)) {
1107: s -> s_mask |= SMASK_SPDU_AA;
1108: (void) spkt2sd (s, sb -> sb_fd, sb -> sb_flags & SB_EXPD
1109: ? 1 : 0, (struct SSAPindication *) 0);
1110: }
1111: #endif
1112: break;
1113:
1114: default:
1115: (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
1116: "session protocol mangled: not expecting 0x%x",
1117: s -> s_code);
1118: break;
1119: }
1120: break;
1121: }
1122:
1123: if (si -> si_abort.sa_reason == SC_TIMER)
1124: return NOTOK;
1125:
1126: out: ;
1127: freespkt (s);
1128: freesblk (sb);
1129:
1130: return NOTOK;
1131: }
1132:
1133: /* */
1134:
1135: /* a decision tree (ugh!) */
1136:
1137: int SDoCollideAux (init, localop, localssn, remoteop, remotessn)
1138: int init,
1139: localop,
1140: remoteop;
1141: long localssn,
1142: remotessn;
1143: {
1144: SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
1145: ("collide: local<%d,%ld,%s> remote<%d,%ld,%s>",
1146: localop, localssn, init ? "initiator" : "responder",
1147: remoteop, remotessn, init ? "responder" : "initiator"));
1148:
1149: if (localop == SYNC_DISC)
1150: return OK;
1151:
1152: if (remoteop == SYNC_DISC)
1153: return NOTOK;
1154:
1155: if (localop == SYNC_INTR)
1156: return OK;
1157:
1158: if (remoteop == SYNC_DISC)
1159: return NOTOK;
1160:
1161: if (localop == SYNC_ABANDON) {
1162: if (remoteop != SYNC_ABANDON)
1163: return OK;
1164:
1165: return (init ? OK : NOTOK);
1166: }
1167: else
1168: if (remoteop == SYNC_ABANDON)
1169: return NOTOK;
1170:
1171: if (localop == SYNC_SET) {
1172: if (remoteop != SYNC_SET)
1173: return OK;
1174:
1175: return (init ? OK : NOTOK);
1176: }
1177: else
1178: if (remoteop == SYNC_SET)
1179: return NOTOK;
1180:
1181: if (localssn == remotessn)
1182: return (init ? OK : NOTOK);
1183:
1184: return (localssn < remotessn ? OK : NOTOK);
1185: }
1186:
1187: /* define vectors for INDICATION events */
1188:
1189: int SSetIndications (sd, data, tokens, sync, activity, report, finish,
1190: abort, si)
1191: int sd;
1192: IFP data,
1193: tokens,
1194: sync,
1195: activity,
1196: report,
1197: finish,
1198: abort;
1199: struct SSAPindication *si;
1200: {
1201: SBV smask;
1202: register struct ssapblk *sb;
1203: struct TSAPdisconnect tds;
1204: register struct TSAPdisconnect *td = &tds;
1205:
1206: if (data || tokens || sync || activity || report || finish || abort) {
1207: missingP (data);
1208: missingP (tokens);
1209: missingP (sync);
1210: missingP (activity);
1211: missingP (report);
1212: missingP (finish);
1213: missingP (abort);
1214: }
1215:
1216: smask = sigioblock ();
1217:
1218: ssapPsig (sb, sd);
1219:
1220: if (TSetIndications (sb -> sb_fd, TDATAser, TDISCser, td) == NOTOK)
1221: if (td -> td_reason == DR_WAITING)
1222: return ssaplose (si, SC_WAITING, NULLCP, NULLCP);
1223: else
1224: return ts2sslose (si, "TSetIndications", td);
1225:
1226: if (sb -> sb_DataIndication = data)
1227: sb -> sb_flags |= SB_ASYN;
1228: else
1229: sb -> sb_flags &= ~SB_ASYN;
1230: sb -> sb_TokenIndication = tokens;
1231: sb -> sb_SyncIndication = sync;
1232: sb -> sb_ActivityIndication = activity;
1233: sb -> sb_ReportIndication = report;
1234: sb -> sb_ReleaseIndication = finish;
1235: sb -> sb_AbortIndication = abort;
1236:
1237: (void) sigiomask (smask);
1238:
1239: return OK;
1240: }
1241:
1242: /* TSAP interface */
1243:
1244: int spkt2sd (s, sd, expedited, si)
1245: register struct ssapkt *s;
1246: int sd,
1247: expedited;
1248: register struct SSAPindication *si;
1249: {
1250: int i,
1251: len,
1252: result;
1253: char *base,
1254: *dp;
1255: struct TSAPdisconnect tds;
1256: register struct TSAPdisconnect *td = &tds;
1257:
1258: if (expedited)
1259: s -> s_mask |= SMASK_SPDU_EXPD;
1260: if (spkt2tsdu (s, &base, &len) == NOTOK) {
1261: (void) ssaplose (si, s -> s_errno, NULLCP, NULLCP);
1262: return NOTOK;
1263: }
1264: if (s -> s_code == SPDU_EX) {/* only SX_EXSIZE octets, so no big deal... */
1265: if (s -> s_udata) {
1266: if ((dp = realloc (base, (unsigned) (i = len + s -> s_ulen)))
1267: == NULL) {
1268: free (base);
1269: (void) ssaplose (si, SC_CONGEST, NULLCP, NULLCP);
1270: return NOTOK;
1271: }
1272: bcopy (s -> s_udata, (base = dp) + len, s -> s_ulen);
1273: len = i;
1274: }
1275: }
1276:
1277: if (len > TX_SIZE)
1278: expedited = 0;
1279: if ((result = expedited ? TExpdRequest (sd, base, len, td)
1280: : TDataRequest (sd, base, len, td)) == NOTOK)
1281: (void) ts2sslose (si, expedited ? "TExpdRequest" : "TDataRequest", td);
1282:
1283: if (base)
1284: free (base);
1285:
1286: return result;
1287: }
1288:
1289: /* */
1290:
1291: struct ssapkt *sb2spkt (sb, si, secs, ty)
1292: register struct ssapblk *sb;
1293: register struct SSAPindication *si;
1294: int secs;
1295: register struct TSAPdata *ty;
1296: {
1297: int cc;
1298: register struct ssapkt *s,
1299: *p;
1300: struct TSAPdata txs;
1301: register struct TSAPdata *tx = &txs;
1302: struct TSAPdisconnect tds;
1303: register struct TSAPdisconnect *td = &tds;
1304:
1305: if (sb -> sb_pr == SPDU_PR && sb -> sb_xspdu) {
1306: SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
1307: ("returning XSDU buffered during preparation"));
1308: s = sb -> sb_xspdu;
1309: sb -> sb_xspdu = NULL;
1310:
1311: return s;
1312: }
1313:
1314: if (sb -> sb_spdu) { /* get previous category 0 SPDU */
1315: SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
1316: ("returning category 0 SPDU previously buffered"));
1317: s = sb -> sb_spdu;
1318: sb -> sb_spdu = NULL;
1319:
1320: return s;
1321: }
1322:
1323: if (ty) {
1324: *tx = *ty; /* struct copy */
1325: tx -> tx_qbuf.qb_forw -> qb_back =
1326: tx -> tx_qbuf.qb_back -> qb_forw = &tx -> tx_qbuf;
1327: bzero ((char *) ty, sizeof *ty);
1328: ty -> tx_qbuf.qb_forw = ty -> tx_qbuf.qb_back = &ty -> tx_qbuf;
1329: }
1330: else
1331: if (TReadRequest (sb -> sb_fd, tx, secs, td) == NOTOK) {
1332: if (td -> td_reason != DR_TIMER)
1333: (void) ts2sslose (si, "TReadRequest", td);
1334: else
1335: (void) ssaplose (si, SC_TIMER, NULLCP, NULLCP);
1336:
1337: return NULL;
1338: }
1339:
1340: DLOG (ssap_log, LLOG_DEBUG, ("read TSDU, size %d", tx -> tx_cc));
1341:
1342: if ((s = tsdu2spkt (&tx -> tx_qbuf, tx -> tx_cc, (cc = 1, &cc))) == NULL
1343: || s -> s_errno != SC_ACCEPT) {
1344: (void) ssaplose (si, s ? s -> s_errno : SC_CONGEST, NULLCP, NULLCP);
1345: bad1: ;
1346: freespkt (s);
1347: TXFREE (tx);
1348: return NULL;
1349: }
1350:
1351: if (tx -> tx_expedited)
1352: s -> s_mask |= SMASK_SPDU_EXPD;
1353: tx -> tx_cc -= cc;
1354:
1355: switch (s -> s_code) {
1356: case SPDU_GT: /* category 0 SPDUs */
1357: case SPDU_PT:
1358: if (tx -> tx_cc <= 0)
1359: goto simple;
1360: break;
1361:
1362: case SPDU_EX: /* category 1 SPDUs with user data */
1363: case SPDU_TD:
1364: if (tx -> tx_qbuf.qb_forw != &tx -> tx_qbuf) {
1365: s -> s_qbuf = tx -> tx_qbuf;/* struct copy */
1366: s -> s_qbuf.qb_forw -> qb_back =
1367: s -> s_qbuf.qb_back -> qb_forw = &s -> s_qbuf;
1368: s -> s_qlen = tx -> tx_cc;
1369: }
1370: return s;
1371:
1372: case SPDU_CN: /* category 1 SPDUs */
1373: case SPDU_AC:
1374: case SPDU_RF:
1375: case SPDU_FN:
1376: case SPDU_DN:
1377: case SPDU_NF:
1378: case SPDU_AB:
1379: case SPDU_AA:
1380: case SPDU_GTC:
1381: case SPDU_GTA:
1382: case SPDU_PR:
1383: if (tx -> tx_cc <= 0) {
1384: simple: ;
1385: TXFREE (tx);
1386: return s;
1387: }
1388: (void) ssaplose (si, SC_PROTOCOL, NULLCP,
1389: "session protocol mangled: not expecting user information after 0x%x (%d bytes)",
1390: s -> s_code, tx -> tx_cc);
1391: goto bad1;
1392:
1393: default:
1394: (void) ssaplose (si, SC_PROTOCOL, NULLCP,
1395: "session protocol mangled: not expecting 0x%x",
1396: s -> s_code);
1397: goto bad1;
1398: }
1399:
1400: sb -> sb_spdu = p = s; /* save category 0 SPDU */
1401:
1402: if ((s = tsdu2spkt (&tx -> tx_qbuf, tx -> tx_cc, (cc = 0, &cc))) == NULL
1403: || s -> s_errno != SC_ACCEPT) {
1404: (void) ssaplose (si, s ? s -> s_errno : SC_CONGEST, NULLCP, NULLCP);
1405: bad2: ;
1406: freespkt (s);
1407: freespkt (p);
1408: sb -> sb_spdu = NULL;
1409: TXFREE (tx);
1410: return NULL;
1411: }
1412:
1413: if (tx -> tx_expedited)
1414: s -> s_mask |= SMASK_SPDU_EXPD;
1415: tx -> tx_cc -= cc;
1416:
1417: switch ((p -> s_code) << 8 | s -> s_code) {
1418: case (SPDU_GT << 8) | SPDU_DT: /* category 2 SPDUs with user data */
1419: if (tx -> tx_qbuf.qb_forw != &tx -> tx_qbuf) {
1420: s -> s_qbuf = tx -> tx_qbuf;/* struct copy */
1421: s -> s_qbuf.qb_forw -> qb_back =
1422: s -> s_qbuf.qb_back -> qb_forw = &s -> s_qbuf;
1423: s -> s_qlen = tx -> tx_cc;
1424: }
1425: break;
1426:
1427: case (SPDU_GT << 8) | SPDU_MIP: /* category 2 SPDUs */
1428: case (SPDU_PT << 8) | SPDU_MIA:
1429: case (SPDU_GT << 8) | SPDU_MAP:
1430: case (SPDU_PT << 8) | SPDU_MAA:
1431: case (SPDU_GT << 8) | SPDU_RS:
1432: case (SPDU_PT << 8) | SPDU_RA:
1433: case (SPDU_GT << 8) | SPDU_AS:
1434: case (SPDU_GT << 8) | SPDU_AR:
1435: case (SPDU_GT << 8) | SPDU_AD:
1436: case (SPDU_PT << 8) | SPDU_ADA:
1437: case (SPDU_GT << 8) | SPDU_AI:
1438: case (SPDU_PT << 8) | SPDU_AIA:
1439: #ifdef notdef
1440: case (SPDU_GT << 8) | SPDU_AE: /* aka SPDU_MAP */
1441: case (SPDU_PT << 8) | SPDU_AEA: /* aka SPDU_MAA */
1442: #endif
1443: case (SPDU_GT << 8) | SPDU_CD:
1444: case (SPDU_PT << 8) | SPDU_CDA:
1445: case (SPDU_PT << 8) | SPDU_ER:
1446: case (SPDU_PT << 8) | SPDU_ED:
1447: if (tx -> tx_cc <= 0) {
1448: TXFREE (tx);
1449: break;
1450: }
1451: (void) ssaplose (si, SC_PROTOCOL, NULLCP,
1452: "session protocol mangled: not expecting user information after 0x%x (%d bytes)",
1453: s -> s_code, tx -> tx_cc);
1454: goto bad2;
1455:
1456: default:
1457: (void) ssaplose (si, SC_PROTOCOL, NULLCP,
1458: "session protocol mangled: not expecting 0x%x to be concatenated after 0x%x",
1459: s -> s_code, p -> s_code);
1460: goto bad2;
1461: }
1462:
1463: switch (s -> s_code) {
1464: default:
1465: if (p -> s_code == SPDU_GT) {
1466: if ((p -> s_mask & SMASK_GT_TOKEN) && p -> s_gt_token)
1467: break;
1468: }
1469: else {
1470: if (((p -> s_mask & SMASK_PT_TOKEN) && p -> s_pt_token)
1471: || p -> s_ulen)
1472: break;
1473: } /* fall... */
1474:
1475: case SPDU_RS:
1476: case SPDU_AD:
1477: case SPDU_AI:
1478: case SPDU_CD:
1479: freespkt (p);
1480: sb -> sb_spdu = NULL;
1481: break;
1482: }
1483:
1484: return s;
1485: }
1486:
1487: /* */
1488:
1489: static int TDATAser (sd, tx)
1490: int sd;
1491: register struct TSAPdata *tx;
1492: {
1493: IFP abort;
1494: register struct ssapblk *sb;
1495: struct SSAPdata sxs;
1496: register struct SSAPdata *sx = &sxs;
1497: struct SSAPindication sis;
1498: register struct SSAPindication *si = &sis;
1499: register struct SSAPabort *sa = &si -> si_abort;
1500:
1501: if ((sb = findsblk (sd)) == NULL)
1502: return;
1503:
1504: abort = sb -> sb_AbortIndication;
1505:
1506: for (;; tx = NULLTX) {
1507: switch (SReadRequestAux (sb, sx, OK, si, 1, tx)) {
1508: case NOTOK:
1509: (*abort) (sd, sa);
1510: return;
1511:
1512: case OK:
1513: (*sb -> sb_DataIndication) (sd, sx);
1514: break;
1515:
1516: case DONE:
1517: switch (si -> si_type) {
1518: case SI_TOKEN:
1519: (*sb -> sb_TokenIndication) (sd, &si -> si_token);
1520: break;
1521:
1522: case SI_SYNC:
1523: (*sb -> sb_SyncIndication) (sd, &si -> si_sync);
1524: break;
1525:
1526: case SI_ACTIVITY:
1527: (*sb -> sb_ActivityIndication) (sd, &si -> si_activity);
1528: break;
1529:
1530: case SI_REPORT:
1531: (*sb -> sb_ReportIndication) (sd, &si -> si_report);
1532: break;
1533:
1534: case SI_FINISH:
1535: (*sb -> sb_ReleaseIndication) (sd, &si -> si_finish);
1536: break;
1537:
1538: case SI_DATA: /* partially assembled (T)SSDU */
1539: break;
1540: }
1541: break;
1542: }
1543:
1544: if (sb -> sb_spdu == NULL)
1545: break;
1546: }
1547: }
1548:
1549: /* */
1550:
1551: static int TDISCser (sd, td)
1552: int sd;
1553: register struct TSAPdisconnect *td;
1554: {
1555: IFP abort;
1556: register struct ssapblk *sb;
1557: struct SSAPindication sis;
1558: register struct SSAPindication *si = &sis;
1559:
1560: if ((sb = findsblk (sd)) == NULL)
1561: return;
1562:
1563: (void) ts2sslose (si, NULLCP, td);
1564:
1565: abort = sb -> sb_AbortIndication;
1566:
1567: sb -> sb_fd = NOTOK;
1568: (void) freesblk (sb);
1569:
1570: (*abort) (sd, &si -> si_abort);
1571: }
1572:
1573: /* */
1574:
1575: int ts2sslose (si, event, td)
1576: register struct SSAPindication *si;
1577: char *event;
1578: register struct TSAPdisconnect *td;
1579: {
1580: int reason;
1581: char *cp,
1582: buffer[BUFSIZ];
1583:
1584: if (event)
1585: SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
1586: (td -> td_cc > 0 ? "%s: %s [%*.*s]": "%s: %s", event,
1587: TErrString (td -> td_reason), td -> td_cc, td -> td_cc,
1588: td -> td_data));
1589:
1590: cp = "";
1591: switch (td -> td_reason) {
1592: case DR_REMOTE:
1593: case DR_CONGEST:
1594: reason = SC_CONGEST;
1595: break;
1596:
1597: case DR_SESSION:
1598: case DR_ADDRESS:
1599: reason = SC_ADDRESS;
1600: break;
1601:
1602: case DR_REFUSED:
1603: reason = SC_REFUSED;
1604: break;
1605:
1606: default:
1607: (void) sprintf (cp = buffer, " (%s at transport)",
1608: TErrString (td -> td_reason));
1609: case DR_NETWORK:
1610: reason = SC_TRANSPORT;
1611: break;
1612: }
1613:
1614: if (td -> td_cc > 0)
1615: return ssaplose (si, reason, NULLCP, "%*.*s%s",
1616: td -> td_cc, td -> td_cc, td -> td_data, cp);
1617: else
1618: return ssaplose (si, reason, NULLCP, "%s", *cp ? cp + 1 : cp);
1619: }
1620:
1621: /* INTERNAL */
1622:
1623: struct ssapblk *newsblk () {
1624: register struct ssapblk *sb;
1625:
1626: sb = (struct ssapblk *) calloc (1, sizeof *sb);
1627: if (sb == NULL)
1628: return NULL;
1629:
1630: sb -> sb_fd = NOTOK;
1631: sb -> sb_qbuf.qb_forw = sb -> sb_qbuf.qb_back = &sb -> sb_qbuf;
1632: sb -> sb_pr = SPDU_PR;
1633:
1634: if (once_only == 0) {
1635: SHead -> sb_forw = SHead -> sb_back = SHead;
1636: once_only++;
1637: }
1638:
1639: insque (sb, SHead -> sb_back);
1640:
1641: return sb;
1642: }
1643:
1644:
1645: int freesblk (sb)
1646: register struct ssapblk *sb;
1647: {
1648: if (sb == NULL)
1649: return;
1650:
1651: if (sb -> sb_fd != NOTOK) {
1652: struct TSAPdata txs;
1653: struct TSAPdisconnect tds;
1654:
1655: /* SunLink says this is proper behavior...
1656: using NOTOK, I've changed it to 10 secs */
1657: if (sb -> sb_flags & SB_FINN)
1658: while (TReadRequest (sb -> sb_fd, &txs, 10, &tds) != NOTOK) {
1659: TXFREE (&txs);
1660: }
1661:
1662: (void) TDiscRequest (sb -> sb_fd, NULLCP, 0, &tds);
1663: }
1664:
1665: if (sb -> sb_retry) {
1666: sb -> sb_retry -> s_mask &= ~SMASK_UDATA_PGI;
1667: sb -> sb_retry -> s_udata = NULL, sb -> sb_retry -> s_ulen = 0;
1668: freespkt (sb -> sb_retry);
1669: }
1670:
1671: if (sb -> sb_xspdu)
1672: freespkt (sb -> sb_xspdu);
1673: if (sb -> sb_spdu)
1674: freespkt (sb -> sb_spdu);
1675:
1676: QBFREE (&sb -> sb_qbuf);
1677:
1678: remque (sb);
1679:
1680: free ((char *) sb);
1681: }
1682:
1683: /* */
1684:
1685: struct ssapblk *findsblk (sd)
1686: register int sd;
1687: {
1688: register struct ssapblk *sb;
1689:
1690: if (once_only == 0)
1691: return NULL;
1692:
1693: for (sb = SHead -> sb_forw; sb != SHead; sb = sb -> sb_forw)
1694: if (sb -> sb_fd == sd)
1695: return sb;
1696:
1697: return NULL;
1698: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.