Files
microser/mmslib/mmsl/mmsinit.c

588 lines
20 KiB
C
Raw Normal View History

2026-06-15 15:48:16 +08:00
/************************************************************************/
/* SISCO SOFTWARE MODULE HEADER *****************************************/
/************************************************************************/
/* (c) Copyright Systems Integration Specialists Company, Inc., */
/* 1986 - 2001, All Rights Reserved. */
/* */
/* PROPRIETARY AND CONFIDENTIAL */
/* */
/* MODULE NAME : mmsinit.c */
/* PRODUCT(S) : MMSEASE, MMSEASE-LITE */
/* */
/* MODULE DESCRIPTION : */
/* This module contains the common functions to decode and encode */
/* an initiate operation. Note that the initiate request and the */
/* initiate response are the same. */
/* */
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
/* */
/* MODIFICATION LOG : */
/* Date Who Rev Comments */
/* -------- --- ------ ------------------------------------------- */
/* 03/31/03 JRB 06 Support MMS Version2. */
/* asn1r_get_bitstr: add max_bits arg. */
/* If received bitstr too long, truncate. */
/* If received bitstr too short, set missing bits=0*/
/* 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 */
/* 12/10/97 MDE 02 Chaned max_nest to ST_INT8 */
/* 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 "mmsdefs.h"
#include "mms_pcon.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
#define MMS_V0_PARAM_SUPP_BITS 7 /* DIS */
#define MMS_V1_PARAM_SUPP_BITS 11
#define MMS_V1_SERV_SUPP_BITS 85
/************************************************************************/
static INIT_INFO *info;
#ifdef CS_SUPPORT
static CS_INIT_INFO *cs_info;
static ST_UCHAR *init_detail_start;
#endif
static ST_BOOLEAN request; /* req/resp flag */
static ST_RET val_err; /* asn1_set_dec_err code for bad value */
/************************************************************************/
/* static functions in this module */
static ST_VOID get_maxseg (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_maxreq_calling (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_maxreq_called (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_max_nest (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_detail_seq (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_version (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_param_prim (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_param_cstr (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_param_done (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_services_cstr (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_services_prim (ASN1_DEC_CTXT *aCtx);
static ST_VOID get_services_done (ASN1_DEC_CTXT *aCtx);
static ST_VOID mms_detail_cstr_done (ASN1_DEC_CTXT *aCtx);
static ST_VOID init_seq_done (ASN1_DEC_CTXT *aCtx);
/************************************************************************/
/************************************************************************/
/* _mms_init_dec */
/* This function is called from mmsdec.c when an initiate (req or resp) */
/* is being decoded. We are in the InitiatePDU sequence. */
/* Allocate an operation specific structure and set up to get either */
/* the segment size or the max outstanding calling */
/************************************************************************/
ST_VOID _mms_init_dec (ASN1_DEC_CTXT *aCtx, ST_BOOLEAN req)
{
request = req; /* save the request flag */
if (request)
val_err = REQ_BAD_VALUE;
else
val_err = RESP_BAD_VALUE;
/* Create an init_info structure data area to put the decoded info into.*/
/* CRITICAL: "info" struct must be calloc'd, so if received bitstrings
* are too short, the missing bits=0.
*/
#ifdef CS_SUPPORT
if (_mmsdec_ctxt == MMS_PCI)
info = (INIT_INFO *) _m_get_dec_buf (aCtx, sizeof (INIT_INFO));
else
cs_info = (CS_INIT_INFO *) _m_get_dec_buf (aCtx, sizeof (CS_INIT_INFO));
#else
info = (INIT_INFO *) _m_get_dec_buf (aCtx, sizeof (INIT_INFO));
#endif
ASN1R_TAG_ADD (aCtx, CTX,0,get_maxseg); /* max seg size (opt) */
ASN1R_TAG_ADD (aCtx, CTX,1,get_maxreq_calling); /* max outstdg calling */
}
/************************************************************************/
/* get_maxseg */
/* The max_msgsegsize parameter has been encountered. Read its value. */
/************************************************************************/
static ST_VOID get_maxseg (ASN1_DEC_CTXT *aCtx)
{
ST_INT32 local_detail;
MLOG_CDEC0 ("get_maxseg");
if (asn1r_get_i32 (aCtx, &local_detail) || local_detail < 0)
{
if (request)
asn1r_set_dec_err (aCtx, REQ_INVAL_ARG);
else
asn1r_set_dec_err (aCtx, RESP_INVAL_RSLT);
}
else
{
#ifdef CS_SUPPORT
if (_mmsdec_ctxt == MMS_PCI)
{
info->max_segsize_pres = SD_TRUE; /* set present flag for segsize */
info->max_segsize = local_detail;
}
else
{
cs_info->local_detail_pres = SD_TRUE; /* set present flag */
cs_info->local_detail = local_detail;
}
#else
info->max_segsize_pres = SD_TRUE; /* set present flag for segsize */
info->max_segsize = local_detail;
#endif
ASN1R_TAG_ADD (aCtx, CTX,1,get_maxreq_calling);
}
}
/************************************************************************/
/* get_maxreq_calling */
/* proposed/negiotiated max outstanding calling encountered */
/************************************************************************/
static ST_VOID get_maxreq_calling (ASN1_DEC_CTXT *aCtx)
{
ST_INT16 maxreq_calling;
MLOG_CDEC0 ("get_maxreq_calling");
/* Get the value of the maxreq_calling parameter. */
if (asn1r_get_i16 (aCtx, &maxreq_calling))
asn1r_set_dec_err (aCtx, val_err);
#ifdef CS_SUPPORT
if (_mmsdec_ctxt == MMS_PCI)
info->maxreq_calling = maxreq_calling;
else
cs_info->maxreq_calling = maxreq_calling;
#else
info->maxreq_calling = maxreq_calling;
#endif
/* The next data element is the maxreq_called parameter. */
ASN1R_TAG_ADD (aCtx, CTX,2,get_maxreq_called);
}
/************************************************************************/
/* get_maxreq_called */
/* proposed/negiotiated max outstanding called encountered */
/************************************************************************/
static ST_VOID get_maxreq_called (ASN1_DEC_CTXT *aCtx)
{
ST_INT16 maxreq_called;
MLOG_CDEC0 ("get_maxreq_called");
/* Get the value of the maxreq_called parameter. */
if (asn1r_get_i16 (aCtx, &maxreq_called))
asn1r_set_dec_err (aCtx, val_err);
#ifdef CS_SUPPORT
if (_mmsdec_ctxt == MMS_PCI)
info->maxreq_called = maxreq_called;
else
cs_info->maxreq_called = maxreq_called;
#else
info->maxreq_called = maxreq_called;
#endif
/* The next data element is either the max_nest parameter (optional) or */
/* the initiate detail sequence or the CS detail. */
/* All are optional, so we could be done */
aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = init_seq_done;
ASN1R_TAG_ADD (aCtx, CTX,3,get_max_nest);
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,4,get_detail_seq);
}
/************************************************************************/
/* get_max_nest */
/* The max_nest parameter has been encountered. Read its value. */
/************************************************************************/
static ST_VOID get_max_nest (ASN1_DEC_CTXT *aCtx)
{
ST_INT8 max_nest;
MLOG_CDEC0 ("get_max_nest");
/* Get the value of the max_nest parameter. */
if (asn1r_get_i8 (aCtx, &max_nest))
asn1r_set_dec_err (aCtx, val_err);
else
{
#ifdef CS_SUPPORT
if (_mmsdec_ctxt == MMS_PCI)
{
info->max_nest_pres = SD_TRUE;
info->max_nest = max_nest;
}
else
{
cs_info->max_nest_pres = SD_TRUE;
cs_info->max_nest = max_nest;
/* Initiate detail sequence may be next, or CS detail */
init_detail_start = aCtx->asn1r_field_ptr;
}
#else
info->max_nest_pres = SD_TRUE;
info->max_nest = max_nest;
#endif
}
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,4,get_detail_seq);
}
/************************************************************************/
/* get_detail_seq */
/* The mms init detail sequence is now starting, first is version # */
/************************************************************************/
static ST_VOID get_detail_seq (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("get_detail_seq");
/* Check if decoding an MMS CORE Initiate or a CS Initiate */
#ifdef CS_SUPPORT
if (_mmsdec_ctxt == MMS_PCI)
{
info->mms_detail_pres = SD_TRUE; /* set detail present flag */
ASN1R_TAG_ADD (aCtx, CTX,0,get_version); /* Next comes version */
}
else /* Companion Standard Initiate, accept sequence */
asn1r_parse_cstr_contents (aCtx, mms_detail_cstr_done);
#else
info->mms_detail_pres = SD_TRUE; /* set detail present flag */
ASN1R_TAG_ADD (aCtx, CTX,0,get_version); /* Next comes version */
#endif
}
/************************************************************************/
/* get_version */
/* The mms init detail sequence is now starting, this is version # */
/************************************************************************/
static ST_VOID get_version (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("get_version");
/* Get the value of the max_nest parameter. */
if (asn1r_get_i16 (aCtx, &info->version) || info->version <0)
asn1r_set_dec_err (aCtx, val_err);
/* Next is parameter support options, a 6 bit bitstring (prim or cstr) */
ASN1R_TAG_ADD (aCtx, CTX,1,get_param_prim);
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,1,get_param_cstr);
}
/************************************************************************/
/* get_param_prim */
/* The parameter support BS has been encountered as a primitive data */
/* element. Read its value. */
/************************************************************************/
static ST_VOID get_param_prim (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("get_param_prim");
/* NOTE: decode only the bits we recognize.
* For version0 (DIS) should get 7 bits.
* For version1 (IS) should get 11 bits.
* For version2 and higher, may get more than 11, but we ignore the
* higher bits because we don't support them.
*/
if (!asn1r_get_bitstr (aCtx, info->param_supp, MMS_V1_PARAM_SUPP_BITS))
get_param_done (aCtx); /* set up for the next data element */
else
asn1r_set_dec_err (aCtx, val_err);
}
/************************************************************************/
/* get_param_cstr */
/* The parameter suport has been encountered as a constructor data */
/* element. Read its value. */
/************************************************************************/
static ST_VOID get_param_cstr (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("get_param_cstr");
/* Set up to call this function when done with constructor bitstring. */
aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = get_param_done;
/* Get the value of the parameter support. For constructor */
/* bitstrings, this requires returning and letting the ASN.1 tools */
/* parse it to any nesting level. */
asn1r_get_bitstr_cstr (aCtx, MMS_V1_PARAM_SUPP_BITS,info->param_supp);
}
/************************************************************************/
/* get_param_done */
/* Function called after the supported parameter has been parsed. */
/************************************************************************/
static ST_VOID get_param_done (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("get_param_done");
ASN1R_TAG_ADD (aCtx, CTX,2,get_services_prim);
ASN1R_TAG_ADD (aCtx, CTX|CONSTR,2,get_services_cstr);
}
/************************************************************************/
/* get_services_prim */
/* The services support BS has been encountered as a primitive data */
/* element. Read its value. */
/************************************************************************/
static ST_VOID get_services_prim (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("get_services_prim");
/* NOTE: decode only the bits we recognize.
* For version0 (DIS) and version1 (IS) should get 85 bits.
* For version2 and higher, may get more than 85, but we ignore the
* higher bits because we don't support them.
*/
if (!asn1r_get_bitstr (aCtx, info->serv_supp, MMS_V1_SERV_SUPP_BITS))
get_services_done (aCtx); /* set up for the next data element */
else
asn1r_set_dec_err (aCtx, val_err);
}
/************************************************************************/
/* get_services_cstr */
/* The service suport BS has been encountered as a constructor data */
/* element. Read its value. */
/************************************************************************/
static ST_VOID get_services_cstr (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("get_services_cstr");
/* Set up to call this function when done with constructor bitstring. */
aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = get_services_done;
/* Get the value of the service support. For constructor */
/* bitstrings, this requires returning and letting the ASN.1 tools */
/* parse it to any nesting level. */
asn1r_get_bitstr_cstr (aCtx, MMS_V1_SERV_SUPP_BITS,info->serv_supp);
}
/************************************************************************/
/* get_services_done */
/* Function called when entire mms_detail constructor is done */
/************************************************************************/
static ST_VOID get_services_done (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("get_services_done");
aCtx->asn1r_c_done_fun[aCtx->asn1r_msg_level] = mms_detail_cstr_done;
}
/************************************************************************/
/* mms_detail_cstr_done */
/* Function called when entire mms_detail constructor is done */
/************************************************************************/
static ST_VOID mms_detail_cstr_done (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("mms_detail_cstr_done");
#ifdef CS_SUPPORT
if (_mmsdec_ctxt != MMS_PCI)
{
cs_info->init_detail_len = aCtx->asn1r_field_ptr - init_detail_start;
cs_info->init_detail = init_detail_start;
}
#endif
}
/************************************************************************/
/* init_seq_done */
/* The parse of the Initiate PDU is complete, either with or without */
/* CS detail. Just set decode done flag. */
/************************************************************************/
static ST_VOID init_seq_done (ASN1_DEC_CTXT *aCtx)
{
MLOG_CDEC0 ("init_seq_done");
aCtx->asn1r_decode_done = SD_TRUE;
aCtx->asn1r_decode_done_fun = _mms_dec_done_ok;
}
/************************************************************************/
/************************************************************************/
/* _ms_mk_init */
/* Function to construct an Initiate request or response PDU in the */
/* selected buffer. Pass a pointer to the end of the build buffer, and */
/* a pointer to a structure of type init_info that contains the build */
/* control and data information. Returns a pointer to the first byte */
/* of the encoded message. */
/************************************************************************/
ST_UCHAR *_ms_mk_init (ASN1_ENC_CTXT *aCtx, ST_UCHAR *buf_ptr, ST_INT buf_len,
INIT_INFO *info_ptr, ST_INT pdutype,
ST_BOOLEAN cs_init)
{
#ifdef DEBUG_SISCO
ST_UCHAR *msg_start; /* These variables used for */
ST_INT msg_len; /* debug print only. */
#endif
#ifdef CS_SUPPORT
CS_INIT_INFO *cs_init_ptr;
#endif
asn1r_strt_asn1_bld (aCtx, buf_ptr,buf_len); /* Initialize the ASN.1 tools */
#ifdef CS_SUPPORT
if (cs_init) /* COMPANION STANDARD INITIATE PDU */
{
cs_init_ptr = (CS_INIT_INFO *) info_ptr;
/* write the CS init detail constructor */
asn1r_strt_constr (aCtx); /* start the CTX 5 cstr */
asn1r_wr_octstr (aCtx, cs_init_ptr->init_detail,cs_init_ptr->init_detail_len);
asn1r_fin_constr (aCtx, 4,CTX,DEF); /* close the CS detail cstr */
/* maximum data nesting (optional) */
if (cs_init_ptr->max_nest_pres) /* if desired to send - */
{
asn1r_wr_i8 (aCtx, (ST_CHAR)cs_init_ptr->max_nest);
asn1r_fin_prim (aCtx, 3,CTX); /* context-specific, tag 2 */
}
/* max outstanding requests from called MMS-user */
asn1r_wr_i16 (aCtx, cs_init_ptr->maxreq_called);
asn1r_fin_prim (aCtx, 2,CTX); /* context-specific, tag 2 */
/* max outstanding requests from calling MMS-user */
asn1r_wr_i16 (aCtx, cs_init_ptr->maxreq_calling);
asn1r_fin_prim (aCtx, 1,CTX); /* context-specific, tag 1 */
/* max segment size (optional) */
if (cs_init_ptr->local_detail_pres) /* if enabled */
{
asn1r_wr_i32 (aCtx, cs_init_ptr->local_detail);
asn1r_fin_prim (aCtx, 0,CTX); /* context-specific, tag 0 */
}
}
else /* MMS CORE INITIATE PDU */
{
#endif
/* Now begin writing primitive data elements from back of PDU to front. */
/* write the mms init detail constructor, if enabled */
if (info_ptr->mms_detail_pres) /* if we have MMS detail */
{
asn1r_strt_constr (aCtx);
asn1r_wr_bitstr (aCtx, info_ptr->serv_supp,MMS_V1_SERV_SUPP_BITS); /* services supported BS */
asn1r_fin_prim (aCtx, 2,CTX); /* context-specific, tag 2 */
/* parameters supported BS, write either 7 (DIS) or 11 (IS) bits */
if (info_ptr->version == 0) /* If DIS is being proposed */
{
asn1r_wr_bitstr (aCtx, info_ptr->param_supp,MMS_V0_PARAM_SUPP_BITS);
asn1r_fin_prim (aCtx, 1,CTX);
}
else /* IS is being proposed */
{
asn1r_wr_bitstr (aCtx, info_ptr->param_supp,MMS_V1_PARAM_SUPP_BITS);
asn1r_fin_prim (aCtx, 1,CTX); /* context-specific, tag 1 */
}
asn1r_wr_i16 (aCtx, info_ptr->version); /* version number */
asn1r_fin_prim (aCtx, 0,CTX); /* context-specific, tag 0 */
asn1r_fin_constr (aCtx, 4,CTX,DEF); /* close the MMS detail cstr */
}
/* Now write the core initiate parameters */
/* maximum data nesting (optional) */
if (info_ptr->max_nest_pres) /* if desired to send - */
{
asn1r_wr_i8 (aCtx, (ST_CHAR)info_ptr->max_nest);
asn1r_fin_prim (aCtx, 3,CTX); /* context-specific, tag 2 */
}
/* max outstanding requests from called MMS-user */
asn1r_wr_i16 (aCtx, info_ptr->maxreq_called);
asn1r_fin_prim (aCtx, 2,CTX); /* context-specific, tag 2 */
/* max outstanding requests from calling MMS-user */
asn1r_wr_i16 (aCtx, info_ptr->maxreq_calling);
asn1r_fin_prim (aCtx, 1,CTX); /* context-specific, tag 1 */
/* max segment size (optional) */
if (info_ptr->max_segsize_pres) /* if enabled */
{
asn1r_wr_i32 (aCtx, info_ptr->max_segsize);
asn1r_fin_prim (aCtx, 0,CTX); /* context-specific, tag 0 */
}
#ifdef CS_SUPPORT
}
#endif
/* Close the PDU. Building of either the request or response message */
/* is complete. */
#ifdef DEBUG_SISCO
asn1r_fin_constr (aCtx, (ST_UINT16) pdutype,CTX,DEF);
msg_start = aCtx->asn1r_field_ptr + 1;
msg_len = (buf_ptr + buf_len) - msg_start;
MLOG_ENC2 ("INITIATE %s built, len = %d",
pdutype == MMSINITREQ ? "request" : "response",
msg_len);
MLOG_ENCH (msg_len,msg_start);
MLOG_PAUSEENC (NULL);
return (msg_start);
#else
asn1r_fin_constr (aCtx, (ST_UINT16) pdutype,CTX,DEF);
return (aCtx->asn1r_field_ptr + 1);
#endif
}