Start development on 386BSD 0.0
[unix-history] / .ref-BSD-4_3_Net_2 / usr / src / contrib / isode / rosap / test / ssapinitiate.c
CommitLineData
dd8036b5
C
1/* ssapinitiate.c - SPM: initiator */
2
3#ifndef lint
4static 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/* \f 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/* \f */
56
57int SAsynConnRequest (ref, calling, called, requirements, settings, isn,
58 data, cc, qos, sc, si, async)
59struct SSAPref *ref;
60struct SSAPaddr *calling,
61 *called;
62int requirements,
63 settings,
64 cc,
65 async;
66long isn;
67char *data;
68struct QOStype *qos;
69struct SSAPconnect *sc;
70struct 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/* \f */
133
134static int SConnRequestAux (ref, calling, called, requirements, settings, isn,
135 data, cc, qos, sc, si, async)
136struct SSAPref *ref;
137struct SSAPaddr *calling,
138 *called;
139int requirements,
140 settings,
141 cc,
142 async;
143long isn;
144char *data;
145struct QOStype *qos;
146struct SSAPconnect *sc;
147struct 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
259out2: ;
260 freespkt (s);
261out1: ;
262 freesblk (sb);
263
264 return result;
265}
266
267/* \f S-ASYN-RETRY.REQUEST (pseudo) */
268
269int SAsynRetryRequest (sd, sc, si)
270int sd;
271struct SSAPconnect *sc;
272struct 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/* \f S-ASYN-NEXT.REQUEST (pseudo) */
326
327int SAsynNextRequest (sd, sc, si)
328int sd;
329struct SSAPconnect *sc;
330struct 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/* \f */
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/* \f */
421
422static int SAsynRetryAux (sb, tc, sc, si)
423register struct ssapblk *sb;
424struct TSAPconnect *tc;
425struct SSAPconnect *sc;
426struct 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
638out2: ;
639 freespkt (s);
640out1: ;
641 freesblk (sb);
642
643 return result;
644}
645
646#undef dotoken