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