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