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