/* * @version: $Revision: 1.2 $ * @date: $Date: 2018/12/19 08:59:51 $ * @author: $Author: lizhongming $ * @state: $State: Exp $ * * @latest: $Id: mvl_acse.c,v 1.2 2018/12/19 08:59:51 lizhongming Exp $ * */ /************************************************************************/ /* SISCO SOFTWARE MODULE HEADER *****************************************/ /************************************************************************/ /* (c) Copyright Systems Integration Specialists Company, Inc., */ /* 1986 - 2004, All Rights Reserved */ /* */ /* MODULE NAME : mvl_acse.c */ /* PRODUCT(S) : MMSEASE-LITE */ /* */ /* MODULE DESCRIPTION : */ /* */ /* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ /* NONE */ /* */ /* MODIFICATION LOG : */ /* Date Who Rev Comments */ /* -------- --- ------ ------------------------------------------- */ /* 07/13/05 MDE 104 Fixed crash caused using mvl_init_ind_hold */ /* 06/07/05 MDE 103 Fixed deadlock caused by mvl_init_ind_hold */ /* 05/10/05 JRB 102 Call new mvl_init_aa_obj_ctrl to init struct */ /* to control AA-Specific object creation */ /* (no longer done by Foundry). */ /* 05/04/05 MDE 101 Added mvl_init_ind_hold */ /* 04/28/05 MDE 100 Added user_conn_id check on abort ind */ /* 04/06/05 MDE 99 Added test probes */ /* 03/09/05 MDE 98 Set stats startTime */ /* 08/11/04 JRB 97 Del global funct ptr u_mvl_connect_ind_fun. */ /* Fix mvl_abort_req(_ex) returns (ST_RET). */ /* 07/14/04 MDE 96 Set mvl_net_info->acse_conn_id on init req */ /* 07/08/04 JRB 95 Del unused global var mvl_local_cl_ar_name. */ /* 06/07/04 EJV 94 Removed call to a_free_security_info */ /* 04/09/04 MDE 93 Removed call to a_free_security_info */ /* 01/21/04 EJV 92 u_a_associate_ind: added a_free_security_info*/ /* added reinfo.auth_info.auth_pres = SD_FALSE*/ /* 01/20/04 MDE 91 Added logging */ /* 11/07/03 JRB 90 Add mmsop_en_version1. */ /* 08/10/03 EJV 89 ACSE_AUTH_ENABLED code wo/defines */ /* Reworked mvl_net_info_to_chan. */ /* Removed defs from around find_rem_dib_entry()*/ /* For MAP30_ACSE use a_get_chan(). */ /* 07/02/03 JRB 88 _mvl_net_service set activityFlag if more */ /* events on list (so user keeps calling). */ /* 06/16/03 EJV 87 Removed m_match.h, s_match.h includes. */ /* Renamed the match funcs & chg arg. */ /* 06/10/03 MDE 86 Added address matching */ /* 04/14/03 JRB 85 Eliminate compiler warnings. */ /* 12/18/02 ASK 84 Only check authentication on POSITIVE connect*/ /* confirm */ /* 10/30/02 JRB 83 mvl_init_audt_addr: check remote tp_type. */ /* _mvl_send_msg: do lock around a_data_req */ /* call to make it thread-safe. */ /* Chg all connID, bindID to ST_LONG to avoid */ /* compile errors on 64-bit systems. */ /* 10/11/02 ASK 82 Added mvla_initiate_req_ex, */ /* u_mvl_connect_ind_ex, and */ /* u_mvl_connect_cnf_ex functions for ACSE */ /* authentication. */ /* 07/19/02 ASK 81 Fix net_info variable in _mvl_send_msg */ /* 07/17/02 MDE 80 Added mvl_conn_filtered_logging to send */ /* 07/10/02 JRB 79 Add maxpend_ind, numpend_ind. */ /* 07/09/02 MDE 78 Fixed bad free for bad decode of init resp */ /* 05/24/02 JRB 77 Put back MVL_COMM_EVENT linked list. */ /* Occasionally copp_event gets 2 events, one */ /* from TP0 and one from TP4. */ /* 05/17/02 JRB 76 mvla_init..: set *req_out=NULL if freed */ /* so user CAN'T free it again. */ /* 05/13/02 MDE 75 Don't scan unbound mvl_net_info */ /* 05/13/02 MDE 74 Now clean up requests for release conf */ /* 05/03/02 MDE 73 Added mvl_add_bind_ctrl, associated changes */ /* 04/29/02 MDE 72 Added MLOG for initiate */ /* 04/29/02 JRB 71 DON'T re-use MVL_NET_INFO until req_pend_list*/ /* is empty, assert if pend_ind is not empty. */ /* 03/07/02 MDE 70 mvla_set_init_ar now takes NULL */ /* 03/04/02 JRB 69 Start with clean "temp_bind_ctrl" so garbage */ /* doesn't get copied. */ /* Return error if num_call*>0 but not supported*/ /* 02/25/02 MDE 68 More changes to MVL_CFG_INFO */ /* 02/20/02 MDE 67 Changes for new MVL_CFG_INFO, multiple bind */ /* 02/14/02 RKR 66 call a_associate_reqm if Marben stack */ /* 02/08/02 JRB 65 Pass MVL_CFG_INFO struct to mvl_start_acse. */ /* Del mvl_local_ar_name,mvl_set_num_connections*/ /* 01/30/02 JRB 64 Add args to copp_initialize (same as MAP30..)*/ /* Del call to a_set_msgsize. */ /* Make sure mmsl_max_msg_size, mvl_num_calling,*/ /* mvl_num_called are set. */ /* Use MMS_INIT_EN instead of MVL_NUM_CALL*. */ /* Del use of COACSE define. */ /* Del mvl_max_comm_event (not used). */ /* Merge mvl_init, _mvl_init_conn_ctrl into */ /* mvl_start_acse. */ /* Replace mvl_init_cl_netinfo funct with */ /* mvl_init_audt_addr. */ /* Del u_a_unit_data_ind & all use of stack_sel.*/ /* 01/09/02 JRB 63 Del all use of clpp_bind & bind id. */ /* Del unused u_cla_except callback function. */ /* 12/04/01 MDE 62 Change to work with MAP30_ACSE */ /* 11/30/01 GLB 61 changed MVL_LOG_ERR1 to MVL_LOG_ERR0 */ /* 11/28/01 MDE 60 mvl_set_num_connections,mvl_set_max_msg_size */ /* 11/21/01 MDE 59 mvl_loc_ar_name now auto set */ /* 11/21/01 MDE 58 Safer num channel operation */ /* 11/05/01 JRB 57 mvl_wait_req_done now returns ST_RET. */ /* 09/21/01 JRB 56 Alloc global bufs only once at startup. */ /* Fix M_FREE context. */ /* 07/31/01 MDE 55 Added mvl_conn_filtered_logging */ /* 05/21/01 MDE 54 Free NET_INFO */ /* 03/13/01 JRB 53 Check for (MMS_INIT_EN & REQ_EN). */ /* 02/26/01 MDE 52 Moved m_smem_ctxt to mem_chks.c */ /* 11/28/00 EJV 51 Changes to interface with Marben stack SUIC */ /* (see MAP30_ACSE define): */ /* Use SUIC find_loc_..., find_rem_dib_entry. */ /* Added param in copp_initialize(). */ /* Added param in mvla_initiate_req(). */ /* Changed params in copp_bind(). */ /* 10/25/00 JRB 50 Del MVL_COMM_EVENT linked list. Only one used*/ /* Del call to _mvl_free_req_pend. */ /* 09/22/00 MDE 49 Changed index init */ /* 08/21/00 RKR 48 Changed prototype of mvl_init_cl_netinfo */ /* 08/23/00 MDE 47 Call '_mvl_set_net_req_done' on aborts too */ /* 05/15/00 MDE 46 Added MMS statistics */ /* 04/27/00 JRB 45 Fixed calloc (0) problem */ /* 04/14/00 JRB 44 Lint cleanup. */ /* 04/12/00 MDE 43 Added AA resize, MVL_STATISTICS */ /* 03/15/00 JRB 42 Del #ifdef MVL_REQ_BUF_ENABLED: not used. */ /* 03/09/00 MDE 41 Added _mvl_init_conn_ctrl */ /* 01/21/00 MDE 40 Now use MEM_SMEM for dynamic memory */ /* 12/20/99 GLB 39 Remove extra initialization and add asserts */ /* 11/23/99 MDE 38 Added mvla_check_req_que (from mvl_serv.c) */ /* 10/20/99 NAV 37 Add maxpend_req support */ /* 11/03/99 RKR 36 Set aborted pend req results to DISCONN */ /* 10/29/99 GLB 35 Added check for lack of connection */ /* 09/07/99 MDE 34 Added _mvlu_rpt_disconnect_rcvd_fun */ /* 07/30/99 JRB 33 Added MVL_GOOSE_SUPPORT define use */ /* Chg ma_clbind_ctrl from static to global. */ /* 07/14/99 JRB 32 On assoc ind, save acse_conn_id first. */ /* 04/13/99 MDE 31 Added '_mvla_initiate_locDe' */ /* 04/07/99 MDE 30 Fixed mvla_initiate_req return code */ /* 04/01/99 MDE 29 Eliminated connection handling memory leaks */ /* 04/01/99 MDE 28 Changes to decode buffer allocation scheme */ /* 03/18/99 MDE 27 Made # connection limits changable runtime */ /* 03/08/99 MDE 26 Added ICCP support */ /* 12/08/98 MDE 25 Cleanup on request control handling */ /* 12/08/98 MDE 24 Allow user to initiate w/o supplying a */ /* 'resp_info' buffer. */ /* 11/16/98 MDE 23 Conclude/Release cleanup, misc cleanup */ /* 10/22/98 JRB 22 mvl_start_acse init mvl_debug_sel. Other lint*/ /* 09/21/98 MDE 21 Minor lint cleanup */ /* 08/25/98 MDE 20 Fixed bind/unbind bug for CLACSE */ /* 08/14/98 MDE 19 Removed !ALLOW_COMPLEX_NET_EVENTS code */ /* 08/14/98 MDE 18 Updated 'u_a_data_ind' parameters as reqd */ /* 07/20/98 JRB 17 If MVL_NUM_CALLED not defined, reject all */ /* associate indications. */ /* 07/16/98 MDE 16 Addded 'mvl_dib_entry_to_app_ref' */ /* 07/06/98 JRB 15 mvl_init_cl_netinfo use new DIB_ENTRY and */ /* init rem_mac_valid so it sends to ALL-ES. */ /* 06/18/98 JRB 14 Bind to TP4 and TCP if tp_type=TP_TYPE_TPX. */ /* 02/10/98 MDE 13 Added 'index' to connection control. */ /* 12/29/97 JRB 12 Call c?pp_terminate if bind fails. */ /* 12/22/97 MDE 11 Changed '_mvl_net_service' to report activity */ /* 09/18/97 MDE 10 Now call 'a_set_msgsize' */ /* 02/07/97 MDE 09 Changed to use new MMS-EASE opcode defines */ /* 12/13/96 MDE 08 Now support CLACSE, other enhancements */ /* 11/18/96 MDE 07 Minor name cleanup, some CLACSE stuff */ /* 11/15/96 MDE 06 Global variable work */ /* 11/11/96 MDE 05 Added async functions, other cleanup */ /* 10/31/96 MDE 04 Added ALLOW_COMPLEX_NET_EVENTS code */ /* 08/19/96 MDE 03 Now save all remote node's initiate info */ /* 07/22/96 MDE 02 Changes towards A-Unit-Data support */ /* 01/21/94 MDE 01 Initial */ /************************************************************************/ #include #include "rdb_client.h" #include "glbtypes.h" #include "sysincs.h" #include "glbsem.h" #include "mmsdefs.h" #include "mms_pvar.h" #include "mms_vvar.h" #include "mms_err.h" #include "mms_pcon.h" #include "asn1defs.h" #include "slog.h" #include "tp4api.h" #include "mvl_acse.h" #include "mvl_defs.h" #include "mvl_log.h" #include "mloguser.h" #include "mmsop_en.h" #include "../cfg_parse/custom_printf.h"//lnk20250225 #if defined(MAP30_ACSE) #include "suicacse.h" /* To limit the number of Marben stack files in the \mmslite\inc we */ /* prototype few referenced SUIC functions here. */ DIB_ENTRY *find_loc_dib_entry (ST_CHAR *name); DIB_ENTRY *find_dib_entry (ST_CHAR *name); #elif defined(LEAN_T) #include "acse2.h" #endif #if defined(_S_TEST_PROBES) #include "stestprb.h" #endif /************************************************************************/ /* 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 /************************************************************************/ MVL_MMS_STATISTICS mvl_mms_statistics; /************************************************************************/ #define NEGIOTIATE_INITIATE_PARAM #define MVL_MMSOP_RELEASE 512 /* Add a MMS opcode define ... */ /************************************************************************/ /* Global variables - Connection Oriented Only */ /* The user must fill in a table of DIB entries for local and remote */ /* nodes of interest. This can be done by the user via the 'init_dirser'*/ /* function, can be hard coded, etc.. */ #if !defined(MAP30_ACSE) /* For MAP30_ACSE use SUIC function instead */ ST_INT num_loc_dib_entries; DIB_ENTRY *loc_dib_table; ST_INT num_rem_dib_entries; DIB_ENTRY *rem_dib_table; #endif DIB_ENTRY *_mvla_initiate_locDe; NET_BIND_CTRL *_mvla_initiate_bc; /* Our connection controls - we support multiple called and/or calling */ /* simultanious connections. */ MVL_NET_INFO *mvl_calling_conn_ctrl; MVL_NET_INFO *mvl_called_conn_ctrl; /* Other user configurable parameters */ #ifndef MMS_INIT_EN #error MMS_INIT_EN not defined. Must include mmsop_en.h #endif #if (MMS_INIT_EN & RESP_EN) INIT_INFO *mvl_init_resp_info; #endif ST_VOID (*u_mvl_disc_ind_fun) (MVL_NET_INFO *cc, ST_INT discType); ST_VOID (*_mvlu_rpt_disconnect_rcvd_fun)(MVL_NET_INFO *netInfo); /************************************************************************/ /* This variable is set SD_TRUE when the ACSE interface is viable */ ST_INT mvl_acse_ok; /************************************************************************/ /* These arrays are created in mmsop_en.c */ extern SD_CONST ST_UCHAR m_param[2]; extern SD_CONST ST_UCHAR m_service_resp[11]; /************************************************************************/ /************************************************************************/ /* Bind Control */ NET_BIND_CTRL ma_clbind_ctrl; /* to save clpp_bind info. */ /* These variables are used in making some asynchronous ACSE functions */ /* work in a blocking mode */ static ST_INT ma_cmd_done; static ST_INT ma_cmd_rslt; /************************************************************************/ MVL_CFG_INFO *mvl_cfg_info; /************************************************************************/ /* MMS COMM EVENT CONTROL MANAGEMENT */ static MVL_COMM_EVENT *mvl_comm_event_up_head; /* ptr to linked list */ /************************************************************************/ /* MVL_NET_INFO handling for incoming A-Unit Data */ #if defined(CLACSE) ST_INT16 mvl_max_net_info = 10; static ST_INT16 mvl_net_info_count; static MVL_NET_INFO *mvl_net_info_avail_head; static MVL_NET_INFO *mvl_get_net_info (ST_VOID); static ST_VOID mvl_free_net_info (MVL_NET_INFO *netInfo); #endif /************************************************************************/ typedef struct { DBL_LNK l; ST_LONG u_bind_id; ST_LONG acse_conn_id; AARQ_APDU *info; } MVL_ASSOC_IND; MVL_ASSOC_IND *mvlAssocIndList; ST_BOOLEAN mvl_init_ind_hold; /************************************************************************/ /* Internal functions */ static ST_VOID ma_wait_req_done (ST_RET *retOut); #if (MMS_INIT_EN & RESP_EN) static MVL_NET_INFO *ma_get_called_conn_ctrl (NET_BIND_CTRL *); #endif #if (MMS_INIT_EN & REQ_EN) static MVL_NET_INFO *ma_get_calling_conn_ctrl (NET_BIND_CTRL *); #endif static ST_VOID copp_unbind_sync (ST_LONG copp_bind_id); static ST_RET ma_bind (NET_BIND_CTRL *bc, ST_BOOLEAN activate); static MVL_COMM_EVENT *mvl_get_com_event (ST_VOID); /************************************************************************/ /************************************************************************/ /* _mvl_net_service */ /************************************************************************/ ST_BOOLEAN _mvl_net_service (MVL_COMM_EVENT **eventOut) { ST_BOOLEAN activityFlag; MVL_ASSOC_IND *mvlAssocInd; *eventOut = NULL; if (mvl_acse_ok != SD_TRUE) return (SD_FALSE); S_LOCK_COMMON_RESOURCES (); /* If we have a delayed initiate indication (ICCP Lite redundancy), */ /* handle it now */ if (mvlAssocIndList && !mvl_init_ind_hold) { mvlAssocInd = list_get_first (&mvlAssocIndList); u_a_associate_ind (mvlAssocInd->u_bind_id, mvlAssocInd->acse_conn_id, mvlAssocInd->info); chk_free (mvlAssocInd); S_UNLOCK_COMMON_RESOURCES (); return (SD_TRUE); } /* May cause the 'acse' user function to be called if something is */ /* going on that we need to know about. If so, the functions will */ /* get the event and put them onto the 'mvl_comm_event_up_head' list */ activityFlag = copp_event (); /* Occasionally copp_event gets 2 events, one from TP0 and one from TP4,*/ /* so they are put on this linked list. "Usually" only one on list. */ if (mvl_comm_event_up_head) *eventOut = (MVL_COMM_EVENT *) list_get_first((ST_VOID **) &mvl_comm_event_up_head); if (mvl_comm_event_up_head != NULL) { /* more events on linked list */ activityFlag=SD_TRUE; /* force it so user knows to call again */ } S_UNLOCK_COMMON_RESOURCES (); return (activityFlag); } /************************************************************************/ /* mvl_get_com_event */ /************************************************************************/ /* This function is used to get a MVL_COMM_EVENT control buffer to be */ /* passed up to the caller of '_mvl_net_service'. */ static MVL_COMM_EVENT *mvl_get_com_event (ST_VOID) { MVL_COMM_EVENT *commEvent; S_LOCK_COMMON_RESOURCES (); commEvent = (MVL_COMM_EVENT *) M_CALLOC (MSMEM_COM_EVENT, 1, sizeof (MVL_COMM_EVENT)); if (commEvent == NULL) { MVL_LOG_ERR0 ("Error: No MVL_COMM_EVENT available"); S_UNLOCK_COMMON_RESOURCES (); return (NULL); } list_add_last((ST_VOID **) &mvl_comm_event_up_head, (ST_VOID *) commEvent); S_UNLOCK_COMMON_RESOURCES (); return (commEvent); } /************************************************************************/ /* _mvl_free_comm_event */ /************************************************************************/ ST_VOID _mvl_free_comm_event (MVL_COMM_EVENT *event) { S_LOCK_COMMON_RESOURCES (); if (event->event_type == MMS_MSG_RCVD) { M_FREE (MSMEM_RXPDU, event->u.mms.pdu); if (event->u.mms.dec_rslt.data_pres) { M_FREE (MSMEM_DEC_OS_INFO, event->u.mms.dec_rslt.data_ptr); } } M_FREE (MSMEM_COM_EVENT, event); S_UNLOCK_COMMON_RESOURCES (); } /************************************************************************/ /* mvl_set_max_msg_size */ /************************************************************************/ ST_VOID mvl_set_max_msg_size (ST_INT max_msg_size) { mvl_cfg_info->max_msg_size = max_msg_size; mmsl_enc_buf_size = max_msg_size + ASN1_MAX_ELEMENT_OVERHEAD; if (mmsl_enc_buf != NULL) M_FREE (MSMEM_STARTUP, mmsl_enc_buf); mmsl_enc_buf = M_MALLOC (MSMEM_STARTUP, mmsl_enc_buf_size); } /************************************************************************/ /* mvl_init_aa_obj_ctrl */ /* Init struct to control AA-Specific object creation (var and nvl). */ /* Init one MVL_AA_OBJ_CTRL struct for one connection. */ /* NOTE: if OBSOLETE_AA_OBJ_INIT, this initialization is done by Foundry.*/ /************************************************************************/ #if !defined(OBSOLETE_AA_OBJ_INIT) static MVL_AA_OBJ_CTRL *mvl_init_aa_obj_ctrl () { MVL_AA_OBJ_CTRL *aa_obj; aa_obj = (MVL_AA_OBJ_CTRL *) M_CALLOC (MSMEM_STARTUP, 1, sizeof(MVL_AA_OBJ_CTRL)); /* Set up for dynamic creation of AA-Specific Variables. */ aa_obj->max_num_var_assoc = mvl_max_dyn.aa_vars; aa_obj->num_var_assoc = 0; if (aa_obj->max_num_var_assoc) aa_obj->var_assoc_tbl = (MVL_VAR_ASSOC **) M_CALLOC (MSMEM_STARTUP, aa_obj->max_num_var_assoc, sizeof (MVL_VAR_ASSOC *)); /* Set up for dynamic creation of AA-Specific NamedVariableLists (NVL). */ aa_obj->max_num_nvlist = mvl_max_dyn.aa_nvls; aa_obj->num_nvlist = 0; if (aa_obj->max_num_nvlist) aa_obj->nvlist_tbl = (MVL_NVLIST_CTRL **) M_CALLOC (MSMEM_STARTUP, aa_obj->max_num_nvlist, sizeof (MVL_NVLIST_CTRL *)); return (aa_obj); } #endif /* #if !defined(OBSOLETE_AA_OBJ_INIT) */ /************************************************************************/ /* mvl_start_acse */ /************************************************************************/ ST_INT mvl_start_acse (MVL_CFG_INFO *cfgInfo) { NET_BIND_CTRL *bind_ctrl_src; NET_BIND_CTRL *bind_ctrl_dest; NET_BIND_CTRL temp_bind_ctrl; ST_INT mvl_cfg_info_size; ST_INT ret; ST_INT i; ST_INT index = 0; extern int mmsop_en_version1; mmsop_en_version1=0; /* value of this var means nothing, but it */ /* causes error if you link to older mmsop_en.c */ MVL_LOG_ACSE0 ("ACSE: Starting"); mvl_debug_sel |= MVLLOG_ERR; /* Always enable error logging. */ /* Here we will make the MVL configuration information persistant */ #if defined(MAP30_ACSE) if (cfgInfo->use_bind_ctrl != SD_TRUE) #endif { /* Create the required bind control structures, if not supplied */ /* Use memset to start with clean structure */ memset (&temp_bind_ctrl, 0, sizeof (NET_BIND_CTRL)); /* CRITICAL*/ strcpy (temp_bind_ctrl.ar_name, cfgInfo->local_ar_name); temp_bind_ctrl.num_calling = cfgInfo->num_calling; temp_bind_ctrl.num_called = cfgInfo->num_called; cfgInfo->bind_ctrl = &temp_bind_ctrl; cfgInfo->max_bind_ctrl = 1; cfgInfo->num_bind_ctrl = 1; } /* OK, now copy the MVL configuration info */ mvl_cfg_info_size = sizeof (MVL_CFG_INFO) + (cfgInfo->max_bind_ctrl * sizeof (NET_BIND_CTRL)); mvl_cfg_info = chk_calloc (1, mvl_cfg_info_size); *mvl_cfg_info = *cfgInfo; if (mvl_cfg_info->max_bind_ctrl == 0) mvl_cfg_info->max_bind_ctrl = mvl_cfg_info->num_bind_ctrl; mvl_cfg_info->calling_used = 0; mvl_cfg_info->called_used = 0; mvl_cfg_info->bind_ctrl = (NET_BIND_CTRL *) (mvl_cfg_info + 1); bind_ctrl_dest = mvl_cfg_info->bind_ctrl; bind_ctrl_src = cfgInfo->bind_ctrl; for (i = 0; i < mvl_cfg_info->num_bind_ctrl; ++i) { *bind_ctrl_dest = *bind_ctrl_src; ++bind_ctrl_src; ++bind_ctrl_dest; } /* Make sure max msg size has been set. */ if (mvl_cfg_info->max_msg_size == 0) { MVL_LOG_ERR0 ("Max MMS message size must be set"); return (SD_FAILURE); } mvl_set_max_msg_size (mvl_cfg_info->max_msg_size); /* save to global & alloc bufs*/ /* Initialize function pointers for MMS allocation. */ m_calloc_os_fun = _mvl_calloc_os; m_realloc_os_fun = _mvl_realloc_os; m_free_os_fun = _mvl_free_os; #if !(MMS_INIT_EN & REQ_EN) if (mvl_cfg_info->num_calling != 0) { MVL_LOG_ERR0 ("num_calling > 0 is illegal because Initiate.Req is NOT enabled"); return (SD_FAILURE); } #endif #if !(MMS_INIT_EN & RESP_EN) if (mvl_cfg_info->num_called != 0) { MVL_LOG_ERR0 ("num_called > 0 is illegal because Initiate.Resp is NOT enabled"); return (SD_FAILURE); } #endif /* Make sure "num_calling" AND/OR "num_called" has been set. */ if (mvl_cfg_info->num_calling == 0 && mvl_cfg_info->num_called == 0) { MVL_LOG_ERR0 ("num_calling AND num_called both 0, must set at least one." ); return (SD_FAILURE); } /* Alloc & fill in array of "calling" connection control structures. */ #if (MMS_INIT_EN & REQ_EN) if (mvl_cfg_info->num_calling != 0) mvl_calling_conn_ctrl = M_CALLOC (MSMEM_GEN, mvl_cfg_info->num_calling, sizeof (MVL_NET_INFO)); for (i = 0; i < mvl_cfg_info->num_calling; ++i) { mvl_calling_conn_ctrl[i].index = index++; #if !defined(OBSOLETE_AA_OBJ_INIT) mvl_calling_conn_ctrl[i].aa_objs = mvl_init_aa_obj_ctrl (); #endif /* #if !defined(OBSOLETE_AA_OBJ_INIT) */ } #endif /* Alloc & fill in array of "called" connection control structures. */ #if (MMS_INIT_EN & RESP_EN) if (mvl_cfg_info->num_called != 0) mvl_called_conn_ctrl = M_CALLOC (MSMEM_GEN, mvl_cfg_info->num_called, sizeof (MVL_NET_INFO)); for (i = 0; i < mvl_cfg_info->num_called; ++i) { mvl_called_conn_ctrl[i].index = index++; #if !defined(OBSOLETE_AA_OBJ_INIT) mvl_called_conn_ctrl[i].aa_objs = mvl_init_aa_obj_ctrl (); #endif /* #if !defined(OBSOLETE_AA_OBJ_INIT) */ } #endif /* Initialize Connection Oriented OSI Stack. */ ret = copp_initialize (mvl_cfg_info->num_calling + mvl_cfg_info->num_called, mmsl_enc_buf_size); if (ret != SD_SUCCESS) { MVL_LOG_ERR1 ("Error: copp_initialize returned error '0x%x'", ret); return (ret); } /* Initialize Connectionless OSI Stack. */ #if defined(CLACSE) ret = clpp_initialize (); if (ret != SD_SUCCESS) { MVL_LOG_ERR1 ("Error: clpp_initialize returned error '0x%x'", ret); return (ret); } #endif /* Bind local AR names */ for (i = 0; i < mvl_cfg_info->num_bind_ctrl; ++i) { ret = ma_bind (&mvl_cfg_info->bind_ctrl[i], SD_TRUE); if (ret != SD_SUCCESS) return (ret); } /* Binding not necessary for CLACSE. */ /* Initialize all mms objects (generated by foundry). */ if (ret == SD_SUCCESS) mvl_init_mms_objs (); if (ret == SD_SUCCESS) mvl_acse_ok = SD_TRUE; else { copp_terminate (); #if defined(CLACSE) clpp_terminate (); #endif } MVL_LOG_ACSE1 ("ACSE: Start complete, returning '0x%x'", ret); mvl_mms_statistics.startTime = sGetMsTime (); return (ret); } /************************************************************************/ /* mvl_end_acse */ /************************************************************************/ ST_INT mvl_end_acse (ST_VOID) { NET_BIND_CTRL *bc; ST_INT i; MVL_LOG_ACSE0 ("ACSE: Ending"); /* Unbind all */ for (i = 0; i < mvl_cfg_info->num_bind_ctrl; ++i) { bc = &mvl_cfg_info->bind_ctrl[i]; #ifdef LEAN_T if (bc->copp_bind_id_tcp) copp_unbind_sync (bc->copp_bind_id_tcp); if (bc->copp_bind_id_tp4) copp_unbind_sync (bc->copp_bind_id_tp4); #else /* !LEAN_T */ copp_unbind_sync (bc->copp_bind_id); #endif /* !LEAN_T */ } /* Shut down the ACSE interface, as well as it's subsystems */ copp_terminate (); #if defined(CLACSE) clpp_terminate (); #endif MVL_LOG_ACSE0 ("ACSE: Ended"); return (SD_SUCCESS); } /************************************************************************/ /* _mvl_send_msg */ /************************************************************************/ ST_INT _mvl_send_msg (ST_UCHAR *pdu, ST_INT pdu_len, MVL_NET_INFO *net_info) { ST_INT ret; /* See if we are supposed to log ACSE data for this connection */ if (mvl_conn_filtered_logging == SD_FALSE || net_info->log_enable) { MVL_LOG_ACSEDATA2 ("ACSE: Sending %d bytes on MVL_NET_INFO 0x%08lx", pdu_len, net_info); MVL_LOG_ACSEDATAH (pdu_len, pdu); } ret = SD_FAILURE; #if (MMS_INIT_EN != REQ_RESP_DIS) if (net_info->conn_active == SD_FALSE) { /* no connection */ ret = MVL_ERR_CNF_DISCONNECTED; /* more precise error code */ MVL_LOG_NERR1 ("ACSE: no connection '0x%x'", ret); } else { /* valid connection */ S_LOCK_COMMON_RESOURCES (); ret = a_data_req (net_info->acse_conn_id, pdu_len, pdu); S_UNLOCK_COMMON_RESOURCES (); if (ret != SD_SUCCESS) { MVL_LOG_NERR1 ("ACSE: a_data_req error '0x%x'", ret); } } #endif return (ret); } /************************************************************************/ /************************************************************************/ /* DIRECTORY SERVICES FUNCTIONS */ /************************************************************************/ /************************************************************************/ /* find_loc_dib_entry */ /************************************************************************/ #if !defined(MAP30_ACSE) /* For MAP30_ACSE use SUIC function instead */ DIB_ENTRY *find_loc_dib_entry (ST_CHAR *name) { ST_INT i; DIB_ENTRY *de; for (i = 0; i < num_loc_dib_entries; i++) { de = &loc_dib_table[i]; if (!strcmp (de->name, name)) return (de); } return (NULL); } #endif /* !defined(MAP30_ACSE) */ /************************************************************************/ /* find_rem_dib_entry */ /************************************************************************/ DIB_ENTRY *find_rem_dib_entry (ST_CHAR *name) { #if !defined(MAP30_ACSE) ST_INT i; #endif DIB_ENTRY *de; #if defined(MAP30_ACSE) /* For Marben stack use SUIC function */ de = find_dib_entry (name); /* searches first loc then rem tables */ return (de); #else /* !defined(MAP30_ACSE) */ for (i = 0; i < num_rem_dib_entries; i++) { de = &rem_dib_table[i]; if (!strcmp (de->name, name)) return (de); } return (NULL); #endif /* !defined(MAP30_ACSE) */ } /************************************************************************/ /* mvl_dib_entry_to_app_ref */ /************************************************************************/ ST_VOID mvl_dib_entry_to_app_ref (DIB_ENTRY *de, APP_REF *appRef) { ST_INT i; appRef->form = APP_REF_FORM2; appRef->ap_title_pres = de->AP_title_pres; if (appRef->ap_title_pres == SD_TRUE) { appRef->ap_title.form_2.num_comps = de->AP_title.num_comps; for (i = 0; i < de->AP_title.num_comps; ++i) appRef->ap_title.form_2.comps[i] = de->AP_title.comps[i]; } appRef->ap_invoke_pres = de->AP_inv_id_pres; appRef->ap_invoke = de->AP_invoke_id; appRef->ae_qual_pres = de->AE_qual_pres; appRef->ae_qual.form_2 = de->AE_qual; appRef->ae_invoke_pres = de->AE_inv_id_pres; appRef->ae_invoke = de->AE_invoke_id; } /************************************************************************/ /************************************************************************/ #if (MMS_INIT_EN != REQ_RESP_DIS) /* COACSE SPECIFIC FUNCTIONS */ /************************************************************************/ ST_RET mvla_set_init_ar (ST_CHAR *ar_name) { NET_BIND_CTRL *bc; ST_INT i; /* See if user want's to use the default AR */ if (ar_name == NULL) { _mvla_initiate_bc = NULL; return (SD_SUCCESS); } for (i = 0; i < mvl_cfg_info->num_bind_ctrl; ++i) { bc = &mvl_cfg_info->bind_ctrl[i]; if (!strcmp (ar_name, bc->ar_name)) { _mvla_initiate_bc = bc; return (SD_SUCCESS); } } return (SD_FAILURE); } #if (MMS_INIT_EN & REQ_EN) /************************************************************************/ /* mvl_initiate_req */ /************************************************************************/ ST_INT mvl_initiate_req (ST_CHAR *remAr, INIT_INFO *req_info, INIT_INFO *resp_info, MVL_NET_INFO **net_info_out) { MVL_REQ_PEND *req; ST_INT rc; if (_mvl_comm_serve_active == SD_TRUE) { MVL_LOG_NERR0 ("Error: mvl_comm_serv active"); return (SD_FAILURE); } rc = mvla_initiate_req (remAr, req_info, resp_info, net_info_out, &req); if (rc != SD_SUCCESS) return (rc); rc = mvl_wait_req_done (req); if (rc != SD_SUCCESS) { MVL_LOG_NERR0 ("ACSE: Initiate failed"); } mvl_free_req_ctrl (req); /* we are done with this req ctrl */ return (rc); } /************************************************************************/ /* mvla_initiate_req */ /************************************************************************/ ST_INT mvla_initiate_req (ST_CHAR *remAr, INIT_INFO *req_info, INIT_INFO *resp_info, MVL_NET_INFO **net_info_out, MVL_REQ_PEND **req_out) { ST_INT rc; rc = mvla_initiate_req_ex (remAr, req_info, resp_info, net_info_out, req_out, NULL, NULL); return rc; } /************************************************************************/ /* mvla_initiate_req_ex */ /************************************************************************/ ST_INT mvla_initiate_req_ex (ST_CHAR *remAr, INIT_INFO *req_info, INIT_INFO *resp_info, MVL_NET_INFO **net_info_out, MVL_REQ_PEND **req_out, ACSE_AUTH_INFO *auth_info, S_SEC_ENCRYPT_CTRL *encrypt_info) { ST_INT rc; MVL_NET_INFO *cc; DIB_ENTRY *locDe; DIB_ENTRY *remDe; AARQ_APDU aarq_apdu; ST_LONG acse_conn_id; MVL_REQ_PEND *req; *req_out = NULL; /* make sure it's initialized */ MVL_LOG_ACSE1 ("ACSE: Initiate Request to '%s'", remAr); /* Get a calling connection control structure */ cc = ma_get_calling_conn_ctrl (_mvla_initiate_bc); if (!cc) { MVL_LOG_ERR0 ("Error - Could not get calling MVL_NET_INFO"); return (MVL_ERR_NO_CONN_CTRL); } MVL_LOG_CACSE1 ("Using MVL_NET_INFO %08lx", cc); req = _mvl_get_req_ctrl (cc, MMSOP_INITIATE); if (!req) { cc->in_use = SD_FALSE; return (MVL_ERR_NO_REQ_CTRL); } *req_out = req; req->invoke_id = -1; rc = mpl_init (req_info); if (rc == SD_SUCCESS) { /* We can log here if so desired */ /* if ((mms_debug_sel & MMS_LOG_REQ) && ml_log_req_info_fun != NULL) (*ml_log_req_info_fun) (0, MMSOP_INITIATE, req_info);*/ /* Save the output pointer in the MMS request control element */ req->u.init.resp_info = resp_info; /* Save our initiate request information ... */ memcpy (&cc->locl_init_info, req_info, sizeof (INIT_INFO)); /* Retrieve the DIB_ENTRY's for local and remote. These are used to set */ /* the AARQ_APDU information */ if (_mvla_initiate_locDe != NULL) locDe = _mvla_initiate_locDe; else locDe = cc->bind_ctrl->de; remDe = find_rem_dib_entry (remAr); if (remDe) { /* Now set up all AARQ_APDU information based on DIB_ENTRY information */ #if !defined(MAP30_ACSE) /* most info not needed for Lite over Marben stack */ /* AP Context is MMS */ aarq_apdu.ASO_context_name_pres = SD_TRUE; aarq_apdu.ASO_context_name.num_comps = 5; aarq_apdu.ASO_context_name.comps[0] = 1; aarq_apdu.ASO_context_name.comps[1] = 0; aarq_apdu.ASO_context_name.comps[2] = 9506; aarq_apdu.ASO_context_name.comps[3] = 2; aarq_apdu.ASO_context_name.comps[4] = 3; /* Calling AE Title */ aarq_apdu.calling_ae_title.AP_title_pres = locDe->AP_title_pres; memcpy (&aarq_apdu.calling_ae_title.AP_title, &locDe->AP_title, sizeof (MMS_OBJ_ID)); aarq_apdu.calling_ae_title.AE_qual_pres = locDe->AE_qual_pres; aarq_apdu.calling_ae_title.AE_qual = locDe->AE_qual; aarq_apdu.calling_ae_title.AP_inv_id_pres = locDe->AP_inv_id_pres; aarq_apdu.calling_ae_title.AP_inv_id = locDe->AP_invoke_id; aarq_apdu.calling_ae_title.AE_qual_pres = locDe->AE_qual_pres; aarq_apdu.calling_ae_title.AE_qual = locDe->AE_qual; aarq_apdu.calling_ae_title.AE_inv_id_pres = locDe->AE_inv_id_pres; aarq_apdu.calling_ae_title.AE_inv_id = locDe->AE_invoke_id; /* Called AE Title */ aarq_apdu.called_ae_title.AP_title_pres = remDe->AP_title_pres; memcpy (&aarq_apdu.called_ae_title.AP_title, &remDe->AP_title, sizeof (MMS_OBJ_ID)); aarq_apdu.called_ae_title.AE_qual_pres = remDe->AE_qual_pres; aarq_apdu.called_ae_title.AE_qual = remDe->AE_qual; aarq_apdu.called_ae_title.AP_inv_id_pres = remDe->AP_inv_id_pres; aarq_apdu.called_ae_title.AP_inv_id = remDe->AP_invoke_id; aarq_apdu.called_ae_title.AE_qual_pres = remDe->AE_qual_pres; aarq_apdu.called_ae_title.AE_qual = remDe->AE_qual; aarq_apdu.called_ae_title.AE_inv_id_pres = remDe->AE_inv_id_pres; aarq_apdu.called_ae_title.AE_inv_id = remDe->AE_invoke_id; #endif /* !defined(MAP30_ACSE) */ #ifdef REDUCED_STACK /* For Reduced Stack, the presentation address consists only of the */ /* ADLC address. */ aarq_apdu.called_paddr.adlcAddr = remDe->adlcAddr; #endif #ifdef LEAN_T /* For Trim 7, the presentation address has all the parts */ memcpy (&aarq_apdu.called_paddr, &remDe->pres_addr, sizeof (PRES_ADDR)); #endif /* ACSE Authentication */ if(auth_info != NULL) memcpy (&aarq_apdu.auth_info, auth_info, sizeof (ACSE_AUTH_INFO)); else aarq_apdu.auth_info.auth_pres = SD_FALSE; /* copy encryption info */ if (encrypt_info != NULL) memcpy (&aarq_apdu.encrypt_ctrl, encrypt_info, sizeof (S_SEC_ENCRYPT_CTRL)); else aarq_apdu.encrypt_ctrl.encryptMode = S_SEC_ENCRYPT_NONE; /* User Data */ aarq_apdu.user_info.ptr = mmsl_msg_start; aarq_apdu.user_info.len = mmsl_msg_len; MVL_LOG_ACSEDATAH (mmsl_msg_len, mmsl_msg_start); /* Send the associate request */ #if defined(MAP30_ACSE) acse_conn_id = a_associate_reqm (cc->bind_ctrl->copp_bind_id, (ST_LONG) cc, &aarq_apdu, cc->bind_ctrl->ar_name, remAr); #elif defined(LEAN_T) if (remDe->pres_addr.tp_type == TP_TYPE_TCP) acse_conn_id = a_associate_req (cc->bind_ctrl->copp_bind_id_tcp, (ST_LONG) cc, &aarq_apdu); else acse_conn_id = a_associate_req (cc->bind_ctrl->copp_bind_id_tp4, (ST_LONG) cc, &aarq_apdu); #else acse_conn_id = a_associate_req (cc->bind_ctrl->copp_bind_id, (ST_LONG) cc, &aarq_apdu); #endif if (!acse_conn_id) { MVL_LOG_NERR0 ("ACSE: a_associate_req failed"); rc = MVL_ERR_ASSOC_REQ; } else ++mvl_mms_statistics.callingConn; } else { MVL_LOG_NERR1 ("ACSE: Remote name '%s' not found", remAr); rc = MVLE_REMOTE_NAME; } } else { MVL_LOG_NERR1 ("ACSE: mpl_init error '0x%x'", rc); } if (rc == SD_SUCCESS) { *net_info_out = cc; cc->acse_conn_id = acse_conn_id; } else { cc->in_use = SD_FALSE; mvl_free_req_ctrl (req); *req_out = NULL; /* So user CANNOT free it too. */ } /* All is good, return the connection control too */ return (rc); } /************************************************************************/ #endif /* #if (MMS_INIT_EN & REQ_EN) */ /************************************************************************/ /************************************************************************/ /* mvl_abort_req */ /* mvl_abort_req_ex */ /************************************************************************/ ST_RET mvl_abort_req (MVL_NET_INFO *cc) { return (mvl_abort_req_ex (cc, SD_FALSE, 0)); } ST_RET mvl_abort_req_ex (MVL_NET_INFO *cc, ST_BOOLEAN diagnostic_pres, ST_ACSE_AUTH diagnostic) { ABRT_APDU abrtinfo; ST_RET ret; MVL_LOG_ACSE1 ("ACSE: sending abort for MVL_NET_INFO %08lx", cc); abrtinfo.source = 0; /* user */ abrtinfo.diagnostic_pres = diagnostic_pres; abrtinfo.diagnostic = diagnostic; abrtinfo.user_info.len = 0; ret = a_abort_req (cc->acse_conn_id, &abrtinfo); if (ret == SD_SUCCESS) { ++mvl_mms_statistics.localAbort; cc->in_use = SD_FALSE; cc->conn_active = SD_FALSE; if (_mvlu_rpt_disconnect_rcvd_fun != NULL) (*_mvlu_rpt_disconnect_rcvd_fun)(cc); _mvl_set_net_req_done (NULL, cc, MVL_ERR_CNF_DISCONNECTED); } else { MVL_LOG_NERR1 ("ACSE: Abort error '0x%x'", ret); echo_warn1("ACSE: Abort error '0x%x'\n", ret); } return (ret); } /************************************************************************/ /* mvl_release_req */ /* mvla_release_req */ /************************************************************************/ ST_INT mvl_release_req (MVL_NET_INFO *cc) { MVL_LOG_ERR0 ("ACSE: Using obsolete function 'mvl_release_req'"); return (SD_FAILURE); } ST_INT mvla_release_req (MVL_NET_INFO *cc, MVL_REQ_PEND **req_out) { MVL_LOG_ERR0 ("ACSE: Using obsolete function 'mvla_release_req'"); return (SD_FAILURE); } /************************************************************************/ /* _mvla_release */ /************************************************************************/ /* Called from conclude confirm */ ST_VOID _mvl_release (MVL_REQ_PEND *req) { RLRQ_APDU rlinfo; ST_INT ret; MVL_NET_INFO *net_info; net_info = req->net_info; req->op = MVL_MMSOP_RELEASE; /* Change the opcode in the req ctrl */ MVL_LOG_ACSE1 ("ACSE: sending release for MVL_NET_INFO %08lx", net_info); rlinfo.reason_pres = SD_TRUE; rlinfo.reason = 1; rlinfo.user_info.len = 0; ret = a_release_req (net_info->acse_conn_id, &rlinfo); if (ret != SD_SUCCESS) { MVL_LOG_NERR1 ("ACSE: Release error '0x%x'", ret); _mvl_set_req_done (req, SD_FAILURE); } else ++mvl_mms_statistics.clientConcl; } /************************************************************************/ /************************************************************************/ /* mvl_add_bind_ctrl */ /************************************************************************/ ST_RET mvl_add_bind_ctrl (NET_BIND_CTRL *bc) { NET_BIND_CTRL *mvlBc; ST_BOOLEAN activate; ST_INT i; ST_RET rc; /* First let's check to see if we have room for one more */ if (mvl_cfg_info->num_bind_ctrl >= mvl_cfg_info->max_bind_ctrl) { MVL_LOG_NERR0 ("Error: no availble bind control"); return (SD_FAILURE); } /* Let's see if this local AR has already been activated */ activate = SD_TRUE; for (i = 0; i < mvl_cfg_info->num_bind_ctrl; ++i) { if (!strcmp (mvl_cfg_info->bind_ctrl[i].ar_name, bc->ar_name)) { activate = SD_FALSE; break; } } /* OK, now we can copy the bind control information */ mvlBc = &mvl_cfg_info->bind_ctrl[mvl_cfg_info->num_bind_ctrl]; *mvlBc = *bc; ++mvl_cfg_info->num_bind_ctrl; rc = ma_bind (mvlBc, activate); return (rc); } /************************************************************************/ /* mvl_bind */ /************************************************************************/ static ST_RET ma_bind (NET_BIND_CTRL *bc, ST_BOOLEAN activate) { #if !defined(MAP30_ACSE) DIB_ENTRY *de; PRES_ADDR loc_pres_addr; #endif ST_INT ret; ST_INT numConn; MVL_NET_INFO *ni; ST_INT j; MVL_LOG_ACSE1 ("ACSE: binding local name '%s'", bc->ar_name); #if !defined(MAP30_ACSE) /* Locate the local DIB entry for this name, so we can find the addr */ de = find_loc_dib_entry (bc->ar_name); if (!de) { MVL_LOG_ERR1 ("Error: Local AR name '%s' not found", bc->ar_name); return (MVLE_LOCAL_NAME); } bc->de = de; #endif if (((bc->num_calling + mvl_cfg_info->calling_used) > mvl_cfg_info->num_calling) || ((bc->num_called + mvl_cfg_info->called_used) > mvl_cfg_info->num_called)) { MVL_LOG_ERR0 ("Error: not enough connections"); return (MVLE_NUM_CONNECTIONS); } numConn = bc->num_calling + bc->num_called; #ifdef REDUCED_STACK /* For Reduced Stack, the presentation address consists only of the */ /* ADLC address. */ loc_pres_addr.adlcAddr = de->adlcAddr; /* We make the binds synchronous */ ma_cmd_done = SD_FALSE; ma_cmd_rslt = REQ_INCOMPLETE; ret = copp_bind ((ST_LONG) bc, &loc_pres_addr, SD_FALSE, numConn); ma_wait_req_done (&ret); if (ret != SD_SUCCESS) { MVL_LOG_ERR2 ("Error: copp_bind (TCP) of AR '%s' returned '0x%x'", bc->ar_name, ret); return (ret); } #endif #ifdef LEAN_T /* For Trim 7, the presentation address has all the parts */ memcpy (&loc_pres_addr, &de->pres_addr, sizeof (PRES_ADDR)); if (de->pres_addr.tp_type == TP_TYPE_TPX) { /* do 2 binds */ /* Bind for TP4 (overwrite the "tp_type" in loc_pres_addr). */ bc->tp_type = loc_pres_addr.tp_type = TP_TYPE_TP4; ma_cmd_done = SD_FALSE; ma_cmd_rslt = REQ_INCOMPLETE; ret = copp_bind ((ST_LONG) bc, &loc_pres_addr, SD_FALSE, numConn); ma_wait_req_done (&ret); if (ret != SD_SUCCESS) { MVL_LOG_ERR2 ("Error: copp_bind (TP4) of AR '%s' returned '0x%x'", bc->ar_name, ret); return (ret); } /* Bind for TCP (overwrite the "tp_type" in loc_pres_addr). */ bc->tp_type = loc_pres_addr.tp_type = TP_TYPE_TCP; ret = copp_bind ((ST_LONG) bc, &loc_pres_addr, SD_FALSE, numConn); ma_wait_req_done (&ret); if (ret != SD_SUCCESS) { MVL_LOG_ERR2 ("Error: copp_bind (TCP) of AR '%s' returned '0x%x'", bc->ar_name, ret); return (ret); } } else /* Not TPX */ { bc->tp_type = loc_pres_addr.tp_type; ma_cmd_done = SD_FALSE; ma_cmd_rslt = REQ_INCOMPLETE; ret = copp_bind ((ST_LONG) bc, &loc_pres_addr, SD_FALSE, numConn); ma_wait_req_done (&ret); if (ret != SD_SUCCESS) { MVL_LOG_ERR2 ("Error: copp_bind of AR '%s' returned '0x%x'", bc->ar_name, ret); return (ret); } } #endif #if defined(MAP30_ACSE) ma_cmd_done = SD_FALSE; ma_cmd_rslt = REQ_INCOMPLETE; ret = _copp_bind ((ST_LONG) bc, bc->ar_name, bc->num_calling, bc->num_called, activate); ma_wait_req_done (&ret); if (ret != SD_SUCCESS) { MVL_LOG_ERR2 ("Error: copp_bind of AR '%s' failed '0x%x'", bc->ar_name, ret); return (ret); } #endif /* defined(MAP30_ACSE) */ MVL_LOG_ACSE0 ("ACSE: bind OK"); /* OK, now attach the bind controls to the MVL_NET_INFO */ ni = mvl_called_conn_ctrl + mvl_cfg_info->called_used; for (j = 0; j < bc->num_called; ++j, ++ni) ni->bind_ctrl = bc; ni = mvl_calling_conn_ctrl + mvl_cfg_info->calling_used; for (j = 0; j < bc->num_calling; ++j, ++ni) ni->bind_ctrl = bc; mvl_cfg_info->calling_used += bc->num_calling; mvl_cfg_info->called_used += bc->num_called; return (ret); } /************************************************************************/ /* copp_unbind_sync */ /************************************************************************/ static ST_VOID copp_unbind_sync (ST_LONG copp_bind_id) { ST_RET ret; ma_cmd_done = SD_FALSE; ma_cmd_rslt = REQ_INCOMPLETE; ret = copp_unbind (copp_bind_id); if (ret != SD_SUCCESS) { MVL_LOG_ERR1 ("Error: unbind result '0x%x'", ret); } else /* Now just wait for the 'confirm' function to be called */ ma_wait_req_done (&ret); } /************************************************************************/ /* COACSE USER FUNCTIONS */ /************************************************************************/ /************************************************************************/ /* u_copp_bind_cnf */ /************************************************************************/ ST_VOID u_copp_bind_cnf (ST_LONG user_bind_id, ST_LONG copp_bind_id, ST_INT result) { NET_BIND_CTRL *bc; /* Save the acse interface's bind ID for future use */ bc = (NET_BIND_CTRL *) user_bind_id; #ifdef LEAN_T if (bc->tp_type == TP_TYPE_TP4) bc->copp_bind_id_tp4 = copp_bind_id; else bc->copp_bind_id_tcp = copp_bind_id; #else bc->copp_bind_id = copp_bind_id; #endif /* Allow sync binds to complete */ ma_cmd_done = SD_TRUE; ma_cmd_rslt = result; } /************************************************************************/ /* u_copp_unbind_cnf */ /************************************************************************/ ST_VOID u_copp_unbind_cnf (ST_LONG user_bind_id) { /* Allow the request function to complete */ ma_cmd_done = SD_TRUE; ma_cmd_rslt = SD_SUCCESS; } /************************************************************************/ /* u_a_associate_ind */ /************************************************************************/ ST_VOID u_a_associate_ind (ST_LONG u_bind_id, ST_LONG acse_conn_id, AARQ_APDU *info) { #if (MMS_INIT_EN & RESP_EN) MMSDEC_INFO rslt; INIT_INFO *init_req; INIT_INFO init_resp; MVL_NET_INFO *cc; #if !defined(ICCP_LITE) ST_ACSE_AUTH auth_ret; #endif ST_INT ret; AARE_APDU reinfo; ST_INT accept; ST_BOOLEAN free_dec_info; MVL_ASSOC_IND *mvlAssocInd; AARQ_APDU *reqinfo; ST_UCHAR *user_info_buf; if (mvl_init_ind_hold) { /* Can't rely on this data being persistent */ /* Allocate buffer big enough for the control structure, */ /* the AARQ info, and the user data */ mvlAssocInd = chk_malloc (sizeof (MVL_ASSOC_IND) + sizeof (AARQ_APDU) + info->user_info.len); mvlAssocInd->u_bind_id = u_bind_id; mvlAssocInd->acse_conn_id = acse_conn_id; /* Copy the AARQ data */ reqinfo = (AARQ_APDU *) (mvlAssocInd + 1); *reqinfo = *info; mvlAssocInd->info = reqinfo; /* Copy the user data, set the pointer to it */ user_info_buf = (ST_UCHAR *) (reqinfo + 1); reqinfo->user_info.ptr = user_info_buf; memcpy (user_info_buf, info->user_info.ptr, info->user_info.len); list_add_last (&mvlAssocIndList, mvlAssocInd); return; } #if defined(_S_TEST_PROBES) if (_sTestProbeEnabled(_MI_TEST_INITIATE_IND_NO_RESPOND)) { echo_warn ("TEST: Initiate indication, do not respond"); return; } #endif ++mvl_mms_statistics.calledConn; MVL_LOG_ACSE0 ("ACSE: Associate Indication received"); MVL_LOG_ACSEDATAH (info->user_info.len, info->user_info.ptr); free_dec_info = SD_FALSE; /* Assume the worst ... */ accept = SD_FALSE; reinfo.user_info.len = 0; reinfo.auth_info.auth_pres = SD_FALSE; /* Get a 'called' connection control structure, if one is available */ cc = ma_get_called_conn_ctrl ((NET_BIND_CTRL *) u_bind_id); if (cc) { MVL_LOG_CACSE1 ("Using MVL_NET_INFO %08lx", cc); /* Copy the whole AARQ Info struct, for the user to see */ memcpy (&cc->ass_ind_info, info, sizeof (AARQ_APDU)); /* IMPORTANT: Save the ACSE connection ID before calling user funtions.*/ cc->acse_conn_id = acse_conn_id; /* We need to parse the MMS Initiate PDU */ free_dec_info = SD_TRUE; _ms_mms_decode (info->user_info.ptr, info->user_info.len, &rslt); if (rslt.err_code == NO_DECODE_ERR && rslt.type == MMSINITREQ) { init_req = (INIT_INFO *) rslt.data_ptr; init_req->mms_p_context_pres = SD_TRUE; /* We can log here if so desired */ if ((mms_debug_sel & MMS_LOG_IND) && ml_log_ind_info_fun != NULL) (*ml_log_ind_info_fun) (0, MMSOP_INITIATE, init_req); /* OK, we handle telling the user differently depending on whether this */ /* is ICCP Lite, and whether ACSE Authentication is in use or not */ #ifdef ICCP_LITE ret = mi_connect_ind_fun (cc, init_req, &reinfo.auth_info); #else /* Let the user have a look to see if they want to accept */ auth_ret = u_mvl_connect_ind_ex(cc, init_req, &cc->ass_ind_info.auth_info, /* partner authentication */ &reinfo.auth_info); /* ret rsp authentication */ /* User did not like something about the authentication */ if (auth_ret != ACSE_AUTH_SUCCESS) { MVL_LOG_ACSE1 ("ACSE: ACSE Authentication failure. Reason: %d", auth_ret); mvl_abort_req_ex (cc, SD_TRUE, auth_ret); return; } ret = SD_SUCCESS; /* User is OK with it */ #endif /* ICCP_LITE */ if (ret == SD_SUCCESS) { /* Build an initiate response PDU, negiotiating the calling init */ /* parameters vs. what we support */ #ifdef NEGIOTIATE_INITIATE_PARAM /* Start with the default initiate response info */ memcpy (&init_resp, mvl_init_resp_info, sizeof (INIT_INFO)); if (init_req->version < init_resp.version)/* thiers is lower */ init_resp.version = init_req->version; /* accept lower version */ if (init_req->max_segsize_pres) { if (init_req->max_segsize < init_resp.max_segsize) init_resp.max_segsize = init_req->max_segsize; } if (init_req->maxreq_calling < init_resp.maxreq_calling) init_resp.maxreq_calling = init_req->maxreq_calling; if (init_req->maxreq_called < init_resp.maxreq_called) init_resp.maxreq_called = init_req->maxreq_called; if (init_req->max_nest_pres) { if (init_req->max_nest < init_resp.max_nest) init_resp.max_nest = init_req->max_nest; } /* These 'supported' bitstring parameters are set up in mmsop_en.c */ memcpy (init_resp.serv_supp, m_service_resp, 11); init_resp.param_supp[0] = m_param[0] & init_req->param_supp[0]; init_resp.param_supp[1] = m_param[1] & init_req->param_supp[1]; #else /* Just send back what the user wants to send */ memcpy (&init_resp, mvl_init_resp_info, sizeof (INIT_INFO)); #endif ret = mpl_init_resp (&init_resp); if (ret == SD_SUCCESS) { /* We can log here if so desired */ if ((mms_debug_sel & MMS_LOG_RESP) && ml_log_resp_info_fun != NULL) (*ml_log_resp_info_fun) (0, MMSOP_INITIATE, &init_resp); accept = SD_TRUE; cc->conn_active = SD_TRUE; /* Save the remote node's initiate information */ memcpy (&cc->rem_init_info, init_req, sizeof (INIT_INFO)); memcpy (&cc->locl_init_info, &init_resp, sizeof (INIT_INFO)); cc->max_pdu_size = (ST_INT) init_resp.max_segsize; /* NOTE: maxreq_calling = num of outstanding indications */ /* allowed at the calling app (similar for maxreq_called). */ cc->maxpend_req = init_resp.maxreq_calling; cc->maxpend_ind = init_resp.maxreq_called; cc->numpend_req = 0; cc->numpend_ind = 0; } } if (ret != SD_SUCCESS) { MVL_LOG_NERR0 ("ACSE: User does not want connection"); ret = mpl_init_err (8, 0); cc->in_use = SD_FALSE; } if (ret == SD_SUCCESS) { reinfo.user_info.len = mmsl_msg_len; reinfo.user_info.ptr = mmsl_msg_start; } } else { MVL_LOG_NERR0 ("ACSE: Initiate indication PDU parse error"); free_dec_info = SD_FALSE; cc->in_use = SD_FALSE; } } else { MVL_LOG_ERR0 ("Error - Could not get called MVL_NET_INFO"); } /* Initiate Response (or error) PDU is built, or len set to 0. */ /* Set the remaining ACSE parameters and send the response */ /* Use the calling context as the responding, to be friendly */ reinfo.ASO_context_name_pres = info->ASO_context_name_pres; memcpy (&reinfo.ASO_context_name, &info->ASO_context_name, sizeof (MMS_OBJ_ID)); /* For now, just reflect the ACSE indication information */ /* Note that it may (or may not) be more appropriate to use the 'local' */ /* DIB_ENTRY info for this purpose. */ memcpy (&reinfo.responding_ae_title, &info->called_ae_title, sizeof (AE_TITLE)); if (accept) { MVL_LOG_ACSE0 ("Accepting the connection"); reinfo.result = 0; /* ACCEPT */ reinfo.result_source_diag_pres = SD_FALSE; } else { MVL_LOG_ACSE0 ("Rejecting the connection"); reinfo.result = 1; /* REJECT */ reinfo.result_source_diag_pres = SD_TRUE; reinfo.result_source = 1; reinfo.result_diag = 9; } /* Send ACSE response */ MVL_LOG_ACSEDATAH (reinfo.user_info.len, reinfo.user_info.ptr); ret = a_associate_rsp (acse_conn_id, (ST_LONG) cc, &reinfo); if (ret != SD_SUCCESS) { MVL_LOG_NERR1 ("ACSE: a_associate_rsp error '0x%x", ret); if (cc != NULL) cc->in_use = SD_FALSE; ++mvl_mms_statistics.calledConnFail; } else ++mvl_mms_statistics.calledConnOK; if (free_dec_info == SD_TRUE) M_FREE (MSMEM_DEC_OS_INFO, _mms_dec_info); #else /* !(MMS_INIT_EN & RESP_EN) */ AARE_APDU reinfo; ST_LONG user_conn_id; ST_INT ret; ++mvl_mms_statistics.calledConn; /* Incoming connections not supported, so Reject the association. */ MVL_LOG_ACSE0 ("ACSE: Associate Indication received. Rejecting."); /* Just use the ASO-context from the request in the response. */ reinfo.ASO_context_name_pres = info->ASO_context_name_pres; memcpy (&reinfo.ASO_context_name, &info->ASO_context_name, sizeof (MMS_OBJ_ID)); /* Just use the called AE-Title as the responding AE-Title. */ memcpy (&reinfo.responding_ae_title, &info->called_ae_title, sizeof (AE_TITLE)); /* Reject */ reinfo.result = 1; /* Rejected-permanent */ reinfo.result_source_diag_pres = SD_TRUE; reinfo.result_source = 1; /* Source = user. */ reinfo.result_diag = 1; /* no-reason-given */ /* No User Information */ reinfo.user_info.len = 0; reinfo.user_info.ptr = NULL; reinfo.auth_info.auth_pres = SD_FALSE; user_conn_id = 0; /* id doesn't matter because rejecting */ if ((ret = a_associate_rsp (acse_conn_id, user_conn_id, &reinfo))!=SD_SUCCESS) { MVL_LOG_ERR1 ("Error sending a_associate_rsp. Error = %d", ret); } ++mvl_mms_statistics.calledConnFail; #endif /* !(MMS_INIT_EN & RESP_EN) */ } /************************************************************************/ /* u_a_associate_cnf */ /************************************************************************/ ST_VOID u_a_associate_cnf (ST_LONG acse_conn_id, ST_LONG user_conn_id, AARE_APDU *info) { #if (MMS_INIT_EN & REQ_EN) MMSDEC_INFO rslt; MVL_NET_INFO *cc; INIT_INFO *init_resp; MVL_REQ_PEND *req; ST_BOOLEAN free_dec_info; ST_RET result; ST_ACSE_AUTH auth_ret; /* Need to save off the ACSE interface's connection ID for future use */ cc = (MVL_NET_INFO *) user_conn_id; cc->acse_conn_id = acse_conn_id; MVL_LOG_ACSE1 ("ACSE: associate confirm for MVL_NET_INFO %08lx", cc); req = _mvl_find_req_ctrl (cc, MMSOP_INITIATE, -1); if (!req) { MVL_LOG_ERR0 ("ACSE: Associate Confirm - no matching req ctrl"); info->result = SD_FAILURE; /* Cause disconnect */ cc->in_use = SD_FALSE; return; } /* Only check ACSE authentication if this is a positive connect confirm */ if (info->result == SD_SUCCESS) { auth_ret = u_mvl_connect_cnf_ex(cc, info); /* User did not like something about the authentication */ if(auth_ret != ACSE_AUTH_SUCCESS) { MVL_LOG_ACSE1 ("ACSE: ACSE Authentication failure. Reason: %d", auth_ret); mvl_abort_req_ex (cc, SD_TRUE, auth_ret); return; } } free_dec_info = SD_FALSE; result = info->result; if (info->result == SD_SUCCESS) { cc->conn_active = SD_TRUE; MVL_LOG_ACSEDATAH (info->user_info.len, info->user_info.ptr); /* OK, now we need to parse the MMS Initiate PDU */ free_dec_info = SD_TRUE; _ms_mms_decode (info->user_info.ptr, info->user_info.len, &rslt); if (rslt.err_code == NO_DECODE_ERR) { switch (rslt.type) { case MMSINITRESP : init_resp = (INIT_INFO *) rslt.data_ptr; init_resp->mms_p_context_pres = SD_TRUE; /* We can log here if so desired */ /* if ((mms_debug_sel & MMS_LOG_CONF) && ml_log_conf_info_fun != NULL) (*ml_log_conf_info_fun) (0, MMSOP_INITIATE, init_resp);*/ if (req->u.init.resp_info != NULL) memcpy (req->u.init.resp_info, init_resp, sizeof (INIT_INFO)); memcpy (&cc->rem_init_info, init_resp, sizeof (INIT_INFO)); MVL_LOG_CACSE0 ("ACSE: initiate confirm OK"); cc->max_pdu_size = init_resp->max_segsize; /* NOTE: maxreq_calling = num of outstanding indications */ /* allowed at the calling app (similar for maxreq_called). */ cc->maxpend_req = init_resp->maxreq_called; cc->maxpend_ind = init_resp->maxreq_calling; cc->numpend_req = 0; cc->numpend_ind = 0; ++mvl_mms_statistics.callingConnOk; break; case MMSINITERR : result = SD_FAILURE; cc->in_use = SD_FALSE; MVL_LOG_NERR0 ("ACSE: initiate confirm error"); ++mvl_mms_statistics.callingConnFail; break; default : MVL_LOG_NERR1 ("ACSE: associate confirm PDU wrong type (%d)", rslt.type); result = SD_FAILURE; cc->in_use = SD_FALSE; info->result = SD_FAILURE; /* Cause disconnect */ ++mvl_mms_statistics.callingConnFail; break; } } else /* PDU decode error, abort the connection */ { MVL_LOG_NERR0 ("ACSE: associate confirm PDU Decode Error"); result = SD_FAILURE; info->result = SD_FAILURE; /* Cause disconnect */ cc->in_use = SD_FALSE; ++mvl_mms_statistics.callingConnFail; } } else { MVL_LOG_NERR0 ("ACSE: associate confirm result != SD_SUCCESS"); cc->in_use = SD_FALSE; ++mvl_mms_statistics.callingConnFail; } _mvl_set_req_done (req, result); if (free_dec_info == SD_TRUE && rslt.data_pres) M_FREE (MSMEM_DEC_OS_INFO, rslt.data_ptr); #endif } /************************************************************************/ /* u_a_data_ind */ /************************************************************************/ ST_VOID u_a_data_ind (ST_LONG user_conn_id, ST_UINT data_len, ST_UCHAR *data) { MVL_NET_INFO *ni; MVL_COMM_EVENT *commEvent; ni = (MVL_NET_INFO *) user_conn_id; /* See if we are supposed to log ACSE data for this connection */ if (mvl_conn_filtered_logging == SD_FALSE || ni->log_enable) { MVL_LOG_ACSEDATA2 ("ACSE: Rx'd %d bytes on MVL_NET_INFO 0x%08lx", data_len, ni); MVL_LOG_ACSEDATAH (data_len, data); } commEvent = mvl_get_com_event (); if (!commEvent) { MVL_LOG_ERR0 ("ACSE: Error - could not get MVL_COMM_EVENT"); u_a_except (user_conn_id, SD_FAILURE, __FILE__, __LINE__); return; } commEvent->event_type = MMS_MSG_RCVD; commEvent->net_info = ni; commEvent->u.mms.pdu_len = data_len; commEvent->u.mms.pdu = (ST_UCHAR *) M_MALLOC (MSMEM_RXPDU,data_len); memcpy (commEvent->u.mms.pdu, data, data_len); } /************************************************************************/ /* u_a_release_ind */ /************************************************************************/ ST_VOID u_a_release_ind (ST_LONG user_conn_id, RLRQ_APDU *info) { RLRE_APDU reinfo; MVL_NET_INFO *cc; cc = (MVL_NET_INFO *) user_conn_id; MVL_LOG_ACSE1 ("ACSE: Release Indication received on MVL_NET_INFO 0x%08lx", cc); ++mvl_mms_statistics.serverConcl; cc->conn_active = SD_FALSE; cc->in_use = SD_FALSE; if (_mvlu_rpt_disconnect_rcvd_fun != NULL) (*_mvlu_rpt_disconnect_rcvd_fun)(cc); reinfo.reason_pres = SD_TRUE; reinfo.reason = 1; /* Send no data on the release response */ reinfo.user_info.len = 0; reinfo.user_info.ptr = NULL; a_release_rsp (cc->acse_conn_id, &reinfo); /* Set any outstanding requests to 'done' */ _mvl_set_net_req_done (NULL, cc, SD_FAILURE); #ifdef ICCP_LITE if (cc->mi_in_use) mi_release_ind_fun (cc); else { if (u_mvl_disc_ind_fun) (*u_mvl_disc_ind_fun) (cc, MVL_ACSE_RELEASE_IND); } #else if (u_mvl_disc_ind_fun) (*u_mvl_disc_ind_fun) (cc, MVL_ACSE_RELEASE_IND); #endif cc->maxpend_req = 0; cc->numpend_req = 0; } /************************************************************************/ /* u_a_abort_ind */ /************************************************************************/ ST_VOID u_a_abort_ind (ST_LONG user_conn_id, ABRT_APDU *info) { MVL_NET_INFO *cc; MVL_ASSOC_IND *mvlAssocInd; ST_BOOLEAN conn_active; cc = (MVL_NET_INFO *) user_conn_id; MVL_LOG_ACSE1 ("ACSE: Abort Indication received on MVL_NET_INFO 0x%08lx", cc); /* This can happen if we have not responded to an initiate indication */ /* In this case, just flush the initiate indication hold list */ if (cc == NULL) { while (mvlAssocIndList) { mvlAssocInd = list_get_first (&mvlAssocIndList); chk_free (mvlAssocInd); } return; } ++mvl_mms_statistics.remoteAbort; /* Verify we can safely use this as a MVL_NET_INFO */ if (user_conn_id == -1L) return; conn_active = cc->conn_active; cc->conn_active = SD_FALSE; cc->in_use = SD_FALSE; if (_mvlu_rpt_disconnect_rcvd_fun != NULL) (*_mvlu_rpt_disconnect_rcvd_fun)(cc); /* Set any outstanding requests to 'done' */ _mvl_set_net_req_done (NULL, cc, MVL_ERR_CNF_DISCONNECTED); if (conn_active == SD_TRUE) { #ifdef ICCP_LITE if (cc->mi_in_use == SD_TRUE) mi_abort_ind_fun (cc); else { if (u_mvl_disc_ind_fun) (*u_mvl_disc_ind_fun) (cc, MVL_ACSE_ABORT_IND); } #else if (u_mvl_disc_ind_fun) (*u_mvl_disc_ind_fun) (cc, MVL_ACSE_ABORT_IND); #endif } cc->maxpend_req = 0; cc->numpend_req = 0; } /************************************************************************/ /* u_a_release_cnf */ /************************************************************************/ ST_VOID u_a_release_cnf (ST_LONG user_conn_id, RLRE_APDU *info) { MVL_NET_INFO *cc; MVL_REQ_PEND *req; cc = (MVL_NET_INFO *) user_conn_id; MVL_LOG_ACSE1 ("ACSE: release confirm received for MVL_NET_INFO %08lx", cc); /* Find the conclude request */ req = _mvl_find_req_ctrl (cc, MVL_MMSOP_RELEASE, -1); if (!req) { MVL_LOG_ERR0 ("ACSE: Release Confirm - no matching req ctrl"); return; } /* Set any outstanding requests to 'done' */ _mvl_set_net_req_done (req, cc, MVL_ERR_CNF_DISCONNECTED); cc->conn_active = SD_FALSE; cc->in_use = SD_FALSE; if (_mvlu_rpt_disconnect_rcvd_fun != NULL) (*_mvlu_rpt_disconnect_rcvd_fun)(cc); _mvl_set_req_done (req, SD_SUCCESS); cc->maxpend_req = 0; cc->numpend_req = 0; } /************************************************************************/ /* u_a_except */ /************************************************************************/ ST_VOID u_a_except (ST_LONG user_conn_id, ST_INT code, ST_CHAR *filename, ST_INT line) { MVL_LOG_ERR2 ("ACSE: Error - Exception, code 0x%x, MVL_NET_INFO %08lx", code, user_conn_id); MVL_LOG_CERR2 ("File %s, Line %d", filename, line); mvl_acse_ok = SD_FALSE; } /************************************************************************/ /* CONNECTION CONTROL RELATED STUFF */ /************************************************************************/ /* ma_get_called_conn_ctrl */ /************************************************************************/ #if (MMS_INIT_EN & RESP_EN) static MVL_NET_INFO *ma_get_called_conn_ctrl (NET_BIND_CTRL *bc) { MVL_NET_INFO *ni; ST_INT i; ni = mvl_called_conn_ctrl; for (i = 0; i < mvl_cfg_info->called_used; ++i, ++ni) { /* CRITICAL: don't reuse 'ni' until req_pend_list cleaned up from */ /* last conn. May be waiting for user to call mvl_free_req_ctrl. */ if (!ni->in_use && ni->req_pend_list==NULL) { if (bc == NULL || !strcmp (bc->ar_name, ni->bind_ctrl->ar_name)) { ni->in_use = SD_TRUE; ni->conn_active = SD_FALSE; return (ni); } } } return (NULL); } #endif /************************************************************************/ /* ma_get_calling_conn_ctrl */ /************************************************************************/ #if (MMS_INIT_EN & REQ_EN) static MVL_NET_INFO *ma_get_calling_conn_ctrl (NET_BIND_CTRL *bc) { MVL_NET_INFO *ni; ST_INT i; ni = mvl_calling_conn_ctrl; for (i = 0; i < mvl_cfg_info->calling_used; ++i, ++ni) { /* CRITICAL: don't reuse 'ni' until req_pend_list cleaned up from */ /* last conn. May be waiting for user to call mvl_free_req_ctrl. */ if (!ni->in_use && ni->req_pend_list==NULL) { if (bc == NULL || !strcmp (bc->ar_name, ni->bind_ctrl->ar_name)) { ni->in_use = SD_TRUE; ni->conn_active = SD_FALSE; return (ni); } } } return (NULL); } #endif /************************************************************************/ #endif /* End of COACSE specific functions */ /************************************************************************/ /************************************************************************/ /************************************************************************/ #if defined(CLACSE) /* CONNECTIONLESS ACSE FUNCTIONS */ /************************************************************************/ /************************************************************************/ /* mvl_get_com_event */ /************************************************************************/ /* This function is used to get a MVL_COMM_EVENT control buffer to be */ /* passed up to the caller of '_mvl_net_service'. */ static MVL_NET_INFO *mvl_get_net_info (ST_VOID) { MVL_NET_INFO *netInfo; #if 1 netInfo = (MVL_NET_INFO *) M_CALLOC (MSMEM_NETINFO, 1, sizeof (MVL_NET_INFO)); if (netInfo == NULL) { MVL_LOG_ERR0 ("Error: No MVL_NET_INFO available"); return (NULL); } #else if (mvl_net_info_avail_head) netInfo = (MVL_NET_INFO *) list_get_first((ST_VOID **) &mvl_net_info_avail_head); else { if (mvl_net_info_count >= mvl_max_net_info) { MVL_LOG_ERR0 ("Error: No MVL_NET_INFO available"); return (NULL); } ++mvl_net_info_count; netInfo = (MVL_NET_INFO *) M_CALLOC (MSMEM_GEN, 1, sizeof (MVL_NET_INFO)); } #endif return (netInfo); } /************************************************************************/ /* mvl_init_audt_addr */ /* User must pass pointer (AUDT_APDU *) to their struct. */ /* This function fills in the addressing info in the struct. */ /************************************************************************/ ST_RET mvl_init_audt_addr (AUDT_APDU *audt, ST_CHAR *locArName, ST_CHAR *remArName) { DIB_ENTRY *locDe; DIB_ENTRY *remDe; /* Retrieve the DIB_ENTRY's for local and remote. These are used to set */ /* the AUDT_APDU information */ locDe = find_loc_dib_entry (locArName); if (!locDe) { MVL_LOG_NERR1 ("ACSE: Local name '%s' not found", locArName); return (MVLE_LOCAL_NAME); } remDe = find_rem_dib_entry (remArName); if (!remDe) { MVL_LOG_NERR1 ("ACSE: Remote name '%s' not found", remArName); return (MVLE_REMOTE_NAME); } if (remDe->pres_addr.tp_type != TP_TYPE_TP4) /* must be TP4 (need NSAP) */ { MVL_LOG_NERR1 ("ACSE: Remote name '%s' is not TP4 Transport type", remArName); return (MVLE_REMOTE_NAME); } /* AP Context is MMS */ audt->ASO_context_name_pres = SD_TRUE; audt->ASO_context_name.num_comps = 5; audt->ASO_context_name.comps[0] = 1; audt->ASO_context_name.comps[1] = 0; audt->ASO_context_name.comps[2] = 9506; audt->ASO_context_name.comps[3] = 2; audt->ASO_context_name.comps[4] = 3; /* Calling Addressing information */ audt->calling_ae_title.AP_title_pres = locDe->AP_title_pres; memcpy (&audt->calling_ae_title.AP_title, &locDe->AP_title, sizeof (MMS_OBJ_ID)); audt->calling_ae_title.AE_qual_pres = locDe->AE_qual_pres; audt->calling_ae_title.AE_qual = locDe->AE_qual; audt->calling_ae_title.AP_inv_id_pres = locDe->AP_inv_id_pres; audt->calling_ae_title.AP_inv_id = locDe->AP_invoke_id; audt->calling_ae_title.AE_qual_pres = locDe->AE_qual_pres; audt->calling_ae_title.AE_qual = locDe->AE_qual; audt->calling_ae_title.AE_inv_id_pres = locDe->AE_inv_id_pres; audt->calling_ae_title.AE_inv_id = locDe->AE_invoke_id; memcpy (&audt->calling_paddr, &locDe->pres_addr, sizeof (PRES_ADDR)); /* Called Addressing information */ audt->called_ae_title.AP_title_pres = remDe->AP_title_pres; memcpy (&audt->called_ae_title.AP_title, &remDe->AP_title, sizeof (MMS_OBJ_ID)); audt->called_ae_title.AE_qual_pres = remDe->AE_qual_pres; audt->called_ae_title.AE_qual = remDe->AE_qual; audt->called_ae_title.AP_inv_id_pres = remDe->AP_inv_id_pres; audt->called_ae_title.AP_inv_id = remDe->AP_invoke_id; audt->called_ae_title.AE_qual_pres = remDe->AE_qual_pres; audt->called_ae_title.AE_qual = remDe->AE_qual; audt->called_ae_title.AE_inv_id_pres = remDe->AE_inv_id_pres; audt->called_ae_title.AE_inv_id = remDe->AE_invoke_id; memcpy (&audt->called_paddr, &remDe->pres_addr, sizeof (PRES_ADDR)); audt->rem_mac_valid = SD_FALSE; /* CRITICAL: must send to ALL-ES MAC*/ return (SD_SUCCESS); } /************************************************************************/ /* mvl_free_net_info */ /************************************************************************/ static ST_VOID mvl_free_net_info (MVL_NET_INFO *netInfo) { #if 1 M_FREE (MSMEM_NETINFO, netInfo); #else list_add_last((ST_VOID **) &mvl_net_info_avail_head, (ST_VOID *) netInfo); #endif } /************************************************************************/ #endif /* End of CLACSE specific functions */ /************************************************************************/ /************************************************************************/ /************************************************************************/ /* UTILITY FUNCTIONS */ /************************************************************************/ /* ma_wait_req_done */ /************************************************************************/ static ST_VOID ma_wait_req_done (ST_RET *retOut) { /* See if the call failed */ if (*retOut != SD_SUCCESS) return; /* Now just wait for the 'confirm' function to be called */ while (ma_cmd_done != SD_TRUE) { copp_event (); if (u_mvl_check_timeout && (*u_mvl_check_timeout)()) break; } /* OK, the function is done or the user gave up */ if (ma_cmd_done == SD_TRUE) *retOut = ma_cmd_rslt; else { /* User timeout */ if (ma_cmd_rslt != SD_SUCCESS) *retOut = ma_cmd_rslt; else *retOut = SD_FAILURE; } } /************************************************************************/ /************************************************************************/ /* AA OBJECT HANDLING FUNCTIONS */ /* These functions must be here because the sizeof MVL_NET_INFO */ /* varies depending on the stack selection. */ /************************************************************************/ /************************************************************************/ /* mvl_aa_resize */ /************************************************************************/ ST_VOID mvl_aa_resize (ST_INT max_num_var, ST_INT max_num_nvl, ST_INT max_num_jou) { MVL_AA_OBJ_CTRL *aa_objs; ST_INT i; /* Do AA specific variables */ for (i = 0; i < mvl_cfg_info->num_called; ++i) { aa_objs = (MVL_AA_OBJ_CTRL *) mvl_called_conn_ctrl[i].aa_objs; if (aa_objs == NULL) { aa_objs = mvl_called_conn_ctrl[i].aa_objs = (MVL_AA_OBJ_CTRL *) M_CALLOC (NULL, 1, sizeof(MVL_AA_OBJ_CTRL)); } mvl_aa_resize_conn (aa_objs, max_num_var, max_num_nvl, max_num_jou); } for (i = 0; i < mvl_cfg_info->num_calling; ++i) { aa_objs = (MVL_AA_OBJ_CTRL *) mvl_calling_conn_ctrl[i].aa_objs; if (aa_objs == NULL) { aa_objs = mvl_calling_conn_ctrl[i].aa_objs = (MVL_AA_OBJ_CTRL *) M_CALLOC (NULL, 1, sizeof(MVL_AA_OBJ_CTRL)); } mvl_aa_resize_conn (aa_objs, max_num_var, max_num_nvl, max_num_jou); } } /************************************************************************/ /* _mvl_clear_aa_objs */ /************************************************************************/ ST_VOID _mvl_clear_aa_objs (MVL_AA_OBJ_CTRL *aa_objs) { ST_INT i; /* Delete NVL's. We need to delete the 'entries' pointer table for each */ /* NVL, then delete the table of NVL's. */ if (aa_objs->max_num_nvlist) { for (i = 0; i < aa_objs->num_nvlist; ++i) mvl_nvl_destroy (aa_objs->nvlist_tbl[i]); } /* Delete the variable association table. */ if (aa_objs->max_num_var_assoc) { for (i = 0; i < aa_objs->num_var_assoc; ++i) M_FREE (MSMEM_GEN, aa_objs->var_assoc_tbl[i]); } /* Delete the Journal control table. */ if (aa_objs->max_num_jou) { for (i = 0; i < aa_objs->num_jou; ++i) M_FREE (MSMEM_GEN, aa_objs->jou_tbl[i]); } aa_objs->num_var_assoc = 0; aa_objs->num_nvlist = 0; aa_objs->num_jou = 0; } /************************************************************************/ ST_VOID mvl_aa_resize_conn (MVL_AA_OBJ_CTRL *aa_objs, ST_INT max_num_var, ST_INT max_num_nvl, ST_INT max_num_jou) { if (max_num_var < aa_objs->num_var_assoc) { MVL_LOG_NERR0 ("Resizing VMD: new max VA is less than current"); max_num_var = aa_objs->num_var_assoc; } if (max_num_nvl < aa_objs->num_nvlist) { MVL_LOG_NERR0 ("Resizing VMD: new max NVL is less than current"); max_num_nvl = aa_objs->num_nvlist; } if (max_num_jou < aa_objs->num_jou) { MVL_LOG_NERR0 ("Resizing VMD: new max JOU is less than current"); max_num_jou = aa_objs->num_jou; } _mvl_resize_ptr_tbl (&(aa_objs->max_num_var_assoc), (ST_VOID ***)&(aa_objs->var_assoc_tbl), max_num_var); _mvl_resize_ptr_tbl (&(aa_objs->max_num_nvlist), (ST_VOID ***)&(aa_objs->nvlist_tbl), max_num_nvl); _mvl_resize_ptr_tbl (&(aa_objs->max_num_jou), (ST_VOID ***)&(aa_objs->jou_tbl), max_num_jou); } /************************************************************************/ /************************************************************************/ /* mvl_match_remote_ar */ /************************************************************************/ ST_RET mvl_match_remote_ar (DIB_MATCH_CTRL *matchCtrl, MVL_NET_INFO *cc, DIB_ENTRY **dib_entry_out) { #if defined(MAP30_ACSE) ST_INT chan; if (a_get_chan (cc->acse_conn_id, &chan) == SD_SUCCESS) return (dib_match_remote_ar (matchCtrl, chan, dib_entry_out)); else return (SD_FAILURE); #else return (dib_match_remote_ar (matchCtrl, &cc->ass_ind_info, dib_entry_out)); #endif } /************************************************************************/ /* mvl_match_local_ar */ /************************************************************************/ ST_RET mvl_match_local_ar (DIB_MATCH_CTRL *matchCtrl, MVL_NET_INFO *cc, DIB_ENTRY **dib_entry_out) { #if defined(MAP30_ACSE) ST_INT chan; if (a_get_chan (cc->acse_conn_id, &chan) == SD_SUCCESS) return (dib_match_local_ar (matchCtrl, chan, dib_entry_out)); else return (SD_FAILURE); #else return (dib_match_local_ar (matchCtrl, &cc->ass_ind_info, dib_entry_out)); #endif } /************************************************************************/ /* mvl_cmp_local_addr */ /************************************************************************/ ST_INT mvl_cmp_local_addr (DIB_MATCH_CTRL *matchCtrl, MVL_NET_INFO *cc, DIB_ENTRY *dib_entry) { #if defined(MAP30_ACSE) ST_INT chan; if (a_get_chan (cc->acse_conn_id, &chan) == SD_SUCCESS) return (dib_cmp_local_addr (matchCtrl, chan, dib_entry)); else return (DIB_MATCH_NOT); #else return (dib_cmp_local_addr (matchCtrl, &cc->ass_ind_info, dib_entry)); #endif } /************************************************************************/ /* mvl_cmp_remote_addr */ /************************************************************************/ ST_INT mvl_cmp_remote_addr (DIB_MATCH_CTRL *matchCtrl, MVL_NET_INFO *cc, DIB_ENTRY *dib_entry) { #if defined(MAP30_ACSE) ST_INT chan; if (a_get_chan (cc->acse_conn_id, &chan) == SD_SUCCESS) return (dib_cmp_remote_addr (matchCtrl, chan, dib_entry)); else return (DIB_MATCH_NOT); #else return (dib_cmp_remote_addr (matchCtrl, &cc->ass_ind_info, dib_entry)); #endif } /************************************************************************/ /* mvl_net_info_to_chan */ /************************************************************************/ ST_RET mvl_net_info_to_chan (MVL_NET_INFO *cc, ST_INT *chanOut) { #if defined(MAP30_ACSE) return (a_get_chan (cc->acse_conn_id, chanOut)); #else return (SD_FAILURE); #endif }