386BSD 0.1 development
[unix-history] / usr / othersrc / contrib / isode / psap2 / psaprespond.c
CommitLineData
c8cf4f3b
WJ
1/* psaprespond.c - PPM: responder */
2
3#ifndef lint
4static 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
55int PInit (vecp, vec, ps, pi)
56int vecp;
57char **vec;
58struct PSAPstart *ps;
59struct 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
272congest: ;
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
322out1: ;
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);
330out2: ;
331 freepblk (pb);
332
333 return NOTOK;
334}
335
336/* \f P-CONNECT.RESPONSE */
337
338int PConnResponse (sd, status, responding, ctxlist, defctxresult,
339 prequirements, srequirements, isn, settings, ref, data, ndata, pi)
340int sd;
341struct PSAPaddr *responding;
342int status,
343 prequirements,
344 srequirements,
345 settings,
346 ndata;
347long isn;
348struct PSAPctxlist *ctxlist;
349int defctxresult;
350struct SSAPref *ref;
351PE *data;
352struct 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) {
461no_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
751out2: ;
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
788out1: ;
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}