|
|
1.1 root 1: /* psaprovider.c - PPM: implement the pseudo-presentation protocol */
2:
3: #ifndef lint
4: static char *rcsid = "$Header: /f/osi/psap2-lpp/RCS/psaprovider.c,v 7.1 90/07/01 21:05:36 mrose Exp $";
5: #endif
6:
7: /*
8: * $Header: /f/osi/psap2-lpp/RCS/psaprovider.c,v 7.1 90/07/01 21:05:36 mrose Exp $
9: *
10: * Contributed by The Wollongong Group, Inc.
11: *
12: *
13: * $Log: psaprovider.c,v $
14: * Revision 7.1 90/07/01 21:05:36 mrose
15: * pepsy
16: *
17: * Revision 7.0 89/11/23 22:16:00 mrose
18: * Release 6.0
19: *
20: */
21:
22: /*
23: * NOTICE
24: *
25: * Acquisition, use, and distribution of this module and related
26: * materials are subject to the restrictions of a license agreement.
27: * Consult the Preface in the User's Manual for the full terms of
28: * this agreement.
29: *
30: */
31:
32:
33: /* LINTLIBRARY */
34:
35: #include <stdio.h>
36: #include <signal.h>
37: #define LPP
38: #include "PS-types.h"
39: #include "ppkt.h"
40: #include "tailor.h"
41:
42: /* DATA */
43:
44: static int once_only = 0;
45: static struct psapblk psapque;
46: static struct psapblk *PHead = &psapque;
47:
48: /* P-DATA.REQUEST */
49:
50: int PDataRequest (sd, data, ndata, pi)
51: int sd;
52: PE *data;
53: int ndata;
54: struct PSAPindication *pi;
55: {
56: SBV smask;
57: int result;
58: register struct psapblk *pb;
59:
60: if (data == NULL || ndata <= 0 || data[0] == NULLPE || ndata > NPDATA_PS)
61: return psaplose (pi, PC_PARAMETER, NULLCP, "bad user data");
62: if (data[0] -> pe_context != PCI_ROSE)
63: return psaplose (pi, PC_PARAMETER, NULLCP,
64: "wrong context for user data");
65: missingP (pi);
66:
67: smask = sigioblock ();
68:
69: psapPsig (pb, sd);
70:
71: if ((result = PDataRequestAux (pb, data[0], pi)) == NOTOK)
72: freepblk (pb);
73:
74: (void) sigiomask (smask);
75:
76: return result;
77: }
78:
79: /* */
80:
81: static int PDataRequestAux (pb, data, pi)
82: register struct psapblk *pb;
83: PE data;
84: struct PSAPindication *pi;
85: {
86: int result;
87: #ifdef DEBUG
88: char *cp;
89: #endif
90: PE pe;
91: PS ps;
92:
93: pe = NULLPE;
94:
95: if (pb -> pb_reliability == LOW_QUALITY) {
96: struct type_PS_CL__UserData__PDU *pdu;
97:
98: if ((pdu = (struct type_PS_CL__UserData__PDU *) malloc (sizeof *pdu))
99: == NULL)
100: return psaplose (pi, PC_CONGEST, NULLCP, "out of memory");
101:
102: pdu -> reference = pb -> pb_reference;
103: pdu -> user__data = data;
104:
105: result = encode_PS_CL__UserData__PDU (&pe, 1, 0, NULLCP, pdu);
106: #ifdef DEBUG
107: cp = "CL-UserData-PDU";
108: #endif
109:
110: pdu -> reference = NULL;
111: pdu -> user__data = NULLPE;
112: free_PS_CL__UserData__PDU (pdu);
113: }
114: else {
115: result = encode_PS_UserData__PDU (&pe, 1, 0, NULLCP, data);
116: #ifdef DEBUG
117: cp = "UserData-PDU";
118: #endif
119: }
120:
121: if (result != NOTOK) {
122: PLOGP (psap2_log,PS_PDUs, pe, cp, 0);
123:
124: if ((result = pe2ps (ps = pb -> pb_stream, pe)) == NOTOK)
125: (void) pslose (pi, ps -> ps_errno);
126: else
127: result = OK;
128: }
129: else
130: (void) psaplose (pi, PC_CONGEST, NULLCP, "error encoding PDU: %s",
131: PY_pepy);
132:
133: if (pe)
134: pe_free (pe);
135:
136: return result;
137: }
138:
139: /* P-READ.REQUEST (pseudo; synchronous read) */
140:
141: int PReadRequest (sd, px, secs, pi)
142: int sd;
143: struct PSAPdata *px;
144: int secs;
145: struct PSAPindication *pi;
146: {
147: SBV smask;
148: int nfds,
149: result;
150: fd_set mask;
151: register struct psapblk *pb;
152: struct PSAPabort *pa = &pi -> pi_abort;
153:
154: missingP (px);
155: missingP (pi);
156:
157: smask = sigioblock ();
158:
159: psapPsig (pb, sd);
160:
161: FD_ZERO (&mask);
162: FD_SET (pb -> pb_fd, &mask);
163: nfds = pb -> pb_fd + 1;
164:
165: for (;;) {
166: fd_set ifds,
167: efds;
168: register PS ps = pb -> pb_stream;
169:
170: ifds = mask; /* struct copy */
171: efds = mask; /* struct copy */
172:
173: if ((ps -> ps_primeP == NULLIFP || (*ps -> ps_primeP) (ps, 1) == OK)
174: && (*pb -> pb_selectfnx) (nfds, &ifds, NULLFD, &efds, secs)
175: <= OK) {
176: result = psaplose (pi, PC_TIMER, NULLCP, NULLCP);
177: break;
178: }
179:
180: if (FD_ISSET (pb -> pb_fd, &ifds) || FD_ISSET (pb -> pb_fd, & efds))
181: if ((result = PReadRequestAux (pb, px, pi)) != NOTOK
182: || secs != NOTOK
183: || pa -> pa_reason != PC_TIMER)
184: break;
185: }
186:
187: if (result == NOTOK && pa -> pa_reason != PC_TIMER)
188: freepblk (pb);
189:
190: (void) sigiomask (smask);
191:
192: return result;
193: }
194:
195: /* */
196:
197: static int PReadRequestAux (pb, px, pi)
198: register struct psapblk *pb;
199: struct PSAPdata *px;
200: struct PSAPindication *pi;
201: {
202: int result;
203: PE pe;
204: PS ps;
205: struct type_PS_PDUs *pdu;
206: struct type_PS_SessionConnectionIdentifier *pref;
207:
208: if ((pe = ps2pe (ps = pb -> pb_stream)) == NULLPE)
209: return pslose (pi, ps -> ps_errno);
210:
211: pdu = NULL;
212: result = decode_PS_PDUs (pe, 1, NULLIP, NULLVP, &pdu);
213:
214: #ifdef DEBUG
215: if (result == OK && (psap2_log -> ll_events & LLOG_PDUS))
216: pvpdu (psap2_log, print_PS_PDUs_P, pe, "PDU", 1);
217: #endif
218:
219: pe_free (pe);
220:
221: if (result == NOTOK) {
222: if (pb -> pb_reliability == LOW_QUALITY)
223: goto bad_ref2;
224:
225: (void) ppktlose (pb, pi, PC_UNRECOGNIZED, NULLRF, NULLCP,
226: "error decoding PDU: %s", PY_pepy);
227: goto out;
228: }
229:
230: switch (pdu -> offset) {
231: case type_PS_PDUs_releaseRequest:
232: {
233: register struct PSAPfinish *pf = &pi -> pi_finish;
234: register struct type_PS_ReleaseRequest__PDU *rr =
235: pdu -> un.releaseRequest;
236:
237: if (pb -> pb_reliability == LOW_QUALITY
238: && refcmp (pb -> pb_reference, (pref = rr -> reference))) {
239: bad_ref1: ;
240: (void) ppktlose (pb, pi, PC_SESSION, pref, NULLCP,
241: "reference mismatch");
242: bad_ref2: ;
243: if (pdu)
244: free_PS_PDUs (pdu);
245: return psaplose (pi, PC_TIMER, NULLCP, NULLCP);
246: }
247:
248: pe = rr -> user__data, rr -> user__data = NULLPE;
249:
250: pi -> pi_type = PI_FINISH;
251: bzero ((char *) pf, sizeof *pf);
252:
253: (pf -> pf_info[0] = pe) -> pe_context = PCI_ACSE;
254: pf -> pf_ninfo = 1;
255:
256: pb -> pb_flags |= PB_FINN;
257: result = DONE;
258: }
259: break;
260:
261: case type_PS_PDUs_abort:
262: {
263: register struct PSAPabort *pa = &pi -> pi_abort;
264: register struct type_PS_Abort__PDU *ab = pdu -> un.abort;
265:
266: if (pb -> pb_reliability == LOW_QUALITY
267: && refcmp (pb -> pb_reference, (pref = ab -> reference)))
268: goto bad_ref2;
269:
270: if (ab -> reason) {
271: switch (ab -> reason -> parm) {
272: case int_PS_Abort__reason_reason__not__specified:
273: default:
274: result = PC_NOTSPECIFIED;
275: break;
276:
277: case int_PS_Abort__reason_unrecognized__ppdu:
278: case int_PS_Abort__reason_unexpected__ppdu:
279: case int_PS_Abort__reason_unrecognized__ppdu__parameter:
280: result = PC_UNRECOGNIZED
281: + (ab -> reason -> parm
282: - int_PS_Abort__reason_unrecognized__ppdu);
283: break;
284:
285: case int_PS_Abort__reason_invalid__ppdu__parameter:
286: result = PC_INVALID;
287: break;
288:
289: case int_PS_Abort__reason_reference__mismatch:
290: result = PC_SESSION;
291: break;
292: }
293: result = psaplose (pi, result, NULLCP, NULLCP);
294: break;
295: }
296: pe = ab -> user__data, ab -> user__data = NULLPE;
297:
298: pi -> pi_type = PI_ABORT;
299: bzero ((char *) pa, sizeof *pa);
300:
301: pa -> pa_peer = 1;
302: pa -> pa_reason = PC_ABORTED;
303: (pa -> pa_info[0] = pe) -> pe_context = PCI_ACSE;
304: pa -> pa_ninfo = 1;
305:
306: result = NOTOK;
307: }
308: break;
309:
310: case type_PS_PDUs_userData:
311: {
312: if (pb -> pb_reliability == LOW_QUALITY)
313: goto bad_ref2;
314:
315: pe = pdu -> un.userData, pdu -> un.userData = NULLPE;
316:
317: bzero ((char *) px, sizeof *px);
318:
319: px -> px_type = SX_NORMAL;
320: (px -> px_info[0] = pe) -> pe_context = PCI_ROSE;
321: px -> px_ninfo = 1;
322:
323: result = OK;
324: }
325: break;
326:
327: case type_PS_PDUs_cL__userData:
328: {
329: register struct type_PS_CL__UserData__PDU *cl =
330: pdu -> un.cL__userData;
331:
332: if (pb -> pb_reliability == LOW_QUALITY
333: && refcmp (pb -> pb_reference, (pref = cl -> reference)))
334: goto bad_ref1;
335:
336: pe = cl -> user__data, cl -> user__data = NULLPE;
337:
338: bzero ((char *) px, sizeof *px);
339:
340: px -> px_type = SX_NORMAL;
341: (px -> px_info[0] = pe) -> pe_context = PCI_ROSE;
342: px -> px_ninfo = 1;
343:
344: result = OK;
345: }
346: break;
347:
348: case type_PS_PDUs_connectRequest:
349: /* this works 'cause the "reference" is always the FIRST element */
350: result = ppktlose (pb, pi, PC_SESSION,
351: pdu -> un.connectRequest -> reference, NULLCP,
352: "unexpected PDU %d", pdu -> offset);
353: break;
354:
355: default:
356: /* this works 'cause the "reference" is always the FIRST element */
357: result = ppktlose (pb, pi, PC_SESSION,
358: pdu -> un.connectResponse -> reference, NULLCP,
359: "unexpected PDU %d", pdu -> offset);
360: break;
361: }
362:
363: out: ;
364: if (pdu)
365: free_PS_PDUs (pdu);
366:
367: return result;
368: }
369:
370: /* define vectors for INDICATION events */
371:
372: /* ARGSUSED */
373:
374: int PSetIndications (sd, data, tokens, sync, activity, report, finish,
375: abort, pi)
376: int sd;
377: IFP data,
378: tokens,
379: sync,
380: activity,
381: report,
382: finish,
383: abort;
384: struct PSAPindication *pi;
385: {
386: missingP (pi);
387:
388: return psaplose (pi, PC_OPERATION, NULLCP, NULLCP);
389: }
390:
391: /* INTERNAL */
392:
393: struct psapblk *newpblk () {
394: register struct psapblk *pb;
395:
396: pb = (struct psapblk *) calloc (1, sizeof *pb);
397: if (pb == NULL)
398: return NULL;
399:
400: pb -> pb_fd = NOTOK;
401:
402: if (once_only == 0) {
403: PHead -> pb_forw = PHead -> pb_back = PHead;
404: once_only++;
405: }
406:
407: insque (pb, PHead -> pb_back);
408:
409: return pb;
410: }
411:
412:
413: int freepblk (pb)
414: register struct psapblk *pb;
415: {
416: #ifdef notdef
417: register int i;
418: register struct PSAPcontext *qp;
419: #endif
420:
421: if (pb == NULL)
422: return;
423:
424: if (pb -> pb_fd != NOTOK && pb -> pb_closefnx)
425: (void) (*pb -> pb_closefnx) (pb -> pb_fd);
426:
427: if (pb -> pb_retry)
428: pe_free (pb -> pb_retry);
429: if (pb -> pb_response)
430: pe_free (pb -> pb_response);
431: if (pb -> pb_reference)
432: free_PS_SessionConnectionIdentifier (pb -> pb_reference);
433: if (pb -> pb_stream)
434: ps_free (pb -> pb_stream);
435:
436: #ifdef notdef /* don't need this stuff */
437: for (qp = pb -> pb_contexts, i = pb -> pb_ncontexts - 1;
438: i >= 0;
439: qp++, i--) {
440: if (qp -> pc_asn)
441: oid_free (qp -> pc_asn);
442: if (qp -> pc_atn)
443: oid_free (qp -> pc_atn);
444: }
445: if (pb -> pb_asn)
446: oid_free (pb -> pb_asn);
447: if (pb -> pb_atn)
448: oid_free (pb -> pb_atn);
449: #endif
450:
451: if (pb -> pb_ber)
452: oid_free (pb -> pb_ber);
453:
454: remque (pb);
455:
456: free ((char *) pb);
457: }
458:
459: /* */
460:
461: struct psapblk *findpblk (sd)
462: register int sd;
463: {
464: register struct psapblk *pb;
465:
466: if (once_only == 0)
467: return NULL;
468:
469: for (pb = PHead -> pb_forw; pb != PHead; pb = pb -> pb_forw)
470: if (pb -> pb_fd == sd)
471: return pb;
472:
473: return NULL;
474: }
475:
476: /* */
477:
478: int refcmp (ref1, ref2)
479: register struct type_PS_SessionConnectionIdentifier *ref1,
480: *ref2;
481: {
482: if (ref1 == NULLRF)
483: return (ref2 != NULLRF);
484: else
485: if (ref2 == NULLRF)
486: return 1;
487:
488: if (qb_cmp (ref1 -> callingSSUserReference, ref2 -> callingSSUserReference)
489: || qb_cmp (ref1 -> commonReference, ref2 -> commonReference)
490: || qb_cmp (ref1 -> additionalReferenceInformation,
491: ref2 -> additionalReferenceInformation)) {
492: SLOG (psap2_log, LLOG_EXCEPTIONS, NULLCP, ("reference mismatch"));
493:
494: return 1;
495: }
496:
497: return 0;
498: }
499:
500:
501: static int qb_cmp (qb1, qb2)
502: register struct qbuf *qb1,
503: *qb2;
504: {
505: register int i,
506: len1,
507: len2;
508: register char *cp1,
509: *cp2;
510: register struct qbuf *qp1,
511: *qp2;
512:
513: if (qb1 == NULL)
514: return (qb2 != NULL);
515: else
516: if (qb2 == NULL)
517: return 1;
518:
519: for (qp1 = qb1 -> qb_forw; qp1 != qb1; qp1 = qp1 -> qb_forw)
520: if ((len1 = qp1 -> qb_len) > 0)
521: break;
522: cp1 = qp1 -> qb_data;
523:
524: for (qp2 = qb2 -> qb_forw; qp2 != qb2; qp2 = qp2 -> qb_forw)
525: if ((len2 = qp2 -> qb_len) > 0)
526: break;
527: cp2 = qp2 -> qb_data;
528:
529: for (;;) {
530: if (qp1 == qb1)
531: return (qb2 != qb2);
532: else
533: if (qp2 == qb2)
534: return 1;
535:
536: if ((i = len1) > len2)
537: i = len2;
538: if (bcmp (cp1, cp2, i))
539: return 1;
540:
541: if ((len1 -= i) <= 0) {
542: for (qp1 = qp1 -> qb_forw; qp1 != qb1; qp1 = qp1 -> qb_forw)
543: if ((len1 = qp1 -> qb_len) > 0)
544: break;
545: cp1 = qp1 -> qb_data;
546: }
547: else
548: cp1 += i;
549:
550: if ((len2 -= i) <= 0) {
551: for (qp2 = qp2 -> qb_forw; qp2 != qb2; qp2 = qp2 -> qb_forw)
552: if ((len2 = qp2 -> qb_len) > 0)
553: break;
554: cp2 = qp2 -> qb_data;
555: }
556: else
557: cp2 += i;
558: }
559: }
560:
561: /* */
562:
563: struct SSAPref *pdu2ref (ref)
564: register struct type_PS_SessionConnectionIdentifier *ref;
565: {
566: int i;
567: static struct SSAPref sfs;
568: register struct SSAPref *sf = &sfs;
569:
570: pdu2sel (sf -> sr_udata, &i, sizeof sf -> sr_udata,
571: ref -> callingSSUserReference);
572: sf -> sr_ulen = i;
573:
574: pdu2sel (sf -> sr_cdata, &i, sizeof sf -> sr_cdata,
575: ref -> commonReference);
576: sf -> sr_clen = i;
577:
578: pdu2sel (sf -> sr_adata, &i, sizeof sf -> sr_adata,
579: ref -> additionalReferenceInformation);
580: sf -> sr_alen = i;
581:
582: sf -> sr_vlen = 0;
583:
584: return sf;
585: }
586:
587: /* */
588:
589: int pdu2sel (sel, len, i, pb)
590: char *sel;
591: int *len;
592: register int i;
593: register struct qbuf *pb;
594: {
595: register char *cp;
596: register struct qbuf *qb;
597:
598: if (pb == NULL) {
599: *len = 0;
600: return;
601: }
602:
603: cp = sel;
604: for (qb = pb -> qb_forw; qb != pb && i > 0; qb = qb -> qb_forw) {
605: if (qb -> qb_len > i)
606: qb -> qb_len = i;
607: bcopy (qb -> qb_data, cp, qb -> qb_len);
608: cp += qb -> qb_len, i -= qb -> qb_len;
609: }
610:
611: *len = cp - sel;
612: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.