Net2/usr/src/contrib/isode/rosap/rosapapdu.c

Compare this file to the similar file:
Show the results in this format:

/* rosapapdu.c - ROPM: interpret APDU */

#ifndef	lint
static char *rcsid = "$Header: /f/osi/rosap/RCS/rosapapdu.c,v 7.4 91/02/22 09:41:27 mrose Interim $";
#endif

/* 
 * $Header: /f/osi/rosap/RCS/rosapapdu.c,v 7.4 91/02/22 09:41:27 mrose Interim $
 *
 * Based on an TCP-based implementation by George Michaelson of University
 * College London.
 *
 *
 * $Log:	rosapapdu.c,v $
 * Revision 7.4  91/02/22  09:41:27  mrose
 * Interim 6.8
 * 
 * Revision 7.3  90/11/05  13:33:11  mrose
 * update
 * 
 * Revision 7.2  90/10/17  11:56:04  mrose
 * sync
 * 
 * Revision 7.1  90/07/01  21:05:58  mrose
 * pepsy
 * 
 * Revision 6.0  89/03/18  23:42:22  mrose
 * Release 5.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>
#include "ROS-types.h"
#include "ropkt.h"
#ifdef	DEBUG
#include "tailor.h"
#endif


int	prob2num ();

/*  */

int	acb2osdu (acb, invokeID, pe, roi)
register struct assocblk  *acb;
int   *invokeID;
PE	pe;
register struct RoSAPindication *roi;
{
    struct type_ROS_ROSEapdus *papdu;
    struct type_ROS_OPDU	*popdu;
    int rosap_type;
    int	result;

    rosap_type = APDU_UNKNOWN;
    if (((acb -> acb_flags & ACB_ACS)
		? decode_ROS_ROSEapdus (pe, 1, NULLIP, NULLVP, &papdu)
		: decode_ROS_OPDU (pe, 1, NULLIP, NULLVP, &popdu))
	    == NOTOK) {
	(void) rosapreject (acb, roi, rosap_type != APDU_UNKNOWN
					    ? ROS_GP_MISTYPED
					    : ROS_GP_UNRECOG,
			    NULLCP, "%s", PY_pepy);
	pe_free (pe);

	return NOTOK;
    }

#ifdef	DEBUG
    if (rosap_log -> ll_events & LLOG_PDUS)
	if (acb -> acb_flags & ACB_ACS)
	    pvpdu (rosap_log, print_ROS_ROSEapdus_P, pe, "ROSEapdus", 1);
	else
	    pvpdu (rosap_log, print_ROS_OPDU_P, pe, "OPDU", 1);
#endif

    if ((acb -> acb_flags & ACB_ACS)) {
	result = apdu_proc (acb -> acb_fd, papdu, &pe, roi, acb, invokeID);
	if (papdu)
	    free_ROS_ROSEapdus (papdu);
    }
    else {
	result = opdu_proc (acb -> acb_fd, popdu, &pe, roi, acb, invokeID);
	if (popdu)
	    free_ROS_OPDU (popdu);
    }

    if (pe)
	pe_free (pe);

    return result;
}

/*  */

/*
 * Process an APDU. This seperates out all the differences between
 * the two cases. Copy all the fields of the structure into the appropriate
 * RoSAPindication structure
 */

static int  apdu_proc (sd, papdu, pe, roi, acb, invokeID)
int	sd;
struct type_ROS_ROSEapdus *papdu;
PE     *pe;
register struct RoSAPindication *roi;
register struct assocblk  *acb;
int   *invokeID;
{
    int	    rosap_id;

    bzero ((char *) roi, sizeof *roi);
    switch (papdu -> offset) {
	case type_ROS_ROSEapdus_roiv__apdu: 
	    roi -> roi_type = ROI_INVOKE;
	    {
		register struct RoSAPinvoke *rox = &roi -> roi_invoke;
		register struct type_ROS_ROIVapdu *piv = papdu->un.roiv__apdu;

		rosap_id = rox -> rox_id = piv -> invokeID -> parm;
		if (!(rox -> rox_nolinked =
		          !(piv -> optionals & opt_ROS_ROIVapdu_linked__ID)))
		    rox -> rox_linkid = piv -> linked__ID;
		rox -> rox_op = piv->operation__value -> parm;
		rox -> rox_args = pe_expunge (*pe, piv -> argument);
		*pe = NULLPE;
	    }
	    break;

	case type_ROS_ROSEapdus_rors__apdu: 
	    roi -> roi_type = ROI_RESULT;
	    {
		register struct RoSAPresult *ror = &roi -> roi_result;
		register struct type_ROS_RORSapdu *pres = papdu->un.rors__apdu;

		rosap_id = ror -> ror_id = pres -> invokeID -> parm;
		if (pres -> element_ROS_0) {
		    ror -> ror_op = pres -> element_ROS_0 -> operation__value -> parm;
		    ror -> ror_result =
			    pe_expunge (*pe, pres -> element_ROS_0 -> result);
		    *pe = NULLPE;
		}
	    }
	    break;

	case type_ROS_ROSEapdus_roer__apdu: 
	    roi -> roi_type = ROI_ERROR;
	    {
		register struct RoSAPerror *roe = &roi -> roi_error;
		register struct type_ROS_ROERapdu *perr = papdu->un.roer__apdu;

		rosap_id = roe -> roe_id = perr -> invokeID-> parm;
		roe -> roe_error = perr -> error__value -> parm;
		roe -> roe_param = pe_expunge (*pe, perr -> parameter);
		*pe = NULLPE;
	    }
	    break;

	case type_ROS_ROSEapdus_rorj__apdu: 
	    roi -> roi_type = ROI_UREJECT;
	    {
		register struct RoSAPureject   *rou = &roi -> roi_ureject;
		register struct type_ROS_RORJapdu   *prej = papdu->un.rorj__apdu;

		if (prej -> invokeID -> offset == choice_ROS_0_2)
		    rou -> rou_noid = 1;
		else {
		    rosap_id = rou -> rou_id =
			prej -> invokeID -> un.choice_ROS_1 -> parm;
		    rou -> rou_noid = 0;
		}

		rou -> rou_reason = prob2num (prej -> problem);
	    }
	    break;
    }

    if (invokeID
	    && (papdu -> offset == type_ROS_ROSEapdus_roiv__apdu
		    || (papdu -> offset == type_ROS_ROSEapdus_rorj__apdu
			    && papdu -> un.rorj__apdu -> invokeID -> offset
				    == choice_ROS_0_2)
		    || *invokeID != rosap_id)
	    && acb -> acb_rosindication) {
	(*acb -> acb_rosindication) (sd = acb -> acb_fd, roi);

	if (findacblk (sd) != acb)/* still not perfect! */
	    return rosaplose (roi, ROS_DONE, NULLCP, NULLCP);
	return OK;
    }

    return DONE;
}

/*  */

/*
 * Process an OPDU. A seperate function is used for this type of PDU to
 * simpilfy matters. What is an OPDU - an Old PDU ??
 */

static int  opdu_proc (sd, popdu, pe, roi, acb, invokeID)
int	sd;
struct type_ROS_OPDU *popdu;
PE	*pe;
register struct RoSAPindication *roi;
register struct assocblk  *acb;
int   *invokeID;
{
    int	rosap_id;

    bzero ((char *) roi, sizeof *roi);
    switch (popdu -> offset) {
	case type_ROS_OPDU_1: 
	    roi -> roi_type = ROI_INVOKE;
	    {
		register struct RoSAPinvoke *rox = &roi -> roi_invoke;
		register struct type_ROS_Invoke *piv = popdu->un.choice_ROS_8;

		rosap_id = rox -> rox_id = piv -> invokeID;
		rox -> rox_op = piv -> element_ROS_2 -> parm;
		rox -> rox_args = pe_expunge (*pe, piv -> argument);
		*pe = NULLPE;
	    }
	    break;

	case type_ROS_OPDU_2: 
	    roi -> roi_type = ROI_RESULT;
	    {
		register struct RoSAPresult *ror = &roi -> roi_result;
		register struct type_ROS_ReturnResult *piv
				= popdu -> un.choice_ROS_9;

		rosap_id = ror -> ror_id = piv -> invokeID -> parm;
		ror -> ror_result = pe_expunge (*pe, piv -> result);
		*pe = NULLPE;
	    }
	    break;

	case type_ROS_OPDU_3: 
	    roi -> roi_type = ROI_ERROR;
	    {
		register struct RoSAPerror *roe = &roi -> roi_error;
		register struct type_ROS_ReturnError *per
				= popdu -> un.choice_ROS_10;

		rosap_id = roe -> roe_id = per -> invokeID;;
		roe -> roe_error = per -> element_ROS_3 -> parm;
		roe -> roe_param = pe_expunge (*pe, per -> parameter);
		*pe = NULLPE;
	    }
	    break;

	case type_ROS_OPDU_4: 
	    roi -> roi_type = ROI_UREJECT;
	    {
		register struct RoSAPureject   *rou = &roi -> roi_ureject;
		register struct type_ROS_Reject *prj = popdu->un.choice_ROS_11;

		if (prj -> invokeID -> offset == choice_ROS_0_2)
		    rou -> rou_noid = 1;
		else {
		    rosap_id = rou -> rou_id = prj -> invokeID -> un.choice_ROS_1 -> parm;
		    rou -> rou_noid = 0;
		}

		rou -> rou_reason = prob2num (prj -> problem);
	    }
	    break;
    }

    if (invokeID
	    && (popdu -> offset == type_ROS_OPDU_1
		|| (popdu -> offset == type_ROS_OPDU_4
		        && popdu -> un.choice_ROS_11 -> invokeID -> offset
		    		== choice_ROS_0_2)
	        || *invokeID != rosap_id)
	    && acb -> acb_rosindication) {
	(*acb -> acb_rosindication) (sd = acb -> acb_fd, roi);

	if (findacblk (sd) != acb)/* still not perfect! */
	    return rosaplose (roi, ROS_DONE, NULLCP, NULLCP);
	return OK;
    }

    return DONE;
}

/*  */

static int Gprob[] = { ROS_GP_UNRECOG, ROS_GP_MISTYPED, ROS_GP_STRUCT };
static int Iprob[] = { ROS_IP_DUP, ROS_IP_UNRECOG, ROS_IP_MISTYPED,
			ROS_IP_LIMIT, ROS_IP_RELEASE, ROS_IP_UNLINKED,
			ROS_IP_LINKED, ROS_IP_CHILD };
static int RRprob[] = { ROS_RRP_UNRECOG, ROS_RRP_UNEXP, ROS_RRP_MISTYPED };
static int REprob[] = { ROS_REP_UNRECOG, ROS_REP_UNEXP, ROS_REP_RECERR,
			ROS_REP_UNEXPERR, ROS_REP_MISTYPED };
/* computes the Number of entries in an array a */
#define NENTRIES(a) (sizeof (a)/sizeof (a[0]))

/* return the ISODE code from the numbers passed in the data or NOTOK if 
 * it finds an illegal value
 */
static int  prob2num (prob)
register struct choice_ROS_3	*prob;
{
    register int num;

    switch (prob -> offset) {
        case choice_ROS_3_1:
	    if ((num = prob -> un.choice_ROS_4 -> parm) < 0
		    || num >= NENTRIES(Gprob))
		goto out;
	    num = Gprob[num];
	    break;

    case choice_ROS_3_2:
	    if ((num = prob -> un.choice_ROS_5 -> parm) < 0
		    || num >= NENTRIES(Iprob))
		goto out;
	    num = Iprob[num];
	    break;

    case choice_ROS_3_3:
	if ((num = prob -> un.choice_ROS_6 -> parm) < 0
	        || num >= NENTRIES(RRprob))
	    goto out;
	    num = RRprob[num];
	    break;


    case choice_ROS_3_4:
	if ((num = prob -> un.choice_ROS_7 -> parm) < 0
	        || num >= NENTRIES(REprob))
	    goto out;
	    num = REprob[num];
	    break;

    default:
out: ;
	    return ROS_PROTOCOL; /* What else can we say ?*/
    }

    return (num);

}