|
|
1.1 ! root 1: /* ts2bsd.c - TPM: 4.4BSD OSI TP4 interface */ ! 2: #define STATIC /**/ ! 3: ! 4: #ifndef lint ! 5: static char *rcsid = "$Header: /f/osi/tsap/RCS/ts2bsd.c,v 7.9 90/07/09 14:51:13 mrose Exp $"; ! 6: #endif ! 7: ! 8: /* ! 9: * $Header: /f/osi/tsap/RCS/ts2bsd.c,v 7.9 90/07/09 14:51:13 mrose Exp $ ! 10: * ! 11: * ! 12: * $Log: ts2bsd.c,v $ ! 13: * Revision 7.9 90/07/09 14:51:13 mrose ! 14: * sync ! 15: * ! 16: * Revision 7.8 90/03/23 17:31:16 mrose ! 17: * 8 ! 18: * ! 19: * Revision 7.7 90/03/22 08:38:02 mrose ! 20: * touch-up ! 21: * ! 22: * Revision 7.6 89/12/19 10:18:28 mrose ! 23: * DLOG ! 24: * ! 25: * Revision 7.5 89/12/18 17:49:48 mrose ! 26: * touch-up ! 27: * ! 28: * Revision 7.4 89/12/08 16:26:47 mrose ! 29: * keith ! 30: * ! 31: * Revision 7.1 89/12/01 10:46:26 mrose ! 32: * touch-up ! 33: * ! 34: * Revision 7.0 89/11/23 22:30:36 mrose ! 35: * Release 6.0 ! 36: * ! 37: */ ! 38: ! 39: /* ! 40: * NOTICE ! 41: * ! 42: * Acquisition, use, and distribution of this module and related ! 43: * materials are subject to the restrictions of a license agreement. ! 44: * Consult the Preface in the User's Manual for the full terms of ! 45: * this agreement. ! 46: * ! 47: */ ! 48: ! 49: ! 50: /* LINTLIBRARY */ ! 51: ! 52: #include <stdio.h> ! 53: #include "tpkt.h" ! 54: ! 55: #ifdef TP4 ! 56: #include "tp4.h" ! 57: #endif ! 58: ! 59: #ifdef BSD_TP4 ! 60: #include <errno.h> ! 61: #include <sys/ioctl.h> ! 62: #include <sys/uio.h> ! 63: #include "tailor.h" ! 64: ! 65: /*#define MAXTP4 8192 /* until we have a dynamic estimate... */ ! 66: #define MAXTP4 1024 /* until we have a dynamic estimate... */ ! 67: #define TP4SLOP 12 /* estimate of largest DT PCI */ ! 68: ! 69: /* DATA */ ! 70: ! 71: STATIC struct msghdr msgs; ! 72: STATIC union osi_control_msg ocm; ! 73: ! 74: ! 75: extern int errno; ! 76: ! 77: /* Ancillary routines */ ! 78: STATIC int sendCmsg(fd, cc, type, data) ! 79: int fd; ! 80: int cc; ! 81: int type; ! 82: char *data; ! 83: { ! 84: int result; ! 85: register struct msghdr *msg = &msgs; ! 86: register union osi_control_msg *oc = &ocm; ! 87: ! 88: bzero ((char *) msg, sizeof *msg); ! 89: msg -> msg_control = oc -> ocm_data; ! 90: ! 91: bzero ((char *) oc, sizeof *oc); ! 92: oc -> ocm_control.ocm_cmhdr.cmsg_level = SOL_TRANSPORT; ! 93: oc -> ocm_control.ocm_cmhdr.cmsg_type = type; ! 94: oc -> ocm_control.ocm_cmhdr.cmsg_len = sizeof oc -> ocm_control.ocm_cmhdr; ! 95: ! 96: if (cc) { ! 97: bcopy (data, oc -> ocm_control.ocm_cmdata, cc); ! 98: oc -> ocm_control.ocm_cmhdr.cmsg_len += cc; ! 99: } ! 100: msg -> msg_controllen = oc -> ocm_control.ocm_cmhdr.cmsg_len; ! 101: ! 102: return sendmsg (fd, msg, 0); ! 103: } ! 104: ! 105: int tp4getCmsg(fd, cc, type, data) ! 106: int fd; ! 107: int *cc; ! 108: int *type; ! 109: char *data; ! 110: { ! 111: int result; ! 112: register struct msghdr *msg = &msgs; ! 113: register union osi_control_msg *oc = &ocm; ! 114: ! 115: bzero ((char *) msg, sizeof *msg); ! 116: msg -> msg_control = oc -> ocm_data; ! 117: msg -> msg_controllen = sizeof oc -> ocm_data; ! 118: ! 119: bzero ((char *) oc, sizeof *oc); ! 120: ! 121: result = recvmsg (fd, msg, 0); ! 122: if (result >= 0 && cc && type && data) { ! 123: register int n = ! 124: (oc -> ocm_control.ocm_cmhdr.cmsg_len ! 125: - sizeof (oc -> ocm_control.ocm_cmhdr)); ! 126: if (n > 0) { ! 127: *type = oc-> ocm_control.ocm_cmhdr.cmsg_type; ! 128: if (n > *cc) ! 129: n = *cc; ! 130: bcopy(oc -> ocm_control.ocm_cmdata, data, n); ! 131: *cc = n; ! 132: } ! 133: } ! 134: return (result); ! 135: } ! 136: ! 137: /* UPPER HALF */ ! 138: ! 139: STATIC int TConnect (tb, expedited, data, cc, td) ! 140: register struct tsapblk *tb; ! 141: char *data; ! 142: int expedited, ! 143: cc; ! 144: struct TSAPdisconnect *td; ! 145: { ! 146: int len; ! 147: union sockaddr_osi sock; ! 148: struct sockaddr_iso *ifaddr = &sock.osi_sockaddr; ! 149: struct tp_conn_param tcp; ! 150: register struct tp_conn_param *p = &tcp; ! 151: ! 152: if (gen2tp4X (&tb -> tb_responding, &sock) == NOTOK) ! 153: return tsaplose (td, DR_ADDRESS, NULLCP, ! 154: "unable to parse remote address"); ! 155: ! 156: len = sizeof *p; ! 157: if (getsockopt (tb -> tb_fd, SOL_TRANSPORT, TPOPT_PARAMS, (char *) p, &len) ! 158: == NOTOK) ! 159: SLOG (tsap_log, LLOG_EXCEPTIONS, "TPOPT_PARAMS", ("unable to get")); ! 160: else { ! 161: if (p -> p_xpd_service ? !expedited : expedited) { ! 162: p -> p_xpd_service = expedited ? 1 : 0; ! 163: if (setsockopt (tb -> tb_fd, SOL_TRANSPORT, TPOPT_PARAMS, ! 164: (char *) p, sizeof *p) == NOTOK) ! 165: SLOG (tsap_log, LLOG_EXCEPTIONS, "TPOPT_PARAMS", ! 166: ("unable to set")); ! 167: } ! 168: ! 169: if (expedited) ! 170: tb -> tb_flags |= TB_EXPD; ! 171: if (p -> p_tpdusize > 0) { ! 172: if (p -> p_tpdusize > 10) ! 173: p -> p_tpdusize = 10; ! 174: tb -> tb_tpduslop = TP4SLOP; ! 175: tb -> tb_tsdusize = (1 << p -> p_tpdusize) - tb -> tb_tpduslop; ! 176: } ! 177: } ! 178: ! 179: if (data && ! 180: sendCmsg(tb->tb_fd, data, cc, TPOPT_CONN_DATA) == NOTOK) ! 181: return tsaplose (td, DR_CONGEST, "TPOPT_CONN_DATA", "unable to send"); ! 182: ! 183: /* ! 184: this is a real hack to pass information between TConnect and TRetry: ! 185: if tb_srcref is 0xffff: this indicates that the connect is still ! 186: in progress ! 187: ! 188: if tb_srcref is 0xfffe: this indicates the connect is done ! 189: ! 190: otherwise: this indicates a TS error ! 191: */ ! 192: ! 193: if (connect (tb -> tb_fd, (struct sockaddr *) ifaddr, ifaddr -> siso_len) ! 194: == NOTOK) { ! 195: if (errno == EINPROGRESS) { ! 196: tb -> tb_srcref = 0xffff; ! 197: return CONNECTING_1; ! 198: } ! 199: ! 200: if (!(errno & TP_ERROR_MASK)) ! 201: return tsaplose (td, DR_REFUSED, "connection", ! 202: "unable to establish"); ! 203: ! 204: tb -> tb_srcref = (errno & ~TP_ERROR_MASK) & 0xff; ! 205: } ! 206: else ! 207: tb -> tb_srcref = 0xfffe; ! 208: ! 209: return DONE; ! 210: } ! 211: ! 212: /* */ ! 213: ! 214: STATIC int TRetry (tb, async, tc, td) ! 215: register struct tsapblk *tb; ! 216: int async; ! 217: struct TSAPconnect *tc; ! 218: struct TSAPdisconnect *td; ! 219: { ! 220: int len, ! 221: onoff, ! 222: flags, ! 223: reason; ! 224: union sockaddr_osi sock; ! 225: struct sockaddr_iso *ifaddr = &sock.osi_sockaddr; ! 226: struct tp_conn_param tcp; ! 227: int cmsgtype = 0; ! 228: register struct tp_conn_param *p = &tcp; ! 229: ! 230: switch (tb -> tb_srcref) { ! 231: case 0xfffe: ! 232: reason = NOTOK; ! 233: break; ! 234: ! 235: default: ! 236: reason = tb -> tb_srcref; ! 237: ! 238: case 0xffff: ! 239: if (async) ! 240: switch ((*tb -> tb_retryfnx) (tb, td)) { ! 241: case NOTOK: ! 242: goto out; ! 243: ! 244: case OK: ! 245: return CONNECTING_1; ! 246: ! 247: case DONE: ! 248: break; ! 249: } ! 250: ! 251: (void) gen2tp4X (&tb -> tb_responding, &sock); ! 252: if (connect (tb -> tb_fd, (struct sockaddr *) ifaddr, ! 253: ifaddr -> siso_len) == NOTOK) ! 254: switch (errno) { ! 255: case EINPROGRESS: ! 256: return CONNECTING_1; ! 257: ! 258: case EISCONN: ! 259: reason = NOTOK; ! 260: break; ! 261: ! 262: default: ! 263: /* for the moment, u.u_error limited to one byte */ ! 264: /* this will be fixed real soon now. */ ! 265: /* if (!(errno & TP_ERROR_MASK)) */ ! 266: if (errno > 0) { ! 267: (void) tsaplose (td, DR_REFUSED, "connection", ! 268: "unable to establish"); ! 269: goto out; ! 270: } ! 271: reason = (errno & ~TP_ERROR_MASK) & 0xff; ! 272: break; ! 273: } ! 274: break; ! 275: } ! 276: ! 277: ! 278: if (async) ! 279: (void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 0, (char *) &onoff)); ! 280: ! 281: if (reason == NOTOK) { ! 282: tc -> tc_sd = tb -> tb_fd; ! 283: tc -> tc_tsdusize = tb -> tb_tsdusize = MAXTP4; ! 284: ! 285: len = sizeof sock; ! 286: if (getsockname (tb -> tb_fd, (struct sockaddr *) ifaddr, &len) ! 287: != NOTOK) { ! 288: ifaddr -> siso_len = len; ! 289: (void) tp42genX (&tb -> tb_responding, &sock); ! 290: } ! 291: else ! 292: SLOG (tsap_log, LLOG_EXCEPTIONS, "failed", ("getpeername")); ! 293: copyTSAPaddrX (&tb -> tb_responding, &tc -> tc_responding); ! 294: ! 295: len = sizeof *p; ! 296: if (getsockopt (tb -> tb_fd, SOL_TRANSPORT, TPOPT_PARAMS, (char *) p, ! 297: &len)== NOTOK) ! 298: SLOG (tsap_log, LLOG_EXCEPTIONS, "TPOPT_PARAMS", ! 299: ("unable to get")); ! 300: else { ! 301: if (!p -> p_xpd_service) ! 302: tb -> tb_flags &= ~TB_EXPD; ! 303: ! 304: if (p -> p_tpdusize > 0) { ! 305: if (p -> p_tpdusize > 10) ! 306: p -> p_tpdusize = 10; ! 307: tb -> tb_tpduslop = TP4SLOP; ! 308: tb -> tb_tsdusize = (1 << p -> p_tpdusize) - tb -> tb_tpduslop; ! 309: } ! 310: } ! 311: tc -> tc_expedited = (tb -> tb_flags & TB_EXPD) ? 1 : 0; ! 312: tc -> tc_cc = sizeof tc -> tc_data; ! 313: if (tp4getCmsg(tb->tb_fd, &cmsgtype, &tc->tc_cc, tc->tc_data) < 0) { ! 314: tc -> tc_cc = 0; ! 315: } else if (cmsgtype != TPOPT_CFRM_DATA) ! 316: tc -> tc_cc = 0; ! 317: ! 318: tb -> tb_flags |= TB_CONN; ! 319: #ifdef MGMT ! 320: if (tb -> tb_manfnx) ! 321: (*tb -> tb_manfnx) (OPREQOUT, tb); ! 322: #endif ! 323: if (tb -> tb_calling) ! 324: free ((char *) tb -> tb_calling), tb -> tb_calling = NULL; ! 325: if (tb -> tb_called) ! 326: free ((char *) tb -> tb_called), tb -> tb_called = NULL; ! 327: ! 328: return DONE; ! 329: } ! 330: ! 331: td -> td_reason = reason; ! 332: td -> td_cc = sizeof td -> td_data; ! 333: if (tp4getCmsg(tb->tb_fd, &cmsgtype, &td->td_cc, td->td_data) < 0) ! 334: td -> td_cc = 0; ! 335: else if (cmsgtype != TPOPT_DISC_DATA) ! 336: td -> td_cc = 0; ! 337: ! 338: out: ; ! 339: freetblk (tb); ! 340: ! 341: return NOTOK; ! 342: } ! 343: ! 344: /* */ ! 345: ! 346: STATIC int TStart (tb, cp, ts, td) ! 347: register struct tsapblk *tb; ! 348: char *cp; ! 349: struct TSAPstart *ts; ! 350: struct TSAPdisconnect *td; ! 351: { ! 352: int i, ! 353: len; ! 354: struct tp_conn_param tcp; ! 355: register struct tp_conn_param *p = &tcp; ! 356: ! 357: len = sizeof *p; ! 358: if (getsockopt (tb -> tb_fd, SOL_TRANSPORT, TPOPT_PARAMS, (char *) p, &len) ! 359: == NOTOK) ! 360: SLOG (tsap_log, LLOG_EXCEPTIONS, "TPOPT_PARAMS", ("unable to get")); ! 361: else { ! 362: if (p -> p_xpd_service) ! 363: tb -> tb_flags |= TB_EXPD; ! 364: if (p -> p_tpdusize > 0) { ! 365: if (p -> p_tpdusize > 10) ! 366: p -> p_tpdusize = 10; ! 367: tb -> tb_tpduslop = TP4SLOP; ! 368: tb -> tb_tsdusize = (1 << p -> p_tpdusize) - tb -> tb_tpduslop; ! 369: } ! 370: } ! 371: ! 372: ts -> ts_sd = tb -> tb_fd; ! 373: copyTSAPaddrX (&tb -> tb_initiating, &ts -> ts_calling); ! 374: copyTSAPaddrX (&tb -> tb_responding, &ts -> ts_called); ! 375: ts -> ts_expedited = (tb -> tb_flags & TB_EXPD) ? 1 : 0; ! 376: ts -> ts_tsdusize = tb -> tb_tsdusize; ! 377: ! 378: if ((i = strlen (cp)) > 0) { ! 379: if (i > 2 * TS_SIZE) ! 380: return tsaplose (td, DR_CONNECT, NULLCP, ! 381: "too much initial user data"); ! 382: ! 383: ts -> ts_cc = implode ((u_char *) ts -> ts_data, cp, i); ! 384: } ! 385: else ! 386: ts -> ts_cc = 0; ! 387: ! 388: return OK; ! 389: } ! 390: ! 391: /* */ ! 392: ! 393: /* ARGSUSED */ ! 394: ! 395: STATIC int TAccept (tb, responding, data, cc, qos, td) ! 396: register struct tsapblk *tb; ! 397: char *data; ! 398: int responding, ! 399: cc; ! 400: struct QOStype *qos; ! 401: struct TSAPdisconnect *td; ! 402: { ! 403: int len; ! 404: struct tp_conn_param tcp; ! 405: register struct tp_conn_param *p = &tcp; ! 406: ! 407: len = sizeof *p; ! 408: if (getsockopt (tb -> tb_fd, SOL_TRANSPORT, TPOPT_PARAMS, (char *) p, &len) ! 409: == NOTOK) ! 410: SLOG (tsap_log, LLOG_EXCEPTIONS, "TPOPT_PARAMS", ("unable to get")); ! 411: else { ! 412: if (!p -> p_xpd_service) ! 413: tb -> tb_flags &= ~TB_EXPD; ! 414: else ! 415: if (!(tb -> tb_flags & TB_EXPD)) { ! 416: p -> p_xpd_service = 0; ! 417: if (setsockopt (tb -> tb_fd, SOL_TRANSPORT, TPOPT_PARAMS, ! 418: (char *) p, sizeof *p) == NOTOK) ! 419: SLOG (tsap_log, LLOG_EXCEPTIONS, "TPOPT_PARAMS", ! 420: ("unable to set")); ! 421: } ! 422: ! 423: if (p -> p_tpdusize > 0) { ! 424: if (p -> p_tpdusize > 10) ! 425: p -> p_tpdusize = 10; ! 426: tb -> tb_tpduslop = TP4SLOP; ! 427: tb -> tb_tsdusize = (1 << p -> p_tpdusize) - tb -> tb_tpduslop; ! 428: } ! 429: } ! 430: ! 431: if (sendCmsg (tb -> tb_fd, cc, TPOPT_CFRM_DATA, data) == NOTOK) ! 432: return tsaplose (td, DR_CONGEST, "TPOPT_CFRM_DATA", "unable to send"); ! 433: ! 434: tb -> tb_flags |= TB_CONN; ! 435: #ifdef MGMT ! 436: if (tb -> tb_manfnx) ! 437: (*tb -> tb_manfnx) (OPREQIN, tb); ! 438: #endif ! 439: ! 440: return OK; ! 441: } ! 442: ! 443: /* */ ! 444: ! 445: /* life would be nice if we didn't have to worry about the maximum number of ! 446: bytes that can be written in a single syscall() */ ! 447: ! 448: #ifndef MSG_MAXIOVLEN ! 449: #define MSG_MAXIOVLEN NTPUV ! 450: #endif ! 451: ! 452: ! 453: STATIC int TWrite (tb, uv, expedited, td) ! 454: register struct tsapblk *tb; ! 455: register struct udvec *uv; ! 456: int expedited; ! 457: struct TSAPdisconnect *td; ! 458: { ! 459: register int cc; ! 460: int flags, ! 461: j, ! 462: len; ! 463: #ifdef MGMT ! 464: int dlen; ! 465: #endif ! 466: register char *bp, ! 467: *ep; ! 468: register struct qbuf *qb; ! 469: register struct msghdr *msg = &msgs; ! 470: struct iovec iovs[MSG_MAXIOVLEN]; ! 471: register struct iovec *vv, ! 472: *wv; ! 473: ! 474: bzero ((char *) msg, sizeof *msg); ! 475: ! 476: flags = expedited ? MSG_OOB : 0; ! 477: ! 478: #ifdef MGMT ! 479: dlen = 0; ! 480: #endif ! 481: ! 482: if (!expedited && (tb -> tb_flags & TB_QWRITES)) { ! 483: int onoff, ! 484: nc; ! 485: struct udvec *xv; ! 486: ! 487: cc = 0; ! 488: for (xv = uv; xv -> uv_base; xv++) ! 489: cc += xv -> uv_len; ! 490: #ifdef MGMT ! 491: dlen = cc; ! 492: #endif ! 493: ! 494: if ((qb = (struct qbuf *) malloc (sizeof *qb + (unsigned) cc)) ! 495: == NULL) { ! 496: (void) tsaplose (td, DR_CONGEST, NULLCP, ! 497: "unable to malloc %d octets for pseudo-writev, failing...", ! 498: cc); ! 499: freetblk (tb); ! 500: ! 501: return NOTOK; ! 502: } ! 503: qb -> qb_forw = qb -> qb_back = qb; ! 504: qb -> qb_data = qb -> qb_base, qb -> qb_len = cc; ! 505: ! 506: bp = qb -> qb_data; ! 507: for (xv = uv; xv -> uv_base; xv++) { ! 508: bcopy (xv -> uv_base, bp, xv -> uv_len); ! 509: bp += xv -> uv_len; ! 510: } ! 511: ! 512: if (tb -> tb_qwrites.qb_forw != &tb -> tb_qwrites) { ! 513: nc = 0; ! 514: goto insert; ! 515: } ! 516: ! 517: vv = iovs; ! 518: vv -> iov_base = qb -> qb_data, vv -> iov_len = qb -> qb_len; ! 519: vv++; ! 520: ! 521: msg -> msg_iov = iovs; ! 522: msg -> msg_iovlen = vv - iovs; ! 523: ! 524: (void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 1, (char *) &onoff)); ! 525: ! 526: nc = sendmsg (tb -> tb_fd, msg, MSG_EOR); ! 527: ! 528: (void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 0, (char *) &onoff)); ! 529: ! 530: if (nc != cc) { ! 531: if (nc == NOTOK) { ! 532: if (errno != EWOULDBLOCK) { ! 533: (void) tsaplose (td, DR_CONGEST, "failed", "sendmsg"); ! 534: goto losing; ! 535: } ! 536: ! 537: nc = 0; ! 538: } ! 539: if ((*tb -> tb_queuePfnx) (tb, 1, td) == NOTOK) ! 540: goto losing; ! 541: ! 542: qb -> qb_data += nc, qb -> qb_len -= nc; ! 543: insert: ; ! 544: insque (qb, tb -> tb_qwrites.qb_back); ! 545: DLOG (tsap_log, LLOG_TRACE, ! 546: ("queueing blocked write of %d of %d octets", nc, cc)); ! 547: } ! 548: else ! 549: free ((char *) qb); ! 550: goto done; ! 551: ! 552: losing: ; ! 553: free ((char *) qb); ! 554: freetblk (tb); ! 555: ! 556: return NOTOK; ! 557: } ! 558: ! 559: ep = (bp = uv -> uv_base) + (cc = uv -> uv_len); ! 560: while (uv -> uv_base) { ! 561: wv = (vv = iovs) + MSG_MAXIOVLEN; ! 562: for (len = tb -> tb_tsdusize; len > 0 && vv < wv; len -= j) { ! 563: j = min (cc, len); ! 564: #ifdef MGMT ! 565: dlen += j; ! 566: #endif ! 567: vv -> iov_base = bp, vv -> iov_len = j, vv++; ! 568: bp += j, cc -= j; ! 569: ! 570: if (bp >= ep) { ! 571: if ((bp = (++uv) -> uv_base) == NULL) ! 572: break; ! 573: ep = bp + (cc = uv -> uv_len); ! 574: } ! 575: } ! 576: ! 577: if (expedited || uv -> uv_base == NULL) ! 578: flags |= MSG_EOR; ! 579: ! 580: msg -> msg_iov = iovs; ! 581: msg -> msg_iovlen = vv - iovs; ! 582: ! 583: if (sendmsg (tb -> tb_fd, msg, flags) == NOTOK) { ! 584: (void) tsaplose (td, DR_CONGEST, "failed", "sendmsg"); ! 585: freetblk (tb); ! 586: ! 587: return NOTOK; ! 588: } ! 589: } ! 590: ! 591: done: ; ! 592: #ifdef MGMT ! 593: if (tb -> tb_manfnx) ! 594: (*tb -> tb_manfnx) (USERDT, tb, dlen); ! 595: #endif ! 596: ! 597: return OK; ! 598: } ! 599: ! 600: /* */ ! 601: ! 602: STATIC int TDrain (tb, td) ! 603: register struct tsapblk *tb; ! 604: struct TSAPdisconnect *td; ! 605: { ! 606: int nc, ! 607: onoff, ! 608: result; ! 609: register struct qbuf *qb; ! 610: register struct msghdr *msg = &msgs; ! 611: struct iovec vvs; ! 612: register struct iovec *vv = &vvs; ! 613: ! 614: bzero ((char *) msg, sizeof *msg); ! 615: msg -> msg_iov = vv, msg -> msg_iovlen = 1; ! 616: ! 617: (void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 1, (char *) &onoff)); ! 618: ! 619: while ((qb = tb -> tb_qwrites.qb_forw) != &tb -> tb_qwrites) { ! 620: vv -> iov_base = qb -> qb_data, vv -> iov_len = qb -> qb_len; ! 621: ! 622: if (nc = sendmsg (tb -> tb_fd, msg, MSG_EOR) != qb -> qb_len) { ! 623: if (nc == NOTOK) { ! 624: if (errno != EWOULDBLOCK) { ! 625: result = tsaplose (td, DR_NETWORK, "failed", ! 626: "write to network"); ! 627: goto out; ! 628: } ! 629: ! 630: nc = 0; ! 631: } ! 632: ! 633: qb -> qb_data += nc, qb -> qb_len -= nc; ! 634: DLOG (tsap_log, LLOG_TRACE, ! 635: ("wrote %d of %d octets from blocked write", nc, ! 636: qb -> qb_len)); ! 637: ! 638: result = OK; ! 639: goto out; ! 640: } ! 641: ! 642: DLOG (tsap_log, LLOG_TRACE, ! 643: ("finished blocked write of %d octets", qb -> qb_len)); ! 644: remque (qb); ! 645: free ((char *) qb); ! 646: } ! 647: result = DONE; ! 648: ! 649: out: ; ! 650: (void) ioctl (tb -> tb_fd, FIONBIO, (onoff = 0, (char *) &onoff)); ! 651: ! 652: return result; ! 653: } ! 654: ! 655: /* */ ! 656: ! 657: /* ARGSUSED */ ! 658: ! 659: STATIC int TRead (tb, tx, td, async, oob) ! 660: register struct tsapblk *tb; ! 661: register struct TSAPdata *tx; ! 662: struct TSAPdisconnect *td; ! 663: int async, ! 664: oob; ! 665: { ! 666: int cc; ! 667: register struct qbuf *qb; ! 668: register struct msghdr *msg = &msgs; ! 669: register union osi_control_msg *oc = &ocm; ! 670: struct iovec iovs[1]; ! 671: static struct qbuf *spare_qb = 0; ! 672: ! 673: bzero ((char *) tx, sizeof *tx); ! 674: tx -> tx_qbuf.qb_forw = tx -> tx_qbuf.qb_back = &tx -> tx_qbuf; ! 675: ! 676: for (;;) { ! 677: qb = NULL; ! 678: if (spare_qb) { ! 679: if (spare_qb -> qb_len >= tb -> tb_tsdusize) ! 680: qb = spare_qb; ! 681: else ! 682: free ((char *)spare_qb); ! 683: spare_qb = NULL; ! 684: } ! 685: if (qb == NULL && (qb = (struct qbuf *) malloc ((unsigned) (sizeof *qb ! 686: + tb -> tb_tsdusize))) ! 687: == NULL) { ! 688: (void) tsaplose (td, DR_CONGEST, NULLCP, NULLCP); ! 689: break; ! 690: } ! 691: qb -> qb_data = qb -> qb_base; ! 692: ! 693: bzero ((char *) msg, sizeof *msg); ! 694: msg -> msg_iov = iovs; ! 695: msg -> msg_iovlen = 1; ! 696: msg -> msg_control = oc -> ocm_data; ! 697: msg -> msg_controllen = sizeof oc -> ocm_data; ! 698: ! 699: iovs[0].iov_base = qb -> qb_data; ! 700: iovs[0].iov_len = tb -> tb_tsdusize; ! 701: ! 702: bzero ((char *) oc, sizeof *oc); ! 703: ! 704: if ((cc = recvmsg(tb -> tb_fd, msg, 0)) == NOTOK) { ! 705: /*if ((cc = recvmsg(tb -> tb_fd, msg, oob ? MSG_OOB : 0)) == NOTOK) */ ! 706: if (!(errno & TP_ERROR_MASK)) { ! 707: (void) tsaplose (td, DR_CONGEST, "failed", "recvfrom"); ! 708: break; ! 709: } ! 710: ! 711: if ((td -> td_reason = errno & ~TP_ERROR_MASK) != DR_NORMAL) ! 712: SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ! 713: ("TP error %d", td -> td_reason)); ! 714: td -> td_cc = 0; ! 715: break; ! 716: } ! 717: ! 718: if (msg -> msg_controllen) { ! 719: if (msg -> msg_controllen < sizeof oc -> ocm_control.ocm_cmhdr) { ! 720: (void) tsaplose (td, DR_CONGEST, NULLCP, ! 721: "truncated control message, got %d expecting at least %d", ! 722: msg -> msg_controllen, ! 723: sizeof oc -> ocm_control.ocm_cmhdr); ! 724: break; ! 725: } ! 726: ! 727: if (oc -> ocm_control.ocm_cmhdr.cmsg_level != SOL_TRANSPORT) { ! 728: (void) tsaplose (td, DR_CONGEST, NULLCP, ! 729: "unexpected message (level 0x%x, type 0x%x)", ! 730: oc -> ocm_control.ocm_cmhdr.cmsg_level, ! 731: oc -> ocm_control.ocm_cmhdr.cmsg_type); ! 732: break; ! 733: } ! 734: if (oc -> ocm_control.ocm_cmhdr.cmsg_type == TPOPT_DISC_DATA) { ! 735: td -> td_reason = DR_NORMAL; ! 736: if ((td -> td_cc = oc -> ocm_control.ocm_cmhdr.cmsg_len ! 737: - sizeof oc -> ocm_control.ocm_cmhdr) > 0) ! 738: bcopy (oc -> ocm_control.ocm_cmdata, td -> td_data, cc); ! 739: break; ! 740: } ! 741: } ! 742: ! 743: if (msg -> msg_flags & MSG_OOB) { ! 744: if (cc > 0) { ! 745: insque (qb, tx -> tx_qbuf.qb_back); ! 746: tx -> tx_cc = (qb -> qb_len = cc); ! 747: } ! 748: else ! 749: free ((char *) qb); ! 750: tx -> tx_expedited = 1; ! 751: ! 752: return OK; ! 753: } ! 754: ! 755: tb -> tb_len += (qb -> qb_len = cc); ! 756: if (cc > 0) { ! 757: register struct qbuf *qb2 = tb -> tb_qbuf.qb_back; ! 758: ! 759: if (qb2 != &tb->tb_qbuf && qb2->qb_len + cc <= tb->tb_tsdusize) { ! 760: bcopy(qb -> qb_data, qb2 -> qb_len + qb2 -> qb_data, cc); ! 761: qb2 -> qb_len += cc; ! 762: (spare_qb = qb) -> qb_len = tb -> tb_tsdusize; ! 763: } else ! 764: insque (qb, qb2); ! 765: } else ! 766: free ((char *) qb); ! 767: ! 768: #ifdef MGMT ! 769: if (tb -> tb_manfnx) ! 770: (*tb -> tb_manfnx) (USERDR, tb, tb -> tb_len); ! 771: #endif ! 772: if (!(msg -> msg_flags & MSG_EOR)) { ! 773: if (async) { ! 774: register struct qbuf *qb2 = tb -> tb_qbuf.qb_back; ! 775: if (qb2 != &tb->tb_qbuf && qb2->qb_len <= tb->tb_tsdusize) ! 776: printf("short return %d\n", qb2->qb_len); ! 777: return DONE; ! 778: } ! 779: continue; ! 780: } ! 781: tx -> tx_expedited = 0; ! 782: if (tb -> tb_qbuf.qb_forw != &tb -> tb_qbuf) { ! 783: tx -> tx_qbuf = tb -> tb_qbuf; /* struct copy */ ! 784: tx -> tx_qbuf.qb_forw -> qb_back = ! 785: tx -> tx_qbuf.qb_back -> qb_forw = &tx -> tx_qbuf; ! 786: tx -> tx_cc = tb -> tb_len; ! 787: tb -> tb_qbuf.qb_forw = ! 788: tb -> tb_qbuf.qb_back = &tb -> tb_qbuf; ! 789: tb -> tb_len = 0; ! 790: } ! 791: ! 792: { ! 793: register struct qbuf *qb2 = tb -> tb_qbuf.qb_back; ! 794: if (qb2 != &tb->tb_qbuf && qb2->qb_len <= tb->tb_tsdusize) ! 795: printf("short return %d\n", qb2->qb_len); ! 796: } ! 797: return OK; ! 798: } ! 799: if (qb) ! 800: free ((char *) qb); ! 801: ! 802: freetblk (tb); ! 803: ! 804: return NOTOK; ! 805: } ! 806: ! 807: /* */ ! 808: ! 809: STATIC int TDisconnect (tb, data, cc, td) ! 810: register struct tsapblk *tb; ! 811: char *data; ! 812: int cc; ! 813: struct TSAPdisconnect *td; ! 814: { ! 815: int result; ! 816: ! 817: if (sendCmsg(tb -> tb_fd, cc, TPOPT_DISC_DATA, data) == NOTOK) ! 818: result = tsaplose (td, DR_CONGEST, "TPOPT_DISC_DATA", ! 819: "unable to send"); ! 820: else ! 821: result = OK; ! 822: ! 823: freetblk (tb); ! 824: ! 825: return result; ! 826: } ! 827: /* */ ! 828: ! 829: /* ARGSUSED */ ! 830: ! 831: STATIC int TLose (tb, reason, td) ! 832: register struct tsapblk *tb; ! 833: int reason; ! 834: struct TSAPdisconnect *td; ! 835: { ! 836: register struct msghdr *msg = &msgs; ! 837: register union osi_control_msg *oc = &ocm; ! 838: ! 839: SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ("TPM error %d", reason)); ! 840: ! 841: bzero ((char *) msg, sizeof *msg); ! 842: msg -> msg_control = oc -> ocm_data; ! 843: msg -> msg_controllen = sizeof oc -> ocm_data; ! 844: ! 845: bzero ((char *) oc, sizeof *oc); ! 846: oc -> ocm_control.ocm_cmhdr.cmsg_level = SOL_TRANSPORT; ! 847: oc -> ocm_control.ocm_cmhdr.cmsg_type = TPOPT_DISC_DATA; ! 848: oc -> ocm_control.ocm_cmhdr.cmsg_len = sizeof oc -> ocm_control.ocm_cmhdr; ! 849: ! 850: if (sendmsg (tb -> tb_fd, msg, 0) == NOTOK) ! 851: SLOG (tsap_log, LLOG_EXCEPTIONS, "TPOPT_DISC_DATA", ! 852: ("unable to send")); ! 853: } ! 854: ! 855: /* LOWER HALF */ ! 856: ! 857: /* ARGSUSED */ ! 858: ! 859: int tp4open (tb, local_ta, local_na, remote_ta, remote_na, td, async) ! 860: register struct tsapblk *tb; ! 861: struct TSAPaddr *local_ta, ! 862: *remote_ta; ! 863: struct NSAPaddr *local_na, ! 864: *remote_na; ! 865: struct TSAPdisconnect *td; ! 866: int async; ! 867: { ! 868: int fd, ! 869: onoff; ! 870: struct TSAPaddr tzs; ! 871: register struct TSAPaddr *tz = &tzs; ! 872: register struct NSAPaddr *nz = tz -> ta_addrs; ! 873: union sockaddr_osi sock; ! 874: struct sockaddr_iso *ifaddr = &sock.osi_sockaddr; ! 875: ! 876: bzero ((char *) tz, sizeof *tz); ! 877: if (local_ta) ! 878: *tz = *local_ta; /* struct copy */ ! 879: if (local_na) { ! 880: *nz = *local_na; /* struct copy */ ! 881: tz -> ta_naddr = 1; ! 882: } ! 883: ! 884: (void) gen2tp4 (tz, &sock); ! 885: ! 886: if ((fd = socket (AF_ISO, SOCK_SEQPACKET, 0)) == NOTOK) ! 887: return tsaplose (td, DR_CONGEST, "socket", "unable to start"); ! 888: ! 889: if (ifaddr->siso_nlen || ifaddr->siso_tlen) ! 890: if (bind (fd, (struct sockaddr *) ifaddr, ifaddr -> siso_len) == NOTOK) { ! 891: (void) tsaplose (td, DR_ADDRESS, "socket", "unable to bind"); ! 892: (void) close (fd); ! 893: return NOTOK; ! 894: } ! 895: ! 896: tb -> tb_fd = fd; ! 897: (void) tp4init (tb); ! 898: ! 899: if (async) ! 900: (void) ioctl (fd, FIONBIO, (onoff = 1, (char *) &onoff)); ! 901: ! 902: return (async ? OK : DONE); ! 903: } ! 904: ! 905: /* */ ! 906: ! 907: /* ARGSUSED */ ! 908: ! 909: STATIC int retry_tp4_socket (tb, td) ! 910: register struct tsapblk *tb; ! 911: struct TSAPdisconnect *td; ! 912: { ! 913: fd_set mask; ! 914: ! 915: FD_ZERO (&mask); ! 916: FD_SET (tb -> tb_fd, &mask); ! 917: if (xselect (tb -> tb_fd + 1, NULLFD, &mask, NULLFD, 0) < 1) ! 918: return OK; ! 919: ! 920: return DONE; ! 921: } ! 922: ! 923: /* */ ! 924: ! 925: /* ARGSUSED */ ! 926: ! 927: char *tp4save (fd, td) ! 928: int fd; ! 929: struct TSAPdisconnect *td; ! 930: { ! 931: static char buffer[BUFSIZ]; ! 932: ! 933: (void) sprintf (buffer, "%c%d", NT_BSD, fd); ! 934: return buffer; ! 935: } ! 936: ! 937: /* */ ! 938: ! 939: int tp4restore (tb, buffer, td) ! 940: register struct tsapblk *tb; ! 941: char *buffer; ! 942: struct TSAPdisconnect *td; ! 943: { ! 944: int fd, len, ucdlen; ! 945: union sockaddr_osi sock; ! 946: struct sockaddr_iso *ifaddr = &sock.osi_sockaddr; ! 947: ! 948: if (sscanf (buffer, "%d", &fd) != 1 || fd < 0) ! 949: return tsaplose (td, DR_PARAMETER, NULLCP, ! 950: "bad initialization vector \"%s\"", buffer); ! 951: ! 952: tb -> tb_fd = fd; ! 953: (void) tp4init (tb); ! 954: len = sizeof sock; ! 955: if (getsockname (fd, (struct sockaddr *) ifaddr, &len) == NOTOK) { ! 956: (void) tsaplose (td, DR_CONGEST, "listen", ! 957: "getsockname failed for tp4restore"); ! 958: (void) close (fd); ! 959: return NOTOK; ! 960: } ! 961: ifaddr -> siso_len = len; ! 962: (void) tp42genX (&tb -> tb_responding, &sock); ! 963: len = sizeof sock; ! 964: if (getpeername (fd, (struct sockaddr *) ifaddr, &len) == NOTOK) { ! 965: (void) tsaplose (td, DR_CONGEST, "listen", ! 966: "getpeername failed for tp4restore"); ! 967: (void) close (fd); ! 968: return NOTOK; ! 969: } ! 970: ifaddr -> siso_len = len; ! 971: (void) tp42genX (&tb -> tb_initiating, &sock); ! 972: return OK; ! 973: } ! 974: ! 975: /* */ ! 976: ! 977: int tp4init (tb) ! 978: register struct tsapblk *tb; ! 979: { ! 980: tb -> tb_connPfnx = TConnect; ! 981: tb -> tb_retryPfnx = TRetry; ! 982: ! 983: tb -> tb_startPfnx = TStart; ! 984: tb -> tb_acceptPfnx = TAccept; ! 985: ! 986: tb -> tb_writePfnx = TWrite; ! 987: tb -> tb_readPfnx = TRead; ! 988: tb -> tb_discPfnx = TDisconnect; ! 989: tb -> tb_losePfnx = TLose; ! 990: ! 991: tb -> tb_drainPfnx = TDrain; ! 992: ! 993: #ifdef MGMT ! 994: tb -> tb_manfnx = TManGen; ! 995: #endif ! 996: ! 997: tb -> tb_flags |= TB_TP4; ! 998: ! 999: tb -> tb_tsdusize = MAXTP4 - (tb -> tb_tpduslop = 0); ! 1000: ! 1001: tb -> tb_retryfnx = retry_tp4_socket; ! 1002: ! 1003: tb -> tb_closefnx = close_tp4_socket; ! 1004: tb -> tb_selectfnx = select_tp4_socket; ! 1005: } ! 1006: ! 1007: /* */ ! 1008: ! 1009: /* ARGSUSED */ ! 1010: ! 1011: int start_tp4_server (local_ta, backlog, opt1, opt2, td) ! 1012: struct TSAPaddr *local_ta; ! 1013: int backlog, ! 1014: opt1, ! 1015: opt2; ! 1016: struct TSAPdisconnect *td; ! 1017: { ! 1018: int sd, ! 1019: onoff; ! 1020: register struct NSAPaddr *na = local_ta -> ta_addrs; ! 1021: union sockaddr_osi sock; ! 1022: struct sockaddr_iso *ifaddr = &sock.osi_sockaddr; ! 1023: ! 1024: (void) gen2tp4 (local_ta, &sock); ! 1025: ! 1026: if ((sd = socket (AF_ISO, SOCK_SEQPACKET, 0)) == NOTOK) ! 1027: return tsaplose (td, DR_CONGEST, "socket", "unable to start"); ! 1028: ! 1029: if (bind (sd, (struct sockaddr *) ifaddr, ifaddr -> siso_len) == NOTOK) { ! 1030: (void) tsaplose (td, DR_ADDRESS, "socket", "unable to bind"); ! 1031: (void) close (sd); ! 1032: return NOTOK; ! 1033: } ! 1034: ! 1035: if (na -> na_addrlen == 0) { /* unique listen */ ! 1036: int len; ! 1037: ! 1038: len = sizeof sock; ! 1039: if (getsockname (sd, (struct sockaddr *) ifaddr, &len) == NOTOK) { ! 1040: (void) tsaplose (td, DR_CONGEST, "listen", ! 1041: "getsockname failed for unique"); ! 1042: (void) close (sd); ! 1043: return NOTOK; ! 1044: } ! 1045: ifaddr -> siso_len = len; ! 1046: ! 1047: (void) tp42gen (local_ta, &sock); ! 1048: } ! 1049: ! 1050: if (opt1) ! 1051: (void) setsockopt (sd, SOL_SOCKET, opt1, NULLCP, 0); ! 1052: if (opt2) ! 1053: (void) setsockopt (sd, SOL_SOCKET, opt2, NULLCP, 0); ! 1054: ! 1055: onoff = 1; ! 1056: ! 1057: (void) listen (sd, backlog); ! 1058: ! 1059: return sd; ! 1060: } ! 1061: ! 1062: /* */ ! 1063: ! 1064: int join_tp4_client (fd, remote_ta, td) ! 1065: int fd; ! 1066: struct TSAPaddr *remote_ta; ! 1067: struct TSAPdisconnect *td; ! 1068: { ! 1069: int len, ! 1070: sd; ! 1071: union sockaddr_osi sock; ! 1072: struct sockaddr_iso *ifaddr = &sock.osi_sockaddr; ! 1073: ! 1074: len = sizeof sock; ! 1075: if ((sd = accept (fd, (struct sockaddr *) ifaddr, &len)) == NOTOK) ! 1076: return tsaplose (td, DR_NETWORK, "socket", "unable to accept"); ! 1077: ifaddr -> siso_len = len; ! 1078: ! 1079: (void) tp42gen (remote_ta, &sock); ! 1080: ! 1081: return sd; ! 1082: } ! 1083: ! 1084: /* */ ! 1085: ! 1086: STATIC int gen2tp4 (generic, specific) ! 1087: struct TSAPaddr *generic; ! 1088: union sockaddr_osi *specific; ! 1089: { ! 1090: register char *cp; ! 1091: struct sockaddr_iso *ifaddr = &specific -> osi_sockaddr; ! 1092: ! 1093: bzero ((char *) specific, sizeof *specific); ! 1094: ! 1095: cp = ifaddr -> siso_data; ! 1096: ! 1097: if (generic -> ta_naddr > 0) { ! 1098: register struct NSAPaddr *na = generic -> ta_addrs; ! 1099: ! 1100: if (ifaddr -> siso_nlen = na -> na_addrlen) { ! 1101: bcopy (na -> na_address, cp, na -> na_addrlen); ! 1102: cp += na -> na_addrlen; ! 1103: } ! 1104: } ! 1105: ! 1106: if (ifaddr -> siso_tlen = generic -> ta_selectlen) { ! 1107: bcopy (generic -> ta_selector, cp, generic -> ta_selectlen); ! 1108: cp += generic -> ta_selectlen; ! 1109: } ! 1110: ! 1111: if ((ifaddr -> siso_len = cp - (char *) ifaddr) < sizeof *ifaddr) ! 1112: ifaddr -> siso_len = sizeof *ifaddr; ! 1113: ifaddr -> siso_family = AF_ISO; ! 1114: ! 1115: return OK; ! 1116: } ! 1117: ! 1118: ! 1119: ! 1120: STATIC int gen2tp4X (generic, specific) ! 1121: struct tsapADDR *generic; ! 1122: union sockaddr_osi *specific; ! 1123: { ! 1124: struct TSAPaddr tas; ! 1125: ! 1126: copyTSAPaddrX (generic, &tas); ! 1127: return gen2tp4 (&tas, specific); ! 1128: } ! 1129: ! 1130: /* */ ! 1131: ! 1132: int tp42gen (generic, specific) ! 1133: struct TSAPaddr *generic; ! 1134: union sockaddr_osi *specific; ! 1135: { ! 1136: register char *cp; ! 1137: register struct NSAPaddr *na = generic -> ta_addrs; ! 1138: struct sockaddr_iso *ifaddr = &specific -> osi_sockaddr; ! 1139: ! 1140: bzero ((char *) generic, sizeof *generic); ! 1141: ! 1142: cp = ifaddr -> siso_data; ! 1143: if (na -> na_addrlen = ifaddr -> siso_nlen) { ! 1144: na -> na_stack = NA_NSAP; ! 1145: na -> na_community = ts_comm_nsap_default; ! 1146: bcopy (cp, na -> na_address, na -> na_addrlen); ! 1147: cp += na -> na_addrlen; ! 1148: ! 1149: generic -> ta_naddr++; ! 1150: } ! 1151: ! 1152: if (generic -> ta_selectlen = ifaddr -> siso_tlen) ! 1153: bcopy (cp, generic -> ta_selector, generic -> ta_selectlen); ! 1154: ! 1155: return OK; ! 1156: } ! 1157: ! 1158: ! 1159: int tp42genX (generic, specific) ! 1160: struct tsapADDR *generic; ! 1161: union sockaddr_osi *specific; ! 1162: { ! 1163: int result; ! 1164: struct TSAPaddr tas; ! 1165: ! 1166: if ((result = tp42gen (&tas, specific)) == OK) ! 1167: copyTSAPaddrY (&tas, generic); ! 1168: ! 1169: return result; ! 1170: } ! 1171: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.