769 lines
27 KiB
C
769 lines
27 KiB
C
/************************************************************************/
|
|
/* SISCO SOFTWARE MODULE HEADER *****************************************/
|
|
/************************************************************************/
|
|
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
|
/* 1986 - 2008, All Rights Reserved. */
|
|
/* */
|
|
/* PROPRIETARY AND CONFIDENTIAL */
|
|
/* */
|
|
/* MODULE NAME : mmsdec.c */
|
|
/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */
|
|
/* */
|
|
/* MODULE DESCRIPTION : */
|
|
/* This module contains the initial MMS message decode functions. */
|
|
/* Decodes the header portion of MMS PDUs. */
|
|
/* */
|
|
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
|
|
/* */
|
|
/* MODIFICATION LOG : */
|
|
/* Date Who Rev Comments */
|
|
/* -------- --- ------ ------------------------------------------- */
|
|
/* 03/17/08 EJV 10 Added slog. */
|
|
/* 12/19/05 JRB 22 Chg cr to cr_mms, del static to fix warning.*/
|
|
/* 09/07/05 JRB 08 Fix backwards client/server error log msgs. */
|
|
/* 07/24/02 EJV 07 mmsdec_ucreq_opcode: corr err in the check */
|
|
/* opcode due to recent MMSOP_xxx changes. */
|
|
/* 12/20/01 JRB 06 Converted to use ASN1R (re-entrant ASN1) */
|
|
/* Del mms_err_invoke_fun proto (see mms_dfun.h)*/
|
|
/* 09/13/99 MDE 05 Added SD_CONST modifiers */
|
|
/* 04/07/99 MDE 04 Logging improvements (unsupported service) */
|
|
/* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */
|
|
/* 06/15/98 MDE 02 Changes to allow compile under C++ */
|
|
/* 03/18/98 JRB 01 Fix mmsdec_map_err for new error values. */
|
|
/* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */
|
|
/* history. */
|
|
/************************************************************************/
|
|
|
|
#include "glbtypes.h"
|
|
#include "sysincs.h"
|
|
|
|
#include "mmsdefs.h"
|
|
#include "mms_err.h"
|
|
#include "asn1defs.h"
|
|
|
|
/************************************************************************/
|
|
/* For debug version, use a static pointer to avoid duplication of */
|
|
/* __FILE__ strings. */
|
|
|
|
#ifdef DEBUG_SISCO
|
|
SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__;
|
|
#endif
|
|
|
|
/************************************************************************/
|
|
|
|
static ST_VOID mmsdec_start (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code);
|
|
static ST_VOID mmsdec_invoke_id (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code);
|
|
#ifdef MOD_SUPPORT /* support modifiers */
|
|
static ST_VOID mmsdec_modlist (ASN1_DEC_CTXT *aCtx, ST_UINT16 el_id);
|
|
static ST_VOID mmsdec_modlist_done_fun (ASN1_DEC_CTXT *aCtx);
|
|
#endif
|
|
static ST_VOID mmsdec_opcode (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code);
|
|
static ST_VOID mmsdec_ucreq_opcode (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code);
|
|
static ST_RET mmsdec_chk_req_op (ASN1_DEC_CTXT *aCtx, ST_INT opcode, ST_INT unsupp_code);
|
|
static ST_RET mmsdec_chk_resp_op (ASN1_DEC_CTXT *aCtx, ST_UINT opcode);
|
|
static ST_VOID mmsdec_map_err (ASN1_DEC_CTXT *aCtx); /* maps ASN.1 tool errors to MMS */
|
|
#ifndef MMS_LITE /* don't assign op id's */
|
|
static ST_VOID mmsdec_assign_rid (ST_INT opcode);
|
|
#endif
|
|
|
|
/************************************************************************/
|
|
const ST_CHAR cr_mms[] =
|
|
"(c) COPYRIGHT SYSTEMS INTEGRATION SPECIALISTS COMPANY INC., 1986 - 2005. All Rights Reserved.";
|
|
/************************************************************************/
|
|
/* Operation Specific Decode Buffer Management */
|
|
|
|
ST_VOID *(*m_calloc_os_fun)(ST_UINT num, ST_UINT size);
|
|
ST_VOID *(*m_realloc_os_fun)(ST_VOID *old, ST_UINT new_size);
|
|
ST_VOID (*m_free_os_fun)(ST_VOID *buf);
|
|
|
|
/************************************************************************/
|
|
/* The array below is used to check the constructed state of a PDU */
|
|
|
|
SD_CONST static ST_UINT16 mmspdu_cstr_chk[] =
|
|
{
|
|
CONSTR, /* CONFIRMED REQUEST IS CONSTRUCTOR */
|
|
CONSTR, /* CONFIRMED RESPONSE */
|
|
CONSTR, /* CONFIRMED ERROR */
|
|
CONSTR, /* UNCONFIRMED PDU */
|
|
CONSTR, /* REJECT */
|
|
0, /* CANCEL REQUEST */
|
|
0, /* CANCEL RESPONSE */
|
|
CONSTR, /* CANCEL ERROR */
|
|
CONSTR, /* INITIATE REQUEST */
|
|
CONSTR, /* INITIATE RESPONSE */
|
|
CONSTR, /* INITIATE ERROR */
|
|
0, /* CONCLUDE REQUEST IS PRIMITIVE */
|
|
0, /* CONCLUDE RESPONSE */
|
|
CONSTR /* CONCLUDE ERROR IS CONSTRUCTOR */
|
|
};
|
|
|
|
|
|
/************************************************************************/
|
|
/************************************************************************/
|
|
/* _ms_mms_decode */
|
|
/* Function to setup and initiate MMS PDU decode */
|
|
/* Only fourteen context specific codes are legal at start */
|
|
/* Input parameters : pointer to message start, length of message, */
|
|
/* pointer to result buffer. */
|
|
/************************************************************************/
|
|
|
|
ST_RET _ms_mms_decode (ST_UCHAR *msg_ptr, ST_INT len, MMSDEC_INFO *rslt_ptr)
|
|
{
|
|
ASN1_DEC_CTXT localDecCtx; /* For readability, use "aCtx" to access this.*/
|
|
ASN1_DEC_CTXT *aCtx = &localDecCtx;
|
|
|
|
MLOG_DEC0 ("Decoding MMS PDU");
|
|
memset (aCtx, 0, sizeof (ASN1_DEC_CTXT)); /* CRITICAL: start clean. */
|
|
|
|
aCtx->asn1r_decode_method = ASN1_CLASS_METHOD; /* select the class method */
|
|
aCtx->asn1r_c_id_fun = mmsdec_start; /* point to mms decode initial function */
|
|
aCtx->asn1r_u_id_fun = asn1r_class_err; /* no universals to start */
|
|
aCtx->asn1r_a_id_fun = asn1r_class_err; /* no applications to start */
|
|
aCtx->asn1r_p_id_fun = asn1r_class_err; /* no privates to start */
|
|
|
|
aCtx->asn1r_decode_done_fun = asn1r_done_err; /* done function = error fun */
|
|
aCtx->asn1r_err_fun = NULL; /* set up error detected fun */
|
|
|
|
_mmsdec_msglen = len; /* save decode message length */
|
|
_mmsdec_msgptr = msg_ptr; /* save decode message ptr */
|
|
_mmsdec_rslt = rslt_ptr; /* save the result pointer */
|
|
rslt_ptr->err_code = NO_DECODE_ERR; /* start with no error */
|
|
rslt_ptr->dec_level = 0; /* start with no usable info */
|
|
rslt_ptr->data_pres = SD_FALSE;
|
|
rslt_ptr->mods.info_pres = SD_FALSE;
|
|
rslt_ptr->cs.cs_pres = SD_FALSE;
|
|
_mms_dec_info_pres = SD_FALSE;
|
|
|
|
/* ASN.1 decode machine is set up for initial MMS decode. */
|
|
/* Call 'asn1r_decode_asn1' to parse the message. */
|
|
|
|
asn1r_decode_asn1 (aCtx, msg_ptr,len); /* do message decode */
|
|
mmsdec_map_err (aCtx); /* write the error code */
|
|
if (aCtx->asn1r_pdu_dec_err == NO_DECODE_ERR)
|
|
return (SD_SUCCESS); /* return 'no error' code */
|
|
#ifndef MMS_LITE
|
|
else
|
|
{
|
|
if (_mmsdec_rslt->mods.info_pres) /* see if there were any mods */
|
|
chk_free (_mmsdec_rslt->mods.mod_list_ptr);
|
|
|
|
/* Note that op specific buffer are free'd in _mms_dec_buf_free on error */
|
|
|
|
}
|
|
#endif
|
|
return (MVE_ASN1_DECODE_ERR); /* return error code */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/************************************************************************/
|
|
/* mmsdec_start */
|
|
/* Initial MMS decode context-specific code service function. This */
|
|
/* function is called when the first data element of the message is a */
|
|
/* context-specific class. */
|
|
/************************************************************************/
|
|
|
|
#define MAX_MMS_PDU_TAG 13
|
|
|
|
static ST_VOID mmsdec_start (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code)
|
|
{
|
|
MLOG_CDEC0 ("mmsdec_start");
|
|
|
|
/* check for valid MMS PDU type, such as request, response, error, etc. */
|
|
/* if valid tag and constructed state OK */
|
|
if (id_code <= MAX_MMS_PDU_TAG &&
|
|
!(mmspdu_cstr_chk[id_code] ^ aCtx->asn1r_constr_elmnt))
|
|
{
|
|
_mmsdec_rslt->dec_level = 1; /* set flag that PDU type is OK */
|
|
_mmsdec_rslt->type = id_code; /* save the type for the user */
|
|
switch (id_code)
|
|
{
|
|
case MMSREQ : /* Confirmed Request PDU */
|
|
aCtx->asn1r_u_id_fun = mmsdec_invoke_id; /* next must be uni, integer */
|
|
/* invoke ID */
|
|
aCtx->asn1r_c_id_fun = asn1r_class_err; /* can not context specific */
|
|
break;
|
|
|
|
case MMSRESP : /* Confirmed Response PDU */
|
|
aCtx->asn1r_u_id_fun = mmsdec_invoke_id; /* next must be uni, integer */
|
|
/* invoke ID */
|
|
aCtx->asn1r_c_id_fun = asn1r_class_err; /* cannot be context specific */
|
|
break;
|
|
|
|
case MMSERROR : /* Confirmed Error PDU */
|
|
aCtx->asn1r_c_id_fun = mms_err_invoke_fun; /* must be context specific */
|
|
break; /* integer (invoke ID) */
|
|
|
|
case MMSUNREQ : /* Unconfirmed PDU */
|
|
aCtx->asn1r_c_id_fun = mmsdec_ucreq_opcode; /* expect context-specific tag */
|
|
break;
|
|
|
|
case MMSREJECT : /* Reject PDU */
|
|
aCtx->asn1r_c_id_fun = mms_reject; /* expect context-specific */
|
|
break;
|
|
|
|
case MMSCANREQ : /* Cancel Request PDU */
|
|
if (!(mmsop_en[MMSOP_CANCEL] & RESP_EN)) /* protocol error if */
|
|
asn1r_set_dec_err (aCtx, CANREQ_UNSPECIFIED); /* unsupported service */
|
|
else
|
|
{
|
|
if (asn1r_get_u32 (aCtx, &_mmsdec_rslt->id))
|
|
asn1r_set_dec_err (aCtx, CANREQ_INVAL_INVOKE);
|
|
else
|
|
{
|
|
_mmsdec_rslt->dec_level = 2;
|
|
(*mms_req_decode_fun [MMSOP_CANCEL]) (aCtx);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MMSCANRESP : /* Cancel Response PDU */
|
|
if (!(mmsop_en[MMSOP_CANCEL] & REQ_EN)) /* protocol error if */
|
|
asn1r_set_dec_err (aCtx, CANRESP_UNSPECIFIED); /* not supported */
|
|
else
|
|
{
|
|
if (asn1r_get_u32 (aCtx, &_mmsdec_rslt->id))
|
|
asn1r_set_dec_err (aCtx, CANRESP_INVAL_INVOKE);
|
|
else
|
|
{
|
|
_mmsdec_rslt->dec_level = 2; /* Save inv. ID in rslt */
|
|
(*mms_rsp_decode_fun [MMSOP_CANCEL]) (aCtx);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MMSCANERR : /* Cancel Error PDU */
|
|
if (!(mmsop_en[MMSOP_CANCEL] & REQ_EN)) /* protocol error if */
|
|
asn1r_set_dec_err (aCtx, CANERR_INVAL_SERV); /* is not supported */
|
|
else /* expect context-spec */
|
|
aCtx->asn1r_c_id_fun = mms_err_invoke_fun;
|
|
break;
|
|
|
|
case MMSINITREQ : /* Initiate Request PDU */
|
|
if (!(mmsop_en[MMSOP_INITIATE] & RESP_EN)) /* if not enabled */
|
|
asn1r_set_dec_err (aCtx, REQ_UNREC_SERV); /* as responder */
|
|
else
|
|
{
|
|
#ifndef MMS_LITE
|
|
mmsdec_assign_rid (MMSOP_INITIATE); /* Assign opcode and */
|
|
/* reserved Initiate ID */
|
|
#endif
|
|
(*mms_req_decode_fun [MMSOP_INITIATE]) (aCtx);
|
|
}
|
|
break;
|
|
|
|
case MMSINITRESP : /* Initiate Response PDU */
|
|
if (!(mmsop_en[MMSOP_INITIATE] & REQ_EN)) /* if not enabled */
|
|
asn1r_set_dec_err (aCtx, RESP_UNREC_SERV); /* as responder */
|
|
else
|
|
{
|
|
#ifndef MMS_LITE
|
|
mmsdec_assign_rid (MMSOP_INITIATE); /* Assign opcode and */
|
|
/* reserved Initiate ID */
|
|
#endif
|
|
(*mms_rsp_decode_fun [MMSOP_INITIATE]) (aCtx);
|
|
}
|
|
break;
|
|
|
|
case MMSINITERR : /* Initiate Error PDU */
|
|
if (!(mmsop_en[MMSOP_INITIATE] & REQ_EN)) /* protocol error if */
|
|
asn1r_set_dec_err (aCtx, ERR_UNREC_SERV); /* is not supported */
|
|
else
|
|
{
|
|
#ifndef MMS_LITE
|
|
mmsdec_assign_rid (MMSOP_INITIATE); /* Assign opcode and */
|
|
/* reserved Initiate ID */
|
|
#endif
|
|
mms_err_rsp (aCtx); /* general err function */
|
|
}
|
|
break;
|
|
|
|
case MMSCNCLREQ : /* Conclude Requset PDU */
|
|
if (!(mmsop_en[MMSOP_CONCLUDE] & RESP_EN)) /* protocol error if */
|
|
asn1r_set_dec_err (aCtx, CONREQ_UNSPECIFIED); /* not supported */
|
|
else
|
|
{
|
|
if (aCtx->asn1r_elmnt_len)
|
|
asn1r_set_dec_err (aCtx, CONREQ_INVAL_ARG);
|
|
else
|
|
{
|
|
#ifndef MMS_LITE
|
|
mmsdec_assign_rid (MMSOP_CONCLUDE);/* Assign opcode and */
|
|
/* reserved Conclude ID */
|
|
#endif
|
|
(*mms_req_decode_fun [MMSOP_CONCLUDE]) (aCtx);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MMSCNCLRESP : /* Conclude Response PDU */
|
|
if (!(mmsop_en[MMSOP_CONCLUDE] & REQ_EN)) /* protocol error if */
|
|
asn1r_set_dec_err (aCtx, CONRESP_UNSPECIFIED); /* not supported */
|
|
else
|
|
{
|
|
if (aCtx->asn1r_elmnt_len)
|
|
asn1r_set_dec_err (aCtx, CONRESP_INVAL_RSLT); /* if constructor */
|
|
else
|
|
{
|
|
#ifndef MMS_LITE
|
|
mmsdec_assign_rid (MMSOP_CONCLUDE); /* Assign opcode and */
|
|
/* reserved Concl ID */
|
|
#endif
|
|
(*mms_rsp_decode_fun [MMSOP_CONCLUDE]) (aCtx);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case MMSCNCLERR : /* Conclude Error PDU */
|
|
if (!(mmsop_en[MMSOP_CONCLUDE] & REQ_EN)) /* protocol error if */
|
|
asn1r_set_dec_err (aCtx, CONERR_INVAL_SERV); /* is not supported */
|
|
else
|
|
{
|
|
#ifndef MMS_LITE
|
|
mmsdec_assign_rid (MMSOP_CONCLUDE); /* Assign opcode and */
|
|
/* reserved Conclude ID */
|
|
#endif
|
|
mms_err_rsp (aCtx); /* general err function */
|
|
}
|
|
break;
|
|
|
|
default:
|
|
asn1r_set_dec_err (aCtx, PDU_UNKNOWN_TYPE); /* Not a legal MMS PDU type. */
|
|
}
|
|
}
|
|
else
|
|
asn1r_set_dec_err (aCtx, PDU_UNKNOWN_TYPE); /* Not a legal MMS PDU type. */
|
|
} /* or constructor error */
|
|
|
|
|
|
/************************************************************************/
|
|
/************************************************************************/
|
|
/* mmsdec_invoke_id */
|
|
/* Universal class service function called when invoke ID is expected */
|
|
/* (after first data element in most MMS confirmed services has been */
|
|
/* decoded, and this data element is a universal). */
|
|
/************************************************************************/
|
|
|
|
static ST_VOID mmsdec_invoke_id (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code)
|
|
{
|
|
if (aCtx->asn1r_constr_elmnt || id_code != INT_CODE)
|
|
asn1r_set_dec_err (aCtx, PDU_INVALID); /* not a constr or INTEGER type */
|
|
else
|
|
{
|
|
if (asn1r_get_u32 (aCtx, &_mmsdec_rslt->id))
|
|
{
|
|
if (_mmsdec_rslt->type == MMSREQ)
|
|
asn1r_set_dec_err (aCtx, REQ_BAD_VALUE); /* not a valid 4-byte integer */
|
|
else
|
|
asn1r_set_dec_err (aCtx, RESP_BAD_VALUE); /* not a valid 4-byte integer */
|
|
return;
|
|
}
|
|
}
|
|
|
|
MLOG_CDEC1 ("Invoke ID = %lu",_mmsdec_rslt->id);
|
|
|
|
_mmsdec_rslt->dec_level = 2; /* set flag that Invoke ID is OK */
|
|
/* setup function pointers for next */
|
|
aCtx->asn1r_c_id_fun = mmsdec_opcode; /* next is explicit context tag */
|
|
#ifdef MOD_SUPPORT
|
|
if (_mmsdec_rslt->type == MMSREQ)/* if MMSREQ a modifier could be next */
|
|
aCtx->asn1r_u_id_fun = mmsdec_modlist; /* modifiers are tagged universal */
|
|
else
|
|
#endif
|
|
aCtx->asn1r_u_id_fun = asn1r_class_err; /* no more universals */
|
|
}
|
|
|
|
#ifdef MOD_SUPPORT
|
|
/************************************************************************/
|
|
/************************************************************************/
|
|
/* mmsdec_modlist */
|
|
/* An MMS request has been received with a modifier list present. We */
|
|
/* change the asn1_decode_method to TAG so _ms_get_mms_modlist can decode it. */
|
|
/* During the decode the modifier list will be attached to _mmsdec_rslt. */
|
|
/* Upon completion of the decode we see if we can give back any unused */
|
|
/* memory and change the decod_method back to CLASS. */
|
|
/************************************************************************/
|
|
|
|
static ST_VOID mmsdec_modlist (ASN1_DEC_CTXT *aCtx, ST_UINT16 el_id)
|
|
{
|
|
#ifdef MMS_LITE
|
|
extern ST_CHAR mms_dec_modbuf [];
|
|
#endif
|
|
|
|
aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* select TAG method for get_mms_modifer*/
|
|
|
|
_mmsdec_rslt->mods.num_of_mods = 0;
|
|
#ifndef MMS_LITE
|
|
_mmsdec_rslt->mods.mod_list_ptr = (MODIFIER *)
|
|
chk_calloc (m_max_mods,
|
|
sizeof (MODIFIER));
|
|
#else
|
|
_mmsdec_rslt->mods.mod_list_ptr = (MODIFIER *) mms_dec_modbuf;
|
|
#endif
|
|
_ms_get_mms_modlist (aCtx, _mmsdec_rslt->mods.mod_list_ptr,
|
|
&(_mmsdec_rslt->mods.num_of_mods),
|
|
m_max_mods,
|
|
mmsdec_modlist_done_fun);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/************************************************************************/
|
|
/* mmsdec_modlist_done_fun */
|
|
/* This function is called when the modifier list has been decoded. */
|
|
/************************************************************************/
|
|
|
|
static ST_VOID mmsdec_modlist_done_fun (ASN1_DEC_CTXT *aCtx)
|
|
{
|
|
|
|
aCtx->asn1r_decode_method = ASN1_CLASS_METHOD; /* restore the class method */
|
|
_mmsdec_rslt->mods.info_pres = SD_TRUE;
|
|
|
|
}
|
|
#endif
|
|
|
|
/************************************************************************/
|
|
/************************************************************************/
|
|
/* mmsdec_opcode */
|
|
/* An MMS request with good invoke ID has been detected. Next field */
|
|
/* should be an implicit context tag which represents the opcode. */
|
|
/* This function is called if a context class is decoded. */
|
|
/************************************************************************/
|
|
|
|
static ST_VOID mmsdec_opcode (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code)
|
|
{
|
|
ST_INT operr;
|
|
|
|
#ifndef MMS_LITE
|
|
if (id_code > MAX_MMS_OPCODE)
|
|
{ /* Must be a legal MMS opcode */
|
|
if (_mmsdec_rslt->type == MMSREQ)
|
|
asn1r_set_dec_err (aCtx, REQ_UNREC_SERV);
|
|
else
|
|
asn1r_set_dec_err (aCtx, RESP_UNREC_SERV);
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
_mmsdec_rslt->dec_level = 3; /* set flag that opcode is read OK */
|
|
_mmsdec_rslt->op = id_code; /* save the opcode for the user */
|
|
|
|
MLOG_CDEC1 ("MMS Opcode = %d",_mmsdec_rslt->op);
|
|
|
|
/* Opcode has been saved. Check that the service corresponding to this */
|
|
/* opcode is supported and there are no parse errors. */
|
|
|
|
if (_mmsdec_rslt->type == MMSREQ)
|
|
{
|
|
/* pass err code */
|
|
operr = mmsdec_chk_req_op (aCtx, _mmsdec_rslt->op,REQ_UNREC_SERV);
|
|
if (!operr)
|
|
(*mms_req_decode_fun [_mmsdec_rslt->op]) (aCtx);
|
|
}
|
|
else
|
|
{
|
|
operr = mmsdec_chk_resp_op (aCtx, _mmsdec_rslt->op);
|
|
if (!operr)
|
|
(*mms_rsp_decode_fun [_mmsdec_rslt->op]) (aCtx);
|
|
}
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/************************************************************************/
|
|
/* mmsdec_ucreq_opcode */
|
|
/* An MMS unconfirmed request has been detected. Next field should be */
|
|
/* an implicit context tag which represents the opcode. This function */
|
|
/* is called if a context class is decoded. */
|
|
/************************************************************************/
|
|
|
|
static ST_VOID mmsdec_ucreq_opcode (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code)
|
|
{
|
|
if (id_code == 0)
|
|
_mmsdec_rslt->op = MMSOP_INFO_RPT;
|
|
else if (id_code == 1)
|
|
_mmsdec_rslt->op = MMSOP_USTATUS;
|
|
else if (id_code == 2)
|
|
_mmsdec_rslt->op = MMSOP_EVENT_NOT;
|
|
else
|
|
{ /* Must be a legal MMS opcode */
|
|
asn1r_set_dec_err (aCtx, PDU_INVALID);
|
|
return;
|
|
}
|
|
|
|
MLOG_CDEC1 ("Unconfirmed request opcode = %d",_mmsdec_rslt->op);
|
|
|
|
_mmsdec_rslt->dec_level = 3; /* set flag that opcode is read OK */
|
|
_mmsdec_rslt->id = UNREQ_INVOKE;
|
|
|
|
/* Opcode has been saved. Check that the service corresponding to this */
|
|
/* opcode is supported and there are no parse errors. */
|
|
|
|
if (!mmsdec_chk_req_op (aCtx, _mmsdec_rslt->op,UNCONF_UNREC_SERV))
|
|
(*mms_req_decode_fun [_mmsdec_rslt->op]) (aCtx); /* continue decode */
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* mmsdec_chk_req_op */
|
|
/* mmsdec_chk_resp_op */
|
|
/* This function checks whether the given opcode is supported as */
|
|
/* request or response (or both), if the data element containing the */
|
|
/* opcode is of the proper form (either primitive or constructor), */
|
|
/* and if it is a NULL when it is supposed to be. The mmsop_en table */
|
|
/* contains the opcode support information. */
|
|
/* Returns 0 for success, else non-zero error code */
|
|
/************************************************************************/
|
|
|
|
static ST_RET mmsdec_chk_req_op (ASN1_DEC_CTXT *aCtx, ST_INT opcode, ST_INT unsupp_code)
|
|
{
|
|
ST_UCHAR op_en;
|
|
|
|
/* First check that opcode range, then whether it is enabled */
|
|
|
|
if ((opcode > MAX_MMSOP_DIS) || ! ((op_en = mmsop_en[opcode]) & RESP_EN))
|
|
{
|
|
if (opcode <= MAX_MMSOP_DIS)
|
|
{
|
|
MLOG_NERR1 ("MMS service %s not supported as server (cannot decode request)",
|
|
mms_op_string[opcode]);
|
|
}
|
|
else
|
|
{
|
|
MLOG_NERR1 ("MMS service opcode %d out of range", opcode);
|
|
}
|
|
asn1r_set_dec_err (aCtx, unsupp_code); /* req not supported */
|
|
return (MVE_REQ_NOT_SUPP);
|
|
}
|
|
else
|
|
{
|
|
if ((aCtx->asn1r_constr_elmnt && !(op_en & 0x04)) ||
|
|
(!aCtx->asn1r_constr_elmnt && (op_en & 0x04)) ||
|
|
(aCtx->asn1r_elmnt_len > 0 && (op_en & 0x10)))
|
|
{
|
|
asn1r_set_dec_err (aCtx, PDU_INVALID);
|
|
return (MVE_INVALID_PDU);
|
|
}
|
|
return (SD_SUCCESS); /* return success code */
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
static ST_RET mmsdec_chk_resp_op (ASN1_DEC_CTXT *aCtx, ST_UINT opcode)
|
|
{
|
|
ST_UCHAR op_en;
|
|
|
|
/* First check that opcode range, then whether it is enabled */
|
|
|
|
if ((opcode > MAX_MMSOP_DIS) || ! ((op_en = mmsop_en[opcode]) & REQ_EN))
|
|
{
|
|
if (opcode <= MAX_MMSOP_DIS)
|
|
{
|
|
MLOG_NERR1 ("MMS service %s not supported as client (cannot decode response)",
|
|
mms_op_string[opcode]);
|
|
}
|
|
else
|
|
{
|
|
MLOG_NERR1 ("MMS service opcode %d out of range", opcode);
|
|
}
|
|
|
|
asn1r_set_dec_err (aCtx, RESP_UNREC_SERV); /* resp not supported */
|
|
return (MVE_RESP_NOT_SUPP);
|
|
}
|
|
else
|
|
{
|
|
if (opcode == MMSOP_INIT_DOWNLOAD)
|
|
{
|
|
#ifndef MMS_LITE
|
|
if (mms_chan_info[_mmsdechan].version) /* IS */
|
|
#else
|
|
if (mmsl_version) /* IS */
|
|
#endif
|
|
{
|
|
if (aCtx->asn1r_constr_elmnt || aCtx->asn1r_elmnt_len)
|
|
{
|
|
asn1r_set_dec_err (aCtx, PDU_INVALID);
|
|
return (MVE_INVALID_PDU);
|
|
}
|
|
}
|
|
else /* DIS */
|
|
{
|
|
if (!aCtx->asn1r_constr_elmnt || !aCtx->asn1r_elmnt_len)
|
|
{
|
|
asn1r_set_dec_err (aCtx, PDU_INVALID);
|
|
return (MVE_INVALID_PDU);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((aCtx->asn1r_constr_elmnt && !(op_en & 0x08)) ||
|
|
(!aCtx->asn1r_constr_elmnt && (op_en & 0x08)) ||
|
|
(aCtx->asn1r_elmnt_len > 0 && (op_en & 0x20)))
|
|
{
|
|
asn1r_set_dec_err (aCtx, PDU_INVALID);
|
|
return (MVE_INVALID_PDU);
|
|
}
|
|
}
|
|
|
|
return (SD_SUCCESS); /* return success code */
|
|
}
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* mmsdec_map_err */
|
|
/* Function to map the error codes supplied by the generic ASN.1 tools */
|
|
/* to the MMS error codes specified for the Reject service. Inputs are */
|
|
/* the global variables: */
|
|
/* ST_UINT16 aCtx->asn1r_pdu_dec_err; */
|
|
/* MMSDEC_INFO *_mmsdec_rslt; */
|
|
/* */
|
|
/* (A aCtx->asn1r_pdu_dec_err value of 0 should not occur and maps to UNSPECIFIED.) */
|
|
/************************************************************************/
|
|
static ST_VOID mmsdec_map_err (ASN1_DEC_CTXT *aCtx)
|
|
{
|
|
ST_INT level;
|
|
|
|
level = 0;
|
|
|
|
/* asn1_pdu_dec_err codes of NO_DECODE_ERR are OK, and codes of > 15 have been */
|
|
/* set by the MMS decode logic and so are OK. 15 is a special number */
|
|
/* because the lowest reject code is a 0x10(REQ_UNSPECIFIED) */
|
|
|
|
if (aCtx->asn1r_pdu_dec_err == NO_DECODE_ERR || aCtx->asn1r_pdu_dec_err >= REQ_UNSPECIFIED)
|
|
{
|
|
_mmsdec_rslt->err_code = aCtx->asn1r_pdu_dec_err;
|
|
}
|
|
|
|
/* We started to decode some type of PDU and it wasn't valid. Here we */
|
|
/* try to determine how much of the PDU we parsed and generate a */
|
|
/* pertainent error code */
|
|
|
|
else
|
|
{
|
|
level = _mmsdec_rslt -> dec_level;
|
|
if (level == 0) /* did we determine it's type ? */
|
|
_mmsdec_rslt->err_code = PDU_INVALID;
|
|
else /* if we knew it's type we */
|
|
{ /* switch to figure out more */
|
|
switch (_mmsdec_rslt->type)
|
|
{
|
|
|
|
/* About the only time we get here and have to do this is when the MMS */
|
|
/* decoder temporarily turned the decode over the the ASN.1 tools (via */
|
|
/* parse_next, parse_cstr_contents, etc) and an error was discovered. */
|
|
/* The error the ASN.1 tools will report is <= 15. Some, most or all */
|
|
/* of the PDU was decoded. It's not fair to just say we couldn't tell */
|
|
/* anything at all about the PDU. */
|
|
/* These are the rules for determining what reject class and code get */
|
|
/* returned for the rejected PDU. The protocol for the begining of */
|
|
/* each MMSpdu is different so almost each type has to dealt with on an */
|
|
/* individual basis. */
|
|
|
|
case MMSREQ : /* request for most confirmed services */
|
|
if (level >= 2)
|
|
_mmsdec_rslt->err_code = REQ_INVAL_ARG;
|
|
else
|
|
_mmsdec_rslt->err_code = REQ_UNSPECIFIED;
|
|
break;
|
|
|
|
case MMSRESP : /* response for most confirmed services */
|
|
if (level >= 2)
|
|
_mmsdec_rslt->err_code = RESP_INVAL_RSLT;
|
|
else
|
|
_mmsdec_rslt->err_code = RESP_UNSPECIFIED;
|
|
break;
|
|
|
|
case MMSERROR : /* error for most confirmed services */
|
|
_mmsdec_rslt->err_code = ERR_UNSPECIFIED;
|
|
break;
|
|
|
|
case MMSUNREQ : /* request for unconfirmed services */
|
|
_mmsdec_rslt->err_code = UNCONF_UNSPECIFIED;
|
|
break;
|
|
|
|
case MMSREJECT : /* reject */
|
|
_mmsdec_rslt->err_code = PDU_UNKNOWN_TYPE;
|
|
break;
|
|
|
|
case MMSCANREQ : /* request for the Cancel service */
|
|
_mmsdec_rslt->err_code = CANREQ_UNSPECIFIED;
|
|
break;
|
|
|
|
case MMSCANRESP : /* response for the Cancel service */
|
|
_mmsdec_rslt->err_code = CANRESP_UNSPECIFIED;
|
|
break;
|
|
|
|
case MMSCANERR : /* error for Cancel service */
|
|
_mmsdec_rslt->err_code = CANERR_UNSPECIFIED;
|
|
break;
|
|
|
|
case MMSINITREQ : /* request for Initiate service */
|
|
_mmsdec_rslt->err_code = REQ_BAD_VALUE;
|
|
break;
|
|
|
|
case MMSINITRESP : /* response for Initiate service */
|
|
_mmsdec_rslt->err_code = RESP_BAD_VALUE;
|
|
break;
|
|
|
|
case MMSINITERR : /* error for Initiate service */
|
|
_mmsdec_rslt->err_code = ERR_BAD_VALUE;
|
|
break;
|
|
|
|
case MMSCNCLREQ : /* request for Conclude service */
|
|
_mmsdec_rslt->err_code = CONREQ_UNSPECIFIED;
|
|
break;
|
|
|
|
case MMSCNCLRESP : /* response for Conclude service */
|
|
_mmsdec_rslt->err_code = CONRESP_UNSPECIFIED;
|
|
break;
|
|
|
|
case MMSCNCLERR : /* error for Conclude service */
|
|
_mmsdec_rslt->err_code = CONERR_UNSPECIFIED;
|
|
break;
|
|
|
|
default:
|
|
_mmsdec_rslt->err_code = PDU_INVALID;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* mmsdec_assign_rid */
|
|
/* Assign a reserved invoke ID for the given service on this channel */
|
|
/* and store it in the _mmsdec_rslt structure. Also, set the opcode for */
|
|
/* the specified service, which must be either Initiate or Conclude */
|
|
/* (or their error responses). */
|
|
/************************************************************************/
|
|
|
|
#ifndef MMS_LITE
|
|
|
|
static ST_VOID mmsdec_assign_rid (ST_INT opcode)
|
|
{
|
|
/* assign reserved invoke id */
|
|
if (opcode == MMSOP_INITIATE)
|
|
_mmsdec_rslt->id = INIT_INVOKE_ID + _mmsdechan; /* for Initiate */
|
|
else
|
|
_mmsdec_rslt->id = CONCL_INVOKE_ID + _mmsdechan; /* for Conclude */
|
|
|
|
_mmsdec_rslt->op = opcode; /* save the opcode */
|
|
_mmsdec_rslt->dec_level = 3; /* opcode & invoke ID are valid */
|
|
}
|
|
|
|
#endif
|
|
|
|
/************************************************************************/
|
|
/************************************************************************/
|
|
/* _m_get_dec_buf */
|
|
/************************************************************************/
|
|
|
|
ST_VOID *_m_get_dec_buf (ASN1_DEC_CTXT *aCtx, ST_UINT size)
|
|
{
|
|
_mms_dec_info = (*m_calloc_os_fun)(1, size);
|
|
aCtx->asn1r_err_fun = _mms_dec_buf_free;
|
|
_mms_dec_info_pres = SD_TRUE;
|
|
aCtx->asn1r_decode_method = ASN1_TAG_METHOD; /* select TAG method for get_mms_modifer*/
|
|
return (_mms_dec_info);
|
|
}
|