Commit | Line | Data |
---|---|---|
dd8036b5 C |
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 | /* \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 | ||
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 | /* \f */ | |
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 | /* \f 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 | /* \f 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 | /* \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 | ||
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 |