/************************************************************************/ /* SISCO SOFTWARE MODULE HEADER *****************************************/ /************************************************************************/ /* (c) Copyright Systems Integration Specialists Company, Inc., */ /* 1986 - 2007, All Rights Reserved. */ /* */ /* PROPRIETARY AND CONFIDENTIAL */ /* */ /* MODULE NAME : mms_err.c */ /* PRODUCT(S) : MMSEASE, MMSEASE-LITE */ /* */ /* MODULE DESCRIPTION : */ /* This module contains the MMS error functions for decoding */ /* & encoding the error response PDUs : */ /* confirmed-ErrorPDU */ /* */ /* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ /* */ /* MODIFICATION LOG : */ /* Date Who Rev Comments */ /* -------- --- ------ ------------------------------------------- */ /* 11/01/07 EJV 08 Rem obsolete LLC30... code. */ /* 04/05/02 MDE 07 Added MLOG logging */ /* 01/23/02 JRB 06 Fix "Response built" msg (was missing header)*/ /* 12/20/01 JRB 05 Converted to use ASN1R (re-entrant ASN1) */ /* 09/13/99 MDE 04 Added SD_CONST modifiers */ /* 03/23/99 MDE 03 Changes to decode buffer allocation scheme */ /* 06/15/98 MDE 02 Changes to allow compile under C++ */ /* 07/03/97 MDE 01 Op-specific info buffer handling changes */ /* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ /* history. */ /************************************************************************/ #include "glbtypes.h" #include "sysincs.h" #include "glbsem.h" #include "mmsdefs.h" #include "mms_pcon.h" #include "asn1defs.h" #include "mloguser.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 /************************************************************************/ /* variables global to the decode : */ static ERR_INFO *err_info_ptr; #ifdef MOD_SUPPORT static ST_VOID err_mod_pos (ASN1_DEC_CTXT *aCtx); #endif static ST_VOID err_rsp2 (ASN1_DEC_CTXT *aCtx); static ST_VOID err_class (ASN1_DEC_CTXT *aCtx); static ST_VOID err_get_cac (ASN1_DEC_CTXT *aCtx); #ifdef CS_SUPPORT static ST_VOID err_get_cs (ASN1_DEC_CTXT *aCtx); static ST_VOID err_cs_done (ASN1_DEC_CTXT *aCtx); #endif static ST_VOID err_class_cstr_done (ASN1_DEC_CTXT *aCtx); static ST_VOID err_get_add_code (ASN1_DEC_CTXT *aCtx); static ST_VOID err_get_add_descr (ASN1_DEC_CTXT *aCtx); static ST_VOID err_add_ssi_cstr (ASN1_DEC_CTXT *aCtx); static ST_VOID err_get_add_ssi_i16 (ASN1_DEC_CTXT *aCtx); static ST_VOID err_get_add_ssi_u32 (ASN1_DEC_CTXT *aCtx); static ST_VOID err_get_dee_obj_name (ASN1_DEC_CTXT *aCtx); static ST_VOID err_dee_obj_name_done (ASN1_DEC_CTXT *aCtx); static ST_VOID err_get_add_serv_err (ASN1_DEC_CTXT *aCtx); static ST_VOID err_adtnl_done (ASN1_DEC_CTXT *aCtx); static ST_VOID err_ssi_done (ASN1_DEC_CTXT *aCtx); /************************************************************************/ /************************************************************************/ /* mms_err_invoke_fun */ /* This function is called from mmsdec.c when invoke ID is expected */ /* in a CONFIRMED or CANCEL ERROR PDU. */ /************************************************************************/ ST_VOID mms_err_invoke_fun (ASN1_DEC_CTXT *aCtx, ST_UINT16 id_code) { ST_INT pdutype; pdutype = _mmsdec_rslt->type; if (aCtx->asn1r_constr_elmnt || id_code != 0) { asn1r_set_dec_err (aCtx, PDU_INVALID); /* wrong code or constructed int*/ return; } if (asn1r_get_u32 (aCtx, &_mmsdec_rslt->id)) { if (pdutype == MMSCANERR) asn1r_set_dec_err (aCtx, CANERR_INVAL_INVOKE); /* not a valid integer contents */ else asn1r_set_dec_err (aCtx, ERR_INVAL_INVOKE); /* not a valid integer contents */ return; } _mmsdec_rslt->dec_level = 2; /* set flag that Invoke ID is OK */ MLOG_CDEC1 ("Invoke ID present, = %ld",_mmsdec_rslt->id); err_info_ptr = (ERR_INFO *) _m_get_dec_buf (aCtx, sizeof (ERR_INFO)); if (pdutype == MMSCANERR) /* Cancel Error PDU, next must */ ASN1R_TAG_ADD (aCtx, CTX | CONSTR,1,err_rsp2); /* be context tag 1 cstr */ else { /* Confirmed Error PDU, next */ #ifdef MOD_SUPPORT ASN1R_TAG_ADD (aCtx, CTX ,1,err_mod_pos); /* Context tag 1 (opt) */ #endif ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,err_rsp2); /* Context tag 2 cstr */ } } #ifdef MOD_SUPPORT /************************************************************************/ /* err_mod_pos */ /* This function is called when a modifier position is detected in a */ /* confirmed_request_error PDU. The only thing which may follow is a */ /* service error description. */ /************************************************************************/ static ST_VOID err_mod_pos (ASN1_DEC_CTXT *aCtx) { MLOG_CDEC0 ("err_mod_pos"); if (asn1r_get_i32 (aCtx, &(err_info_ptr->adtnl.mod_pos))) /* read mod position */ asn1r_set_dec_err (aCtx, ERR_UNSPECIFIED); err_info_ptr -> adtnl.mod_pos_pres = SD_TRUE; ASN1R_TAG_ADD (aCtx, CTX | CONSTR,2,err_rsp2); /* Context tag 2 cstr */ } #endif /************************************************************************/ /************************************************************************/ /* mms_err_rsp */ /* This function is called from mmsdec.c when an Error Response PDU is */ /* being decoded for initiate or conclude error ONLY */ /* When this is called directly, we need to allocate the buffer */ /************************************************************************/ ST_VOID mms_err_rsp (ASN1_DEC_CTXT *aCtx) { MLOG_CDEC0 ("mms_err_rsp"); err_info_ptr = (ERR_INFO *) _m_get_dec_buf (aCtx, sizeof (ERR_INFO)); aCtx->asn1r_err_fun = _mms_dec_buf_free; err_rsp2 (aCtx); /* set tags */ } /************************************************************************/ /************************************************************************/ /* _mms_get_service_err */ /* This function is called from rs_termd.c when IS is used and the */ /* 'discarded' parameter is send (service error) -or- from rs_evnot.c */ /* when the action result is failure. */ /************************************************************************/ ST_VOID _mms_get_service_err (ASN1_DEC_CTXT *aCtx, ERR_INFO *err_ptr) { err_info_ptr = err_ptr; /* use caller's storage */ err_rsp2 (aCtx); /* set tags */ } /************************************************************************/ /************************************************************************/ /* err_rsp2 */ /* This function is called when an Error Response PDU is being decoded */ /* for confirmed error. */ /************************************************************************/ static ST_VOID err_rsp2 (ASN1_DEC_CTXT *aCtx) { MLOG_CDEC0 ("err_rsp2"); ASN1R_TAG_ADD (aCtx, CTX|CONSTR,0,err_class); } /************************************************************************/ /* err_class */ /* This function is invoked when the ServiceError is being decoded, and */ /* the errorClass choice is encountered. */ /************************************************************************/ static ST_VOID err_class (ASN1_DEC_CTXT *aCtx) { MLOG_CDEC0 ("err_class"); ASN1R_TAG_ADD (aCtx, CTX, 0, err_get_cac); ASN1R_TAG_ADD (aCtx, CTX, 1, err_get_cac); ASN1R_TAG_ADD (aCtx, CTX, 2, err_get_cac); ASN1R_TAG_ADD (aCtx, CTX, 3, err_get_cac); ASN1R_TAG_ADD (aCtx, CTX, 4, err_get_cac); ASN1R_TAG_ADD (aCtx, CTX, 5, err_get_cac); ASN1R_TAG_ADD (aCtx, CTX, 6, err_get_cac); ASN1R_TAG_ADD (aCtx, CTX, 7, err_get_cac); ASN1R_TAG_ADD (aCtx, CTX, 8, err_get_cac); ASN1R_TAG_ADD (aCtx, CTX, 9, err_get_cac); ASN1R_TAG_ADD (aCtx, CTX,10, err_get_cac); ASN1R_TAG_ADD (aCtx, CTX,11, err_get_cac); ASN1R_TAG_ADD (aCtx, CTX,12, err_get_cac); #ifdef CS_SUPPORT #ifndef MMS_LITE if (mms_chan_info[_mmsdechan].version) /* IS */ #else if (mmsl_version) /* IS */ #endif ASN1R_TAG_ADD (aCtx, CTX|CONSTR,13, err_get_cs); /* CS error */ #endif } /************************************************************************/ /* err_get_cac */ /* error response is being decoded: context tagged error class has */ /* been encountered, get the error class and error code. */ /************************************************************************/ static ST_VOID err_get_cac (ASN1_DEC_CTXT *aCtx) { MLOG_CDEC0 ("err_get_cac"); err_info_ptr->eclass = aCtx->asn1r_elmnt_id; /* save the error class */ if (asn1r_get_i16 (aCtx, &(err_info_ptr->code))) /* read the error code */ asn1r_set_dec_err (aCtx, ERR_UNSPECIFIED); aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = err_class_cstr_done; /* choice cstr done */ } #ifdef CS_SUPPORT /************************************************************************/ /* err_get_cs */ /* error response is being decoded: context tagged error class 13 has */ /* been encountered, get the CS service error. */ /************************************************************************/ static ST_VOID err_get_cs (ASN1_DEC_CTXT *aCtx) { MLOG_CDEC0 ("err_get_cs"); err_info_ptr->adtnl.ss_error_data= aCtx->asn1r_field_ptr; /* save ptr to field */ err_info_ptr->adtnl.ss_error_len = aCtx->asn1r_elmnt_len; /* save len of field */ asn1r_parse_next (aCtx, err_cs_done); /* parse the contents */ } /************************************************************************/ /* err_cs_done */ /* Companion Standard service error has been parsed OK. */ /************************************************************************/ static ST_VOID err_cs_done (ASN1_DEC_CTXT *aCtx) { aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = err_class_cstr_done; /* choice cstr done */ } #endif /************************************************************************/ /* err_class_cstr_done */ /* errorClass constructor (choice) is complete */ /* set up to get additional (optional) information */ /************************************************************************/ static ST_VOID err_class_cstr_done (ASN1_DEC_CTXT *aCtx) { MLOG_CDEC0 ("err_class_cstr_done"); /* add tags for optional information */ ASN1R_TAG_ADD (aCtx, CTX, 1, err_get_add_code); ASN1R_TAG_ADD (aCtx, CTX, 2, err_get_add_descr); ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 3, err_add_ssi_cstr); aCtx->asn1r_decode_done_fun = _mms_dec_done_ok; if ((_mmsdec_rslt->type == MMSREQ) || /* terminate download request */ (_mmsdec_rslt->type == MMSUNREQ)) /* or Event Notification */ /* Terminate Download req or Event Notification unconfirmed */ /* request is being decoded, decode can be done, but check for */ /* companion standard information. */ _ms_set_cs_check (aCtx); else asn1r_set_all_cstr_done (aCtx); /* clear all cstr done funtions */ } /************************************************************************/ /* err_get_add_code */ /* error response is being decoded: additional error code has been */ /* encountered. */ /************************************************************************/ static ST_VOID err_get_add_code (ASN1_DEC_CTXT *aCtx) { MLOG_CDEC0 ("err_get_add_code"); err_info_ptr->adtnl.info_pres = SD_TRUE; /* set info present */ err_info_ptr->adtnl.code_pres = SD_TRUE; /* set code present */ /* read the additional error code */ if (asn1r_get_i32 (aCtx, &(err_info_ptr->adtnl.code))) asn1r_set_dec_err (aCtx, ERR_UNSPECIFIED); ASN1R_TAG_ADD (aCtx, CTX, 2, err_get_add_descr); ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 3, err_add_ssi_cstr); if ((_mmsdec_rslt->type == MMSREQ) || /* terminate download request */ (_mmsdec_rslt->type == MMSUNREQ)) /* or Event Notification */ /* Terminate Download req or Event Notification unconfirmed */ /* request is being decoded, decode can be done, but check for */ /* companion standard information. */ _ms_set_cs_check (aCtx); else asn1r_set_all_cstr_done (aCtx); /* clear all cstr done funtions */ } /************************************************************************/ /* err_get_add_descr */ /* error response is being decoded: additional error description has */ /* been encountered. */ /************************************************************************/ static ST_VOID err_get_add_descr (ASN1_DEC_CTXT *aCtx) { MLOG_CDEC0 ("err_get_add_descr"); err_info_ptr->adtnl.info_pres = SD_TRUE; /* set info present */ err_info_ptr->adtnl.descr_pres = SD_TRUE; /* set descr present */ /* read the additional error description */ /* copy error description back onto itself shifted by one character */ err_info_ptr->adtnl.descr = (ST_CHAR *)aCtx->asn1r_field_ptr -1; if (asn1r_get_vstr (aCtx, err_info_ptr->adtnl.descr)) asn1r_set_dec_err (aCtx, ERR_UNSPECIFIED); ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 3, err_add_ssi_cstr); if ((_mmsdec_rslt->type == MMSREQ) || /* terminate download request */ (_mmsdec_rslt->type == MMSUNREQ)) /* or Event Notification */ /* Terminate Download req or Event Notification unconfirmed */ /* request is being decoded, decode can be done, but check for */ /* companion standard information. */ _ms_set_cs_check (aCtx); else asn1r_set_all_cstr_done (aCtx); /* clear all cstr done funtions */ } /************************************************************************/ /* err_add_ssi_cstr */ /* error response is being decoded: additional service specific error */ /* information constructor has been encountered. */ /************************************************************************/ static ST_VOID err_add_ssi_cstr (ASN1_DEC_CTXT *aCtx) { MLOG_CDEC0 ("err_get_ssi_cstr"); /* add tags for all choices */ ASN1R_TAG_ADD (aCtx, CTX, 0, err_get_add_ssi_i16); ASN1R_TAG_ADD (aCtx, CTX, 1, err_get_add_ssi_i16); ASN1R_TAG_ADD (aCtx, CTX, 2, err_get_add_ssi_i16); ASN1R_TAG_ADD (aCtx, CTX, 3, err_get_add_ssi_i16); ASN1R_TAG_ADD (aCtx, CTX, 4, err_get_add_ssi_i16); ASN1R_TAG_ADD (aCtx, CTX, 5, err_get_add_ssi_u32); ASN1R_TAG_ADD (aCtx, CTX, 6, err_get_add_ssi_u32); ASN1R_TAG_ADD (aCtx, CTX, 7, err_get_add_ssi_u32); #ifndef MMS_LITE if (mms_chan_info[_mmsdechan].version) /* IS */ #else if (mmsl_version) /* IS */ #endif { ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 8, err_get_dee_obj_name); /* def ev enroll*/ ASN1R_TAG_ADD (aCtx, CTX, 9, err_get_add_ssi_i16); /* file rename */ ASN1R_TAG_ADD (aCtx, CTX|CONSTR,10, err_get_add_serv_err); /* adtnl service*/ } else { ASN1R_TAG_ADD (aCtx, CTX, 8, err_get_add_ssi_i16); /* file rename */ ASN1R_TAG_ADD (aCtx, CTX|CONSTR, 9, err_get_add_serv_err); /* adtnl service*/ } } /************************************************************************/ /* err_get_add_ssi_i16 */ /* error response is being decoded: additional service specific error */ /* information has been encountered for obtain file, start, stop, */ /* resume, reset or file rename. */ /************************************************************************/ static ST_VOID err_get_add_ssi_i16 (ASN1_DEC_CTXT *aCtx) { ST_INT16 ssi_error; MLOG_CDEC0 ("err_get_add_ssi_i16"); err_info_ptr->adtnl.info_pres = SD_TRUE; /* set info present indicator */ err_info_ptr->adtnl.ssi_pres = SD_TRUE; /* set additional service pres */ err_info_ptr->adtnl.service = aCtx->asn1r_elmnt_id; /* save the service id */ /* read the additional service error */ if (asn1r_get_i16 (aCtx, &ssi_error)) asn1r_set_dec_err (aCtx, ERR_UNSPECIFIED); else err_info_ptr->adtnl.ss_error_val = (ST_UINT32) ssi_error; aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = err_ssi_done; } /************************************************************************/ /* err_get_add_ssi_u32 */ /* error response is being decoded: additional service specific error */ /* information has been encountered for delete varaible access, delete */ /* named variable list or delete named type. */ /************************************************************************/ static ST_VOID err_get_add_ssi_u32 (ASN1_DEC_CTXT *aCtx) { MLOG_CDEC0 ("err_get_add_ssi_u32"); err_info_ptr->adtnl.info_pres = SD_TRUE; /* set info present indicator */ err_info_ptr->adtnl.ssi_pres = SD_TRUE; /* set additional service pres */ err_info_ptr->adtnl.service = aCtx->asn1r_elmnt_id; /* save the service id */ /* read the additional service error */ if (asn1r_get_u32 (aCtx, &(err_info_ptr->adtnl.ss_error_val))) asn1r_set_dec_err (aCtx, ERR_UNSPECIFIED); aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = err_ssi_done; } /************************************************************************/ /* err_get_dee_obj_name */ /* error response is being decoded: additional service specific error */ /* information has been encountered for define event enrollment error */ /* get the object name. */ /************************************************************************/ static ST_VOID err_get_dee_obj_name (ASN1_DEC_CTXT *aCtx) { MLOG_CDEC0 ("err_get_dee_obj_name"); err_info_ptr->adtnl.info_pres = SD_TRUE; /* set info present indicator */ err_info_ptr->adtnl.ssi_pres = SD_TRUE; /* set additional service pres */ err_info_ptr->adtnl.service = aCtx->asn1r_elmnt_id; /* save the service id */ /* read the object name */ _ms_get_mms_objname (aCtx, &err_info_ptr->adtnl.ss_error_oname, err_dee_obj_name_done); } /************************************************************************/ /* err_dee_obj_name_done */ /* define event enrollment error is being decoded: object name has */ /* been obtained. */ /************************************************************************/ static ST_VOID err_dee_obj_name_done (ASN1_DEC_CTXT *aCtx) { MLOG_CDEC0 ("err_dee_obj_name_done"); aCtx->asn1r_c_done_fun [aCtx->asn1r_msg_level] = err_adtnl_done; } /************************************************************************/ /* err_get_add_serv_err */ /* error response is being decoded: additional service specific error */ /* information has been encountered for additional service error. */ /************************************************************************/ static ST_VOID err_get_add_serv_err (ASN1_DEC_CTXT *aCtx) { MLOG_CDEC0 ("err_get_add_serv_err"); err_info_ptr->adtnl.info_pres = SD_TRUE; /* set info present indicator */ err_info_ptr->adtnl.ssi_pres = SD_TRUE; /* set additional service pres */ err_info_ptr->adtnl.service = aCtx->asn1r_elmnt_id; /* save the service id */ /* Companion Standard additional service error */ err_info_ptr->adtnl.ss_error_data = aCtx->asn1r_field_ptr; /* save ptr to field */ err_info_ptr->adtnl.ss_error_len = aCtx->asn1r_elmnt_len; /* save len of field */ asn1r_parse_next (aCtx, err_adtnl_done); /* parse contents */ } /************************************************************************/ /* err_adtnl_done */ /* IS: define event enrollment, object name has been obtained -OR- */ /* Companion Standard ANY has been parsed OK. Message is now done. */ /************************************************************************/ static ST_VOID err_adtnl_done (ASN1_DEC_CTXT *aCtx) { aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = err_ssi_done; } /************************************************************************/ /* err_ssi_done */ /* Service specific info constructor done */ /************************************************************************/ static ST_VOID err_ssi_done (ASN1_DEC_CTXT *aCtx) { if ((_mmsdec_rslt->type == MMSREQ) || /* terminate download request */ (_mmsdec_rslt->type == MMSUNREQ)) /* or Event Notification */ /* Terminate Download req or Event Notification unconfirmed */ /* request is being decoded, decode can be done, but check for */ /* companion standard information. */ _ms_set_cs_check (aCtx); else aCtx->asn1r_decode_done = SD_TRUE; /* just terminate the parse */ } #ifndef MMS_LITE /************************************************************************/ /************************************************************************/ /* mp_err_resp */ /* Create and send a general error response */ /************************************************************************/ ST_RET mp_err_resp (MMSREQ_IND *indptr, ST_INT16 class, ST_INT16 code) { ST_UCHAR *msg_ptr; /* pointer to start of message */ ST_INT msg_len; /* length of message built */ ST_RET ret; /* function return value */ ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ ASN1_ENC_CTXT *aCtx = &localEncCtx; S_LOCK_COMMON_RESOURCES (); if (!(ret = _ms_check_ind_actv (indptr))) { msg_ptr = _ms_mk_err_resp (aCtx, m_build_buf,mms_max_msgsize,indptr->op,indptr->id, class,code); msg_len = M_BUILD_BUF_END - msg_ptr; if (aCtx->asn1r_encode_overrun) /* Check for encode overrun */ ret = ME_ASN1_ENCODE_OVERRUN; else ret = _mms_send_data (indptr->chan, msg_len, msg_ptr, indptr->context, indptr->add_addr_info); /* If a response logging function is installed, call it */ if (!ret && m_log_error_resp_fun && (mms_debug_sel & MMS_LOG_RESP)) (*m_log_error_resp_fun) (indptr, class, code); _ms_ind_serve_done (indptr); } S_UNLOCK_COMMON_RESOURCES (); return (ret); } #else /************************************************************************/ /************************************************************************/ /* mpl_err_resp */ /* Create and send a general error response */ /* Initiate, Conclude, Confirmed Service */ /************************************************************************/ ST_RET mpl_err_resp (ST_INT opcode, ST_UINT32 invoke, ST_INT16 err_class, ST_INT16 code) { ST_INT ret; ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ ASN1_ENC_CTXT *aCtx = &localEncCtx; ERR_INFO err_info; S_LOCK_COMMON_RESOURCES (); mmsl_msg_start = _ms_mk_err_resp (aCtx, mmsl_enc_buf,mmsl_enc_buf_size,opcode,invoke, err_class,code); mmsl_msg_len = (mmsl_enc_buf + mmsl_enc_buf_size) - mmsl_msg_start; if (!aCtx->asn1r_encode_overrun) /* Check for encode overrun */ ret = SD_SUCCESS; else ret = ME_ASN1_ENCODE_OVERRUN; if ((mms_debug_sel & MMS_LOG_RESP) && ret == SD_SUCCESS && ml_log_error_resp_fun) { memset (&err_info, 0, sizeof (err_info)); err_info.code = code; err_info.eclass = err_class; (*ml_log_error_resp_fun) (invoke, &err_info); } S_UNLOCK_COMMON_RESOURCES (); return (ret); } #endif /************************************************************************/ /************************************************************************/ /* _ms_mk_err_resp */ /* This function is called to build a general error response. */ /* adtnl_err_info is a global variable containing additional error */ /* information. */ /************************************************************************/ ST_UCHAR *_ms_mk_err_resp (ASN1_ENC_CTXT *aCtx, ST_UCHAR *buf_ptr, ST_INT buf_len, ST_INT op, ST_UINT32 id, ST_INT16 err_class, ST_INT16 code) { ST_INT pdu_type; /* PDU type to go in error PDU. */ #ifdef DEBUG_SISCO ST_UCHAR *msg_start; /* These variables used for */ ST_INT msg_len; /* debug print only */ #endif asn1r_strt_asn1_bld (aCtx, buf_ptr,buf_len); /* init the ASN.1 tools */ _ms_wr_service_err (aCtx, err_class,code,&adtnl_err_info); /* Write SEQUENCE header and invoke id, if this opcode is NOT initiate */ /* or conclude. */ if ((op == MMSOP_INITIATE) || (op == MMSOP_CONCLUDE)) ; else { /* Finish the serviceError sequence. */ if (op == MMSOP_CANCEL) asn1r_fin_constr (aCtx, 1,CTX,DEF); /* context tag 1 for cancel */ else asn1r_fin_constr (aCtx, 2,CTX,DEF); /* context 2 for confirmed err */ #ifdef MOD_SUPPORT if (adtnl_err_info.mod_pos_pres) /* send the modifier position */ { asn1r_wr_u32 (aCtx, adtnl_err_info.mod_pos); asn1r_fin_prim (aCtx, 1,CTX); adtnl_err_info.mod_pos_pres = SD_FALSE; } #endif asn1r_wr_u32 (aCtx, id); /* Write the invoke ID. */ asn1r_fin_prim (aCtx, 0,CTX); /* conf and cancl both use CTX 0 tag */ } /* Reset add'l info structure to empty */ adtnl_err_info.info_pres = SD_FALSE; switch (op) { case MMSOP_INITIATE : pdu_type = MMSINITERR; break; case MMSOP_CONCLUDE : pdu_type = MMSCNCLERR; break; case MMSOP_CANCEL : pdu_type = MMSCANERR; break; default: pdu_type = MMSERROR; } #ifdef DEBUG_SISCO asn1r_fin_constr (aCtx, (ST_UINT16) pdu_type,CTX,DEF); msg_start = aCtx->asn1r_field_ptr + 1; msg_len = (buf_ptr + buf_len) - msg_start; MLOG_ENC1 ("ERROR Response built : len = %d ",msg_len); MLOG_ENCH (msg_len,msg_start); MLOG_PAUSEENC (NULL); return (msg_start); #else asn1r_fin_constr (aCtx, (ST_UINT16) pdu_type,CTX,DEF); return (aCtx->asn1r_field_ptr + 1); #endif } /************************************************************************/ /************************************************************************/ /* wr_service_err */ /************************************************************************/ ST_VOID _ms_wr_service_err (ASN1_ENC_CTXT *aCtx, ST_INT16 err_class, ST_INT16 code, ADTNL_ERR_RESP_INFO *adtnl_info) { ST_INT16 ssi_error; asn1r_strt_constr (aCtx); /* start sequence constructor */ if (adtnl_info->info_pres) { /* write additional info if present */ if (adtnl_info->ssi_pres) { /* write the service specific info */ asn1r_strt_constr (aCtx); switch (adtnl_info->service) { case 0 : /* obtain file */ case 1 : /* start */ case 2 : /* stop */ case 3 : /* resume */ case 4 : /* reset */ ssi_error = (ST_INT16) adtnl_info->ss_error_val; asn1r_wr_i16 (aCtx, ssi_error); asn1r_fin_prim (aCtx, adtnl_info->service,CTX); break; case 5 : /* delete variable access */ case 6 : /* delete named variable list */ case 7 : /* delete named type */ asn1r_wr_u32 (aCtx, adtnl_info->ss_error_val); asn1r_fin_prim (aCtx, adtnl_info->service,CTX); break; case 8 : #ifndef MMS_LITE if (mms_chan_info[_mmsdechan].version) /* IS */ #else if (mmsl_version) /* IS */ #endif { /* IS, define event enrollment */ asn1r_strt_constr (aCtx); _ms_wr_mms_objname (aCtx, &adtnl_info->ss_error_oname); asn1r_fin_constr (aCtx, 8,CTX,DEF); } else { /* DIS, file rename */ ssi_error = (ST_INT16) adtnl_info->ss_error_val; asn1r_wr_i16 (aCtx, ssi_error); asn1r_fin_prim (aCtx, adtnl_info->service,CTX); } break; case 9 : #ifndef MMS_LITE if (mms_chan_info[_mmsdechan].version) /* IS */ #else if (mmsl_version) /* IS */ #endif { /* IS, file rename */ ssi_error = (ST_INT16) adtnl_info->ss_error_val; asn1r_wr_i16 (aCtx, ssi_error); asn1r_fin_prim (aCtx, adtnl_info->service,CTX); } else { /* DIS, additional service err */ asn1r_strt_constr (aCtx); asn1r_wr_delmnt (aCtx, adtnl_info->ss_error_data,adtnl_info->ss_error_len); asn1r_fin_constr (aCtx, 9,CTX,DEF); } break; default: /* IS, additional service error */ asn1r_strt_constr (aCtx); asn1r_wr_delmnt (aCtx, adtnl_info->ss_error_data,adtnl_info->ss_error_len); asn1r_fin_constr (aCtx, 10,CTX,DEF); } asn1r_fin_constr (aCtx, 3,CTX,DEF); } if (adtnl_info->descr_pres) { /* write the additional description */ asn1r_wr_vstr (aCtx, adtnl_info->descr); asn1r_fin_prim (aCtx, 2,CTX); } if (adtnl_info->code_pres) { /* write the service specific info */ asn1r_wr_i32 (aCtx, adtnl_info->code); asn1r_fin_prim (aCtx, 1,CTX); } adtnl_info->info_pres = SD_FALSE; } asn1r_strt_constr (aCtx); /* start choice constructor */ asn1r_wr_i16 (aCtx, code); /* write the value */ asn1r_fin_prim (aCtx, err_class,CTX); /* finish the contents */ asn1r_fin_constr (aCtx, 0,CTX,DEF); /* context 0 cstr */ }