|
|
1.1 ! root 1: /* tp0ts.c - TPM: TP0 engine */ ! 2: ! 3: #ifndef lint ! 4: static char *rcsid = "$Header: /f/osi/tsap/RCS/tp0ts.c,v 7.6 90/07/27 08:48:10 mrose Exp $"; ! 5: #endif ! 6: ! 7: /* ! 8: * $Header: /f/osi/tsap/RCS/tp0ts.c,v 7.6 90/07/27 08:48:10 mrose Exp $ ! 9: * ! 10: * ! 11: * $Log: tp0ts.c,v $ ! 12: * Revision 7.6 90/07/27 08:48:10 mrose ! 13: * update ! 14: * ! 15: * Revision 7.5 90/03/23 17:31:10 mrose ! 16: * 8 ! 17: * ! 18: * Revision 7.4 89/12/19 10:18:22 mrose ! 19: * DLOG ! 20: * ! 21: * Revision 7.3 89/12/08 09:41:23 mrose ! 22: * touch-up ! 23: * ! 24: * Revision 7.2 89/12/07 22:15:39 mrose ! 25: * touch-up ! 26: * ! 27: * Revision 7.1 89/12/07 01:07:30 mrose ! 28: * queued writes ! 29: * ! 30: * Revision 7.0 89/11/23 22:30:33 mrose ! 31: * Release 6.0 ! 32: * ! 33: */ ! 34: ! 35: /* ! 36: * NOTICE ! 37: * ! 38: * Acquisition, use, and distribution of this module and related ! 39: * materials are subject to the restrictions of a license agreement. ! 40: * Consult the Preface in the User's Manual for the full terms of ! 41: * this agreement. ! 42: * ! 43: */ ! 44: ! 45: ! 46: /* LINTLIBRARY */ ! 47: ! 48: #include <stdio.h> ! 49: #include "tpkt.h" ! 50: #include "mpkt.h" ! 51: #include "tailor.h" ! 52: ! 53: ! 54: #if defined(TCP) || defined(X25) ! 55: ! 56: /* */ ! 57: ! 58: static int TConnect (tb, expedited, data, cc, td) ! 59: register struct tsapblk *tb; ! 60: char *data; ! 61: int expedited, ! 62: cc; ! 63: struct TSAPdisconnect *td; ! 64: { ! 65: register struct tsapkt *t; ! 66: ! 67: if (!(tb -> tb_flags & TB_TCP)) { ! 68: expedited = 0; ! 69: if (cc > 0) ! 70: return tsaplose (td, DR_PARAMETER, NULLCP, ! 71: "initial user data not allowed with class 0"); ! 72: } ! 73: ! 74: tb -> tb_srcref = htons ((u_short) (getpid () & 0xffff)); ! 75: tb -> tb_dstref = htons ((u_short) 0); ! 76: ! 77: if ((t = newtpkt (TPDU_CR)) == NULL) ! 78: return tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); ! 79: ! 80: t -> t_cr.cr_dstref = tb -> tb_dstref; ! 81: t -> t_cr.cr_srcref = tb -> tb_srcref; ! 82: t -> t_cr.cr_class = CR_CLASS_TP0; ! 83: if (!(tb -> tb_flags & TB_TCP)) { ! 84: register int i, ! 85: j; ! 86: int k; ! 87: ! 88: i = k = tb -> tb_tsdusize + tb -> tb_tpduslop; ! 89: for (j = 0; i > 0; j++) ! 90: i >>= 1; ! 91: if (k == (1 << (j - 1))) ! 92: j--; ! 93: if (j > SIZE_MAXTP0) { ! 94: j = SIZE_MAXTP0; ! 95: tb -> tb_tsdusize = (1 << j) - tb -> tb_tpduslop; ! 96: } ! 97: if (j != SIZE_DFLT) ! 98: t -> t_tpdusize = j; ! 99: } ! 100: bcopy (tb -> tb_initiating.ta_selector, t -> t_calling, ! 101: t -> t_callinglen = tb -> tb_initiating.ta_selectlen); ! 102: ! 103: bcopy (tb -> tb_responding.ta_selector, t -> t_called, ! 104: t -> t_calledlen = tb -> tb_responding.ta_selectlen); ! 105: if (expedited) { ! 106: tb -> tb_flags |= TB_EXPD; ! 107: t -> t_options |= OPT_TEXPEDITE; ! 108: } ! 109: ! 110: copyTPKTdata (t, data, cc); /* XXX: user musn't touch! */ ! 111: ! 112: tb -> tb_retry = t; ! 113: ! 114: return OK; ! 115: } ! 116: ! 117: /* */ ! 118: ! 119: static int TRetry (tb, async, tc, td) ! 120: register struct tsapblk *tb; ! 121: int async; ! 122: struct TSAPconnect *tc; ! 123: struct TSAPdisconnect *td; ! 124: { ! 125: int len; ! 126: register struct tsapkt *t; ! 127: ! 128: if (t = tb -> tb_retry) { ! 129: tb -> tb_retry = NULL; ! 130: ! 131: if (async) ! 132: switch ((*tb -> tb_retryfnx) (tb, td)) { ! 133: case NOTOK: ! 134: goto out; ! 135: ! 136: case OK: ! 137: tb -> tb_retry = t; ! 138: return CONNECTING_1; ! 139: ! 140: case DONE: ! 141: break; ! 142: } ! 143: ! 144: if (tpkt2fd (tb, t, tb -> tb_writefnx) == NOTOK) { ! 145: (void) tsaplose (td, t -> t_errno, NULLCP, NULLCP); ! 146: goto out; ! 147: } ! 148: ! 149: freetpkt (t), t = NULL; ! 150: } ! 151: ! 152: if (async) { ! 153: fd_set mask; ! 154: ! 155: FD_ZERO (&mask); ! 156: FD_SET (tb -> tb_fd, &mask); ! 157: ! 158: if (xselect (tb -> tb_fd + 1, &mask, NULLFD, NULLFD, 0) == OK) ! 159: return CONNECTING_2; ! 160: } ! 161: ! 162: if ((t = fd2tpkt (tb -> tb_fd, tb -> tb_initfnx, tb -> tb_readfnx)) == NULL ! 163: || t -> t_errno != OK) { ! 164: (void) tsaplose (td, t ? t -> t_errno : DR_CONGEST, NULLCP, NULLCP); ! 165: goto out; ! 166: } ! 167: ! 168: switch (TPDU_CODE (t)) { ! 169: case TPDU_CC: ! 170: tc -> tc_sd = tb -> tb_fd; ! 171: if (CR_CLASS (t) != CR_CLASS_TP0) { ! 172: (void) tpktlose (tb, td, DR_PROTOCOL, NULLCP, ! 173: "proposed class 0, got back 0x%x", CR_CLASS (t)); ! 174: goto out; ! 175: } ! 176: if (tb -> tb_srcref != t -> t_cc.cc_dstref) { ! 177: (void) tpktlose (tb, td, DR_MISMATCH, NULLCP, ! 178: "sent srcref of 0x%x, got 0x%x", ! 179: ntohs (tb -> tb_srcref), ntohs (t -> t_cc.cc_dstref)); ! 180: goto out; ! 181: } ! 182: tb -> tb_dstref = t -> t_cc.cc_srcref; ! 183: if (!(tb -> tb_flags & TB_TCP)) { ! 184: if (t -> t_tpdusize == 0) ! 185: t -> t_tpdusize = SIZE_DFLT; ! 186: else ! 187: if (t -> t_tpdusize > SIZE_MAXTP0) ! 188: t -> t_tpdusize = SIZE_MAXTP0; ! 189: tb -> tb_tpdusize = 1 << t -> t_tpdusize; ! 190: tb -> tb_tsdusize = tb -> tb_tpdusize - tb -> tb_tpduslop; ! 191: } ! 192: if ((len = t -> t_calledlen) > 0) { ! 193: if (len > sizeof tb -> tb_responding.ta_selector) ! 194: len = sizeof tb -> tb_responding.ta_selector; ! 195: bcopy (t -> t_called, tb -> tb_responding.ta_selector, ! 196: tb -> tb_responding.ta_selectlen = len); ! 197: } ! 198: copyTSAPaddrX (&tb -> tb_responding, &tc -> tc_responding); ! 199: if (!(t -> t_options & OPT_TEXPEDITE) ! 200: || !(tb -> tb_flags & TB_TCP)) ! 201: tb -> tb_flags &= ~TB_EXPD; ! 202: tc -> tc_expedited = (tb -> tb_flags & TB_EXPD) ? 1 : 0; ! 203: tc -> tc_tsdusize = tb -> tb_tsdusize; ! 204: tc -> tc_qos = tb -> tb_qos; /* struct copy */ ! 205: if (t -> t_qbuf) { ! 206: copyTSAPdata (t -> t_qbuf -> qb_data, t -> t_qbuf -> qb_len, ! 207: tc); ! 208: } ! 209: else ! 210: tc -> tc_cc = 0; ! 211: ! 212: freetpkt (t); ! 213: tb -> tb_flags |= TB_CONN; ! 214: #ifdef MGMT ! 215: if (tb -> tb_manfnx) ! 216: (*tb -> tb_manfnx) (OPREQOUT, tb); ! 217: #endif ! 218: if (tb -> tb_calling) ! 219: free ((char *) tb -> tb_calling), tb -> tb_calling = NULL; ! 220: if (tb -> tb_called) ! 221: free ((char *) tb -> tb_called), tb -> tb_called = NULL; ! 222: ! 223: return DONE; ! 224: ! 225: case TPDU_DR: ! 226: td -> td_reason = t -> t_dr.dr_reason; ! 227: if (t -> t_qbuf) { ! 228: copyTSAPdata (t -> t_qbuf -> qb_data, t -> t_qbuf -> qb_len, ! 229: td); ! 230: } ! 231: else ! 232: td -> td_cc = 0; ! 233: goto out; ! 234: ! 235: case TPDU_ER: ! 236: switch (t -> t_er.er_reject) { ! 237: case ER_REJ_NOTSPECIFIED: ! 238: default: ! 239: td -> td_reason = DR_CONNECT; ! 240: break; ! 241: ! 242: case ER_REJ_CODE: ! 243: case ER_REJ_TPDU: ! 244: case ER_REJ_VALUE: ! 245: td -> td_reason = DR_PROTOCOL; ! 246: break; ! 247: } ! 248: td -> td_cc = 0; ! 249: goto out; ! 250: ! 251: default: ! 252: (void) tpktlose (tb, td, DR_PROTOCOL, NULLCP, ! 253: "transport protocol mangled: expecting 0x%x, got 0x%x", ! 254: TPDU_CC, TPDU_CODE (t)); ! 255: goto out; ! 256: } ! 257: ! 258: out: ; ! 259: freetpkt (t); ! 260: /* freetblk (tb); */ ! 261: ! 262: return NOTOK; ! 263: } ! 264: ! 265: /* */ ! 266: ! 267: static int TStart (tb, cp, ts, td) ! 268: register struct tsapblk *tb; ! 269: char *cp; ! 270: struct TSAPstart *ts; ! 271: struct TSAPdisconnect *td; ! 272: { ! 273: int len, ! 274: result; ! 275: register struct tsapkt *t; ! 276: ! 277: if ((t = str2tpkt (cp)) == NULL || t -> t_errno != OK) { ! 278: result = tsaplose (td, DR_PARAMETER, NULLCP, ! 279: "bad initialization vector"); ! 280: goto out; ! 281: } ! 282: ! 283: if (CR_CLASS (t) != CR_CLASS_TP0) { ! 284: if (t -> t_cr.cr_alternate & (ALT_TP0 | ALT_TP1)) ! 285: t -> t_cr.cr_class = CR_CLASS_TP0; ! 286: else { ! 287: result = tpktlose (tb, td, DR_CONNECT, NULLCP, ! 288: "only class 0 supported, not 0x%x", CR_CLASS (t)); ! 289: goto out; ! 290: } ! 291: } ! 292: ! 293: tb -> tb_srcref = htons ((u_short) (getpid () & 0xffff)); ! 294: tb -> tb_dstref = t -> t_cr.cr_srcref; ! 295: if (!(tb -> tb_flags & TB_TCP)) { ! 296: if (t -> t_tpdusize == 0) ! 297: t -> t_tpdusize = SIZE_DFLT; ! 298: else ! 299: if (t -> t_tpdusize > SIZE_MAXTP0) ! 300: t -> t_tpdusize = SIZE_MAXTP0; ! 301: tb -> tb_tpdusize = 1 << t -> t_tpdusize; ! 302: tb -> tb_tsdusize = tb -> tb_tpdusize - tb -> tb_tpduslop; ! 303: } ! 304: if ((len = t -> t_callinglen) > 0) { ! 305: if (len > sizeof tb -> tb_initiating.ta_selector) ! 306: len = sizeof tb -> tb_initiating.ta_selector; ! 307: bcopy (t -> t_calling, tb -> tb_initiating.ta_selector, ! 308: tb -> tb_initiating.ta_selectlen = len); ! 309: } ! 310: if ((len = t -> t_calledlen) > 0) { ! 311: if (len > sizeof tb -> tb_responding.ta_selector) ! 312: len = sizeof tb -> tb_responding.ta_selector; ! 313: bcopy (t -> t_called, tb -> tb_responding.ta_selector, ! 314: tb -> tb_responding.ta_selectlen = len); ! 315: } ! 316: if ((t -> t_options & OPT_TEXPEDITE) && (tb -> tb_flags & TB_TCP)) ! 317: tb -> tb_flags |= TB_EXPD; ! 318: ! 319: ts -> ts_sd = tb -> tb_fd; ! 320: copyTSAPaddrX (&tb -> tb_initiating, &ts -> ts_calling); ! 321: copyTSAPaddrX (&tb -> tb_responding, &ts -> ts_called); ! 322: ts -> ts_expedited = (tb -> tb_flags & TB_EXPD) ? 1 : 0; ! 323: ts -> ts_tsdusize = tb -> tb_tsdusize; ! 324: ts -> ts_qos = tb -> tb_qos; /* struct copy */ ! 325: ! 326: if (t -> t_qbuf) { ! 327: copyTSAPdata (t -> t_qbuf -> qb_data, t -> t_qbuf -> qb_len, ts); ! 328: } ! 329: else ! 330: ts -> ts_cc = 0; ! 331: ! 332: result = OK; ! 333: ! 334: out: ; ! 335: freetpkt (t); ! 336: ! 337: return result; ! 338: } ! 339: ! 340: /* */ ! 341: ! 342: /* ARGSUSED */ ! 343: ! 344: static int TAccept (tb, responding, data, cc, qos, td) ! 345: register struct tsapblk *tb; ! 346: char *data; ! 347: int responding, ! 348: cc; ! 349: struct QOStype *qos; ! 350: struct TSAPdisconnect *td; ! 351: { ! 352: int result; ! 353: register struct tsapkt *t; ! 354: ! 355: if (!(tb -> tb_flags & TB_TCP) && cc > 0) ! 356: return tsaplose (td, DR_PARAMETER, NULLCP, ! 357: "initial user data not allowed with class 0"); ! 358: ! 359: if ((t = newtpkt (TPDU_CC)) == NULL) ! 360: return tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); ! 361: ! 362: t -> t_cc.cc_dstref = tb -> tb_dstref; ! 363: t -> t_cc.cc_srcref = tb -> tb_srcref; ! 364: t -> t_cc.cc_class = CR_CLASS_TP0; ! 365: if (!(tb -> tb_flags & TB_TCP)) { ! 366: register int i, ! 367: j; ! 368: int k; ! 369: ! 370: i = k = tb -> tb_tsdusize + tb -> tb_tpduslop; ! 371: for (j = 0; i > 0; j++) ! 372: i >>= 1; ! 373: if (k == (1 << (j - 1))) ! 374: j--; ! 375: if (j > SIZE_MAXTP0) { ! 376: j = SIZE_MAXTP0; ! 377: tb -> tb_tsdusize = (1 << j) - tb -> tb_tpduslop; ! 378: } ! 379: if (j != SIZE_DFLT) ! 380: t -> t_tpdusize = j; ! 381: } ! 382: if (responding) ! 383: bcopy (tb -> tb_responding.ta_selector, t -> t_called, ! 384: t -> t_calledlen = tb -> tb_responding.ta_selectlen); ! 385: if (tb -> tb_flags & TB_EXPD) ! 386: t -> t_options |= OPT_TEXPEDITE; ! 387: copyTPKTdata (t, data, cc); ! 388: ! 389: if ((result = tpkt2fd (tb, t, tb -> tb_writefnx)) == NOTOK) ! 390: (void) tsaplose (td, t -> t_errno, NULLCP, NULLCP); ! 391: else { ! 392: tb -> tb_flags |= TB_CONN; ! 393: #ifdef MGMT ! 394: if (tb -> tb_manfnx) ! 395: (*tb -> tb_manfnx) (OPREQIN, tb); ! 396: #endif ! 397: } ! 398: ! 399: freetpkt (t); ! 400: ! 401: return result; ! 402: } ! 403: ! 404: /* */ ! 405: ! 406: static int TWrite (tb, uv, expedited, td) ! 407: register struct tsapblk *tb; ! 408: register struct udvec *uv; ! 409: int expedited; ! 410: struct TSAPdisconnect *td; ! 411: { ! 412: int cc, ! 413: j, ! 414: len, ! 415: result; ! 416: #if defined(X25) || defined(MGMT) ! 417: int dlen; ! 418: #endif ! 419: register char *bp, ! 420: *ep; ! 421: register struct tsapkt *t; ! 422: register struct udvec *vv, ! 423: *wv; ! 424: ! 425: #if defined(X25) || defined(MGMT) ! 426: dlen = 0; ! 427: #endif ! 428: ! 429: ep = (bp = uv -> uv_base) + (cc = uv -> uv_len); ! 430: while (uv -> uv_base) { ! 431: if ((t = newtpkt (expedited ? TPDU_ED : TPDU_DT)) == NULL) ! 432: return tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); ! 433: ! 434: wv = (vv = t -> t_udvec) + NTPUV - 1; ! 435: len = tb -> tb_tpdusize ? (tb -> tb_tpdusize - tb -> tb_tpduslop) ! 436: : tb -> tb_tsdusize; ! 437: for (; len > 0 && vv < wv; len -= j) { ! 438: j = min (cc, len); ! 439: #if defined(X25) || defined(MGMT) ! 440: dlen += j; ! 441: #endif ! 442: vv -> uv_base = bp, vv -> uv_len = j, vv++; ! 443: bp += j, cc -= j; ! 444: ! 445: if (bp >= ep) { ! 446: if ((bp = (++uv) -> uv_base) == NULL) ! 447: break; ! 448: ep = bp + (cc = uv -> uv_len); ! 449: } ! 450: } ! 451: ! 452: if (uv -> uv_base == NULL) ! 453: t -> t_dt.dt_nr |= DT_EOT; ! 454: ! 455: if ((result = tpkt2fd (tb, t, tb -> tb_writefnx)) == NOTOK) { ! 456: (void) tsaplose (td, t -> t_errno, NULLCP, NULLCP); ! 457: #ifdef X25 ! 458: if (tb -> tb_flags & TB_X25) ! 459: LLOG (x25_log, LLOG_NOTICE, ! 460: ("connection %d broken, %d/%d octets sent/recv", ! 461: tb -> tb_fd, tb -> tb_sent, tb -> tb_recv)); ! 462: #endif ! 463: freetblk (tb); ! 464: } ! 465: ! 466: freetpkt (t); ! 467: if (result == NOTOK) ! 468: return NOTOK; ! 469: } ! 470: ! 471: #ifdef X25 ! 472: tb -> tb_sent += dlen; ! 473: #endif ! 474: #ifdef MGMT ! 475: if (tb -> tb_manfnx) ! 476: (*tb -> tb_manfnx) (USERDT, tb, dlen); ! 477: #endif ! 478: ! 479: return OK; ! 480: } ! 481: ! 482: /* */ ! 483: ! 484: /* ARGSUSED */ ! 485: ! 486: static int TRead (tb, tx, td, async, oob) ! 487: register struct tsapblk *tb; ! 488: register struct TSAPdata *tx; ! 489: struct TSAPdisconnect *td; ! 490: int async, ! 491: oob; ! 492: { ! 493: int eot; ! 494: register struct tsapkt *t; ! 495: ! 496: bzero ((char *) tx, sizeof *tx); ! 497: tx -> tx_qbuf.qb_forw = tx -> tx_qbuf.qb_back = &tx -> tx_qbuf; ! 498: ! 499: for (;;) { ! 500: if ((t = fd2tpkt (tb -> tb_fd, tb -> tb_initfnx, tb -> tb_readfnx)) ! 501: == NULL ! 502: || t -> t_errno != OK) { ! 503: (void) tsaplose (td, t ? t -> t_errno : DR_CONGEST, NULLCP, ! 504: NULLCP); ! 505: #ifdef X25 ! 506: if (tb -> tb_flags & TB_X25) ! 507: LLOG (x25_log, LLOG_NOTICE, ! 508: ("connection %d broken, %d/%d octets sent/recv", ! 509: tb -> tb_fd, tb -> tb_sent, tb -> tb_recv)); ! 510: #endif ! 511: break; ! 512: } ! 513: ! 514: switch (TPDU_CODE (t)) { ! 515: case TPDU_DT: ! 516: eot = t -> t_dt.dt_nr & DT_EOT; ! 517: if (t -> t_qbuf) { ! 518: insque (t -> t_qbuf, tb -> tb_qbuf.qb_back); ! 519: tb -> tb_len += t -> t_qbuf -> qb_len; ! 520: #ifdef X25 ! 521: tb -> tb_recv += t -> t_qbuf -> qb_len; ! 522: #endif ! 523: t -> t_qbuf = NULL; ! 524: } ! 525: freetpkt (t); ! 526: #ifdef MGMT ! 527: if (tb -> tb_manfnx) ! 528: (*tb -> tb_manfnx) (USERDR, tb, tb -> tb_len); ! 529: #endif ! 530: if (!eot) { ! 531: if (async) ! 532: return DONE; ! 533: ! 534: continue; ! 535: } ! 536: tx -> tx_expedited = 0; ! 537: if (tb -> tb_qbuf.qb_forw != &tb -> tb_qbuf) { ! 538: tx -> tx_qbuf = tb -> tb_qbuf;/* struct copy */ ! 539: tx -> tx_qbuf.qb_forw -> qb_back = ! 540: tx -> tx_qbuf.qb_back -> qb_forw = &tx -> tx_qbuf; ! 541: tx -> tx_cc = tb -> tb_len; ! 542: tb -> tb_qbuf.qb_forw = ! 543: tb -> tb_qbuf.qb_back = &tb -> tb_qbuf; ! 544: tb -> tb_len = 0; ! 545: } ! 546: return OK; ! 547: ! 548: case TPDU_ED: ! 549: if (t -> t_qbuf) { ! 550: insque (t -> t_qbuf, tx -> tx_qbuf.qb_back); ! 551: tx -> tx_cc = t -> t_qbuf -> qb_len; ! 552: t -> t_qbuf = NULL; ! 553: } ! 554: freetpkt (t); ! 555: tx -> tx_expedited = 1; ! 556: return OK; ! 557: ! 558: case TPDU_DR: ! 559: td -> td_reason = t -> t_dr.dr_reason; ! 560: if (t -> t_qbuf) { ! 561: copyTSAPdata (t -> t_qbuf -> qb_data, ! 562: t -> t_qbuf -> qb_len, td); ! 563: } ! 564: else ! 565: td -> td_cc = 0; ! 566: break; ! 567: ! 568: case TPDU_ER: ! 569: switch (t -> t_er.er_reject) { ! 570: case ER_REJ_NOTSPECIFIED: ! 571: default: ! 572: td -> td_reason = DR_UNKNOWN; ! 573: break; ! 574: ! 575: case ER_REJ_CODE: ! 576: case ER_REJ_TPDU: ! 577: case ER_REJ_VALUE: ! 578: td -> td_reason = DR_PROTOCOL; ! 579: break; ! 580: } ! 581: td -> td_cc = 0; ! 582: break; ! 583: ! 584: default: ! 585: (void) tpktlose (tb, td, DR_PROTOCOL, NULLCP, ! 586: "transport protocol mangled: not expecting 0x%x", ! 587: TPDU_CODE (t)); ! 588: break; ! 589: } ! 590: break; ! 591: } ! 592: ! 593: freetpkt (t); ! 594: freetblk (tb); ! 595: ! 596: return NOTOK; ! 597: } ! 598: ! 599: /* */ ! 600: ! 601: static int TDisconnect (tb, data, cc, td) ! 602: register struct tsapblk *tb; ! 603: char *data; ! 604: int cc; ! 605: struct TSAPdisconnect *td; ! 606: { ! 607: int result; ! 608: #ifdef TCP ! 609: register struct tsapkt *t; ! 610: #endif ! 611: ! 612: result = OK; ! 613: #ifdef TCP ! 614: if (tb -> tb_flags & TB_TCP) { ! 615: if (t = newtpkt (TPDU_DR)) { ! 616: t -> t_dr.dr_srcref = tb -> tb_srcref; ! 617: t -> t_dr.dr_dstref = tb -> tb_dstref; ! 618: t -> t_dr.dr_reason = DR_NORMAL; ! 619: copyTPKTdata (t, data, cc); ! 620: ! 621: if ((result = tpkt2fd (tb, t, tb -> tb_writefnx)) == NOTOK) ! 622: (void) tsaplose (td, t -> t_errno, NULLCP, NULLCP); ! 623: ! 624: freetpkt (t); ! 625: } ! 626: else ! 627: result = tsaplose (td, DR_CONGEST, NULLCP, "out of memory"); ! 628: } ! 629: #endif ! 630: #ifdef X25 ! 631: if (tb -> tb_flags & TB_X25) ! 632: LLOG (x25_log, LLOG_NOTICE, ! 633: ("connection %d closed, %d/%d octets sent/recv", ! 634: tb -> tb_fd, tb -> tb_sent, tb -> tb_recv)); ! 635: #endif ! 636: freetblk (tb); ! 637: ! 638: return result; ! 639: } ! 640: ! 641: /* */ ! 642: ! 643: static TLose (tb, reason, td) ! 644: register struct tsapblk *tb; ! 645: int reason; ! 646: struct TSAPdisconnect *td; ! 647: { ! 648: struct tsapkt *t; ! 649: ! 650: switch (reason) { ! 651: case DR_UNKNOWN: ! 652: case DR_CONGEST: ! 653: case DR_SESSION: ! 654: case DR_ADDRESS: ! 655: if ((t = newtpkt (TPDU_DR)) == NULLPKT) ! 656: break; ! 657: ! 658: t -> t_dr.dr_srcref = tb -> tb_srcref; ! 659: t -> t_dr.dr_dstref = tb -> tb_dstref; ! 660: t -> t_dr.dr_reason = reason; ! 661: copyTPKTdata (t, td -> td_data, td -> td_cc); ! 662: break; ! 663: ! 664: default: ! 665: if ((t = newtpkt (TPDU_ER)) == NULLPKT) ! 666: break; ! 667: ! 668: t -> t_er.er_dstref = tb -> tb_dstref; ! 669: switch (reason) { ! 670: case DR_PROTOCOL: ! 671: t -> t_er.er_reject = ER_REJ_TPDU; ! 672: break; ! 673: ! 674: default: ! 675: t -> t_er.er_reject = ER_REJ_NOTSPECIFIED; ! 676: break; ! 677: } ! 678: break; ! 679: } ! 680: if (t) { ! 681: (void) tpkt2fd (tb, t, tb -> tb_writefnx); ! 682: freetpkt (t); ! 683: } ! 684: } ! 685: ! 686: /* */ ! 687: ! 688: /* at present, used by TCP, X.25 and BRG back-ends... */ ! 689: ! 690: #ifndef TCP ! 691: #undef WRITEV ! 692: #endif ! 693: ! 694: #include <errno.h> ! 695: #include <sys/ioctl.h> ! 696: #ifdef WRITEV ! 697: #include <sys/uio.h> ! 698: #endif ! 699: #ifdef TCP ! 700: #include "internet.h" ! 701: #else ! 702: #define write_tcp_socket NULLIFP ! 703: #endif ! 704: #ifdef X25 ! 705: #include "x25.h" ! 706: #else ! 707: #define write_x25_socket NULLIFP ! 708: #endif ! 709: ! 710: ! 711: extern int errno; ! 712: ! 713: /* */ ! 714: ! 715: int tp0write (tb, t, cp, n) ! 716: register struct tsapblk *tb; ! 717: register struct tsapkt *t; ! 718: char *cp; ! 719: int n; ! 720: { ! 721: register int cc; ! 722: register char *p, ! 723: *q; ! 724: register struct qbuf *qb; ! 725: register struct udvec *uv; ! 726: #if defined(WRITEV) || defined(SUN_X25) || defined(CAMTEC_CCL) ! 727: struct iovec iovs[NTPUV + 4]; ! 728: register struct iovec *iov; ! 729: #endif ! 730: ! 731: #if defined(WRITEV) || defined(SUN_X25) || defined(CAMTEC_CCL) ! 732: #ifdef FIONBIO ! 733: if (tb -> tb_flags & TB_QWRITES) ! 734: goto single; ! 735: #endif ! 736: iov = iovs; ! 737: cc = 0; ! 738: ! 739: if (tb -> tb_flags & TB_X25) { ! 740: iov -> iov_base = (char *) &t -> t_li; ! 741: cc += (iov -> iov_len = sizeof t -> t_li); ! 742: iov++; ! 743: ! 744: iov -> iov_base = (char *) &t -> t_code; ! 745: cc += (iov -> iov_len = sizeof t -> t_code); ! 746: iov++; ! 747: ! 748: } ! 749: else { ! 750: iov -> iov_base = (char *) &t -> t_pkthdr; ! 751: cc += (iov -> iov_len = TPKT_HDRLEN (t)); ! 752: iov++; ! 753: } ! 754: ! 755: iov -> iov_base = cp; ! 756: cc += (iov -> iov_len = n); ! 757: iov++; ! 758: ! 759: if (t -> t_vdata) { ! 760: iov -> iov_base = t -> t_vdata; ! 761: cc += (iov -> iov_len = t -> t_vlen); ! 762: iov++; ! 763: } ! 764: ! 765: for (uv = t -> t_udvec; uv -> uv_base; uv++) { ! 766: iov -> iov_base = uv -> uv_base; ! 767: cc += (iov -> iov_len = uv -> uv_len); ! 768: iov++; ! 769: } ! 770: ! 771: if ((n = writev (tb -> tb_fd, iovs, iov - iovs)) != cc) { ! 772: cc = NOTOK; ! 773: #ifdef SUN_X25 ! 774: if (tb -> tb_flags & TB_X25 ! 775: && compat_log -> ll_events & LLOG_EXCEPTIONS) ! 776: (void) log_cause_and_diag (tb -> tb_fd); ! 777: #endif ! 778: } ! 779: else ! 780: if (tb -> tb_flags & TB_X25) { ! 781: DLOG (compat_log, LLOG_DEBUG, ("X.25 write %d bytes", cc)); ! 782: } ! 783: goto out; ! 784: ! 785: single: ; ! 786: #endif ! 787: ! 788: cc = ((tb -> tb_flags & TB_X25) ? sizeof t -> t_li + sizeof t -> t_code ! 789: : TPKT_HDRLEN (t)) ! 790: + n; ! 791: if (t -> t_vdata) ! 792: cc += t -> t_vlen; ! 793: for (uv = t -> t_udvec; uv -> uv_base; uv++) ! 794: cc += uv -> uv_len; ! 795: ! 796: if (p = malloc (sizeof *qb + (unsigned) cc)) { ! 797: int nc, ! 798: onoff; ! 799: IFP wfnx = (tb -> tb_flags & TB_X25) ? write_x25_socket ! 800: : write_tcp_socket; ! 801: ! 802: #ifdef FIONBIO ! 803: if (tb -> tb_flags & TB_QWRITES) { ! 804: qb = (struct qbuf *) p; ! 805: qb -> qb_forw = qb -> qb_back = qb; ! 806: qb -> qb_data = qb -> qb_base, qb -> qb_len = cc; ! 807: p = qb -> qb_data; ! 808: } ! 809: #endif ! 810: ! 811: if (tb -> tb_flags & TB_X25) { ! 812: bcopy ((char *) &t -> t_li, q = p, sizeof t -> t_li); ! 813: q += sizeof t -> t_li; ! 814: ! 815: bcopy ((char *) &t -> t_code, q, sizeof t -> t_code); ! 816: q += sizeof t -> t_code; ! 817: } ! 818: else { ! 819: bcopy ((char *) &t -> t_pkthdr, q = p, TPKT_HDRLEN (t)); ! 820: q += TPKT_HDRLEN (t); ! 821: } ! 822: ! 823: bcopy (cp, q, n); ! 824: q += n; ! 825: ! 826: if (t -> t_vdata) { ! 827: bcopy (t -> t_vdata, q, t -> t_vlen); ! 828: q += t -> t_vlen; ! 829: } ! 830: ! 831: for (uv = t -> t_udvec; uv -> uv_base; uv++) { ! 832: bcopy (uv -> uv_base, q, uv -> uv_len); ! 833: q += uv -> uv_len; ! 834: } ! 835: ! 836: #ifdef FIONBIO ! 837: if (tb -> tb_qwrites.qb_forw != &tb -> tb_qwrites) { ! 838: nc = 0; ! 839: goto insert; ! 840: } ! 841: ! 842: if (tb -> tb_flags & TB_QWRITES) ! 843: (void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 1, (char *) &onoff)); ! 844: #endif ! 845: ! 846: nc = (*wfnx) (tb -> tb_fd, p, cc); ! 847: ! 848: #ifdef FIONBIO ! 849: if (tb -> tb_flags & TB_QWRITES) ! 850: (void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 0, (char *) &onoff)); ! 851: #endif ! 852: ! 853: if (nc != cc) { ! 854: #ifdef FIONBIO ! 855: if (tb -> tb_flags & TB_QWRITES) { ! 856: if (nc == NOTOK) { ! 857: if (errno != EWOULDBLOCK) ! 858: goto losing; ! 859: nc = 0; ! 860: } ! 861: else ! 862: if (nc > 0 && (tb -> tb_flags & TB_X25)) { ! 863: SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ! 864: ("partial write (%d of %d octets) to X.25", ! 865: nc, cc)); ! 866: goto losing; ! 867: } ! 868: ! 869: if ((*tb -> tb_queuePfnx) (tb, 1, (struct TSAPdisconnect *) 0) ! 870: == NOTOK) ! 871: goto losing; ! 872: ! 873: qb -> qb_data += nc, qb -> qb_len -= nc; ! 874: insert: ; ! 875: insque (qb, tb -> tb_qwrites.qb_back); ! 876: DLOG (tsap_log, LLOG_TRACE, ! 877: ("queueing blocked write of %d of %d octets", nc, cc)); ! 878: qb = NULL; ! 879: } ! 880: else ! 881: #endif ! 882: { ! 883: losing: ; ! 884: cc = NOTOK; ! 885: } ! 886: } ! 887: ! 888: #ifdef FIONBIO ! 889: if (tb -> tb_flags & TB_QWRITES) { ! 890: if (qb) ! 891: free ((char *) qb); ! 892: } ! 893: else ! 894: #endif ! 895: free (p); ! 896: goto out; ! 897: } ! 898: if ((tb -> tb_flags & TB_X25) || tb -> tb_flags & TB_QWRITES) { ! 899: SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ! 900: ("unable to malloc %d octets for pseudo-writev, failing...", ! 901: cc)); ! 902: ! 903: cc = NOTOK; ! 904: goto out; ! 905: } ! 906: ! 907: #ifdef TCP ! 908: SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ! 909: ("unable to malloc %d octets for pseudo-writev, continuing...", ! 910: cc)); ! 911: ! 912: cc = TPKT_HDRLEN (t); ! 913: if (write_tcp_socket (tb -> tb_fd, (char *) &t -> t_pkthdr, cc) != cc) { ! 914: err: ; ! 915: cc = NOTOK; ! 916: goto out; ! 917: } ! 918: ! 919: if (write_tcp_socket (tb -> tb_fd, cp, n) != n) ! 920: goto err; ! 921: cc += n; ! 922: ! 923: if (t -> t_vdata ! 924: && write_tcp_socket (tb -> tb_fd, t -> t_vdata, t -> t_vlen) ! 925: != t -> t_vlen) ! 926: goto err; ! 927: cc += t -> t_vlen; ! 928: ! 929: for (uv = t -> t_udvec; uv -> uv_base; uv++) { ! 930: if (write_tcp_socket (tb -> tb_fd, uv -> uv_base, uv -> uv_len) ! 931: != uv -> uv_len) ! 932: goto err; ! 933: cc += uv -> uv_len; ! 934: } ! 935: #endif ! 936: ! 937: out: ; ! 938: ! 939: return cc; ! 940: } ! 941: ! 942: /* */ ! 943: ! 944: #ifdef FIONBIO ! 945: static int TDrain (tb, td) ! 946: register struct tsapblk *tb; ! 947: struct TSAPdisconnect *td; ! 948: { ! 949: int nc, ! 950: onoff, ! 951: result; ! 952: register struct qbuf *qb; ! 953: IFP wfnx = (tb -> tb_flags & TB_X25) ? write_x25_socket ! 954: : write_tcp_socket; ! 955: ! 956: (void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 1, (char *) &onoff)); ! 957: ! 958: while ((qb = tb -> tb_qwrites.qb_forw) != &tb -> tb_qwrites) { ! 959: if ((nc = (*wfnx) (tb -> tb_fd, qb -> qb_data, qb -> qb_len)) ! 960: != qb -> qb_len) { ! 961: if (nc == NOTOK) { ! 962: if (errno != EWOULDBLOCK) { ! 963: result = tsaplose (td, DR_NETWORK, "failed", ! 964: "write to network"); ! 965: goto out; ! 966: } ! 967: ! 968: nc = 0; ! 969: } ! 970: else ! 971: if (nc > 0 && (tb -> tb_flags & TB_X25)) { ! 972: SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ! 973: ("partial write (%d of %d octets) to X.25", ! 974: nc, qb -> qb_len)); ! 975: result = tsaplose (td, DR_NETWORK, NULLCP, ! 976: "partial write (%d of %d octets) to X.25", ! 977: nc, qb -> qb_len); ! 978: goto out; ! 979: } ! 980: ! 981: DLOG (tsap_log, LLOG_TRACE, ! 982: ("wrote %d of %d octets from blocked write", nc, ! 983: qb -> qb_len)); ! 984: qb -> qb_data += nc, qb -> qb_len -= nc; ! 985: ! 986: result = OK; ! 987: goto out; ! 988: } ! 989: ! 990: DLOG (tsap_log, LLOG_TRACE, ! 991: ("finished blocked write of %d octets", qb -> qb_len)); ! 992: remque (qb); ! 993: free ((char *) qb); ! 994: } ! 995: result = DONE; ! 996: ! 997: out: ; ! 998: (void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 0, (char *) &onoff)); ! 999: ! 1000: return result; ! 1001: } ! 1002: #endif ! 1003: ! 1004: /* */ ! 1005: ! 1006: int tp0init (tb) ! 1007: register struct tsapblk *tb; ! 1008: { ! 1009: tb -> tb_connPfnx = TConnect; ! 1010: tb -> tb_retryPfnx = TRetry; ! 1011: ! 1012: tb -> tb_startPfnx = TStart; ! 1013: tb -> tb_acceptPfnx = TAccept; ! 1014: ! 1015: tb -> tb_writePfnx = TWrite; ! 1016: tb -> tb_readPfnx = TRead; ! 1017: tb -> tb_discPfnx = TDisconnect; ! 1018: tb -> tb_losePfnx = TLose; ! 1019: ! 1020: #ifdef FIONBIO ! 1021: tb -> tb_drainPfnx = TDrain; ! 1022: #endif ! 1023: ! 1024: #ifdef MGMT ! 1025: tb -> tb_manfnx = TManGen; ! 1026: #endif ! 1027: } ! 1028: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.