|
|
1.1 root 1: /* ssapinitiate.c - SPM: initiator */
2:
3: #ifndef lint
4: static char *rcsid = "$Header: /f/osi/ssap/RCS/ssapinitiate.c,v 7.2 90/01/27 10:27:27 mrose Exp $";
5: #endif
6:
7: /*
8: * $Header: /f/osi/ssap/RCS/ssapinitiate.c,v 7.2 90/01/27 10:27:27 mrose Exp $
9: *
10: *
11: * $Log: ssapinitiate.c,v $
12: * Revision 7.2 90/01/27 10:27:27 mrose
13: * touch-up
14: *
15: * Revision 7.1 89/11/27 10:30:40 mrose
16: * sync
17: *
18: * Revision 7.0 89/11/23 22:25:27 mrose
19: * Release 6.0
20: *
21: */
22:
23: /*
24: * NOTICE
25: *
26: * Acquisition, use, and distribution of this module and related
27: * materials are subject to the restrictions of a license agreement.
28: * Consult the Preface in the User's Manual for the full terms of
29: * this agreement.
30: *
31: */
32:
33:
34: /* LINTLIBRARY */
35:
36: #include <stdio.h>
37: #include <signal.h>
38: #include "spkt.h"
39: #include "tailor.h"
40:
41: /* S-(ASYN-)CONNECT.REQUEST */
42:
43: #define dotoken(requires,shift,bit,type) \
44: { \
45: if (requirements & requires) \
46: switch (settings & (ST_MASK << shift)) { \
47: case ST_INIT_VALUE << shift: \
48: case ST_RESP_VALUE << shift: \
49: case ST_CALL_VALUE << shift: \
50: break; \
51: \
52: default: \
53: return ssaplose (si, SC_PARAMETER, NULLCP, \
54: "improper choice of %s token setting", type); \
55: } \
56: }
57:
58: /* */
59:
60: int SAsynConnRequest (ref, calling, called, requirements, settings, isn,
61: data, cc, qos, sc, si, async)
62: struct SSAPref *ref;
63: struct SSAPaddr *calling,
64: *called;
65: int requirements,
66: settings,
67: cc,
68: async;
69: long isn;
70: char *data;
71: struct QOStype *qos;
72: struct SSAPconnect *sc;
73: struct SSAPindication *si;
74: {
75: SBV smask;
76: int result;
77:
78: isodetailor (NULLCP, 0);
79:
80: missingP (ref);
81: refmuchP (ref);
82: if (ref -> sr_vlen)
83: return ssaplose (si, SC_PARAMETER, NULLCP, "bad format for reference");
84: #ifdef notdef
85: missingP (calling);
86: #endif
87: missingP (called);
88:
89: if (requirements & ~SR_MYREQUIRE)
90: return ssaplose (si, SC_PARAMETER, NULLCP,
91: "requirements settings not supported");
92: if ((requirements & SR_EXCEPTIONS)
93: && !(requirements & SR_HALFDUPLEX))
94: return ssaplose (si, SC_PARAMETER, NULLCP,
95: "exception service requires half-duplex service");
96:
97: dotokens ();
98:
99: if (requirements & (SR_MINORSYNC | SR_MAJORSYNC | SR_RESYNC)) {
100: if (!(requirements & SR_ACTIVITY) || isn != SERIAL_NONE)
101: if (SERIAL_MIN > isn || isn > SERIAL_MAX + 1)
102: return ssaplose (si, SC_PARAMETER, NULLCP,
103: "bad choice for initial serial number");
104: }
105: else
106: if (isn != SERIAL_NONE)
107: return ssaplose (si, SC_PARAMETER, NULLCP,
108: "initial serial number invalid given requirements");
109:
110: if (data == NULL)
111: cc = 0;
112: else
113: if (cc > CONNECT_MAX)
114: return ssaplose (si, SC_PARAMETER, NULLCP,
115: "too much initial user data, %d octets", cc);
116:
117: #ifdef notdef
118: missingP (qos);
119: #endif
120: missingP (sc);
121: missingP (si);
122:
123: smask = sigioblock ();
124:
125: result = SConnRequestAux (ref, calling, called, requirements, settings,
126: isn, data, cc, qos, sc, si, async);
127:
128: (void) sigiomask (smask);
129:
130: return result;
131: }
132:
133: #undef dotoken
134:
135: /* */
136:
137: static int SConnRequestAux (ref, calling, called, requirements, settings, isn,
138: data, cc, qos, sc, si, async)
139: struct SSAPref *ref;
140: struct SSAPaddr *calling,
141: *called;
142: int requirements,
143: settings,
144: cc,
145: async;
146: long isn;
147: char *data;
148: struct QOStype *qos;
149: struct SSAPconnect *sc;
150: struct SSAPindication *si;
151: {
152: int result;
153: register struct ssapkt *s;
154: register struct ssapblk *sb;
155: struct TSAPconnect tcs;
156: register struct TSAPconnect *tc = &tcs;
157: struct TSAPdisconnect tds;
158: register struct TSAPdisconnect *td = &tds;
159:
160: if ((sb = newsblk ()) == NULL)
161: return ssaplose (si, SC_CONGEST, NULLCP, "out of memory");
162: if (!async || qos == NULLQOS || qos -> qos_maxtime <= 0)
163: sb -> sb_maxtime = NOTOK;
164: else
165: sb -> sb_maxtime = qos -> qos_maxtime;
166:
167: if ((s = newspkt (SPDU_CN)) == NULL) {
168: (void) ssaplose (si, SC_CONGEST, NULLCP, "out of memory");
169: goto out1;
170: }
171:
172: #ifdef notdef
173: if (called -> sa_selectlen > 0) {
174: if (calling == NULLSA) {
175: static struct SSAPaddr sas;
176:
177: calling = &sas;
178: bzero ((char *) calling, sizeof *calling);
179: }
180:
181: if (calling -> sa_selectlen == 0) {
182: calling -> sa_port =
183: htons ((u_short) (0x8000 | (getpid () & 0x7fff)));
184: calling -> sa_selectlen = sizeof calling -> sa_port;
185: }
186: }
187: #endif
188:
189: if (calling) {
190: if (calling -> sa_selectlen > 0) {
191: s -> s_mask |= SMASK_CN_CALLING;
192: bcopy (calling -> sa_selector, s -> s_calling,
193: s -> s_callinglen = calling -> sa_selectlen);
194: }
195: sb -> sb_initiating = *calling; /* struct copy */
196: }
197:
198: if (called -> sa_selectlen > 0) {
199: s -> s_mask |= SMASK_CN_CALLED;
200: bcopy (called -> sa_selector, s -> s_called,
201: s -> s_calledlen = called -> sa_selectlen);
202: }
203: sb -> sb_responding = *called; /* struct copy */
204:
205: sb -> sb_requirements = requirements;
206: sb -> sb_settings = settings;
207:
208: if ((result = TAsynConnRequest (calling ? &calling -> sa_addr : NULLTA,
209: &called -> sa_addr,
210: (qos ? qos -> qos_extended : 0)
211: || ((requirements & SR_EXPEDITED) ? 1 : 0),
212: NULLCP, 0, qos, tc, td, async)) == NOTOK) {
213: (void) ts2sslose (si, "TAsynConnRequest", td);
214:
215: bzero ((char *) sc, sizeof *sc);
216: sc -> sc_sd = NOTOK;
217: sc -> sc_result = si -> si_abort.sa_reason;
218:
219: result = DONE;
220: goto out2;
221: }
222:
223: sb -> sb_fd = tc -> tc_sd;
224: if (qos && qos -> qos_sversion < 0) {
225: sb -> sb_version = SB_VRSN1;
226: sb -> sb_vrsnmask = SB_ALLVRSNS;
227: }
228: else
229: sb -> sb_vrsnmask = 1 << (sb -> sb_version =
230: (cc > SS_SIZE
231: || (qos && qos -> qos_sversion > 1))
232: ? SB_VRSN2 : SB_VRSN1);
233:
234: s -> s_mask |= SMASK_CN_REF | SMASK_CN_OPT | SMASK_CN_VRSN;
235: s -> s_cn_reference = *ref; /* struct copy */
236: s -> s_options = CR_OPT_NULL;
237: s -> s_cn_version = sb -> sb_vrsnmask;
238:
239: if (isn != SERIAL_NONE) {
240: s -> s_mask |= SMASK_CN_ISN;
241: s -> s_isn = isn;
242: }
243:
244: if (cc > 0) { /* XXX: user musn't touch! */
245: s -> s_mask |= SMASK_UDATA_PGI;
246: s -> s_udata = data, s -> s_ulen = cc;
247: }
248: else
249: s -> s_udata = NULL, s -> s_ulen = 0;
250:
251: sb -> sb_retry = s;
252: if (async) {
253: switch (result) {
254: case CONNECTING_1:
255: case CONNECTING_2:
256: sc -> sc_sd = sb -> sb_fd;
257: return result;
258: }
259: }
260: if ((result = SAsynRetryAux (sb, tc, sc, si)) == DONE && !async)
261: result = OK;
262: return result;
263:
264: out2: ;
265: freespkt (s);
266: out1: ;
267: freesblk (sb);
268:
269: return result;
270: }
271:
272: /* S-ASYN-RETRY.REQUEST (pseudo) */
273:
274: int SAsynRetryRequest (sd, sc, si)
275: int sd;
276: struct SSAPconnect *sc;
277: struct SSAPindication *si;
278: {
279: SBV smask;
280: int result;
281: register struct ssapblk *sb;
282: struct TSAPconnect tcs;
283: register struct TSAPconnect *tc = &tcs;
284: struct TSAPdisconnect tds;
285: register struct TSAPdisconnect *td = &tds;
286:
287: missingP (sc);
288: missingP (si);
289:
290: smask = sigioblock ();
291:
292: if ((sb = findsblk (sd)) == NULL) {
293: (void) sigiomask (smask);
294: return ssaplose (si, SC_PARAMETER, NULLCP,
295: "invalid session descriptor");
296: }
297: if (sb -> sb_flags & SB_CONN) {
298: (void) sigiomask (smask);
299: return ssaplose (si, SC_OPERATION, NULLCP,
300: "session descriptor connected");
301: }
302:
303: switch (result = TAsynRetryRequest (sb -> sb_fd, tc, td)) {
304: case NOTOK:
305: (void) ts2sslose (si, "TAsynRetryRequest", td);
306: sb -> sb_fd = NOTOK;
307:
308: bzero ((char *) sc, sizeof *sc);
309: sc -> sc_sd = NOTOK;
310: sc -> sc_result = si -> si_abort.sa_reason;
311:
312: result = DONE;
313: freesblk (sb);
314: break;
315:
316: case CONNECTING_1:
317: case CONNECTING_2:
318: break;
319:
320: case DONE:
321: result = SAsynRetryAux (sb, tc, sc, si);
322: break;
323: }
324:
325: (void) sigiomask (smask);
326:
327: return result;
328: }
329:
330: /* S-ASYN-NEXT.REQUEST (pseudo) */
331:
332: int SAsynNextRequest (sd, sc, si)
333: int sd;
334: struct SSAPconnect *sc;
335: struct SSAPindication *si;
336: {
337: SBV smask;
338: int result;
339: register struct ssapblk *sb;
340: struct TSAPconnect tcs;
341: register struct TSAPconnect *tc = &tcs;
342: struct TSAPdisconnect tds;
343: register struct TSAPdisconnect *td = &tds;
344:
345: missingP (sc);
346: missingP (si);
347:
348: smask = sigioblock ();
349:
350: if ((sb = findsblk (sd)) == NULL) {
351: (void) sigiomask (smask);
352: return ssaplose (si, SC_PARAMETER, NULLCP,
353: "invalid session descriptor");
354: }
355: if (sb -> sb_flags & SB_CONN) {
356: (void) sigiomask (smask);
357: return ssaplose (si, SC_OPERATION, NULLCP,
358: "session descriptor connected");
359: }
360:
361: switch (result = TAsynNextRequest (sb -> sb_fd, tc, td)) {
362: case NOTOK:
363: (void) ts2sslose (si, "TAsynRetryRequest", td);
364: sb -> sb_fd = NOTOK;
365:
366: bzero ((char *) sc, sizeof *sc);
367: sc -> sc_sd = NOTOK;
368: sc -> sc_result = si -> si_abort.sa_reason;
369:
370: result = DONE;
371: freesblk (sb);
372: break;
373:
374: case CONNECTING_1:
375: case CONNECTING_2:
376: break;
377:
378: case DONE:
379: result = SAsynRetryAux (sb, tc, sc, si);
380: break;
381: }
382:
383: (void) sigiomask (smask);
384:
385: return result;
386: }
387:
388: /* */
389:
390: #define dotoken(requires,shift,bit,type) \
391: { \
392: if (sb -> sb_requirements & requires) { \
393: switch (sb -> sb_settings & (ST_MASK << shift)) { \
394: case ST_CALL_VALUE << shift: \
395: if (!(s -> s_mask & SMASK_CN_SET)) \
396: s -> s_settings = ST_INIT_VALUE << shift; \
397: switch (s -> s_settings & (ST_MASK << shift)) { \
398: case ST_INIT_VALUE << shift: \
399: default: \
400: sb -> sb_owned |= bit; \
401: sc -> sc_settings |= ST_INIT_VALUE << shift; \
402: break; \
403: \
404: case ST_RESP_VALUE << shift: \
405: sc -> sc_settings |= ST_RESP_VALUE << shift; \
406: break; \
407: } \
408: break; \
409: \
410: case ST_INIT_VALUE << shift: \
411: sb -> sb_owned |= bit; \
412: sc -> sc_settings |= ST_INIT_VALUE << shift; \
413: break; \
414: \
415: case ST_RESP_VALUE << shift: \
416: sc -> sc_settings |= ST_RESP_VALUE << shift; \
417: break; \
418: } \
419: \
420: if ((s -> s_mask & SMASK_AC_TOKEN) && (s -> s_ac_token & bit)) \
421: sc -> sc_please |= bit; \
422: } \
423: }
424:
425: /* */
426:
427: static int SAsynRetryAux (sb, tc, sc, si)
428: register struct ssapblk *sb;
429: struct TSAPconnect *tc;
430: struct SSAPconnect *sc;
431: struct SSAPindication *si;
432: {
433: int len,
434: result;
435: register struct ssapkt *s;
436:
437: s = sb -> sb_retry;
438: sb -> sb_retry = NULL;
439:
440: sb -> sb_responding.sa_addr = tc -> tc_responding; /* struct copy */
441: if (tc -> tc_expedited)
442: sb -> sb_flags |= SB_EXPD;
443: else
444: sb -> sb_requirements &= ~SR_EXPEDITED;
445: if (sb -> sb_version < SB_VRSN2) /* XXX */
446: sb -> sb_tsdu_us = sb -> sb_tsdu_them =
447: GET_TSDU_SIZE (tc -> tc_tsdusize);
448:
449: if (sb -> sb_tsdu_us || sb -> sb_tsdu_them) {
450: s -> s_mask |= SMASK_CN_TSDU;
451: s -> s_tsdu_resp = GET_TSDU_SIZE (sb -> sb_tsdu_us);
452: s -> s_tsdu_init = GET_TSDU_SIZE (sb -> sb_tsdu_them);
453: }
454:
455: s -> s_mask |= SMASK_CN_REQ;
456: if ((s -> s_cn_require = sb -> sb_requirements) & SR_TOKENS) {
457: s -> s_mask |= SMASK_CN_SET;
458: s -> s_settings = sb -> sb_settings;
459: }
460:
461: result = spkt2sd (s, sb -> sb_fd, 0, si);
462: s -> s_mask &= ~SMASK_UDATA_PGI;
463: s -> s_udata = NULL, s -> s_ulen = 0;
464:
465: freespkt (s);
466: if (result == NOTOK)
467: goto out1;
468:
469: if ((s = sb2spkt (sb, si, sb -> sb_maxtime, NULLTX)) == NULL) {
470: if (si -> si_abort.sa_reason == SC_TIMER)
471: (void) ssaplose (si, SC_CONGEST, NULLCP, "remote SPM timed-out");
472: result = NOTOK;
473: goto out2;
474: }
475:
476: bzero ((char *) sc, sizeof *sc);
477: switch (s -> s_code) {
478: case SPDU_AC:
479: sc -> sc_sd = sb -> sb_fd;
480: sc -> sc_result = SC_ACCEPT;
481: if (s -> s_mask & SMASK_CN_REF)
482: sc -> sc_connect = s -> s_cn_reference; /* struct copy */
483: if (s -> s_mask & SMASK_CN_OPT)
484: sb -> sb_options = s -> s_options;
485: if (!(s -> s_mask & SMASK_CN_TSDU))
486: s -> s_tsdu_init = s -> s_tsdu_resp = 0;
487: if (s -> s_tsdu_init < sb -> sb_tsdu_us)
488: sb -> sb_tsdu_us = s -> s_tsdu_init;
489: if (s -> s_tsdu_resp < sb -> sb_tsdu_them)
490: sb -> sb_tsdu_them = s -> s_tsdu_resp;
491: if (BAD_TSDU_SIZE (sb -> sb_tsdu_us)) {
492: result = spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
493: "perposterous TSDU size (%d) for initiator",
494: sb -> sb_tsdu_us);
495: goto out2;
496: }
497: if (BAD_TSDU_SIZE (sb -> sb_tsdu_them)) {
498: result = spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
499: "perposterous TSDU size (%d) for responder",
500: sb -> sb_tsdu_them);
501: goto out2;
502: }
503: if (s -> s_mask & SMASK_CN_VRSN) {
504: if (!(s -> s_cn_version & sb -> sb_vrsnmask)) {
505: /* not SC_VERSION */
506: result = spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
507: "version mismatch: expecting something in 0x%x, got 0x%x",
508: sb -> sb_vrsnmask, s -> s_cn_version);
509: goto out2;
510: }
511: sb -> sb_vrsnmask &= s -> s_cn_version;
512: }
513: sb -> sb_version = (sb -> sb_vrsnmask & (1 << SB_VRSN2))
514: ? SB_VRSN2 : SB_VRSN1;
515: if (s -> s_mask & SMASK_CN_ISN)
516: sc -> sc_isn = sb -> sb_V_A = sb -> sb_V_M = s -> s_isn;
517: else
518: sc -> sc_isn = SERIAL_NONE;
519: if (!(s -> s_mask & SMASK_CN_REQ)) {
520: s -> s_mask |= SMASK_CN_REQ;
521: s -> s_cn_require = SR_DEFAULT;
522: }
523: switch (sb -> sb_requirements & (SR_HALFDUPLEX | SR_DUPLEX)) {
524: case SR_HALFDUPLEX:
525: if (s -> s_cn_require & SR_HALFDUPLEX)
526: break;
527: result = spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
528: "half-duplex negotiation failed");
529: goto out2;
530:
531: case SR_DUPLEX:
532: if (s -> s_cn_require & SR_DUPLEX)
533: break;
534: result = spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
535: "full-duplex negotiation failed");
536: goto out2;
537:
538: default:
539: break;
540: }
541: #ifdef notdef /* screwy session protocol... */
542: if (s -> s_cn_require & ~sb -> sb_requirements) {
543: result = spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
544: "requirements negotiation failed");
545: goto out2;
546: }
547: #endif
548: sb -> sb_requirements &= s -> s_cn_require;
549: switch (sb -> sb_requirements & (SR_HALFDUPLEX | SR_DUPLEX)) {
550: case SR_HALFDUPLEX:
551: case SR_DUPLEX:
552: break;
553:
554: default:
555: result = spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
556: "half/full-duplex negotiation failed");
557: goto out2;
558: }
559: if ((sb -> sb_requirements & SR_EXCEPTIONS)
560: && !(sb -> sb_requirements & SR_HALFDUPLEX)) {
561: result = spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
562: "exception service requires half-duplex service");
563: goto out2;
564: }
565: sc -> sc_requirements = sb -> sb_requirements;
566: sc -> sc_settings = sc -> sc_please = 0;
567: dotokens ();
568: if (s -> s_mask & SMASK_CN_CALLED) {
569: if ((len = s -> s_calledlen)
570: > sizeof sb -> sb_responding.sa_selector)
571: len = sizeof sb -> sb_responding.sa_selector;
572: bcopy (s -> s_called, sb -> sb_responding.sa_selector,
573: sb -> sb_responding.sa_selectlen = len);
574: }
575: sc -> sc_responding = sb -> sb_responding; /* struct copy */
576: if ((sc -> sc_ssdusize = sb -> sb_tsdu_us - SSDU_MAGIC) < 0)
577: sc -> sc_ssdusize = tc -> tc_tsdusize - SSDU_MAGIC;
578: sc -> sc_qos = tc -> tc_qos; /* struct copy */
579: sc -> sc_qos.qos_sversion = sb -> sb_version + 1;
580: sc -> sc_qos.qos_extended = (sb -> sb_flags & SB_EXPD) ? 1 : 0;
581: copySPKTdata (s, sc);
582:
583: freespkt (s);
584: sb -> sb_flags |= SB_CONN | SB_INIT;
585:
586: return DONE;
587:
588: case SPDU_RF: /* ignore s -> s_rf_disconnect */
589: sc -> sc_sd = NOTOK;
590: sc -> sc_result = s -> s_rlen > 0 ? *s -> s_rdata
591: : SC_NOTSPECIFIED;
592: if (s -> s_mask & SMASK_RF_REF)
593: sc -> sc_connect = s -> s_rf_reference; /* struct copy */
594: if ((sc -> sc_result == SC_REJECTED)
595: && (s -> s_mask & SMASK_RF_REQ))
596: sc -> sc_requirements = s -> s_rf_require;
597: if ((s -> s_mask & SMASK_CN_CALLED)
598: && (sc -> sc_result & SC_BASE)) {
599: if ((len = s -> s_calledlen)
600: > sizeof sb -> sb_responding.sa_selector)
601: len = sizeof sb -> sb_responding.sa_selector;
602: bcopy (s -> s_called, sb -> sb_responding.sa_selector,
603: sb -> sb_responding.sa_selectlen = len);
604: }
605: sc -> sc_responding = sb -> sb_responding; /* struct copy */
606: sc -> sc_data = s -> s_rdata + 1, sc -> sc_cc = s -> s_rlen - 1;
607: sc -> sc_realdata = s -> s_rdata, s -> s_rdata = NULL;
608: si -> si_type = SI_ABORT;
609: {
610: register struct SSAPabort *sa = &si -> si_abort;
611:
612: sa -> sa_peer = 0;
613: sa -> sa_reason = sc -> sc_result;
614: sa -> sa_info = sc -> sc_data, sa -> sa_cc = sc -> sc_cc;
615: sa -> sa_realinfo = NULL;
616: }
617: result = DONE;
618: break;
619:
620: case SPDU_AB:
621: sc -> sc_sd = NOTOK;
622: sc -> sc_result = SC_ABORT;
623: si -> si_type = SI_ABORT;
624: {
625: register struct SSAPabort *sa = &si -> si_abort;
626:
627: if (!(sa -> sa_peer = (s -> s_ab_disconnect & AB_DISC_USER)
628: ? 1 : 0))
629: sa -> sa_reason = sc -> sc_result;
630: sa -> sa_info = s -> s_udata, sa -> sa_cc = s -> s_ulen;
631: sa -> sa_realinfo = s -> s_udata, s -> s_udata = NULL;
632: }
633: result = DONE;
634: break;
635:
636: default:
637: result = spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
638: "session protocol mangled: expecting 0x%x, got 0x%x",
639: SPDU_AC, s -> s_code);
640: break;
641: }
642:
643: out2: ;
644: freespkt (s);
645: out1: ;
646: freesblk (sb);
647:
648: return result;
649: }
650:
651: #undef dotoken
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.