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