Commit | Line | Data |
---|---|---|
c8cf4f3b WJ |
1 | /* psaprespond.c - PPM: responder */ |
2 | ||
3 | #ifndef lint | |
4 | static char *rcsid = "$Header: /f/osi/psap2/RCS/psaprespond.c,v 7.6 91/03/09 11:55:40 mrose Exp $"; | |
5 | #endif | |
6 | ||
7 | /* | |
8 | * $Header: /f/osi/psap2/RCS/psaprespond.c,v 7.6 91/03/09 11:55:40 mrose Exp $ | |
9 | * | |
10 | * | |
11 | * $Log: psaprespond.c,v $ | |
12 | * Revision 7.6 91/03/09 11:55:40 mrose | |
13 | * update | |
14 | * | |
15 | * Revision 7.5 91/02/22 09:37:44 mrose | |
16 | * Interim 6.8 | |
17 | * | |
18 | * Revision 7.4 90/10/23 20:43:51 mrose | |
19 | * update | |
20 | * | |
21 | * Revision 7.3 90/10/17 11:52:49 mrose | |
22 | * sync | |
23 | * | |
24 | * Revision 7.2 90/07/01 21:05:08 mrose | |
25 | * pepsy | |
26 | * | |
27 | * Revision 7.1 89/11/24 16:22:17 mrose | |
28 | * sync | |
29 | * | |
30 | * Revision 7.0 89/11/23 22:14:30 mrose | |
31 | * Release 6.0 | |
32 | * | |
33 | */ | |
34 | ||
35 | /* | |
36 | * NOTICE | |
37 | * | |
38 | * Acquisition, use, and distribution of this module and related | |
39 | * materials are subject to the restrictions of a license agreement. | |
40 | * Consult the Preface in the User's Manual for the full terms of | |
41 | * this agreement. | |
42 | * | |
43 | */ | |
44 | ||
45 | ||
46 | /* LINTLIBRARY */ | |
47 | ||
48 | #include <stdio.h> | |
49 | #include "PS-types.h" | |
50 | #include "ppkt.h" | |
51 | #include "tailor.h" | |
52 | ||
53 | /* \f P-CONNECT.INDICATION */ | |
54 | ||
55 | int PInit (vecp, vec, ps, pi) | |
56 | int vecp; | |
57 | char **vec; | |
58 | struct PSAPstart *ps; | |
59 | struct PSAPindication *pi; | |
60 | { | |
61 | int i, | |
62 | len, | |
63 | result, | |
64 | result2; | |
65 | char *base; | |
66 | register struct psapblk *pb; | |
67 | PE pe = NULLPE; | |
68 | struct SSAPref ref; | |
69 | struct SSAPstart sss; | |
70 | register struct SSAPstart *ss = &sss; | |
71 | struct SSAPindication sis; | |
72 | register struct SSAPindication *si = &sis; | |
73 | register struct SSAPabort *sa = &si -> si_abort; | |
74 | struct type_PS_CP__type *cp; | |
75 | register struct element_PS_0 *cp_normal; | |
76 | register struct type_PS_CPR__type *cpr; | |
77 | ||
78 | isodetailor (NULLCP, 0); | |
79 | ||
80 | missingP (vec); | |
81 | missingP (ps); | |
82 | missingP (pi); | |
83 | ||
84 | if ((pb = newpblk ()) == NULL) | |
85 | return psaplose (pi, PC_CONGEST, NULLCP, "out of memory"); | |
86 | ||
87 | cp = NULL, cpr = NULL; | |
88 | ||
89 | if (SInit (vecp, vec, ss, si) == NOTOK) { | |
90 | (void) ss2pslose (pb, pi, "SInit", sa); | |
91 | goto out2; | |
92 | } | |
93 | ||
94 | pb -> pb_fd = ss -> ss_sd; | |
95 | ||
96 | if ((pe = ssdu2pe (ss -> ss_data, ss -> ss_cc, NULLCP, &result)) | |
97 | == NULLPE) { | |
98 | if (result == PS_ERR_NMEM) | |
99 | goto congest; | |
100 | ||
101 | (void) ppktlose (pb, pi, PC_PROTOCOL, PPDU_CP, NULLCP, "%s", | |
102 | ps_error (result)); | |
103 | goto out1; | |
104 | } | |
105 | ||
106 | SSFREE (ss); | |
107 | ||
108 | pb -> pb_srequirements = ss -> ss_requirements; | |
109 | ||
110 | pb -> pb_ssdusize = ss -> ss_ssdusize; | |
111 | ||
112 | bzero ((char *) ps, sizeof *ps); | |
113 | ||
114 | if (decode_PS_CP__type (pe, 1, NULLIP, NULLVP, &cp) == NOTOK) { | |
115 | (void) ppktlose (pb, pi, PC_UNRECOGNIZED, PPDU_CP, NULLCP, "%s", | |
116 | PY_pepy); | |
117 | goto out1; | |
118 | } | |
119 | ||
120 | PLOGP (psap2_log,PS_CP__type, pe, "CP-type", 1); | |
121 | ||
122 | if (cp -> mode -> parm != int_PS_Mode__selector_normal__mode) { | |
123 | (void) ppktlose (pb, pi, PC_INVALID, PPDU_CP, NULLCP, | |
124 | "X.410-mode not supported"); | |
125 | goto out1; | |
126 | } | |
127 | cp_normal = cp -> normal__mode; | |
128 | ||
129 | ps -> ps_sd = pb -> pb_fd; | |
130 | ||
131 | ps -> ps_connect = ss -> ss_connect; /* struct copy */ | |
132 | ||
133 | ps -> ps_calling.pa_addr = ss -> ss_calling;/* struct copy */ | |
134 | if (cp_normal -> calling) { | |
135 | if ((base = qb2str (cp_normal -> calling)) == NULLCP) | |
136 | goto congest; | |
137 | if ((len = cp_normal -> calling -> qb_len) > | |
138 | sizeof ps -> ps_calling.pa_selector) | |
139 | len = sizeof ps -> ps_calling.pa_selector; | |
140 | bcopy (base, ps -> ps_calling.pa_selector, | |
141 | ps -> ps_calling.pa_selectlen = len); | |
142 | free (base); | |
143 | } | |
144 | ps -> ps_called.pa_addr = ss -> ss_called; /* struct copy */ | |
145 | if (cp_normal -> called) { | |
146 | if ((base = qb2str (cp_normal -> called)) == NULLCP) | |
147 | goto congest; | |
148 | if ((len = cp_normal -> called -> qb_len) > | |
149 | sizeof ps -> ps_called.pa_selector) | |
150 | len = sizeof ps -> ps_called.pa_selector; | |
151 | bcopy (base, ps -> ps_called.pa_selector, | |
152 | ps -> ps_called.pa_selectlen = len); | |
153 | free (base); | |
154 | } | |
155 | ||
156 | if ((pb -> pb_asn = ode2oid (DFLT_ASN)) == NULLOID) { | |
157 | (void) ppktlose (pb, pi, PC_ABSTRACT, PPDU_CP, NULLCP, "%s: unknown", | |
158 | DFLT_ASN); | |
159 | goto out1; | |
160 | } | |
161 | if ((pb -> pb_asn = oid_cpy (pb -> pb_asn)) == NULLOID) | |
162 | goto congest; | |
163 | if ((pb -> pb_atn = ode2oid (DFLT_ATN)) == NULLOID) { | |
164 | (void) ppktlose (pb, pi, PC_TRANSFER, PPDU_CP, NULLCP, "%s: unknown", | |
165 | DFLT_ATN); | |
166 | goto out1; | |
167 | } | |
168 | if ((pb -> pb_atn = oid_cpy (pb -> pb_atn)) == NULLOID) | |
169 | goto congest; | |
170 | if ((pb -> pb_ber = oid_cpy (pb -> pb_atn)) == NULLOID) | |
171 | goto congest; | |
172 | ||
173 | { | |
174 | register struct PSAPcontext *pp, | |
175 | *qp; | |
176 | register struct type_PS_Definition__list *lp; | |
177 | ||
178 | i = 0; | |
179 | for (lp = cp_normal -> context__list, | |
180 | pp = ps -> ps_ctxlist.pc_ctx, | |
181 | qp = pb -> pb_contexts; | |
182 | lp; | |
183 | lp = lp -> next, pp++, qp++, i++) { | |
184 | register struct element_PS_6 *pctx = lp -> element_PS_5; | |
185 | register struct element_PS_7 *atn; | |
186 | ||
187 | pp -> pc_id = qp -> pc_id = pctx -> identifier; | |
188 | ||
189 | pp -> pc_result = PC_ACCEPT; | |
190 | pp -> pc_asn = pctx -> abstract__syntax; | |
191 | pctx -> abstract__syntax = NULLOID; | |
192 | if ((qp -> pc_asn = oid_cpy (pp -> pc_asn)) == NULLOID) | |
193 | goto congest; | |
194 | ||
195 | for (atn = pctx -> transfer__syntax__list; atn; atn = atn -> next) | |
196 | if (atn_is_ok (pb, atn -> Transfer__syntax__name)) { | |
197 | qp -> pc_atn = atn -> Transfer__syntax__name; | |
198 | atn -> Transfer__syntax__name = NULLOID; | |
199 | break; | |
200 | } | |
201 | if (atn == NULL) | |
202 | pp -> pc_result = PC_TRANSFER; | |
203 | pp -> pc_atn = NULLOID; | |
204 | ||
205 | qp -> pc_result = pp -> pc_result; | |
206 | } | |
207 | ||
208 | ps -> ps_ctxlist.pc_nctx = pb -> pb_ncontext = i; | |
209 | } | |
210 | ||
211 | if (ppdu2info (pb, pi, cp_normal -> user__data, ps -> ps_info, | |
212 | &ps -> ps_ninfo, PPDU_CP) == NOTOK) | |
213 | goto out1; | |
214 | ||
215 | ps -> ps_defctxresult = PC_ACCEPT; | |
216 | if (cp_normal -> default__context) { | |
217 | oid_free (pb -> pb_asn); | |
218 | pb -> pb_asn = cp_normal -> default__context -> abstract__syntax; | |
219 | cp_normal -> default__context -> abstract__syntax = NULLOID; | |
220 | if ((ps -> ps_defctx = oid_cpy (pb -> pb_asn)) == NULLOID) | |
221 | goto congest; | |
222 | ||
223 | oid_free (pb -> pb_atn); | |
224 | pb -> pb_atn = cp_normal -> default__context -> transfer__syntax; | |
225 | cp_normal -> default__context -> transfer__syntax = NULLOID; | |
226 | if (!atn_is_ok (pb, pb -> pb_atn)) | |
227 | ps -> ps_defctxresult = PC_TRANSFER; | |
228 | ||
229 | pb -> pb_flags |= PB_DFLT; | |
230 | } | |
231 | pb -> pb_result = ps -> ps_defctxresult; | |
232 | ||
233 | if (cp_normal -> presentation__fu) { | |
234 | register struct pair *pp; | |
235 | ||
236 | if (!(pb -> pb_srequirements & SR_TYPEDATA)) { | |
237 | (void) bit_off (cp_normal -> presentation__fu, | |
238 | bit_PS_Presentation__requirements_context__management); | |
239 | (void) bit_off (cp_normal -> presentation__fu, | |
240 | bit_PS_Presentation__requirements_restoration); | |
241 | } | |
242 | ||
243 | for (pp = preq_pairs; pp -> p_mask; pp++) | |
244 | if (bit_test (cp_normal -> presentation__fu, pp -> p_bitno) == 1) | |
245 | pb -> pb_prequirements |= pp -> p_mask; | |
246 | } | |
247 | ps -> ps_prequirements = (pb -> pb_prequirements &= PR_MYREQUIRE); | |
248 | ||
249 | if (cp_normal -> session__fu) { | |
250 | register struct pair *pp; | |
251 | ||
252 | for (pp = sreq_pairs; pp -> p_mask; pp++) | |
253 | if (bit_test (cp_normal -> session__fu, pp -> p_bitno) == 1) | |
254 | pb -> pb_urequirements |= pp -> p_mask; | |
255 | } | |
256 | else | |
257 | pb -> pb_urequirements = pb -> pb_srequirements; | |
258 | ps -> ps_srequirements = (pb -> pb_urequirements & pb -> pb_srequirements); | |
259 | ||
260 | ps -> ps_settings = ss -> ss_settings; | |
261 | ps -> ps_isn = ss -> ss_isn; | |
262 | ||
263 | ps -> ps_ssdusize = ss -> ss_ssdusize; | |
264 | ||
265 | ps -> ps_qos = ss -> ss_qos; /* struct copy */ | |
266 | ||
267 | pe_free (pe); | |
268 | free_PS_CP__type (cp); | |
269 | ||
270 | return OK; | |
271 | ||
272 | congest: ; | |
273 | result = SC_CONGESTION; | |
274 | (void) psaplose (pi, result2 = PC_CONGEST, NULLCP, NULLCP); | |
275 | ||
276 | if (pe) { | |
277 | pe_free (pe); | |
278 | pe = NULLPE; | |
279 | } | |
280 | ||
281 | if (cpr = (struct type_PS_CPR__type *) calloc (1, sizeof *cpr)) { | |
282 | if (cp | |
283 | && cp -> mode | |
284 | && cp -> mode -> parm == | |
285 | int_PS_Mode__selector_x410__1984__mode) { | |
286 | cpr -> offset = type_PS_CPR__type_x410__mode; | |
287 | if (pe = pe_alloc (PE_CLASS_UNIV, PE_FORM_CONS, PE_CONS_SET)) { | |
288 | cpr -> un.x410__mode = pe; | |
289 | (void) set_add (pe, num2prim ((integer) (result2 != PC_CONGEST ? 0 : 3), | |
290 | PE_CLASS_CONT, 0)); | |
291 | } | |
292 | } | |
293 | else { | |
294 | register struct element_PS_2 *cpr_normal; | |
295 | ||
296 | cpr -> offset = type_PS_CPR__type_normal__mode; | |
297 | if (cpr_normal = (struct element_PS_2 *) | |
298 | calloc (1, sizeof *cpr_normal)) { | |
299 | cpr -> un.normal__mode = cpr_normal; | |
300 | cpr_normal -> optionals |= opt_PS_element_PS_2_reason; | |
301 | cpr_normal -> reason = result2 - PC_PROV_BASE; | |
302 | } | |
303 | } | |
304 | } | |
305 | ||
306 | if (encode_PS_CPR__type (&pe, 1, 0, NULLCP, cpr) != NOTOK) { | |
307 | PLOGP (psap2_log,PS_CPR__type, pe, "CPR-type", 0); | |
308 | ||
309 | if (pe) | |
310 | (void) pe2ssdu (pe, &base, &len); | |
311 | } | |
312 | else | |
313 | base = NULL, len = 0; | |
314 | ||
315 | bzero ((char *) &ref, sizeof ref); | |
316 | (void) SConnResponse (ss -> ss_sd, &ref, NULLSA, result, 0, 0, | |
317 | SERIAL_NONE, base, len, si); | |
318 | if (base) | |
319 | free (base); | |
320 | (void) psaplose (pi, result2, NULLCP, NULLCP); | |
321 | ||
322 | out1: ; | |
323 | SSFREE (ss); | |
324 | if (pe) | |
325 | pe_free (pe); | |
326 | if (cp) | |
327 | free_PS_CP__type (cp); | |
328 | if (cpr) | |
329 | free_PS_CPR__type (cpr); | |
330 | out2: ; | |
331 | freepblk (pb); | |
332 | ||
333 | return NOTOK; | |
334 | } | |
335 | ||
336 | /* \f P-CONNECT.RESPONSE */ | |
337 | ||
338 | int PConnResponse (sd, status, responding, ctxlist, defctxresult, | |
339 | prequirements, srequirements, isn, settings, ref, data, ndata, pi) | |
340 | int sd; | |
341 | struct PSAPaddr *responding; | |
342 | int status, | |
343 | prequirements, | |
344 | srequirements, | |
345 | settings, | |
346 | ndata; | |
347 | long isn; | |
348 | struct PSAPctxlist *ctxlist; | |
349 | int defctxresult; | |
350 | struct SSAPref *ref; | |
351 | PE *data; | |
352 | struct PSAPindication *pi; | |
353 | { | |
354 | int i, | |
355 | len, | |
356 | result, | |
357 | result2; | |
358 | char *base; | |
359 | PE pe; | |
360 | register struct psapblk *pb; | |
361 | struct SSAPindication sis; | |
362 | register struct SSAPindication *si = &sis; | |
363 | register struct SSAPabort *sa = &si -> si_abort; | |
364 | struct type_PS_CPA__type *cpa; | |
365 | register struct element_PS_1 *cpa_normal; | |
366 | struct type_PS_CPR__type *cpr; | |
367 | register struct element_PS_2 *cpr_normal; | |
368 | ||
369 | if ((pb = findpblk (sd)) == NULL || (pb -> pb_flags & PB_CONN)) | |
370 | return psaplose (pi, PC_PARAMETER, NULLCP, | |
371 | "invalid presentation descriptor"); | |
372 | #ifdef notdef | |
373 | missingP (responding); | |
374 | #endif | |
375 | switch (status) { | |
376 | case PC_ACCEPT: | |
377 | case PC_REJECTED: | |
378 | break; | |
379 | ||
380 | default: | |
381 | return psaplose (pi, PC_PARAMETER, NULLCP, | |
382 | "bad value for status parameter"); | |
383 | } | |
384 | ||
385 | if (ctxlist) { | |
386 | register struct PSAPcontext *pp, | |
387 | *qp; | |
388 | ||
389 | if (ctxlist -> pc_nctx != pb -> pb_ncontext) | |
390 | return psaplose (pi, PC_PARAMETER, NULLCP, | |
391 | "proposed/resulting presentation contexts mismatch"); | |
392 | ||
393 | i = pb -> pb_ncontext - 1; | |
394 | for (pp = ctxlist -> pc_ctx, qp = pb -> pb_contexts; | |
395 | i >= 0; | |
396 | i--, pp++, qp++) { | |
397 | if (pp -> pc_id != qp -> pc_id) | |
398 | return psaplose (pi, PC_PARAMETER, NULLCP, | |
399 | "bad context id %d at offset %d (wanted %d)", | |
400 | pp -> pc_id, pp - ctxlist -> pc_ctx, qp -> pc_id); | |
401 | switch (pp -> pc_result) { | |
402 | case PC_ACCEPT: | |
403 | case PC_REJECTED: | |
404 | if (qp -> pc_result != PC_ACCEPT) | |
405 | return psaplose (pi, PC_PARAMETER, NULLCP, | |
406 | "invalid result %d for context id %d", | |
407 | pp -> pc_result, pp -> pc_id); | |
408 | qp -> pc_result = pp -> pc_result; | |
409 | break; | |
410 | ||
411 | default: | |
412 | if (qp -> pc_result != pp -> pc_result) | |
413 | return psaplose (pi, PC_PARAMETER, NULLCP, | |
414 | "invalid result %d for context id %d", | |
415 | pp -> pc_result, pp -> pc_id); | |
416 | break; | |
417 | } | |
418 | } | |
419 | } | |
420 | ||
421 | switch (defctxresult) { | |
422 | case PC_ACCEPT: | |
423 | case PC_REJECTED: | |
424 | if (pb -> pb_result != PC_ACCEPT) | |
425 | return psaplose (pi, PC_PARAMETER, NULLCP, | |
426 | "invalid result %d for default context name", | |
427 | defctxresult); | |
428 | if ((pb -> pb_result = defctxresult) == PC_REJECTED | |
429 | && status != PC_REJECTED) | |
430 | return psaplose (pi, PC_PARAMETER, NULLCP, | |
431 | "default context rejected implies connection rejected"); | |
432 | break; | |
433 | ||
434 | default: | |
435 | if (pb -> pb_result != defctxresult) | |
436 | return psaplose (pi, PC_PARAMETER, NULLCP, | |
437 | "invalid result %d for default context name", | |
438 | defctxresult); | |
439 | break; | |
440 | } | |
441 | if (prequirements & ~pb -> pb_prequirements) | |
442 | return psaplose (pi, PC_PARAMETER, NULLCP, | |
443 | "presentation requirements not available"); | |
444 | if (srequirements & ~pb -> pb_urequirements) | |
445 | return psaplose (pi, PC_PARAMETER, NULLCP, | |
446 | "session requirements not available"); | |
447 | ||
448 | /* let session provider catch errors in remainder of session parameters */ | |
449 | ||
450 | toomuchP (data, ndata, NPDATA, "initial"); | |
451 | missingP (pi); | |
452 | ||
453 | base = NULLCP; | |
454 | pe = NULLPE; | |
455 | cpa = NULL, cpr = NULL; | |
456 | ||
457 | switch (status) { | |
458 | case PC_ACCEPT: | |
459 | if ((cpa = (struct type_PS_CPA__type *) calloc (1, sizeof *cpa)) | |
460 | == NULL) { | |
461 | no_mem: ; | |
462 | (void) psaplose (pi, PC_CONGEST, NULLCP, "out of memory"); | |
463 | goto out2; | |
464 | } | |
465 | if ((cpa -> mode = (struct type_PS_Mode__selector *) | |
466 | malloc (sizeof *cpa -> mode)) == NULL) | |
467 | goto no_mem; | |
468 | cpa -> mode -> parm = int_PS_Mode__selector_normal__mode; | |
469 | if ((cpa_normal = (struct element_PS_1 *) | |
470 | calloc (1, sizeof *cpa_normal)) == NULL) | |
471 | goto no_mem; | |
472 | cpa -> normal__mode = cpa_normal; | |
473 | break; | |
474 | ||
475 | case PC_REJECTED: | |
476 | if ((cpr = (struct type_PS_CPR__type *) calloc (1, sizeof *cpr)) | |
477 | == NULL) | |
478 | goto no_mem; | |
479 | cpr -> offset = type_PS_CPR__type_normal__mode; | |
480 | if ((cpr_normal = (struct element_PS_2 *) | |
481 | calloc (1, sizeof *cpr_normal)) == NULL) | |
482 | goto no_mem; | |
483 | cpr -> un.normal__mode = cpr_normal; | |
484 | break; | |
485 | } | |
486 | ||
487 | { | |
488 | register struct qbuf *qb = NULL; | |
489 | ||
490 | if (responding | |
491 | && responding -> pa_selectlen > 0 | |
492 | && (qb = str2qb (responding -> pa_selector, | |
493 | responding -> pa_selectlen, 1)) == NULL) | |
494 | goto no_mem; | |
495 | ||
496 | if (status == PC_ACCEPT) | |
497 | cpa_normal -> responding = qb; | |
498 | else | |
499 | cpr_normal -> responding = qb; | |
500 | } | |
501 | ||
502 | if (pb -> pb_ncontext > 0) { | |
503 | register struct PSAPcontext *qp; | |
504 | register struct type_PS_Definition__result__list *cd, | |
505 | **cp; | |
506 | ||
507 | if (status == PC_ACCEPT) | |
508 | cp = &cpa_normal -> context__list; | |
509 | else | |
510 | cp = &cpr_normal -> context__list; | |
511 | ||
512 | i = pb -> pb_ncontext - 1; | |
513 | for (qp = pb -> pb_contexts; i >= 0; i--, qp++) { | |
514 | switch (qp -> pc_result) { | |
515 | case PC_ACCEPT: | |
516 | result = int_PS_result_acceptance; | |
517 | break; | |
518 | ||
519 | case PC_REJECTED: | |
520 | result = int_PS_result_user__rejection; | |
521 | break; | |
522 | ||
523 | case PC_ABSTRACT: | |
524 | result = int_PS_result_provider__rejection; | |
525 | result2 = int_PS_provider__reason_abstract__syntax__not__supported; | |
526 | break; | |
527 | ||
528 | case PC_TRANSFER: | |
529 | result = int_PS_result_provider__rejection; | |
530 | result2 = int_PS_provider__reason_proposed__transfer__syntaxes__not__supported; | |
531 | break; | |
532 | ||
533 | case PC_CONGEST: | |
534 | result = int_PS_result_provider__rejection; | |
535 | result2 = int_PS_provider__reason_local__limit__on__DCS__exceeded; | |
536 | break; | |
537 | ||
538 | case PC_NOTSPECIFIED: | |
539 | default: | |
540 | result = int_PS_result_provider__rejection; | |
541 | result2 = int_PS_provider__reason_reason__not__specified; | |
542 | break; | |
543 | } | |
544 | ||
545 | if ((cd = (struct type_PS_Definition__result__list *) | |
546 | calloc (1, sizeof *cd)) == NULL) | |
547 | goto no_mem; | |
548 | *cp = cd; | |
549 | cp = &cd -> next; | |
550 | if ((cd -> element_PS_12 = (struct element_PS_13 *) | |
551 | calloc (1, sizeof (struct element_PS_13))) == NULL) | |
552 | goto no_mem; | |
553 | cd -> element_PS_12 -> result = result; | |
554 | switch (qp -> pc_result) { | |
555 | case PC_ACCEPT: | |
556 | if ((cd -> element_PS_12 -> transfer__syntax = | |
557 | oid_cpy (qp -> pc_atn)) == NULLOID) | |
558 | goto no_mem; | |
559 | break; | |
560 | ||
561 | case PC_REJECTED: | |
562 | break; | |
563 | ||
564 | default: | |
565 | cd -> element_PS_12 -> optionals |= | |
566 | opt_PS_element_PS_13_provider__reason; | |
567 | cd -> element_PS_12 -> provider__reason = result2; | |
568 | break; | |
569 | } | |
570 | } | |
571 | ||
572 | i = pb -> pb_ncontext - 1; | |
573 | for (qp = pb -> pb_contexts + i; i >= 0; i--, qp--) | |
574 | if (qp -> pc_result != PC_ACCEPT) { | |
575 | register struct PSAPcontext *qqp; | |
576 | ||
577 | qqp = pb -> pb_contexts + --pb -> pb_ncontext; | |
578 | if (qp -> pc_asn) { | |
579 | oid_free (qp -> pc_asn); | |
580 | qp -> pc_asn = NULLOID; | |
581 | } | |
582 | if (qp -> pc_atn) { | |
583 | oid_free (qp -> pc_atn); | |
584 | qp -> pc_atn = NULLOID; | |
585 | } | |
586 | if (qp != qqp) | |
587 | *qp = *qqp; /* struct copy */ | |
588 | } | |
589 | } | |
590 | ||
591 | pb -> pb_srequirements &= srequirements; | |
592 | if (pb -> pb_prequirements & PR_MANAGEMENT) | |
593 | pb -> pb_srequirements |= SR_TYPEDATA; | |
594 | if (status == PC_ACCEPT) { | |
595 | if ((pb -> pb_prequirements &= prequirements) != PR_MYREQUIRE) { | |
596 | register struct pair *pp; | |
597 | ||
598 | if ((cpa_normal -> presentation__fu = | |
599 | prim2bit (pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, | |
600 | PE_PRIM_BITS))) == NULL) | |
601 | goto no_mem; | |
602 | ||
603 | for (pp = preq_pairs; pp -> p_mask; pp++) | |
604 | if ((pb -> pb_prequirements & pp -> p_mask) | |
605 | && bit_on (cpa_normal -> presentation__fu, pp -> p_bitno) | |
606 | == NOTOK) | |
607 | goto no_mem; | |
608 | ||
609 | if (bit2prim (cpa_normal -> presentation__fu) == NULLPE) | |
610 | goto no_mem; | |
611 | } | |
612 | ||
613 | if ((pb -> pb_urequirements &= srequirements) | |
614 | != pb -> pb_srequirements) { | |
615 | register struct pair *pp; | |
616 | ||
617 | if ((cpa_normal -> session__fu = prim2bit (pe_alloc (PE_CLASS_UNIV, | |
618 | PE_FORM_PRIM, | |
619 | PE_PRIM_BITS))) | |
620 | == NULL) | |
621 | goto no_mem; | |
622 | ||
623 | for (pp = sreq_pairs; pp -> p_mask; pp++) | |
624 | if ((pb -> pb_urequirements & pp -> p_mask) | |
625 | && bit_on (cpa_normal -> session__fu, pp -> p_bitno) | |
626 | == NOTOK) | |
627 | goto no_mem; | |
628 | ||
629 | if (bit2prim (cpa_normal -> session__fu) == NULLPE) | |
630 | goto no_mem; | |
631 | } | |
632 | ||
633 | status = SC_ACCEPT; | |
634 | } | |
635 | else { | |
636 | if (pb -> pb_flags & PB_DFLT) { | |
637 | if ((cpr_normal -> default__context = | |
638 | (struct type_PS_Context__result *) | |
639 | malloc (sizeof *cpr_normal -> default__context)) | |
640 | == NULL) | |
641 | goto no_mem; | |
642 | switch (defctxresult) { | |
643 | case PC_ACCEPT: | |
644 | default: | |
645 | result = int_PS_Result_acceptance; | |
646 | break; | |
647 | ||
648 | case PC_REJECTED: | |
649 | result = int_PS_Result_user__rejection; | |
650 | break; | |
651 | ||
652 | case PC_NOTSPECIFIED: | |
653 | result = int_PS_Result_provider__rejection; | |
654 | break; | |
655 | } | |
656 | cpr_normal -> default__context -> parm = result; | |
657 | } | |
658 | ||
659 | status = SC_REJECTED; | |
660 | } | |
661 | ||
662 | if (data && ndata > 0) { | |
663 | struct type_PS_User__data *info; | |
664 | ||
665 | if ((info = info2ppdu (pb, pi, data, ndata, status == SC_ACCEPT | |
666 | ? PPDU_CPA : PPDU_CPR)) == NULL) | |
667 | goto out2; | |
668 | ||
669 | if (status == SC_ACCEPT) | |
670 | cpa_normal -> user__data = info; | |
671 | else | |
672 | cpr_normal -> user__data = info; | |
673 | } | |
674 | ||
675 | if (status == SC_ACCEPT) { | |
676 | result = encode_PS_CPA__type (&pe, 1, 0, NULLCP, cpa); | |
677 | ||
678 | #ifdef DEBUG | |
679 | if (result == OK && (psap2_log -> ll_events & LLOG_PDUS)) | |
680 | pvpdu (psap2_log, print_PS_CPA__type_P, pe, "CPA-type", 0); | |
681 | #endif | |
682 | } | |
683 | else { | |
684 | result = encode_PS_CPR__type (&pe, 1, 0, NULLCP, cpr); | |
685 | ||
686 | #ifdef DEBUG | |
687 | if (result == OK && (psap2_log -> ll_events & LLOG_PDUS)) | |
688 | pvpdu (psap2_log, print_PS_CPR__type_P, pe, "CPR-type", 0); | |
689 | #endif | |
690 | } | |
691 | ||
692 | if (result == NOTOK) { | |
693 | (void) psaplose (pi, PC_CONGEST, NULLCP, "error encoding PDU: %s", | |
694 | PY_pepy); | |
695 | goto out2; | |
696 | } | |
697 | ||
698 | if (pe2ssdu (pe, &base, &len) == NOTOK) | |
699 | goto no_mem; | |
700 | ||
701 | if (status == SC_ACCEPT) { | |
702 | free_PS_CPA__type (cpa); | |
703 | cpa = NULL; | |
704 | } | |
705 | else { | |
706 | free_PS_CPR__type (cpr); | |
707 | cpr = NULL; | |
708 | } | |
709 | ||
710 | pe_free (pe); | |
711 | pe = NULL; | |
712 | ||
713 | if (SConnResponse (pb -> pb_fd, ref, responding ? &responding -> pa_addr | |
714 | : NULLSA, status, pb -> pb_srequirements, settings, isn, base, | |
715 | len, si) == NOTOK) | |
716 | if (SC_FATAL (sa -> sa_reason)) { | |
717 | (void) ss2pslose (pb, pi, "SConnResponse", sa); | |
718 | goto out2; | |
719 | } | |
720 | else { /* assume SS-user parameter error */ | |
721 | result = ss2pslose (NULLPB, pi, "SConnResponse", sa); | |
722 | goto out1; | |
723 | } | |
724 | ||
725 | if (status == SC_ACCEPT) { | |
726 | pb -> pb_flags |= PB_CONN; | |
727 | #define dotoken(requires,shift,bit,type) \ | |
728 | { \ | |
729 | if (pb -> pb_srequirements & requires) \ | |
730 | switch (settings & (ST_MASK << shift)) { \ | |
731 | case ST_INIT_VALUE << shift: \ | |
732 | pb -> pb_owned |= bit; \ | |
733 | pb -> pb_avail |= bit; \ | |
734 | break; \ | |
735 | \ | |
736 | case ST_RESP_VALUE << shift: \ | |
737 | pb -> pb_avail |= bit; \ | |
738 | break; \ | |
739 | } \ | |
740 | } | |
741 | dotokens (); | |
742 | #undef dotoken | |
743 | } | |
744 | else { | |
745 | pb -> pb_fd = NOTOK; | |
746 | freepblk (pb); | |
747 | } | |
748 | result = OK; | |
749 | goto out1; | |
750 | ||
751 | out2: ; | |
752 | result = NOTOK; | |
753 | if (cpr) { | |
754 | free_PS_CPR__type (cpr); | |
755 | cpr = NULL; | |
756 | } | |
757 | ||
758 | if (cpr = (struct type_PS_CPR__type *) calloc (1, sizeof *cpr)) { | |
759 | cpr -> offset = type_PS_CPR__type_normal__mode; | |
760 | if (cpr_normal = (struct element_PS_2 *) | |
761 | calloc (1, sizeof *cpr_normal)) { | |
762 | cpr -> un.normal__mode = cpr_normal; | |
763 | cpr_normal -> optionals |= opt_PS_element_PS_2_reason; | |
764 | cpr_normal -> reason = int_PS_reason_temporary__congestion; | |
765 | } | |
766 | } | |
767 | ||
768 | if (encode_PS_CPR__type (&pe, 1, 0, NULLCP, cpr) != NOTOK) { | |
769 | PLOGP (psap2_log,PS_CPR__type, pe, "CPR-type", 0); | |
770 | ||
771 | if (pe) | |
772 | (void) pe2ssdu (pe, &base, &len); | |
773 | } | |
774 | else | |
775 | base = NULL, len = 0; | |
776 | ||
777 | (void) SConnResponse (pb -> pb_fd, ref, NULLSA, result, 0, 0, | |
778 | SERIAL_NONE, base, len, si); | |
779 | ||
780 | if (base) | |
781 | free (base); | |
782 | (void) pe2ssdu (pe, &base, &len); | |
783 | (void) SConnResponse (pb -> pb_fd, ref, NULLSA, SC_CONGESTION, 0, 0, | |
784 | SERIAL_NONE, base, len, si); | |
785 | ||
786 | freepblk (pb); | |
787 | ||
788 | out1: ; | |
789 | if (base) | |
790 | free (base); | |
791 | ||
792 | if (pe) | |
793 | pe_free (pe); | |
794 | if (cpa) | |
795 | free_PS_CPA__type (cpa); | |
796 | if (cpr) | |
797 | free_PS_CPR__type (cpr); | |
798 | ||
799 | return result; | |
800 | } |