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