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