|
|
1.1 ! root 1: /* fd2tpkt.c - read/write a TPDU thru a socket */ ! 2: ! 3: #ifndef lint ! 4: static char *rcsid = "$Header: /f/osi/tsap/RCS/fd2tpkt.c,v 7.1 89/12/07 01:07:25 mrose Exp $"; ! 5: #endif ! 6: ! 7: /* ! 8: * $Header: /f/osi/tsap/RCS/fd2tpkt.c,v 7.1 89/12/07 01:07:25 mrose Exp $ ! 9: * ! 10: * ! 11: * $Log: fd2tpkt.c,v $ ! 12: * Revision 7.1 89/12/07 01:07:25 mrose ! 13: * queued writes ! 14: * ! 15: * Revision 7.0 89/11/23 22:30:26 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 "tpkt.h" ! 36: #include "tailor.h" ! 37: ! 38: /* */ ! 39: ! 40: struct tsapkt *fd2tpkt (fd, initfnx, readfnx) ! 41: int fd; ! 42: IFP initfnx, ! 43: readfnx; ! 44: { ! 45: register struct tsapkt *t; ! 46: ! 47: if ((t = newtpkt (0)) == NULL) ! 48: return NULL; ! 49: ! 50: if ((t -> t_errno = fd2tpktaux (fd, t, initfnx, readfnx)) != OK) { ! 51: if (t -> t_vdata != NULL) ! 52: free (t -> t_vdata), t -> t_vdata = NULL, t -> t_vlen = 0; ! 53: ! 54: if (t -> t_qbuf) ! 55: free ((char *) t -> t_qbuf), t -> t_qbuf = NULL; ! 56: } ! 57: ! 58: #ifdef DEBUG ! 59: if (tsap_log -> ll_events & LLOG_PDUS) ! 60: tpkt2text (tsap_log, t, 1); ! 61: #endif ! 62: ! 63: return t; ! 64: } ! 65: ! 66: /* */ ! 67: ! 68: static int fd2tpktaux (fd, t, initfnx, readfnx) ! 69: int fd; ! 70: register struct tsapkt *t; ! 71: IFP initfnx, ! 72: readfnx; ! 73: { ! 74: register int code, ! 75: len, ! 76: vlen; ! 77: register char *vptr; ! 78: ! 79: if ((code = (*initfnx) (fd, t)) != OK) ! 80: return code; ! 81: if (t -> t_li > TPDU_MAXLEN (t)) ! 82: return DR_LENGTH; ! 83: ! 84: switch (TPDU_CODE (t)) { ! 85: case TPDU_CR: ! 86: case TPDU_CC: ! 87: if (t -> t_li < TPDU_MINLEN (t, CR)) ! 88: return DR_LENGTH; ! 89: if (readx (fd, (char *) &t -> t_cr, CR_SIZE (t), readfnx) ! 90: != CR_SIZE (t)) ! 91: return DR_NETWORK; ! 92: ! 93: if (vlen = t -> t_vlen = t -> t_li - TPDU_MINLEN (t, CR)) { ! 94: if ((vptr = t -> t_vdata = malloc ((unsigned) vlen)) == NULL) ! 95: return DR_CONGEST; ! 96: if (readx (fd, t -> t_vdata, t -> t_vlen, readfnx) ! 97: != t -> t_vlen) ! 98: return DR_NETWORK; ! 99: for (; vlen > 0; vptr += len, vlen -= len) { ! 100: int ilen; ! 101: ! 102: if (vlen < 2) ! 103: return DR_LENGTH; ! 104: code = *vptr++ & 0xff; ! 105: len = *vptr++ & 0xff; ! 106: if ((vlen -= 2) < len) ! 107: return DR_LENGTH; ! 108: ! 109: switch (code) { ! 110: case VDAT_TSAP_SRV: ! 111: if ((ilen = len) > sizeof t -> t_called) ! 112: ilen = sizeof t -> t_called; ! 113: bcopy (vptr, t -> t_called, ! 114: t -> t_calledlen = ilen); ! 115: break; ! 116: ! 117: case VDAT_TSAP_CLI: ! 118: if ((ilen = len) > sizeof t -> t_calling) ! 119: ilen = sizeof t -> t_calling; ! 120: bcopy (vptr, t -> t_calling, ! 121: t -> t_callinglen = ilen); ! 122: break; ! 123: ! 124: case VDAT_SIZE: ! 125: if (len != 1) ! 126: return DR_LENGTH; ! 127: t -> t_tpdusize = *vptr & 0xff; ! 128: break; ! 129: ! 130: case VDAT_OPTIONS: ! 131: if (len != 1) ! 132: return DR_LENGTH; ! 133: t -> t_options = *vptr & 0xff; ! 134: break; ! 135: ! 136: case VDAT_ALTERNATE: ! 137: { ! 138: register int i; ! 139: register char *ap; ! 140: ! 141: for (ap = vptr, i = len; i > 0; ap++, i--) ! 142: t -> t_cr.cr_alternate |= ! 143: 1 << ((*ap >> 4) & 0x0f); ! 144: } ! 145: break; ! 146: ! 147: case VDAT_VRSN: ! 148: case VDAT_SECURITY: ! 149: case VDAT_CHECKSUM: ! 150: case VDAT_ACKTIME: ! 151: case VDAT_THROUGHPUT: ! 152: case VDAT_ERRORATE: ! 153: case VDAT_PRIORITY: ! 154: case VDAT_DELAY: ! 155: case VDAT_TTR: ! 156: break; ! 157: ! 158: default: /* IS 8073 says to ignore it on CRs */ ! 159: SLOG (tsap_log, LLOG_EXCEPTIONS, NULLCP, ! 160: ("unknown option 0x%x (length 0x%x) in %s TPDU", ! 161: code, len, ! 162: TPDU_CODE (t) == TPDU_CR ? "CR" : "CC")); ! 163: if (TPDU_CODE (t) == TPDU_CR) ! 164: break; ! 165: return DR_PROTOCOL; ! 166: } ! 167: } ! 168: } ! 169: break; ! 170: ! 171: case TPDU_DR: ! 172: if (t -> t_li < TPDU_MINLEN (t, DR)) ! 173: return DR_LENGTH; ! 174: if (readx (fd, (char *) &t -> t_dr, DR_SIZE (t), readfnx) ! 175: != DR_SIZE (t)) ! 176: return DR_NETWORK; ! 177: ! 178: if (vlen = t -> t_vlen = t -> t_li - TPDU_MINLEN (t, DR)) { ! 179: if ((vptr = t -> t_vdata = malloc ((unsigned) vlen)) == NULL) ! 180: return DR_CONGEST; ! 181: if (readx (fd, t -> t_vdata, t -> t_vlen, readfnx) ! 182: != t -> t_vlen) ! 183: return DR_NETWORK; ! 184: for (; vlen > 0; vptr += len, vlen -= len) { ! 185: if (vlen < 2) ! 186: return DR_LENGTH; ! 187: code = *vptr++ & 0xff; ! 188: len = *vptr++ & 0xff; ! 189: if ((vlen -= 2) < len) ! 190: return DR_LENGTH; ! 191: ! 192: switch (code) { ! 193: case VDAT_ADDITIONAL: ! 194: case VDAT_CHECKSUM: ! 195: break; ! 196: ! 197: default: ! 198: return DR_PROTOCOL; ! 199: } ! 200: } ! 201: } ! 202: break; ! 203: ! 204: case TPDU_DT: ! 205: if (t -> t_li < TPDU_MINLEN (t, DT)) ! 206: return DR_LENGTH; ! 207: if (readx (fd, (char *) &t -> t_dt, DT_SIZE (t), readfnx) ! 208: != DT_SIZE (t)) ! 209: return DR_NETWORK; ! 210: ! 211: if (vlen = t -> t_vlen = t -> t_li - TPDU_MINLEN (t, DT)) { ! 212: if ((vptr = t -> t_vdata = malloc ((unsigned) vlen)) == NULL) ! 213: return DR_CONGEST; ! 214: if (readx (fd, t -> t_vdata, t -> t_vlen, readfnx) ! 215: != t -> t_vlen) ! 216: return DR_NETWORK; ! 217: for (; vlen > 0; vptr += len, vlen -= len) { ! 218: if (vlen < 2) ! 219: return DR_LENGTH; ! 220: code = *vptr++ & 0xff; ! 221: len = *vptr++ & 0xff; ! 222: if ((vlen -= 2) < len) ! 223: return DR_LENGTH; ! 224: ! 225: switch (code) { ! 226: case VDAT_CHECKSUM: ! 227: break; ! 228: ! 229: default: ! 230: return DR_PROTOCOL; ! 231: } ! 232: } ! 233: } ! 234: break; ! 235: ! 236: case TPDU_ED: ! 237: if (t -> t_li < TPDU_MINLEN (t, ED)) ! 238: return DR_LENGTH; ! 239: if (readx (fd, (char *) &t -> t_ed, ED_SIZE (t), readfnx) ! 240: != ED_SIZE (t)) ! 241: return DR_NETWORK; ! 242: t -> t_ed.ed_nr = ntohs (t -> t_ed.ed_nr); ! 243: ! 244: if (vlen = t -> t_vlen = t -> t_li - TPDU_MINLEN (t, ED)) { ! 245: if ((vptr = t -> t_vdata = malloc ((unsigned) vlen)) == NULL) ! 246: return DR_CONGEST; ! 247: if (readx (fd, t -> t_vdata, t -> t_vlen, readfnx) ! 248: != t -> t_vlen) ! 249: return DR_NETWORK; ! 250: ! 251: for (; vlen > 0; vptr += len, vlen -= len) { ! 252: if (vlen < 2) ! 253: return DR_LENGTH; ! 254: code = *vptr++ & 0xff; ! 255: len = *vptr++ & 0xff; ! 256: if ((vlen -= 2) < len) ! 257: return DR_LENGTH; ! 258: ! 259: switch (code) { ! 260: case VDAT_CHECKSUM: ! 261: case VDAT_SUBSEQ: ! 262: case VDAT_FLOWCTL: ! 263: break; ! 264: ! 265: default: ! 266: return DR_PROTOCOL; ! 267: } ! 268: } ! 269: } ! 270: break; ! 271: ! 272: case TPDU_ER: ! 273: if (t -> t_li < TPDU_MINLEN (t, ER)) ! 274: return DR_LENGTH; ! 275: if (readx (fd, (char *) &t -> t_er, ER_SIZE (t), readfnx) ! 276: != ER_SIZE (t)) ! 277: return DR_NETWORK; ! 278: ! 279: if (vlen = t -> t_vlen = t -> t_li - TPDU_MINLEN (t, ER)) { ! 280: if ((vptr = t -> t_vdata = malloc ((unsigned) vlen)) == NULL) ! 281: return DR_CONGEST; ! 282: if (readx (fd, t -> t_vdata, t -> t_vlen, readfnx) ! 283: != t -> t_vlen) ! 284: return DR_NETWORK; ! 285: for (; vlen > 0; vptr += len, vlen -= len) { ! 286: if (vlen < 2) ! 287: return DR_LENGTH; ! 288: code = *vptr++ & 0xff; ! 289: len = *vptr++ & 0xff; ! 290: if ((vlen -= 2) < len) ! 291: return DR_LENGTH; ! 292: ! 293: switch (code) { ! 294: case VDAT_INVALID: ! 295: case VDAT_CHECKSUM: ! 296: break; ! 297: ! 298: default: ! 299: return DR_PROTOCOL; ! 300: } ! 301: } ! 302: } ! 303: break; ! 304: ! 305: default: ! 306: return DR_PROTOCOL; ! 307: } ! 308: ! 309: if (len = TPDU_USRLEN (t)) { ! 310: if ((t -> t_qbuf = (struct qbuf *) ! 311: malloc (sizeof *t -> t_qbuf + (unsigned) len)) ! 312: == NULL) ! 313: return DR_CONGEST; ! 314: t -> t_qbuf -> qb_forw = t -> t_qbuf -> qb_back = t -> t_qbuf; ! 315: if (readx (fd, t -> t_qbuf -> qb_data = t -> t_qbuf -> qb_base, ! 316: t -> t_qbuf -> qb_len = len, readfnx) != len) ! 317: return DR_NETWORK; ! 318: } ! 319: ! 320: return OK; ! 321: } ! 322: ! 323: /* */ ! 324: ! 325: static int readx (fd, buffer, n, readfnx) ! 326: int fd; ! 327: char *buffer; ! 328: int n; ! 329: IFP readfnx; ! 330: { ! 331: register int i, ! 332: cc; ! 333: register char *bp; ! 334: ! 335: for (bp = buffer, i = n; i > 0; bp += cc, i -= cc) { ! 336: switch (cc = (*readfnx) (fd, bp, i)) { ! 337: case NOTOK: ! 338: return (i = bp - buffer) ? i : NOTOK; ! 339: ! 340: case OK: ! 341: break; ! 342: ! 343: default: ! 344: continue; ! 345: } ! 346: break; ! 347: } ! 348: ! 349: return (bp - buffer); ! 350: } ! 351: ! 352: /* */ ! 353: ! 354: int tpkt2fd (tb, t, writefnx) ! 355: register struct tsapblk *tb; ! 356: register struct tsapkt *t; ! 357: IFP writefnx; ! 358: { ! 359: SBV smask; ! 360: int i, ! 361: ilen, ! 362: ulen; ! 363: char *cp, ! 364: *vptr, ! 365: *outptr; ! 366: register struct udvec *uv; ! 367: SFP pstat; ! 368: ! 369: if (t -> t_errno != OK) ! 370: return t -> t_errno; ! 371: ! 372: if (t -> t_vrsn != TPKT_VRSN) ! 373: if (t -> t_vrsn) ! 374: return DR_PROTOCOL; ! 375: else ! 376: t -> t_vrsn = TPKT_VRSN; ! 377: ! 378: if (t -> t_vdata != NULL) { ! 379: free (t -> t_vdata); ! 380: t -> t_vdata = NULL; ! 381: } ! 382: t -> t_vlen = 0; ! 383: ! 384: for (ulen = 0, uv = t -> t_udvec; uv -> uv_base; uv++) ! 385: ulen += uv -> uv_len; ! 386: ! 387: switch (TPDU_CODE (t)) { ! 388: case TPDU_CR: ! 389: case TPDU_CC: ! 390: if ((vptr = t -> t_vdata = ! 391: malloc ((unsigned) (3 + 7 + (2 + t -> t_callinglen) ! 392: + (2 + t -> t_calledlen) + 3))) == NULL) ! 393: return DR_CONGEST; ! 394: if (t -> t_options) { ! 395: *vptr++ = VDAT_OPTIONS; ! 396: *vptr++ = 1; ! 397: *vptr++ = t -> t_options; ! 398: t -> t_vlen += 3; ! 399: } ! 400: if (CR_CLASS (t) != CR_CLASS_TP0 && t -> t_cr.cr_alternate) { ! 401: /* XXX: this doesn't preserve the order of alternates */ ! 402: *vptr++ = VDAT_ALTERNATE; ! 403: cp = vptr++; ! 404: if (t -> t_cr.cr_alternate & ALT_TP0) ! 405: *vptr++ = CR_CLASS_TP0; ! 406: if (t -> t_cr.cr_alternate & ALT_TP1) ! 407: *vptr++ = CR_CLASS_TP1; ! 408: if (t -> t_cr.cr_alternate & ALT_TP2) ! 409: *vptr++ = CR_CLASS_TP2; ! 410: if (t -> t_cr.cr_alternate & ALT_TP3) ! 411: *vptr++ = CR_CLASS_TP3; ! 412: if (t -> t_cr.cr_alternate & ALT_TP4) ! 413: *vptr++ = CR_CLASS_TP4; ! 414: i = (vptr - cp) - 1; ! 415: *cp = i & 0xff; ! 416: t -> t_vlen += (2 + i) & 0xff; ! 417: } ! 418: if (t -> t_callinglen > 0) { ! 419: *vptr++ = VDAT_TSAP_CLI; ! 420: *vptr++ = t -> t_callinglen; ! 421: bcopy (t -> t_calling, vptr, t -> t_callinglen); ! 422: vptr += t -> t_callinglen; ! 423: t -> t_vlen += 2 + t -> t_callinglen; ! 424: } ! 425: if (t -> t_calledlen > 0) { ! 426: *vptr++ = VDAT_TSAP_SRV; ! 427: *vptr++ = t -> t_calledlen; ! 428: bcopy (t -> t_called, vptr, t -> t_calledlen); ! 429: vptr += t -> t_calledlen; ! 430: t -> t_vlen += 2 + t -> t_calledlen; ! 431: } ! 432: if (t -> t_tpdusize) { ! 433: *vptr++ = VDAT_SIZE; ! 434: *vptr++ = 1; ! 435: *vptr++ = t -> t_tpdusize; ! 436: t -> t_vlen += 3; ! 437: } ! 438: if (t -> t_vlen == 0) { ! 439: free (t -> t_vdata); ! 440: t -> t_vdata = NULL; ! 441: } ! 442: t -> t_li = TPDU_MINLEN (t, CR) + t -> t_vlen; ! 443: outptr = (char *) &t -> t_cr; ! 444: ilen = CR_SIZE (t); ! 445: break; ! 446: ! 447: case TPDU_DR: ! 448: t -> t_li = TPDU_MINLEN (t, DR) + t -> t_vlen; ! 449: outptr = (char *) &t -> t_dr; ! 450: ilen = DR_SIZE (t); ! 451: break; ! 452: ! 453: case TPDU_DT: ! 454: t -> t_li = TPDU_MINLEN (t, DT) + t -> t_vlen; ! 455: outptr = (char *) &t -> t_dt; ! 456: ilen = DT_SIZE (t); ! 457: break; ! 458: ! 459: case TPDU_ED: ! 460: t -> t_li = TPDU_MINLEN (t, ED) + t -> t_vlen; ! 461: t -> t_ed.ed_nr = htons (t -> t_ed.ed_nr); ! 462: outptr = (char *) &t -> t_ed; ! 463: ilen = ED_SIZE (t); ! 464: break; ! 465: ! 466: case TPDU_ER: ! 467: t -> t_li = TPDU_MINLEN (t, ER) + t -> t_vlen; ! 468: outptr = (char *) &t -> t_er; ! 469: ilen = ER_SIZE (t); ! 470: if (ulen > 0) ! 471: return DR_PROTOCOL; ! 472: break; ! 473: ! 474: default: ! 475: return DR_PROTOCOL; ! 476: } ! 477: ! 478: t -> t_length = htons (t -> t_li + 5 + ulen); ! 479: ! 480: #ifdef DEBUG ! 481: if (tsap_log -> ll_events & LLOG_PDUS) ! 482: tpkt2text (tsap_log, t, 0); ! 483: #endif ! 484: ! 485: pstat = signal (SIGPIPE, SIG_IGN); ! 486: smask = sigioblock (); ! 487: ! 488: i = (*writefnx) (tb, t, outptr, ilen); ! 489: ! 490: (void) sigiomask (smask); ! 491: (void) signal (SIGPIPE, pstat); ! 492: ! 493: if (i != NOTOK) ! 494: i = OK; ! 495: else ! 496: if (t -> t_errno == DR_UNKNOWN) ! 497: t -> t_errno = DR_NETWORK; ! 498: ! 499: return i; ! 500: } ! 501: ! 502: /* */ ! 503: ! 504: struct tsapkt *newtpkt (code) ! 505: int code; ! 506: { ! 507: register struct tsapkt *t; ! 508: ! 509: t = (struct tsapkt *) calloc (1, sizeof *t); ! 510: if (t == NULL) ! 511: return NULL; ! 512: ! 513: t -> t_vrsn = TPKT_VRSN; ! 514: t -> t_code = code; ! 515: ! 516: return t; ! 517: } ! 518: ! 519: ! 520: int freetpkt (t) ! 521: register struct tsapkt *t; ! 522: { ! 523: if (t == NULL) ! 524: return; ! 525: ! 526: if (t -> t_vdata) ! 527: free (t -> t_vdata); ! 528: ! 529: if (t -> t_qbuf) ! 530: free ((char *) t -> t_qbuf); ! 531: ! 532: free ((char *) t); ! 533: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.