/************************************************************************/ /* 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); }