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