439 lines
15 KiB
C
439 lines
15 KiB
C
/************************************************************************/
|
|
/* SISCO SOFTWARE MODULE HEADER *****************************************/
|
|
/************************************************************************/
|
|
/* (c) Copyright Systems Integration Specialists Company, Inc., */
|
|
/* 1994 - 1996, All Rights Reserved */
|
|
/* */
|
|
/* MODULE NAME : s_write.c */
|
|
/* PRODUCT(S) : MMSEASE-LITE */
|
|
/* */
|
|
/* MODULE DESCRIPTION : */
|
|
/* */
|
|
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
|
|
/* NONE */
|
|
/* */
|
|
/* MODIFICATION LOG : */
|
|
/* Date Who Rev Comments */
|
|
/* -------- --- ------ ------------------------------------------- */
|
|
/* 02/02/09 JRB 32 Chk va_to_free before ...free_va. */
|
|
/* 01/23/09 MDE 31 Use 0x%X for hex values in log msgs. */
|
|
/* 01/13/09 MDE 30 Free VA (and temp type) in case of errors */
|
|
/* 05/01/08 JRB 29 Chk ms_asn1_to_local return & set */
|
|
/* WRITE_RESULT "failure" appropriately. */
|
|
/* 04/09/07 MDE 28 Enhanced filtered logging */
|
|
/* 10/30/06 JRB 27 Use new mvl_vmd_* object handling functions. */
|
|
/* Add args on call to _mvl_objname_to_va. */
|
|
/* Elim use of global "_mvl_curr_net_info". */
|
|
/* Elim use of global "_mvl_curr_usr_ind_ctrl". */
|
|
/* 08/09/06 JRB 26 ALWAYS set resp_tag & failure in wr_rslt */
|
|
/* same as in vaCtrl. In put_asn1_data, set */
|
|
/* vaCtrl->failure to appropriate value. */
|
|
/* 01/30/06 GLB 25 Integrated porting changes for VMS */
|
|
/* 05/16/05 JRB 24 Send appropriate failure codes in write resp.*/
|
|
/* Move statistics code so it is always executed*/
|
|
/* 03/13/03 JRB 23 Use mvl_type_ctrl_find. */
|
|
/* 07/24/02 JRB 22 Use mvl_send_resp_i like ALL responses. */
|
|
/* 07/09/02 MDE 21 Add maxpend_ind support */
|
|
/* 09/21/01 JRB 20 Alloc global bufs only once at startup. */
|
|
/* 05/25/01 MDE 19 Moved where the old data is saved */
|
|
/* 03/30/01 MDE 18 Changed MSMEM_ENC_INFO to MSMEM_ENC_OS_INFO */
|
|
/* 10/25/00 JRB 17 Del u_mvl funct ptrs. Call functs directly. */
|
|
/* Control with #ifdefs. */
|
|
/* 10/06/00 MDE 16 Now restore old data for write failure */
|
|
/* 05/15/00 MDE 15 Added MMS statistics */
|
|
/* 01/21/00 MDE 14 Now use MEM_SMEM for dynamic memory */
|
|
/* 11/22/99 JRB 13 mvlas_write_resp: del indCtrl from link list */
|
|
/* 09/13/99 MDE 12 Added SD_CONST modifiers */
|
|
/* 04/07/99 MDE 11 Logging improvements */
|
|
/* 12/11/98 MDE 10 Removed scope references from VA */
|
|
/* 12/08/98 MDE 09 Fixed write handling for alternate access */
|
|
/* 11/16/98 MDE 08 Renamed internal functions (prefix '_') */
|
|
/* 09/21/98 MDE 07 Minor lint cleanup */
|
|
/* 06/15/98 MDE 06 Changes to allow compile under C++ */
|
|
/* 05/15/98 JRB 05 Chg mvl_process.. arg to (MVL_IND_PEND *). */
|
|
/* 05/15/98 JRB 04 Call u_mvl_write_ind direct (no funct ptr). */
|
|
/* 02/20/98 MDE 03 Fixed usrVa set problem */
|
|
/* 02/10/98 MDE 02 Removed NEST_RT_TYPES, always support AA, */
|
|
/* added 'u_mvl_wr_ind_start' and */
|
|
/* 'u_mvl_wr_resp_sent', other */
|
|
/* 09/10/97 MDE 01 MMS-LITE V4.0 Release */
|
|
/************************************************************************/
|
|
|
|
#include "glbtypes.h"
|
|
#include "sysincs.h"
|
|
#include "mmsdefs.h"
|
|
#include "mms_pvar.h"
|
|
#include "mms_vvar.h"
|
|
#include "mvl_defs.h"
|
|
#include "mvl_log.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
|
|
|
|
/************************************************************************/
|
|
|
|
ST_RET (*u_mvl_wr_ind_start) (MVL_IND_PEND *indCtrl);
|
|
ST_VOID (*u_mvl_wr_resp_sent) (MVL_IND_PEND *indCtrl);
|
|
|
|
/************************************************************************/
|
|
/* Internal functions */
|
|
|
|
static ST_VOID put_asn1_data (MVL_IND_PEND *indCtrl, VARIABLE_LIST *vl,
|
|
ST_UCHAR *asn1_buffer, ST_INT asn1_len,
|
|
MVLAS_WR_VA_CTRL *vaCtrl);
|
|
|
|
/************************************************************************/
|
|
/************************************************************************/
|
|
/* _mvl_process_write_ind */
|
|
/* A write indication has been received, process it and respond */
|
|
/************************************************************************/
|
|
|
|
ST_VOID _mvl_process_write_ind (MVL_IND_PEND *indCtrl)
|
|
{
|
|
MVLAS_WRITE_CTRL *wrCtrl;
|
|
MVLAS_WR_VA_CTRL *vaCtrl;
|
|
WRITE_REQ_INFO *write_info;
|
|
ST_INT num_var;
|
|
VARIABLE_LIST *vl_ptr;
|
|
VAR_ACC_DATA *va_ptr;
|
|
ST_INT i;
|
|
ST_RET rc;
|
|
|
|
write_info = (WRITE_REQ_INFO *) indCtrl->event->u.mms.dec_rslt.data_ptr;
|
|
num_var = write_info->va_spec.num_of_variables;
|
|
|
|
/* verify that this is a list of variables */
|
|
if (write_info->va_spec.var_acc_tag != VAR_ACC_VARLIST)
|
|
{
|
|
_mplas_err_resp (indCtrl,7,2); /* access, non-existent */
|
|
return;
|
|
}
|
|
|
|
if (u_mvl_wr_ind_start)
|
|
{
|
|
/* This might set optional user pointer "indCtrl->usr_ind_ctrl". */
|
|
rc = (*u_mvl_wr_ind_start) (indCtrl);
|
|
if (rc != SD_SUCCESS)
|
|
{
|
|
_mplas_err_resp (indCtrl,7,2); /* access, non-existent */
|
|
return;
|
|
}
|
|
}
|
|
|
|
wrCtrl = &indCtrl->u.wr;
|
|
wrCtrl->vaCtrlTbl = (MVLAS_WR_VA_CTRL *) M_CALLOC (MSMEM_GEN, num_var,
|
|
sizeof(MVLAS_WR_VA_CTRL));
|
|
vaCtrl = wrCtrl->vaCtrlTbl;
|
|
wrCtrl->numVar = num_var;
|
|
|
|
/* Looks OK, prepare to process each variable in the list */
|
|
vl_ptr = (VARIABLE_LIST *) (write_info+1);
|
|
va_ptr = write_info->va_data;
|
|
|
|
for (i = 0; i < num_var; ++i, ++vl_ptr, ++va_ptr, ++vaCtrl)
|
|
put_asn1_data (indCtrl, vl_ptr, va_ptr->data, va_ptr->len, vaCtrl);
|
|
|
|
u_mvl_write_ind (indCtrl);
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* mvlas_write_resp */
|
|
/************************************************************************/
|
|
|
|
ST_VOID mvlas_write_resp (MVL_IND_PEND *indCtrl)
|
|
{
|
|
MVLAS_WRITE_CTRL *wrCtrl;
|
|
MVLAS_WR_VA_CTRL *vaCtrl;
|
|
MVL_COMM_EVENT *event;
|
|
MVL_NET_INFO *net_info;
|
|
ST_RET rc;
|
|
ST_CHAR *resp_buf;
|
|
ST_INT num_var;
|
|
ST_INT va_data_size;
|
|
WRITE_RESP_INFO *resp_info;
|
|
WRITE_RESULT *wr_rslt;
|
|
ST_INT i;
|
|
MVL_TYPE_CTRL *type_ctrl;
|
|
|
|
net_info = indCtrl->event->net_info;
|
|
event = indCtrl->event;
|
|
wrCtrl = &indCtrl->u.wr;
|
|
vaCtrl = wrCtrl->vaCtrlTbl;
|
|
num_var = wrCtrl->numVar;
|
|
|
|
resp_buf = (ST_CHAR *) M_CALLOC (MSMEM_ENC_OS_INFO, 1, sizeof(WRITE_RESP_INFO) +
|
|
(num_var * sizeof (WRITE_RESULT)));
|
|
|
|
/* Create a write response info struct */
|
|
resp_info = (WRITE_RESP_INFO *) resp_buf;
|
|
resp_info->num_of_result = num_var;
|
|
wr_rslt = (WRITE_RESULT *) (resp_info +1);
|
|
|
|
for (i = 0; i < num_var; ++i, ++wr_rslt, ++vaCtrl)
|
|
{
|
|
wr_rslt->resp_tag = vaCtrl->resp_tag;
|
|
wr_rslt->failure = vaCtrl->failure;
|
|
if (vaCtrl->va != NULL)
|
|
{
|
|
if (wr_rslt->resp_tag == WR_RSLT_FAILURE)
|
|
{ /* On a failure, restore the previous data */
|
|
type_ctrl = mvl_type_ctrl_find (vaCtrl->va->type_id);
|
|
va_data_size = type_ctrl->data_size;
|
|
memcpy (vaCtrl->va->data, vaCtrl->oldData, va_data_size);
|
|
}
|
|
M_FREE (MSMEM_GEN, vaCtrl->oldData);
|
|
#if defined(MVL_UCA) || defined(USE_MANUFACTURED_OBJS)
|
|
if (vaCtrl->va->va_to_free != NULL)
|
|
u_mvl_free_va (MMSOP_WRITE, vaCtrl->va, event->net_info);
|
|
#endif /* defined(MVL_UCA) || defined(USE_MANUFACTURED_OBJS) */
|
|
}
|
|
|
|
if (wr_rslt->resp_tag == WR_RSLT_SUCCESS)
|
|
++mvl_mms_statistics.serverVarWrOk;
|
|
else
|
|
++mvl_mms_statistics.serverVarWrErr;
|
|
} /* end loop */
|
|
|
|
/* Build a write response */
|
|
rc = mpl_write_resp (event->u.mms.dec_rslt.id, resp_info);
|
|
if (rc == SD_SUCCESS)
|
|
mpl_resp_log (indCtrl, resp_info);
|
|
|
|
if (u_mvl_wr_resp_sent)
|
|
(*u_mvl_wr_resp_sent) (indCtrl);
|
|
|
|
M_FREE (MSMEM_ENC_OS_INFO, resp_buf);
|
|
M_FREE (MSMEM_GEN, wrCtrl->vaCtrlTbl);
|
|
|
|
/* NOTE: This funct frees indCtrl. DO NOT use after this. */
|
|
/* NOTE: if rc != SD_SUCCESS, this funct sends error resp. */
|
|
_mvl_send_resp_i (indCtrl, rc);
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* put_asn1_data */
|
|
/* This function is to provide ASN.1 encoded data, given the variable */
|
|
/* list element. */
|
|
/************************************************************************/
|
|
|
|
static ST_VOID put_asn1_data (MVL_IND_PEND *indCtrl, VARIABLE_LIST *vl,
|
|
ST_UCHAR *asn1_buffer, ST_INT asn1_len,
|
|
MVLAS_WR_VA_CTRL *vaCtrl)
|
|
{
|
|
MVL_VAR_ASSOC *va;
|
|
RUNTIME_TYPE *rt;
|
|
ST_INT num_rt;
|
|
ST_RET rc;
|
|
ST_CHAR *temp_data_buf;
|
|
ST_CHAR *va_data;
|
|
ST_INT va_data_size;
|
|
ST_INT aa_mode;
|
|
ALT_ACCESS alt_acc; /* Alternate Access specification */
|
|
ST_BOOLEAN alt_access_pres;
|
|
ST_BOOLEAN alt_access_done;
|
|
MVL_TYPE_CTRL *type_ctrl;
|
|
|
|
/* There are more ways to fail than to succeed! */
|
|
/* Assume failure=ARE_TYPE_INCONSISTENT, but may be changed in some cases.*/
|
|
vaCtrl->resp_tag = WR_RSLT_FAILURE;
|
|
vaCtrl->failure = ARE_TYPE_INCONSISTENT;
|
|
|
|
alt_access_pres = vl->alt_access_pres;
|
|
if (alt_access_pres) /* no alternate access support now */
|
|
{
|
|
#if !defined(MVL_AA_SUPP)
|
|
MVL_LOG_NERR0 ("Put ASN1 Data : Alternate Access not supported");
|
|
return;
|
|
#else
|
|
/* now create the AA, given the ASN.1 spec */
|
|
if (ms_asn1_to_aa (vl->alt_access.data, vl->alt_access.len,
|
|
&alt_acc))
|
|
{
|
|
MVL_LOG_NERR0 ("Write Indication : ASN.1 -> AA failure");
|
|
return;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
switch (vl->var_spec.var_spec_tag)
|
|
{
|
|
case VA_SPEC_NAMED :
|
|
va = _mvl_objname_to_va (&mvl_vmd, indCtrl->event->net_info, MMSOP_WRITE, &vl->var_spec.vs.name,
|
|
&vaCtrl->va_scope,
|
|
alt_access_pres,
|
|
&alt_acc,
|
|
&alt_access_done);
|
|
|
|
if (alt_access_pres && alt_access_done)
|
|
{
|
|
M_FREE (MSMEM_GEN, alt_acc.aa);
|
|
alt_access_pres = SD_FALSE;
|
|
}
|
|
|
|
if (!va) /* could not find variable association */
|
|
{
|
|
MVL_LOG_NERR1 ("Write ind : Variable Association '%s' not found",
|
|
vl->var_spec.vs.name.obj_name.vmd_spec);
|
|
vaCtrl->failure = ARE_OBJ_NONEXISTENT;
|
|
return;
|
|
}
|
|
|
|
vaCtrl->va = va;
|
|
va->usr_ind_ctrl = indCtrl->usr_ind_ctrl; /* save optional user pointer in va*/
|
|
|
|
/* Save the current data in case the user rejects the write */
|
|
|
|
type_ctrl = mvl_type_ctrl_find (va->type_id); /* find type */
|
|
va_data_size = type_ctrl->data_size;
|
|
vaCtrl->oldData = (ST_UCHAR *) M_MALLOC (MSMEM_GEN, va_data_size);
|
|
memcpy (vaCtrl->oldData, va->data, va_data_size);
|
|
|
|
/* We have obtained a variable association */
|
|
/* Now do the alternate access preprocess function if appropriate */
|
|
|
|
#if defined(MVL_AA_SUPP)
|
|
aa_mode = MVL_USE_UNPACKED_AA;
|
|
if (alt_access_pres && va->proc && va->proc->proc_write_aa)
|
|
{
|
|
rc = (*va->proc->proc_write_aa)(&va, &alt_acc,
|
|
indCtrl->event->net_info, &aa_mode);
|
|
|
|
if (rc != SD_SUCCESS)
|
|
{
|
|
MVL_LOG_NERR1 ("Write : proc_write_aa returned %d", rc);
|
|
return;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
/* Now take care of the data conversion (asn1 to local) */
|
|
rc = mvl_get_runtime (va->type_id, &rt, &num_rt);
|
|
if (rc != SD_SUCCESS)
|
|
{
|
|
M_FREE (MSMEM_GEN, vaCtrl->oldData);
|
|
MVL_LOG_NERR1 ("Could not get type_id %d", va->type_id);
|
|
vaCtrl->va = NULL;
|
|
return;
|
|
}
|
|
|
|
/* Sanity check, because foundry can generate configured vars w/o */
|
|
/* the data pointer initialized. */
|
|
if (va->data == NULL)
|
|
{
|
|
M_FREE (MSMEM_GEN, vaCtrl->oldData);
|
|
MVL_LOG_NERR1 ("Write Indication : va '%s' data is NULL", va->name);
|
|
vaCtrl->va = NULL;
|
|
return;
|
|
}
|
|
|
|
va_data = (ST_CHAR *) va->data;
|
|
/* "va_data_size" already set above */
|
|
break;
|
|
|
|
case VA_SPEC_DESCRIBED :
|
|
default :
|
|
MVL_LOG_NERR0 ("Put ASN1 Data : Invalid Variable Specification Tag");
|
|
vaCtrl->failure = ARE_OBJ_ACC_UNSUPPORTED;
|
|
return;
|
|
break;
|
|
}
|
|
|
|
/* If we got here, we have a valid runtime and have resolved local */
|
|
/* data pointer and size. Go ahead and convert the ASN.1 data element to*/
|
|
/* local data format */
|
|
|
|
temp_data_buf = (ST_CHAR *) M_MALLOC (MSMEM_WR_DATA_DEC_BUF, va_data_size);
|
|
|
|
|
|
#if defined(MVL_AA_SUPP)
|
|
if (alt_access_pres == SD_FALSE || aa_mode == MVL_USE_NO_AA)
|
|
rc = ms_asn1_to_local (rt, num_rt, asn1_buffer, asn1_len, temp_data_buf);
|
|
else
|
|
{
|
|
/* This is an alternate access write, we must first copy the data */
|
|
/* contents to to the temp buffer, then only the selected elements */
|
|
/* will be written by the data conversion. */
|
|
memcpy (temp_data_buf, va_data, va_data_size);
|
|
|
|
if (aa_mode == MVL_USE_PACKED_AA)
|
|
m_alt_acc_packed = SD_TRUE;
|
|
else
|
|
m_alt_acc_packed = SD_FALSE;
|
|
|
|
rc = ms_asn1_to_local_aa (rt, num_rt, &alt_acc,
|
|
asn1_buffer, asn1_len, temp_data_buf);
|
|
}
|
|
#else
|
|
rc = ms_asn1_to_local (rt, num_rt, asn1_buffer, asn1_len, temp_data_buf);
|
|
#endif
|
|
|
|
if (rc != SD_SUCCESS)
|
|
{
|
|
MVL_LOG_NERR1 ("Put ASN1 Data : ms_asn1_to_local failed, rc = 0x%X", rc);
|
|
M_FREE (MSMEM_GEN, vaCtrl->oldData);
|
|
M_FREE (MSMEM_WR_DATA_DEC_BUF, temp_data_buf);
|
|
|
|
#if defined(MVL_UCA) || defined(USE_MANUFACTURED_OBJS)
|
|
/* Need to free VA (caller will not if vaCtrl->va == NULL) */
|
|
if (vaCtrl->va->va_to_free != NULL)
|
|
u_mvl_free_va (MMSOP_WRITE, vaCtrl->va, NULL);
|
|
#endif
|
|
vaCtrl->va = NULL;
|
|
if (rc == ASN1E_UNEXPECTED_TAG)
|
|
/* Tag mismatch in this context indicates MMS type mismatch. */
|
|
vaCtrl->failure = ARE_TYPE_INCONSISTENT;
|
|
else
|
|
vaCtrl->failure = ARE_OBJ_VALUE_INVALID;
|
|
return;
|
|
}
|
|
|
|
/* Call the preprocessing function for this variable, if it exists */
|
|
if (va->proc && va->proc->pre_write_aa)
|
|
{
|
|
rc = (*va->proc->pre_write_aa)(va, alt_access_pres, &alt_acc,
|
|
indCtrl->event->net_info,
|
|
temp_data_buf, va_data_size);
|
|
|
|
if (rc != SD_SUCCESS)
|
|
{
|
|
MVL_LOG_NERR1 ("Put ASN1 Data : call to Write pre-processor failed, rc = 0x%X", rc);
|
|
M_FREE (MSMEM_GEN, vaCtrl->oldData);
|
|
#if defined(MVL_UCA) || defined(USE_MANUFACTURED_OBJS)
|
|
/* Need to free VA (caller will not if vaCtrl->va == NULL) */
|
|
if (vaCtrl->va->va_to_free != NULL)
|
|
u_mvl_free_va (MMSOP_WRITE, vaCtrl->va, NULL);
|
|
#endif
|
|
vaCtrl->va = NULL;
|
|
}
|
|
}
|
|
|
|
/* OK, almost done. The data has been converted OK and the user has had */
|
|
/* a chance to look at it. If rc == SD_SUCCESS, we are OK. */
|
|
|
|
if (rc == SD_SUCCESS)
|
|
{
|
|
vaCtrl->resp_tag = WR_RSLT_SUCCESS;
|
|
memcpy (va_data, temp_data_buf, va_data_size);
|
|
|
|
/* Call the postprocessing function for this variable, if it exists */
|
|
if (va->proc && va->proc->post_write_aa)
|
|
(*va->proc->post_write_aa)(va, alt_access_pres, &alt_acc, indCtrl->event->net_info);
|
|
}
|
|
|
|
#if defined(MVL_AA_SUPP)
|
|
if (alt_access_pres) /* if we calloc'd this AA, free it */
|
|
M_FREE (MSMEM_GEN, alt_acc.aa);
|
|
#endif
|
|
M_FREE (MSMEM_WR_DATA_DEC_BUF, temp_data_buf);
|
|
}
|