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