|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T p
Length: 14409 (0x3849) Types: TextFile Names: »psapinitiate.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0 └─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z« └─⟦de7628f85⟧ └─⟦this⟧ »isode-6.0/psap2-lpp/psapinitiate.c«
/* psapinitiate.c - PPM: initiator */ #ifndef lint static char *rcsid = "$Header: /f/osi/psap2-lpp/RCS/psapinitiate.c,v 7.1 89/12/01 10:51:43 mrose Exp $"; #endif /* * $Header: /f/osi/psap2-lpp/RCS/psapinitiate.c,v 7.1 89/12/01 10:51:43 mrose Exp $ * * Contributed by The Wollongong Group, Inc. * * * $Log: psapinitiate.c,v $ * Revision 7.1 89/12/01 10:51:43 mrose * touch-up * * Revision 7.0 89/11/23 22:15:53 mrose * Release 6.0 * */ /* * NOTICE * * Acquisition, use, and distribution of this module and related * materials are subject to the restrictions of a license agreement. * Consult the Preface in the User's Manual for the full terms of * this agreement. * */ /* LINTLIBRARY */ #include <stdio.h> #include <signal.h> #define LPP #include "PS-types.h" #include "ppkt.h" #include "tailor.h" /* \f P-(ASYN-)CONNECT.REQUEST */ #ifndef notdef /* ARGSUSED */ #endif int PAsynConnRequest (calling, called, ctxlist, defctxname, prequirements, srequirements, isn, settings, ref, data, ndata, qos, pc, pi, async) struct PSAPaddr *calling, *called; int prequirements, srequirements, settings, ndata, async; long isn; struct PSAPctxlist *ctxlist; OID defctxname; struct SSAPref *ref; PE *data; struct QOStype *qos; struct PSAPconnect *pc; struct PSAPindication *pi; { SBV smask; int result; isodetailor (NULLCP, 0); #ifdef notdef missingP (calling); #endif missingP (called); if (ctxlist == NULL || ctxlist -> pc_nctx != NPCTX_PS) return psaplose (pi, PC_PARAMETER, NULLCP, "exactly %d proposed presentation contexts supported", NPCTX_PS); #ifdef notdef if (defctxname) return psaplose (pi, PC_PARAMETER, NULLCP, "default context name not allowed"); #endif if (prequirements != PR_KERNEL) return psaplose (pi, PC_PARAMETER, NULLCP, "presentation requirements settings not supported"); if (srequirements != SR_DUPLEX) return psaplose (pi, PC_PARAMETER, NULLCP, "session requirements settings not supported"); if (isn != SERIAL_NONE) return psaplose (pi, PC_PARAMETER, NULLCP, "initial serial number not permitted"); if (settings != 0) /* not really an accurate test... */ return psaplose (pi, PC_PARAMETER, NULLCP, "initial token settings not permitted"); missingP (ref); if (ref -> sr_ulen > SREF_USER_SIZE || ref -> sr_ulen <= 2 || ref -> sr_clen > SREF_COMM_SIZE || ref -> sr_clen <= 2 || ref -> sr_alen > SREF_ADDT_SIZE || ref -> sr_alen == 1 || ref -> sr_vlen > 0) return psaplose (pi, PC_PARAMETER, NULLCP, "bad format for reference"); if (data == NULL || ndata <= 0 || data[0] == NULLPE || ndata > NPDATA_PS) return psaplose (pi, PC_PARAMETER, NULLCP, "bad initial user data"); if (data[0] -> pe_context != PCI_ACSE) return psaplose (pi, PC_PARAMETER, NULLCP, "wrong context for initial user data"); missingP (pc); missingP (pi); smask = sigioblock (); result = PConnRequestAux (calling, called, ctxlist, ref, data[0], qos, pc, pi, async); (void) sigiomask (smask); return result; } /* \f */ static int PConnRequestAux (calling, called, ctxlist, ref, data, qos, pc, pi, async) struct PSAPaddr *calling, *called; struct PSAPctxlist *ctxlist; struct SSAPref *ref; PE data; struct QOStype *qos; struct PSAPconnect *pc; struct PSAPindication *pi; int async; { int result; OID asn; register struct psapblk *pb; register struct type_PS_ConnectRequest__PDU *pdu; register struct type_PS_SessionConnectionIdentifier *pref; if ((pb = newpblk ()) == NULL) return psaplose (pi, PC_CONGEST, NULLCP, "out of memory"); if ((pref = (struct type_PS_SessionConnectionIdentifier *) malloc (sizeof *pref)) == NULL) { (void) psaplose (pi, PC_CONGEST, NULLCP, "out of memory"); goto out1; } pb -> pb_reference = pref; pdu = NULL; if ((pref -> callingSSUserReference = str2qb (ref -> sr_udata + 2, (int) ref -> sr_ulen - 2, 1)) == NULL || (pref -> commonReference = str2qb (ref -> sr_cdata + 2, (int) ref -> sr_clen - 2, 1)) == NULL) { no_mem: ; (void) psaplose (pi, PC_CONGEST, NULLCP, "out of memory"); goto out2; } if (ref -> sr_alen > 0) { if ((pref -> additionalReferenceInformation = str2qb (ref -> sr_adata + 2, (int) ref -> sr_alen - 2, 1)) == NULL) goto no_mem; } else pref -> additionalReferenceInformation = NULL; if ((pb -> pb_ber = ode2oid (DFLT_ATN)) == NULLOID) { (void) psaplose (pi, PC_ABSTRACT, NULLCP, "%s: unknown", DFLT_ATN); goto out2; } if ((pb -> pb_ber = oid_cpy (pb -> pb_ber)) == NULLOID) goto no_mem; asn = NULLOID; { register int i; register struct PSAPcontext *pp, *qp; i = ctxlist -> pc_nctx - 1; for (pp = ctxlist -> pc_ctx, qp = pb -> pb_contexts; i >= 0; i--, pp++, qp++) { switch (qp -> pc_id = pp -> pc_id) { case PCI_ROSE: asn = pp -> pc_asn; /* and fall */ case PCI_ACSE: break; default: (void) psaplose (pi, PC_PARAMETER, NULLCP, "illegal value for PCI (%d)", pp -> pc_id); goto out2; } if (pp -> pc_asn == NULLOID) { (void) psaplose (pi, PC_PARAMETER, NULLCP, "no abstract syntax name given for context %d", pp -> pc_id); goto out2; } if (pp -> pc_atn && !atn_is_ok (pb, pp -> pc_atn)) { (void) psaplose (pi, PC_TRANSFER, NULLCP, "unknown transfer syntax given for context %d", pp -> pc_id); goto out2; } qp -> pc_result = PC_ACCEPT; pb -> pb_ncontext++; } } if (asn == NULLOID) { (void) psaplose (pi, PC_PARAMETER, NULLCP, "PCI for SASE not present"); goto out2; } if ((pdu = (struct type_PS_ConnectRequest__PDU *) malloc (sizeof *pdu)) == NULL) goto no_mem; pdu -> version = int_PS_version_version__1; pdu -> reference = pref; if (calling && calling -> pa_selectlen > 0) { if ((pdu -> calling = str2qb (calling -> pa_selector, calling -> pa_selectlen, 1)) == NULL) goto no_mem; } else pdu -> calling = NULL; if (called -> pa_selectlen > 0) { if ((pdu -> called = str2qb (called -> pa_selector, called -> pa_selectlen, 1)) == NULL) goto no_mem; } else pdu -> called = NULL; if ((pdu -> asn = oid_cpy (asn)) == NULLOID) goto no_mem; pdu -> user__data = data; pb -> pb_retry = NULLPE; result = encode_PS_ConnectRequest__PDU (&pb -> pb_retry, 1, 0, NULLCP, pdu); pdu -> reference = NULL; pdu -> user__data = NULLPE; free_PS_ConnectRequest__PDU (pdu); pdu = NULL; if (result == NOTOK) { (void) psaplose (pi, PC_CONGEST, NULLCP, "error encoding PDU: %s", PY_pepy); goto out1; } if ((result = PConnRequestAux2 (pb, calling ? &calling -> pa_addr.sa_addr : NULLTA, &called -> pa_addr.sa_addr, qos, pi, async)) == NOTOK) goto out1; if (async && result == OK) { pc -> pc_sd = pb -> pb_fd; return result; } if ((result = PAsynRetryAux (pb, pc, pi)) == DONE && !async) result = OK; return result; out2: ; if (pdu) { pdu -> reference = NULL; pdu -> user__data = NULLPE; free_PS_ConnectRequest__PDU (pdu); } out1: ; freepblk (pb); return NOTOK; } /* \f */ #define QOS_RELIABLE_DFLT HIGH_QUALITY int tcpopen (), udpopen (); static struct nsapent { int ns_reliability; int ns_tset; IFP ns_open; } nsaps[] = { HIGH_QUALITY, NA_TSET_TCP, tcpopen, LOW_QUALITY, NA_TSET_UDP, udpopen, NULL }; static int PConnRequestAux2 (pb, calling, called, qos, pi, async) struct psapblk *pb; struct TSAPaddr *calling, *called; struct QOStype *qos; struct PSAPindication *pi; int async; { int reliability, result; register int n = called -> ta_naddr - 1; register struct NSAPaddr *na = called -> ta_addrs; reliability = qos ? qos -> qos_reliability : QOS_RELIABLE_DFLT; for (; n >= 0; na++, n--) { register int l; register struct NSAPaddr *la; register struct nsapent *ns; if (na -> na_type != NA_TCP) continue; if (na -> na_tset == 0) na -> na_tset = NA_TSET_TCP; for (ns = nsaps; ns -> ns_open; ns++) if (ns -> ns_reliability == reliability && (ns -> ns_tset & na -> na_tset)) break; if (!ns -> ns_open) continue; if (calling) { for (l = calling -> ta_naddr - 1, la = calling -> ta_addrs; l >= 0; la++, l--) { if (la -> na_type != NA_TCP) continue; if (ns -> ns_tset & la -> na_tset) break; } if (l < 0) la = NULLNA; } else la = NULLNA; if ((result = (*ns -> ns_open) (pb, la, na, pi, async)) != NOTOK) break; } { register struct TSAPaddr *ta = &pb -> pb_responding.pa_addr.sa_addr; ta -> ta_addrs[0] = *na; /* struct copy */ ta -> ta_naddr = 1; } return (pb -> pb_fd != NOTOK ? result : NOTOK); } /* \f P-ASYN-RETRY.REQUEST (pseudo) */ int PAsynRetryRequest (sd, pc, pi) int sd; struct PSAPconnect *pc; struct PSAPindication *pi; { SBV smask; int result; register struct psapblk *pb; missingP (pc); missingP (pi); smask = sigioblock (); if ((pb = findpblk (sd)) == NULL) { (void) sigiomask (smask); return psaplose (pi, PC_PARAMETER, NULLCP, "invalid presentation descriptor"); } if (pb -> pb_flags & PB_CONN) { (void) sigiomask (smask); return psaplose (pi, PC_OPERATION, NULLCP, "presentation descriptor connected"); } switch (result = (*pb -> pb_retryfnx) (pb, pi)) { case NOTOK: pb -> pb_fd = NOTOK; freepblk (pb); break; case OK: break; case DONE: result = PAsynRetryAux (pb, pc, pi); break; } (void) sigiomask (smask); return result; } /* \f */ static int PAsynRetryAux (pb, pc, pi) register struct psapblk *pb; struct PSAPconnect *pc; struct PSAPindication *pi; { int result; PE pe; struct type_PS_PDUs *pdu; pdu = NULL; result = decode_PS_PDUs (pb -> pb_response, 1, NULLIP, NULLVP, &pdu); #ifdef DEBUG if (result == OK && (psap2_log -> ll_events & LLOG_PDUS)) vpdu (psap2_log, print_PS_PDUs, pb -> pb_response, "PDU", 1); #endif if (pb -> pb_retry) { pe_free (pb -> pb_retry); pb -> pb_retry = NULLPE; } pe_free (pb -> pb_response); pb -> pb_response = NULL; if (result == NOTOK) { (void) ppktlose (pb, pi, PC_UNRECOGNIZED, NULLRF, NULLCP, "error decoding PDU: %s", PY_pepy); goto out; } bzero ((char *) pc, sizeof *pc); switch (pdu -> offset) { case type_PS_PDUs_connectResponse: { register struct type_PS_ConnectResponse__PDU *cr = pdu -> un.connectResponse; if (pb -> pb_reliability == LOW_QUALITY && refcmp (pb -> pb_reference, cr -> reference)) { result = ppktlose (pb, pi, PC_SESSION, cr -> reference, NULLCP, "reference mismatch"); goto out; } if (cr -> reason == NULL) { pb -> pb_flags |= PB_CONN; pc -> pc_sd = pb -> pb_fd; pc -> pc_result = PC_ACCEPT; pc -> pc_qos.qos_reliability = pb -> pb_reliability; pc -> pc_qos.qos_sversion = 2; } else { pc -> pc_sd = NOTOK; pc -> pc_result = cr -> reason -> parm; } pdu2sel (pb -> pb_responding.pa_selector, &pb -> pb_responding.pa_selectlen, sizeof pb -> pb_responding.pa_selector, cr -> responding); pc -> pc_responding = pb -> pb_responding; /* struct copy */ pc -> pc_defctxresult = pb -> pb_result = PC_ACCEPT; { register int i; register struct PSAPcontext *pp, *qp; i = pb -> pb_ncontext; for (pp = pb -> pb_contexts, qp = pc -> pc_ctxlist.pc_ctx; i >= 0; i--, pp++, qp++) { qp -> pc_id = pp -> pc_id; qp -> pc_asn = qp -> pc_atn = NULLOID; qp -> pc_result = PC_ACCEPT; } pc -> pc_ctxlist.pc_nctx = pb -> pb_ncontext; } pc -> pc_prequirements = PR_KERNEL; pc -> pc_srequirements = SR_DUPLEX; pc -> pc_isn = SERIAL_NONE; pc -> pc_connect = *pdu2ref (pb -> pb_reference); /* struct copy */ pe = cr -> user__data, cr -> user__data = NULLPE; if (pc -> pc_info[0] = pe) { pe -> pe_context = PCI_ACSE; pc -> pc_ninfo = 1; } free_PS_PDUs (pdu); return DONE; } case type_PS_PDUs_abort: { register struct PSAPabort *pa = &pi -> pi_abort; register struct type_PS_Abort__PDU *ab = pdu -> un.abort; if (pb -> pb_reliability == LOW_QUALITY && refcmp (pb -> pb_reference, ab -> reference)) { result = psaplose (pi, PC_SESSION, NULLCP, "reference mismatch"); goto out; } if (ab -> reason) { switch (ab -> reason -> parm) { case int_PS_Abort__reason_reason__not__specified: default: result = PC_NOTSPECIFIED; break; case int_PS_Abort__reason_unrecognized__ppdu: case int_PS_Abort__reason_unexpected__ppdu: case int_PS_Abort__reason_unrecognized__ppdu__parameter: result = PC_UNRECOGNIZED + (ab -> reason -> parm - int_PS_Abort__reason_unrecognized__ppdu); break; case int_PS_Abort__reason_invalid__ppdu__parameter: result = PC_INVALID; break; case int_PS_Abort__reason_reference__mismatch: result = PC_SESSION; break; } result = psaplose (pi, result, NULLCP, NULLCP); goto out; } pe = ab -> user__data, ab -> user__data = NULLPE; pi -> pi_type = PI_ABORT; bzero ((char *) pa, sizeof *pa); pa -> pa_peer = 1; pa -> pa_reason = PC_ABORTED; if (pa -> pa_info[0] = pe) { pe -> pe_context = PCI_ACSE; pa -> pa_ninfo = 1; } pc -> pc_sd = NOTOK; pc -> pc_result = PC_ABORTED; result = DONE; } break; default: /* this works 'cause the "reference" is always the FIRST element */ result = ppktlose (pb, pi, PC_SESSION, pdu -> un.connectResponse -> reference, NULLCP, "unexpected PDU %d", pdu -> offset); break; } out: ; if (pdu) free_PS_PDUs (pdu); freepblk (pb); return result; } /* \f P-ASYN-NEXT.REQUEST (pseudo) */ /* ARGSUSED */ int PAsynNextRequest (sd, pc, pi) int sd; struct PSAPconnect *pc; struct PSAPindication *pi; { return psaplose (pi, PC_OPERATION, NULLCP, "operation not supported with lightweight presentation"); }