/************************************************************************/ /* SISCO SOFTWARE MODULE HEADER *****************************************/ /************************************************************************/ /* (c) Copyright Systems Integration Specialists Company, Inc., */ /* 1995-2008, All Rights Reserved */ /* */ /* MODULE NAME : acse2enc.c */ /* PRODUCT(S) : */ /* */ /* MODULE DESCRIPTION : */ /* ACSE Encode Functions. */ /* */ /* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ /* */ /* MODIFICATION LOG : */ /* Date Who Rev Comments */ /* -------- --- ------ ------------------------------------------- */ /* 02/27/08 EJV 35 a_associate_rsp: do not free acse_conn. */ /* 11/07/06 EJV 34 MMSEASE_MOSI:elim HPUX warn when logging PSEL*/ /* 07/06/05 EJV 33 a_associate_req: log "IP ADDR: ip" same line,*/ /* MMSEASE_MOSI: log local PSEL,SSEL,TSEL. */ /* 05/06/05 EJV 32 Log PORT if configured. */ /* 01/24/05 JRB 31 Move acse_debug_sel & "*_logstr" to lean_var.c*/ /* 09/17/04 JRB 30 a_abort_req: don't access acse_conn after */ /* copp_u_abort_req (it may have been freed). */ /* 08/06/04 EJV 29 Added typecast (ST_UCHAR *) ...password. */ /* 03/04/04 JRB 28 Mov thisFil.. after incs, they may define DEBUG_..*/ /* Del logging of A-DATA.req (use MVL or COPP) */ /* 12/18/03 JRB 27 If MOSI, use cosp_buf, DON't use acse_buf. */ /* Use ASN1_ENC_PTR, ASN1_ENC_LEN macros. */ /* 10/21/03 JRB 26 Add a_get_event_handles_unix. */ /* 08/20/03 EJV 25 Chg cosp_msgsize to fit larger User Data */ /* ACSE_AUTH_ENABLED code wo/define. */ /* Added security functions. */ /* Added param to tp4_connect . */ /* Fix the ACSE Auth encode. */ /* 06/17/03 EJV 24 Added _acse_dib_logstr. */ /* 10/22/02 ASK 23 Wrap ifdef TP0_ENABLED around inet_ntoa calls*/ /* 10/14/02 ASK 22 Added encoding for abort diagnostic. */ /* 08/26/02 ASK 21 Added password mechanism encoding in */ /* a_associate_req and a_associate rsp. */ /* 07/16/02 JRB 20 Add tp0_sock.h for sockets/IP defs. */ /* 06/26/02 JRB 19 associate_req: Log calling/called address. */ /* 01/22/02 JRB 18 Add args to copp_initialize (same as MAP30..)*/ /* Del a_set_msgsize (no longer needed). */ /* 01/02/02 JRB 17 Converted to use ASN1R (re-entrant ASN1) */ /* 06/22/01 JRB 16 Fix a_release_rsp handling of STATE_RESP_COLL*/ /* state per ISO 8650 (was kluged before). */ /* 03/15/01 JRB 15 Use new SMEM allocation functions. */ /* 01/04/01 EJV 14 a_get_event_handles used only on _WIN32 */ /* 09/24/99 JRB 13 a_get_event_handles not used on */ /* DOS, QNX or VXWORKS */ /* 09/13/99 MDE 12 Added SD_CONST modifiers */ /* 08/05/99 JRB 11 Add "a_get_event_handles" function for MOSI. */ /* 10/08/98 MDE 10 Migrated to updated SLOG interface */ /* 08/13/98 JRB 09 Lint cleanup. */ /* 07/10/98 JRB 08 Del *_obj_id, use acse2var.c */ /* 03/23/98 NAV 07 Free buffers on termination */ /* 02/16/98 JRB 06 Del or "#if out" unused locals. */ /* 11/10/97 JRB 05 Chg cosp_buf to (ST_UCHAR *). */ /* 09/22/97 JRB 04 acse_msgsize MUST be set before copp_init. */ /* a_data_req (MOSI): check for buffer overflow */ /* 09/04/97 JRB 03 Pass SPDU msgsize arg to tp4_initialize. */ /* 07/31/97 JRB 02 copp_bind & a_associate_req set "tp_type" */ /* in tp4_addr. New TP4 needs it. */ /* 06/09/97 JRB 01 If !MOSI, on A-ASSOCIATE.rsp-, just set */ /* state=STATE_IDLE. Don't free as did on 3/7/97*/ /* 05/27/97 JRB 7.00 MMSEASE 7.0 release. */ /* 05/02/97 JRB 24 wr_* functs now ret void, so don't check. */ /* 04/09/97 JRB 23 a_associate_req return (0L) for any error. */ /* 03/19/97 JRB 22 Add MOSI "CALLING" support. */ /* 03/19/97 JRB 21 Encode AARQ in a_associate_req: need for MOSI*/ /* In a_release_req, chg handling if send fails.*/ /* Use acse_free_conn to free conn ctrl struct. */ /* Improve logging. */ /* Improve release collision handling. */ /* 03/07/97 JRB 20 Always send result-source-diag on AARE. */ /* Rechecked spec, and this is MANDATORY. */ /* 03/07/97 JRB 19 If !MOSI, free acse_conn on negative */ /* A-Associate.rsp (MOSI frees in COSP). */ /* 03/07/97 JRB 18 Use new "acse_free_con" to free acse_conn. */ /* 03/07/97 JRB 17 Added MOSI support. */ /* 02/11/97 JRB 16 In a_release_rsp, if send fails, don't free */ /* acse_conn and don't change state. */ /* 01/23/97 JRB 15 Init acse_debug_sel in copp_initialize. */ /* 11/18/96 JRB 14 Del acse_dummyfun call. Funct is gone now. */ /* 11/15/96 JRB 13 Don't initialize globals. */ /* Move acse_debug_sel global here. */ /* 08/19/96 MDE 12 Add dummy a_buffers_avail for Reduced Stack */ /* 08/14/96 JRB 11 Add a_buffers_avail function. */ /* 07/19/96 JRB 10 Change DEBUG_MMS to DEBUG_SISCO. */ /* 07/15/96 JRB 09 Only free acse_conn->aarq_apdu.user_info.ptr */ /* if len != 0 (wasn't alloc'd otherwise). */ /* 05/02/96 JRB 08 Add STATE_TP4CONN_WAIT. */ /* 04/23/96 MDE 07 Fixed minor warning */ /* 04/18/96 JRB 06 a_associate_req return acse_conn_id or NULL */ /* on error, instead of just SD_SUCCESS or error. */ /* if (acse_conn->state == STATE_AARE_WAIT) */ /* in a_abort_req, set to STATE_AARE_ABANDON. */ /* 03/26/96 MDE 05 Added REDUCED_STACK support */ /* 03/11/96 JRB 04 Move acse_msgsize here & use for acse_buf. */ /* 03/07/96 JRB 03 Handle aarq_apdu->user_info.len = 0. */ /* 01/19/96 JRB 02 Cast constant chars to ST_UCHAR. */ /* 10/30/95 JRB 01 Created */ /************************************************************************/ #include "glbtypes.h" #include "sysincs.h" #include "mem_chk.h" #include "asn1defs.h" #include "acse2.h" #if defined (MOSI) #include "cosp_usr.h" #include "copp_usr.h" #endif /* MOSI */ #if defined (MMSEASE_MOSI) #include "cosp.h" /* for cosp_only_sel */ #include "copp.h" /* for only_loc_psel */ #include "tp4.h" /* for tp0_check_bind_id */ #endif #include "tp4api.h" #include "tp0_sock.h" #ifdef DEBUG_SISCO SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__; #endif ST_UINT acse_msgsize; /* Buffer for building init, release, and abort reqests. */ #if defined (MOSI) ST_UINT cosp_msgsize; ST_UCHAR *cosp_buf; /* Buffer containing "acse_buf" + COSP&COPP headers.*/ static ST_VOID acse_encode_user_info (ASN1_ENC_CTXT *aCtx, ACSE_CONN *acse_conn, BUFFER *user_info); #else /* !MOSI */ static ST_UCHAR *acse_buf; #endif /* !MOSI */ #define TP4_EOT 1 /* for tp4_data calls. */ /************************************************************************/ /* copp_initialize */ /* Save "msg_size". Pass "max_conns" to tp4_initialize. */ /************************************************************************/ ST_RET copp_initialize (ST_INT max_conns, ST_UINT msg_size) { ST_RET ret; acse_msgsize = msg_size; /* Save msg size in global. */ /* Always enable error logging. */ #if defined(DEBUG_SISCO) acse_debug_sel |= (ACSE_LOG_ERR | COPP_LOG_ERR | COSP_LOG_ERR); #endif if (acse_msgsize == 0) { /* ACSE user must call a_set_msgsize first. */ ACSELOG_ERR0 ("ACSE-ERROR: msg size not set"); return (E_ACSE_INVALID_PARAM); /* Invalid Parameter */ } #if defined(MOSI) cosp_msgsize = max(acse_msgsize, COSP_MAX_UDATA_CON) + MAX_COSP_COPP_HEADER; cosp_buf = (ST_UCHAR *) M_MALLOC (MSMEM_STARTUP, cosp_msgsize); ret = tp4_initialize (max_conns, cosp_msgsize); #else /* !MOSI */ acse_buf = (ST_UCHAR *) M_MALLOC (MSMEM_STARTUP, acse_msgsize); ret = tp4_initialize (max_conns, acse_msgsize); #endif /* !MOSI */ return (ret); } /************************************************************************/ /* copp_terminate */ /************************************************************************/ ST_RET copp_terminate (ST_VOID) { #ifdef MOSI if (cosp_buf) M_FREE (MSMEM_STARTUP, cosp_buf); #else if(acse_buf) M_FREE (MSMEM_STARTUP, acse_buf); #endif return (tp4_terminate ()); } /************************************************************************/ /* copp_event */ /************************************************************************/ ST_BOOLEAN copp_event (ST_VOID) { return (tp4_event ()); } #if !defined (MOSI) /* see copp_enc.c for MOSI bind functs. */ /************************************************************************/ /* copp_bind */ /************************************************************************/ ST_RET copp_bind (ST_LONG user_bind_id, PRES_ADDR *pres_addr, ST_INT sharable, ST_INT max_conns) { TP4_ADDR tp4_addr; ACSELOG_ENC1 ("COPP-Bind Req. user_bind_id =%9ld", user_bind_id); #if !defined(REDUCED_STACK) /* Copy tsel and nsap from pres_addr to tp4_addr struct */ tp4_addr.tp_type = pres_addr->tp_type; tp4_addr.tp4_sel_len = pres_addr->tsel_len; memcpy (tp4_addr.tp4_sel, pres_addr->tsel, pres_addr->tsel_len); tp4_addr.net_addr_len = pres_addr->nsap_len; memcpy (tp4_addr.net_addr, pres_addr->nsap, pres_addr->nsap_len); #else tp4_addr.adlcAddr = pres_addr->adlcAddr; #endif /* Call tp4_bind. */ return (tp4_bind (user_bind_id, &tp4_addr, sharable, max_conns)); } /************************************************************************/ /* copp_unbind */ /************************************************************************/ ST_RET copp_unbind (ST_LONG copp_bind_id) { ACSELOG_ENC1 ("COPP-Unbind Req. copp_bind_id =%9ld", copp_bind_id); return (tp4_unbind (copp_bind_id)); } #endif /* !MOSI */ /************************************************************************/ /* a_associate_req */ /************************************************************************/ ST_LONG a_associate_req ( ST_LONG copp_bind_id, /* ACSE's bind ID received in u_copp_bind_cnf*/ ST_LONG user_conn_id, /* USER's connection ID */ AARQ_APDU *aarq_apdu) /* AARQ_APDU info */ { #if !defined (MOSI) TP4_ADDR tp4_addr; #endif /* !MOSI */ ACSE_CONN *acse_conn; AE_TITLE *ae_title; ST_UCHAR version1_bit_str = BIT_VERSION1; /* Bit 0 of bitstr (high bit) set */ ST_UCHAR auth_bit_str = BIT_AUTHENTICATION; ST_UCHAR *msg_ptr; ST_UINT msg_len; ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ ASN1_ENC_CTXT *aCtx = &localEncCtx; ST_INT j; /* Allocate connection tracking structure "acse_conn". */ acse_conn = (ACSE_CONN *) M_CALLOC (MSMEM_ACSE_CONN, 1, sizeof (ACSE_CONN)); /* Save USER's connection ID. Use it in calls to user functions. */ acse_conn->user_conn_id = user_conn_id; /* save the encryption info */ acse_conn->encrypt_ctrl = aarq_apdu->encrypt_ctrl; ACSELOG_ENC2 ("A-ASSOCIATE.req: acse_conn_id =0x%08X user_conn_id =%4ld", acse_conn, acse_conn->user_conn_id); ACSELOG_ENC0C ("DST (CALLED) ADDRESS:"); if (aarq_apdu->called_ae_title.AP_title_pres) { for (j = 0; j < aarq_apdu->called_ae_title.AP_title.num_comps; ++j) { /* Verbose but gets the job done. */ ACSELOG_ENC2C (" AP_title.comps[%d] = %d", j, aarq_apdu->called_ae_title.AP_title.comps[j]); } } if (aarq_apdu->called_ae_title.AE_qual_pres) { ACSELOG_ENC1C (" AE_qual = %ld", aarq_apdu->called_ae_title.AE_qual); } ACSELOG_ENC0C (" PSEL:"); ACSELOG_ENCH (aarq_apdu->called_paddr.psel_len, aarq_apdu->called_paddr.psel); ACSELOG_ENC0C (" SSEL:"); ACSELOG_ENCH (aarq_apdu->called_paddr.ssel_len, aarq_apdu->called_paddr.ssel); ACSELOG_ENC0C (" TSEL:"); ACSELOG_ENCH (aarq_apdu->called_paddr.tsel_len, aarq_apdu->called_paddr.tsel); if (aarq_apdu->called_paddr.tp_type == TP_TYPE_TCP) { struct in_addr sin_addr; /* inet_ntoa needs this addr format*/ sin_addr.s_addr = aarq_apdu->called_paddr.netAddr.ip; #if defined(TP0_ENABLED) ACSELOG_ENC1C (" IP ADDR: %s", inet_ntoa (sin_addr)); if (!aarq_apdu->encrypt_ctrl.encryptMode == S_SEC_ENCRYPT_SSL && aarq_apdu->called_paddr.port) ACSELOG_ENC1C (" PORT: %u", (ST_UINT) aarq_apdu->called_paddr.port); #endif if (aarq_apdu->encrypt_ctrl.encryptMode == S_SEC_ENCRYPT_SSL) ACSELOG_ENC1C (" Encryption: SSL, port=%d", aarq_apdu->encrypt_ctrl.u.ssl.port); else ACSELOG_ENC0C (" Encryption: None"); if (aarq_apdu->auth_info.auth_pres) { if (aarq_apdu->auth_info.mech_type == ACSE_AUTH_MECH_MACE_CERT) ACSELOG_ENC0C (" Authentication: MACE"); else if (aarq_apdu->auth_info.mech_type == ACSE_AUTH_MECH_PASSWORD) ACSELOG_ENC0C (" Authentication: password"); else ACSELOG_ENC0C (" Authentication: other"); } else ACSELOG_ENC0C (" Authentication: None"); } else { ACSELOG_ENC0C (" NSAP:"); ACSELOG_ENCH (aarq_apdu->called_paddr.nsap_len, aarq_apdu->called_paddr.netAddr.nsap); } ACSELOG_ENC0C ("SRC (CALLING) ADDRESS:"); if (aarq_apdu->calling_ae_title.AP_title_pres) { for (j = 0; j < aarq_apdu->calling_ae_title.AP_title.num_comps; ++j) { /* Verbose but gets the job done. */ ACSELOG_ENC2C (" AP_title.comps[%d] = %d", j, aarq_apdu->calling_ae_title.AP_title.comps[j]); } } if (aarq_apdu->calling_ae_title.AE_qual_pres) { ACSELOG_ENC1C (" AE_qual = %ld", aarq_apdu->calling_ae_title.AE_qual); } #if defined (MMSEASE_MOSI) { ST_UCHAR *tp0_loc_tsap; ACSELOG_ENC0C (" PSEL:"); if (only_loc_psel[0]) ACSELOG_ENCH ((ST_UINT) only_loc_psel[0], &only_loc_psel[1]); ACSELOG_ENC0C (" SSEL:"); if (cosp_only_ssel[0]) ACSELOG_ENCH ((ST_UINT) cosp_only_ssel[0], &cosp_only_ssel[1]); ACSELOG_ENC0C (" TSEL:"); if (tp0_check_bind_id (copp_bind_id, &tp0_loc_tsap) == SD_SUCCESS) ACSELOG_ENCH ((ST_UINT) tp0_loc_tsap[0], &tp0_loc_tsap[1]); } #else /* NOTE: aarq_apdu->calling_paddr is NOT logged because caller may */ /* not set it, and even if they do, it is not used. The address */ /* passed to "copp_bind" is used as the calling_paddr. */ #endif /* Begin encoding request. */ #if defined (MOSI) asn1r_strt_asn1_bld (aCtx, cosp_buf,cosp_msgsize); #else asn1r_strt_asn1_bld (aCtx, acse_buf,acse_msgsize); #endif asn1r_strt_constr (aCtx); /* Start AARQ APDU constructor */ /* Write user_info. */ if (aarq_apdu->user_info.len) { asn1r_strt_constr (aCtx); #if defined (MOSI) /* PCI's must be set before any encoding. */ acse_conn->pciacse = 1; acse_conn->pcimms = 3; acse_encode_user_info (aCtx, acse_conn, &aarq_apdu->user_info); #else /* !MOSI */ asn1r_wr_octstr (aCtx, aarq_apdu->user_info.ptr, aarq_apdu->user_info.len); /* No P-Contexts in this implementation, so skip transfer-syntax */ /* and p-context-id. */ #endif /* !MOSI */ asn1r_fin_constr (aCtx, AARQ_user_info,CTX,DEF); } if(aarq_apdu->auth_info.auth_pres == SD_TRUE) { if(aarq_apdu->auth_info.mech_type == ACSE_AUTH_MECH_PASSWORD) { ACSELOG_ENC0C (" Authentication: password"); /* Write the password value */ asn1r_strt_constr (aCtx); asn1r_wr_octstr (aCtx, (ST_UCHAR *) aarq_apdu->auth_info.u.pw_auth.password, strlen(aarq_apdu->auth_info.u.pw_auth.password)); /* Strip off the NULL */ asn1r_fin_prim (aCtx, 0,CTX); asn1r_fin_constr (aCtx, AARQ_CALLING_auth_value,CTX,DEF); /* Write the mechanism name (password in this case) */ asn1r_wr_objid (aCtx, a_auth_password_obj_id.comps, a_auth_password_obj_id.num_comps); asn1r_fin_prim (aCtx, AARQ_mechanism_name, CTX); } else { if (aarq_apdu->auth_info.mech_type == ACSE_AUTH_MECH_MACE_CERT) ACSELOG_ENC0C ("Authentication: MACE"); else ACSELOG_ENC0C ("Authentication: other"); asn1r_strt_constr (aCtx); asn1r_strt_constr (aCtx); /* Authentication-value */ asn1r_strt_constr (aCtx); /* Single ASN.1 Type */ asn1r_wr_octstr (aCtx, aarq_apdu->auth_info.u.other_auth.auth_value.ptr, aarq_apdu->auth_info.u.other_auth.auth_value.len); asn1r_fin_constr (aCtx, 0, CTX, SD_FALSE); /* Single ASN.1 Type */ asn1r_fin_constr (aCtx, 2, CTX, SD_FALSE); /* Authentication-value */ asn1r_fin_constr (aCtx, AARQ_CALLING_auth_value,CTX,DEF); /* Write the mechanism name */ asn1r_wr_objid (aCtx, aarq_apdu->auth_info.u.other_auth.mech_id.comps, aarq_apdu->auth_info.u.other_auth.mech_id.num_comps); asn1r_fin_prim (aCtx, AARQ_mechanism_name, CTX); } /* Let's encode the authentication present bit to enable security */ asn1r_wr_bitstr (aCtx, &auth_bit_str, 1); asn1r_fin_prim (aCtx, AARQ_acse_requirements, CTX); } /* Write CALLING AE Title (i.e. AP_title, AE_qual, AP_inv_id, AE_inv_id).*/ ae_title = &aarq_apdu->calling_ae_title; if (ae_title->AE_inv_id_pres) { asn1r_strt_constr (aCtx); asn1r_wr_i32 (aCtx, ae_title->AE_inv_id); asn1r_fin_prim (aCtx, INT_CODE,UNI); asn1r_fin_constr (aCtx, AARQ_CALLING_AE_inv_id,CTX,DEF); } if (ae_title->AP_inv_id_pres) { asn1r_strt_constr (aCtx); asn1r_wr_i32 (aCtx, ae_title->AP_inv_id); asn1r_fin_prim (aCtx, INT_CODE,UNI); asn1r_fin_constr (aCtx, AARQ_CALLING_AP_inv_id,CTX,DEF); } if (ae_title->AE_qual_pres) { asn1r_strt_constr (aCtx); asn1r_wr_i32 (aCtx, ae_title->AE_qual); asn1r_fin_prim (aCtx, INT_CODE,UNI); asn1r_fin_constr (aCtx, AARQ_CALLING_AE_qual,CTX,DEF); } if (ae_title->AP_title_pres) { asn1r_strt_constr (aCtx); asn1r_wr_objid (aCtx, ae_title->AP_title.comps, ae_title->AP_title.num_comps); asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI); asn1r_fin_constr (aCtx, AARQ_CALLING_AP_title,CTX,DEF); } /* Write CALLED AE Title (i.e. AP_title, AE_qual, AP_inv_id, AE_inv_id).*/ ae_title = &aarq_apdu->called_ae_title; if (ae_title->AE_inv_id_pres) { asn1r_strt_constr (aCtx); asn1r_wr_i32 (aCtx, ae_title->AE_inv_id); asn1r_fin_prim (aCtx, INT_CODE,UNI); asn1r_fin_constr (aCtx, AARQ_CALLED_AE_inv_id,CTX,DEF); } if (ae_title->AP_inv_id_pres) { asn1r_strt_constr (aCtx); asn1r_wr_i32 (aCtx, ae_title->AP_inv_id); asn1r_fin_prim (aCtx, INT_CODE,UNI); asn1r_fin_constr (aCtx, AARQ_CALLED_AP_inv_id,CTX,DEF); } if (ae_title->AE_qual_pres) { asn1r_strt_constr (aCtx); asn1r_wr_i32 (aCtx, ae_title->AE_qual); asn1r_fin_prim (aCtx, INT_CODE,UNI); asn1r_fin_constr (aCtx, AARQ_CALLED_AE_qual,CTX,DEF); } if (ae_title->AP_title_pres) { asn1r_strt_constr (aCtx); asn1r_wr_objid (aCtx, ae_title->AP_title.comps, ae_title->AP_title.num_comps); asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI); asn1r_fin_constr (aCtx, AARQ_CALLED_AP_title,CTX,DEF); } /* Write ASO Context Name. */ if (aarq_apdu->ASO_context_name_pres) { asn1r_strt_constr (aCtx); asn1r_wr_objid (aCtx, aarq_apdu->ASO_context_name.comps, aarq_apdu->ASO_context_name.num_comps); asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI); asn1r_fin_constr (aCtx, AARQ_ASO_context_name,CTX,DEF); } /* Write protocol_version. */ asn1r_wr_bitstr (aCtx, &version1_bit_str, 1); asn1r_fin_prim (aCtx, AARQ_protocol_version, CTX); asn1r_fin_constr (aCtx, TAG_AARQ,APP,DEF); /* Finish AARQ APDU */ msg_ptr = ASN1_ENC_PTR (aCtx); /* point to beginning of PDU. */ msg_len = ASN1_ENC_LEN (aCtx); #if ! (defined(REDUCED_STACK) || defined(MOSI) ) /* Fastbyte Presentation and Session (2 bytes). */ *(--msg_ptr) = 0x01; /* Short-CP mode = BER */ *(--msg_ptr) = (ST_UCHAR) 0xE8; /* Short-SCN, SI = 11101, 0 params */ msg_len+=2; /* adjust len */ #endif /* ! (defined(REDUCED_STACK) || defined(MOSI) ) */ if (msg_len > acse_msgsize) return (0L); #if defined (MOSI) acse_conn->apdu_ptr = msg_ptr; acse_conn->apdu_len = msg_len; /* Send AARQ APDU via P-CONNECT.req */ if (copp_con_req (copp_bind_id, acse_conn, &aarq_apdu->called_paddr) != SD_SUCCESS) { acse_free_con (acse_conn); /* Dump conn tracking struct */ return (0L); } acse_conn->state = STATE_AARE_WAIT; /* Waiting for AARE-apdu */ #else /* !MOSI */ /* Save AARQ APDU (in save_buf) to send when tp4 connection */ /* established (see tp4_connect_cnf). */ acse_conn->save_buf.len = msg_len; acse_conn->save_buf.ptr = (ST_UCHAR *) M_MALLOC (MSMEM_ACSE_DATA, msg_len); memcpy (acse_conn->save_buf.ptr, msg_ptr, msg_len); /* Send Transport connect request. */ /* The connection ID is just a pointer to "acse_conn" cast to a ST_LONG. */ /* Copy tsel and nsap from aarq_apdu->called_paddr to tp4_addr */ #if !defined(REDUCED_STACK) tp4_addr.tp_type = aarq_apdu->called_paddr.tp_type; tp4_addr.tp4_sel_len = aarq_apdu->called_paddr.tsel_len; memcpy (tp4_addr.tp4_sel, aarq_apdu->called_paddr.tsel, aarq_apdu->called_paddr.tsel_len); tp4_addr.net_addr_len = aarq_apdu->called_paddr.nsap_len; memcpy (tp4_addr.net_addr, aarq_apdu->called_paddr.nsap, aarq_apdu->called_paddr.nsap_len); #else tp4_addr.adlcAddr = aarq_apdu->called_paddr.adlcAddr; #endif if (tp4_connect (copp_bind_id, (ST_LONG) acse_conn, &tp4_addr, 0, NULL, NULL) != SD_SUCCESS) { acse_free_con (acse_conn); /* Dump conn tracking struct */ return (0L); } acse_conn->state = STATE_TP4CONN_WAIT; /* Waiting for TP4 connection*/ #endif /* !MOSI */ return ((ST_LONG)acse_conn); } /************************************************************************/ /* a_associate_rsp */ /************************************************************************/ ST_RET a_associate_rsp ( ST_LONG acse_conn_id, /* ACSE's connection ID */ ST_LONG user_conn_id, /* USER's connection ID */ AARE_APDU *info) /* AARE_APDU info */ { AE_TITLE *ae_title; ST_UCHAR version1_bit_str = BIT_VERSION1; /* Bit 0 of bitstr (high bit) set */ ST_UCHAR auth_bit_str = BIT_AUTHENTICATION; ST_UCHAR *msg_ptr; ST_UINT msg_len; ACSE_CONN *acse_conn; ST_RET retcode; ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ ASN1_ENC_CTXT *aCtx = &localEncCtx; ACSELOG_ENC2 ("A-ASSOCIATE.rsp: acse_conn_id =0x%08X user_conn_id =%4ld", acse_conn_id, user_conn_id); acse_conn = (ACSE_CONN *) acse_conn_id; if (acse_conn == NULL) return (E_ACSE_INVALID_CONN_ID); /* Invalid acse_conn_id */ if (acse_conn->state != STATE_AASCRSP_WAIT) return (E_ACSE_INVALID_STATE); /* Invalid state for this operation*/ /* Save USER's connection ID. Use it in calls to user functions. */ acse_conn->user_conn_id = user_conn_id; /* Everything looks OK. Go ahead and encode response and send it. */ #if defined (MOSI) asn1r_strt_asn1_bld (aCtx, cosp_buf,cosp_msgsize); #else asn1r_strt_asn1_bld (aCtx, acse_buf,acse_msgsize); #endif asn1r_strt_constr (aCtx); /* Start AARE APDU constructor */ /* Write user_info. */ if (info->user_info.len) { asn1r_strt_constr (aCtx); #if defined (MOSI) acse_encode_user_info (aCtx, acse_conn, &info->user_info); #else /* !MOSI */ asn1r_wr_octstr (aCtx, info->user_info.ptr, info->user_info.len); /* No P-Contexts in this implementation, so skip transfer-syntax */ /* and p-context-id. */ #endif /* !MOSI */ asn1r_fin_constr (aCtx, AARE_user_info,CTX,DEF); } if(info->auth_info.auth_pres == SD_TRUE) { if(info->auth_info.mech_type == ACSE_AUTH_MECH_PASSWORD) { /* Write the password value */ asn1r_strt_constr (aCtx); asn1r_wr_octstr (aCtx, (ST_UCHAR *) info->auth_info.u.pw_auth.password, strlen(info->auth_info.u.pw_auth.password)); /* Strip off the NULL */ asn1r_fin_prim (aCtx, 0,CTX); asn1r_fin_constr (aCtx, AARE_RESPONDING_auth_value,CTX,DEF); /* Write the mechanism name (password in this case) */ asn1r_wr_objid (aCtx, a_auth_password_obj_id.comps, a_auth_password_obj_id.num_comps); asn1r_fin_prim (aCtx, AARE_mechanism_name, CTX); } else { if (info->auth_info.mech_type == ACSE_AUTH_MECH_MACE_CERT) ACSELOG_ENC0C ("Authentication: MACE"); else ACSELOG_ENC0C ("Authentication: other"); asn1r_strt_constr (aCtx); asn1r_strt_constr (aCtx); /* Authentication-value */ asn1r_strt_constr (aCtx); /* Single ASN.1 Type */ asn1r_wr_octstr (aCtx, info->auth_info.u.other_auth.auth_value.ptr, info->auth_info.u.other_auth.auth_value.len); asn1r_fin_constr (aCtx, 0, CTX, SD_FALSE); /* Single ASN.1 Type */ asn1r_fin_constr (aCtx, 2, CTX, SD_FALSE); /* Authentication-value */ asn1r_fin_constr (aCtx, AARE_RESPONDING_auth_value,CTX,DEF); /* Write the mechanism name */ asn1r_wr_objid (aCtx, info->auth_info.u.other_auth.mech_id.comps, info->auth_info.u.other_auth.mech_id.num_comps); asn1r_fin_prim (aCtx, AARE_mechanism_name, CTX); } /* Let's encode the authentication present bit to enable security */ asn1r_wr_bitstr (aCtx, &auth_bit_str, 1); asn1r_fin_prim (aCtx, AARE_RESPONDER_acse_requirements, CTX); } /* Write RESP AE Title (i.e. AP_title, AE_qual, AP_inv_id, AE_inv_id) */ /* fields of AARE APDU. */ ae_title = &info->responding_ae_title; if (ae_title->AE_inv_id_pres) { asn1r_strt_constr (aCtx); asn1r_wr_i32 (aCtx, ae_title->AE_inv_id); asn1r_fin_prim (aCtx, INT_CODE,UNI); asn1r_fin_constr (aCtx, AARE_RESPONDING_AE_inv_id,CTX,DEF); } if (ae_title->AP_inv_id_pres) { asn1r_strt_constr (aCtx); asn1r_wr_i32 (aCtx, ae_title->AP_inv_id); asn1r_fin_prim (aCtx, INT_CODE,UNI); asn1r_fin_constr (aCtx, AARE_RESPONDING_AP_inv_id,CTX,DEF); } if (ae_title->AE_qual_pres) { asn1r_strt_constr (aCtx); asn1r_wr_i32 (aCtx, ae_title->AE_qual); asn1r_fin_prim (aCtx, INT_CODE,UNI); asn1r_fin_constr (aCtx, AARE_RESPONDING_AE_qual,CTX,DEF); } if (ae_title->AP_title_pres) { asn1r_strt_constr (aCtx); asn1r_wr_objid (aCtx, ae_title->AP_title.comps, ae_title->AP_title.num_comps); asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI); asn1r_fin_constr (aCtx, AARE_RESPONDING_AP_title,CTX,DEF); } /* Write result-source-diagnostic. */ /* DEBUG: If user required to set "result_source" and "result_diag", */ /* "result_source_diag_pres" would no longer be needed. */ if (info->result_source_diag_pres == 0) { /* User probably didn't set values, so set to default. */ info->result_source = 1; /* Source = acse-service-user. */ info->result_diag = 0; /* Diag = null. */ } asn1r_strt_constr (aCtx); asn1r_strt_constr (aCtx); asn1r_wr_i16 (aCtx, info->result_diag); asn1r_fin_prim (aCtx, INT_CODE,UNI); if (info->result_source != 1 && info->result_source != 2) return (E_ACSE_ENC_ERR); /* Make sure source legal. */ asn1r_fin_constr (aCtx, info->result_source,CTX,DEF); asn1r_fin_constr (aCtx, AARE_result_source_diagnostic,CTX,DEF); /* Write result */ asn1r_strt_constr (aCtx); asn1r_wr_i16 (aCtx, info->result); asn1r_fin_prim (aCtx, INT_CODE,UNI); asn1r_fin_constr (aCtx, AARE_result,CTX,DEF); /* Write ASO Context Name. */ if (info->ASO_context_name_pres) { asn1r_strt_constr (aCtx); asn1r_wr_objid (aCtx, info->ASO_context_name.comps, info->ASO_context_name.num_comps); asn1r_fin_prim (aCtx, OBJ_ID_CODE,UNI); asn1r_fin_constr (aCtx, AARE_ASO_context_name,CTX,DEF); } /* Write protocol_version. */ asn1r_wr_bitstr (aCtx, &version1_bit_str, 1); asn1r_fin_prim (aCtx, AARE_protocol_version, CTX); asn1r_fin_constr (aCtx, TAG_AARE,APP,DEF); /* Finish AARE APDU */ msg_ptr = ASN1_ENC_PTR (aCtx); /* point to beginning of PDU. */ msg_len = ASN1_ENC_LEN (aCtx); #if !(defined(REDUCED_STACK) || defined(MOSI)) /* Fastbyte Presentation and Session (2 bytes). */ *(--msg_ptr) = 0x01; /* Short-CP mode = BER */ switch (info->result) { case 0: *(--msg_ptr)=(ST_UCHAR)0xF0; /* Short-SAC (SI=11110) 0 params */ break; case 1: *(--msg_ptr)=(ST_UCHAR)0xE3; /* Short-SRF (SI=11100) 0 params, */ /* transport conn released, permanent */ break; case 2: *(--msg_ptr)=(ST_UCHAR)0xE2; /* Short-SRF (SI=11100) 0 params, */ /* transport conn released, transient */ break; default: return (E_ACSE_INVALID_PARAM); /* Invalid Parameter */ } msg_len+=2; /* adjust len */ #endif /* !(defined(REDUCED_STACK) || defined(MOSI)) */ if (msg_len > acse_msgsize) return (E_ACSE_BUFFER_OVERFLOW); #if defined(MOSI) acse_conn->apdu_ptr = msg_ptr; acse_conn->apdu_len = msg_len; if (info->result) /* NOTE: COSP will free "acse_conn" after T-disconnect. */ retcode = copp_con_rsp_neg (acse_conn, -1); /* -1 means "from user" */ else { retcode = copp_con_rsp_pos (acse_conn); if (retcode == SD_SUCCESS) acse_conn->state = STATE_ASSOCIATED; } if (retcode != SD_SUCCESS) { #if 0 /* EJV 2/27/2008: if copp_con_rsp_* fails then the most probable cause is */ /* that the socket was disconencted. In this case the */ /* the tp0_disconnect_ind will free the acse_conn. */ /* If it was other error the application will issue an abort */ /* to cleanup the connection. */ acse_free_con (acse_conn); /* Dump conn tracking struct */ #endif /* 0 */ ACSELOG_ENC0 ("ACSE-ERROR: failed to send A-ASSOCIATE.rsp (disconnected socket or other error)."); return (E_ACSE_SEND_ERR); } #else /* !MOSI */ /* Send via tp4_data. */ /* The "user_conn_id" is just a pointer to "acse_conn" cast to a ST_LONG.*/ retcode = tp4_data (acse_conn->tp4_conn_id, TP4_EOT, msg_len, (ST_CHAR *) msg_ptr); if (retcode != SD_SUCCESS) { acse_free_con (acse_conn); /* Dump conn tracking struct */ return (E_ACSE_SEND_ERR); } if (info->result == 0) acse_conn->state = STATE_ASSOCIATED; else acse_conn->state = STATE_IDLE; #endif /* !MOSI */ return (SD_SUCCESS); } /************************************************************************/ /* a_release_req */ /************************************************************************/ ST_RET a_release_req ( ST_LONG acse_conn_id, /* ACSE's connection ID */ RLRQ_APDU *info) /* RLRQ_APDU info */ { ST_UCHAR *msg_ptr; ST_UINT msg_len; ACSE_CONN *acse_conn; ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ ASN1_ENC_CTXT *aCtx = &localEncCtx; acse_conn = (ACSE_CONN *)acse_conn_id; ACSELOG_ENC2 ("A-RELEASE.req: acse_conn_id =0x%08X user_conn_id =%4ld", acse_conn, acse_conn->user_conn_id); if (acse_conn == NULL) return (E_ACSE_INVALID_CONN_ID); /* Invalid acse_conn_id */ if (acse_conn->state != STATE_ASSOCIATED) return (E_ACSE_INVALID_STATE); /* Invalid state for this operation*/ /* Everything looks OK. Go ahead and encode request and send it. */ #if defined (MOSI) asn1r_strt_asn1_bld (aCtx, cosp_buf,cosp_msgsize); #else asn1r_strt_asn1_bld (aCtx, acse_buf,acse_msgsize); #endif asn1r_strt_constr (aCtx); /* Start RLRQ APDU constructor */ /* Write user_info. */ if (info->user_info.len) { asn1r_strt_constr (aCtx); #if defined (MOSI) acse_encode_user_info (aCtx, acse_conn, &info->user_info); #else /* !MOSI */ asn1r_wr_octstr (aCtx, info->user_info.ptr, info->user_info.len); /* No P-Contexts in this implementation, so skip transfer-syntax */ /* and p-context-id. */ #endif /* !MOSI */ asn1r_fin_constr (aCtx, RLRQ_user_info,CTX,DEF); } /* Write Release Reason. */ if (info->reason_pres) { asn1r_wr_i16 (aCtx, info->reason); asn1r_fin_prim (aCtx, RLRQ_reason,CTX); } asn1r_fin_constr (aCtx, TAG_RLRQ,APP,DEF); /* Finish RLRQ APDU */ msg_ptr = ASN1_ENC_PTR (aCtx); /* point to beginning of PDU. */ msg_len = ASN1_ENC_LEN (aCtx); if (msg_len > acse_msgsize) return (E_ACSE_BUFFER_OVERFLOW); #if defined(MOSI) acse_conn->apdu_ptr = msg_ptr; acse_conn->apdu_len = msg_len; /* Send RLRQ APDU via P-RELEASE.req */ if (copp_rel_req (acse_conn) != SD_SUCCESS) return (E_ACSE_SEND_ERR); #else /* !MOSI */ /* Send RLRQ APDU via T-DATA.req */ if (tp4_data (acse_conn->tp4_conn_id, TP4_EOT, msg_len, (ST_CHAR *) msg_ptr) != SD_SUCCESS) return (E_ACSE_SEND_ERR); #endif /* !MOSI */ acse_conn->state = STATE_RLRE_WAIT; return (SD_SUCCESS); } /************************************************************************/ /* a_release_rsp */ /************************************************************************/ ST_RET a_release_rsp ( ST_LONG acse_conn_id, /* ACSE's connection ID */ RLRE_APDU *info) /* RLRE_APDU info */ { ST_UCHAR *msg_ptr; ST_UINT msg_len; ACSE_CONN *acse_conn; ST_RET retcode; ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ ASN1_ENC_CTXT *aCtx = &localEncCtx; acse_conn = (ACSE_CONN *)acse_conn_id; ACSELOG_ENC2 ("A-RELEASE.rsp: acse_conn_id =0x%08X user_conn_id =%4ld", acse_conn, acse_conn->user_conn_id); if (acse_conn == 0) return (E_ACSE_INVALID_CONN_ID); /* Invalid acse_conn_id */ /* This state may happen, but ACSE state machine says do nothing. */ if (acse_conn->state == STATE_RESP_COLL) { ACSELOG_ENC0C ("A-RELEASE.rsp not sent because this is Responder side of RELEASE collision"); return (SD_SUCCESS); } if (acse_conn->state != STATE_ARLSRSP_WAIT && acse_conn->state != STATE_INIT_COLL) return (E_ACSE_INVALID_STATE); /* Invalid state for this operation*/ /* Everything looks OK. Go ahead and encode response and send it. */ #if defined (MOSI) asn1r_strt_asn1_bld (aCtx, cosp_buf,cosp_msgsize); #else asn1r_strt_asn1_bld (aCtx, acse_buf,acse_msgsize); #endif asn1r_strt_constr (aCtx); /* Start RLRE APDU constructor */ /* Write user_info. */ if (info->user_info.len) { asn1r_strt_constr (aCtx); #if defined (MOSI) acse_encode_user_info (aCtx, acse_conn, &info->user_info); #else /* !MOSI */ asn1r_wr_octstr (aCtx, info->user_info.ptr, info->user_info.len); /* No P-Contexts in this implementation, so skip transfer-syntax */ /* and p-context-id. */ #endif /* !MOSI */ asn1r_fin_constr (aCtx, RLRE_user_info,CTX,DEF); } /* Write Release Reason. */ if (info->reason_pres) { asn1r_wr_i16 (aCtx, info->reason); asn1r_fin_prim (aCtx, RLRE_reason,CTX); } asn1r_fin_constr (aCtx, TAG_RLRE,APP,DEF); /* Finish RLRE APDU */ msg_ptr = ASN1_ENC_PTR (aCtx); /* point to beginning of PDU. */ msg_len = ASN1_ENC_LEN (aCtx); if (msg_len > acse_msgsize) return (E_ACSE_BUFFER_OVERFLOW); #if defined(MOSI) acse_conn->apdu_ptr = msg_ptr; acse_conn->apdu_len = msg_len; /* NOTE: Only "affirmative" allowed because "Negotiated Release" not */ /* supported by Session. */ retcode = copp_rel_rsp_pos (acse_conn); #else /* !MOSI */ /* Send Transport Data request. */ retcode = tp4_data (acse_conn->tp4_conn_id, TP4_EOT, msg_len, (ST_CHAR *) msg_ptr); #endif /* !MOSI */ if (retcode != SD_SUCCESS) return (E_ACSE_SEND_ERR); if (acse_conn->state == STATE_ARLSRSP_WAIT) acse_conn->state = STATE_IDLE; else /* must be STATE_INIT_COLL */ acse_conn->state = STATE_RLRE_WAIT; return (SD_SUCCESS); } /************************************************************************/ /* a_abort_req */ /************************************************************************/ ST_RET a_abort_req ( ST_LONG acse_conn_id, /* ACSE's connection ID */ ABRT_APDU *info) /* ABRT_APDU info */ { ST_UCHAR *msg_ptr; ST_UINT msg_len; ACSE_CONN *acse_conn; ASN1_ENC_CTXT localEncCtx; /* For readability, use "aCtx" to access this.*/ ASN1_ENC_CTXT *aCtx = &localEncCtx; acse_conn = (ACSE_CONN *)acse_conn_id; ACSELOG_ENC2 ("A-ABORT.req: acse_conn_id =0x%08X user_conn_id =%4ld", acse_conn, acse_conn->user_conn_id); if (acse_conn == NULL) return (E_ACSE_INVALID_CONN_ID); /* Invalid acse_conn_id */ if (acse_conn->state == STATE_IDLE) /* Waiting for T-DISCONNECT */ return (E_ACSE_INVALID_STATE); /* Invalid state for this operation*/ #ifndef MOSI if (acse_conn->state == STATE_TP4CONN_WAIT) { /* Don't free struct now. When get response, don't pass up to user */ /* and free acse_conn then. */ acse_conn->state = STATE_AARE_ABANDON; return (SD_SUCCESS); } if (acse_conn->state == STATE_AARE_WAIT) { /* Don't free struct now. When get response, don't pass up to user */ /* and free acse_conn then. */ acse_conn->state = STATE_AARE_ABANDON; return (SD_SUCCESS); } #endif /* !MOSI */ /* Everything looks OK. Go ahead and encode request and send it. */ #if defined (MOSI) asn1r_strt_asn1_bld (aCtx, cosp_buf,cosp_msgsize); #else asn1r_strt_asn1_bld (aCtx, acse_buf,acse_msgsize); #endif asn1r_strt_constr (aCtx); /* Start ABRT APDU constructor */ /* Write user_info. */ if (info->user_info.len) { asn1r_strt_constr (aCtx); #if defined (MOSI) acse_encode_user_info (aCtx, acse_conn, &info->user_info); #else /* !MOSI */ asn1r_wr_octstr (aCtx, info->user_info.ptr, info->user_info.len); /* No P-Contexts in this implementation, so skip transfer-syntax */ /* and p-context-id. */ #endif /* !MOSI */ asn1r_fin_constr (aCtx, ABRT_user_info,CTX,DEF); } /* Write Abort Diagnostic. */ if(info->diagnostic_pres == SD_TRUE) { asn1r_wr_i16 (aCtx, info->diagnostic); asn1r_fin_prim (aCtx, ABRT_diagnostic,CTX); } /* Write Abort Source. */ asn1r_wr_i16 (aCtx, info->source); asn1r_fin_prim (aCtx, ABRT_source,CTX); asn1r_fin_constr (aCtx, TAG_ABRT,APP,DEF); /* Finish ABRT APDU */ msg_ptr = ASN1_ENC_PTR (aCtx); /* point to beginning of PDU. */ msg_len = ASN1_ENC_LEN (aCtx); if (msg_len > acse_msgsize) return (E_ACSE_BUFFER_OVERFLOW); #if defined(MOSI) /* Send P-U-Abort Request. */ acse_conn->apdu_ptr = msg_ptr; acse_conn->apdu_len = msg_len; acse_conn->state = STATE_IDLE; /* COSP will free acse_conn. */ if (copp_u_abort_req (acse_conn) != SD_SUCCESS) return (E_ACSE_SEND_ERR); /* CRITICAL: DO NOT access acse_conn after abort. It may have been */ /* freed by cosp_u_abort_req (called from copp_u_abort_req). */ #else /* !MOSI */ /* Send Transport Disconnect request. */ tp4_disconnect (acse_conn->tp4_conn_id, msg_len, (ST_CHAR *) msg_ptr); acse_free_con (acse_conn); /* Dump conn tracking struct */ #endif /* !MOSI */ return (SD_SUCCESS); } /************************************************************************/ /* a_data_req - Send A-Data req. */ /************************************************************************/ ST_RET a_data_req ( ST_LONG acse_conn_id, /* ACSE's ID for this connection */ ST_UINT data_len, ST_UCHAR *data) { ACSE_CONN *acse_conn; acse_conn = (ACSE_CONN *)acse_conn_id; #if defined(MOSI) if (data_len > acse_msgsize) { /* Should never happen if ACSE user code is correct. */ ACSELOG_ERR2 ("ACSE-ERROR: A-DATA.req: data len (%d) > max (%d)", data_len, acse_msgsize); return (E_ACSE_BUFFER_OVERFLOW); } /* Just copy data to end of "cosp_buf" & set apdu_ptr, apdu_len. */ /* copp_data_req will add COPP encoding in front of this data. */ acse_conn->apdu_ptr = cosp_buf + cosp_msgsize - data_len; acse_conn->apdu_len = data_len; memcpy (acse_conn->apdu_ptr, data, data_len); return (copp_data_req (acse_conn)); #else /* !MOSI */ return (tp4_data (acse_conn->tp4_conn_id, TP4_EOT, data_len,(ST_CHAR *)data)); #endif /* !MOSI */ } #if defined (MOSI) /************************************************************************/ /* acse_encode_user_info */ /************************************************************************/ static ST_VOID acse_encode_user_info (ASN1_ENC_CTXT *aCtx, ACSE_CONN *acse_conn, BUFFER *user_info) { asn1r_strt_constr (aCtx); /* start EXTERNAL */ asn1r_strt_constr (aCtx); /* start single-ASN1-type */ asn1r_wr_octstr (aCtx, user_info->ptr, user_info->len); asn1r_fin_constr (aCtx, 0,CTX,DEF); /* finish single-ASN1-type */ asn1r_wr_i8 (aCtx, acse_conn->pcimms); /* PCI for MMS */ asn1r_fin_prim (aCtx, INT_CODE,UNI); /* NOTE: Transfer-syntax-name (OPTIONAL) not sent. Saves few bytes. */ asn1r_fin_constr (aCtx, EXTERN_CODE,UNI,DEF); /* finish EXTERNAL */ return; } #endif /* MOSI */ #if !defined (MOSI) /************************************************************************/ /* acse_free_con */ /*----------------------------------------------------------------------*/ /* This function will free the pointer to connection info. */ /* For MOSI, a slightly different "acse_free_con" function is */ /* defined in COSP????.c */ /************************************************************************/ ST_VOID acse_free_con (ACSE_CONN *acse_conn) { if (acse_conn->save_buf.len) M_FREE (MSMEM_ACSE_DATA, acse_conn->save_buf.ptr); M_FREE (MSMEM_ACSE_CONN, acse_conn); } #endif /* !MOSI */ /************************************************************************/ /* a_buffers_avail - Buffers available for sending A-Data req. */ /* This function returns the number of buffers available for sending */ /* A-Data. This may be used, for example, when sending Information */ /* Reports, to make sure there are always enough buffers for sending */ /* responses to incoming requests. */ /* */ /* Parameters: */ /* ST_LONG acse_conn_id ACSE Connection ID */ /* */ /* Return: */ /* ST_INT # of ACSE transmit buffers available */ /************************************************************************/ #if defined(LEAN_T) || defined(REDUCED_STACK) ST_INT a_buffers_avail ( ST_LONG acse_conn_id) /* ACSE's ID for this connection */ { #if defined(LEAN_T) ACSE_CONN *acse_conn; acse_conn = (ACSE_CONN *)acse_conn_id; return (tp4_buffers_avail (acse_conn->tp4_conn_id)); #endif #if defined(REDUCED_STACK) return (2); #endif } #endif #if defined (MOSI) /* Only MOSI uses events. */ #if defined(_WIN32) /* Not used for DOS, QNX, or VXWORKS */ /************************************************************************/ /* a_get_event_handles */ /* Returns a pointer to an array of (ST_EVENT_SEM) and sets */ /* (*pNumEntries) equal to the number of entries. */ /************************************************************************/ ST_EVENT_SEM a_get_event_handles (ST_INT *pNumEntries) { static ST_EVENT_SEM EventArray [2]; ST_INT NumEntries = 0; #if defined (TP4_ENABLED) /* If "hMainEvent" initialized, use it instead of default "hMMSEvent"*/ if (hMainEvent) EventArray [NumEntries++] = hMainEvent; /* CLNP thread event. */ else EventArray [NumEntries++] = hMMSEvent; /* driver event */ #endif #if defined (TP0_ENABLED) EventArray [NumEntries++] = hTcpEvent; /* TCP/IP sockets event */ #endif *pNumEntries = NumEntries; return (EventArray); } #else /* !defined(_WIN32) */ /************************************************************************/ /* a_get_event_handles_unix */ /* Returns a pointer to an array of handles and sets */ /* (*pNumEntries) equal to the number of entries. */ /* NOTE: The TP4_ENABLED option currently only works on "linux". */ /************************************************************************/ #if defined(TP4_ENABLED) #if defined(linux) extern int hPktSock; #else #error TP4 not supported on this platform #endif #endif #if defined(TP0_ENABLED) extern int pipe_to_main; /* DEBUG: move to include */ #endif int *a_get_event_handles_unix (ST_INT *pNumEntries) { static int fd_array [2]; ST_INT NumEntries = 0; #if defined(TP4_ENABLED) fd_array[NumEntries++] = hPktSock; #endif #if defined(TP0_ENABLED) fd_array[NumEntries++] = pipe_to_main; #endif *pNumEntries = NumEntries; return (fd_array); } #endif /* !defined(_WIN32) */ #endif /* MOSI */ /*------------------------------------------------------*/ /* Security functions */ /*------------------------------------------------------*/ /********************************************************************************/ /* a_get_security_info */ /*------------------------------------------------------------------------------*/ /* Returns pointers to encryption control and partner's authentication info */ /* from the specified channel info. This functions should be called after */ /* connection indication was received to retrieve the security informations. */ /* After the connection terminates call the s_free_part_security_info() to free */ /* the allocated auth_value buf and cleanup the channel info. */ /* Parameters: */ /* ST_LONG acse_conn_id indirect ptr to access security info */ /* S_SEC_PARAMS *secParams pointer where to ret security info. */ /* Return: */ /* ST_RET SD_SUCCESS if get operation succeeded, otherwise */ /* SD_FAILURE or other error. */ /********************************************************************************/ ST_RET a_get_security_info (ST_LONG acse_conn_id, S_SEC_SPARAMS *secParams) { ST_RET ret = SD_SUCCESS; ACSE_CONN *acse_conn; secParams->authInfo = NULL; /* local auth info not stored */ secParams->partAuthInfo = NULL; /* partner auth info */ secParams->encryptCtrl = NULL; /* connection encryption info */ if (acse_conn_id) { acse_conn= (ACSE_CONN *) acse_conn_id; if (acse_conn) { secParams->partAuthInfo = &acse_conn->part_auth_info; secParams->encryptCtrl = &acse_conn->encrypt_ctrl; } } else ret = SD_FAILURE; /* cc should be valid in this call */ return (ret); } /********************************************************************************/ /* a_free_security_info */ /*------------------------------------------------------------------------------*/ /* Releases authentication info resources. */ /* Parameters: */ /* ACSE_AUTH_INFO *authInfo ptr to free the security resources */ /* Return: */ /* ST_RET SD_SUCCESS if free operation succeeded */ /* SD_FAILURE otherwise */ /********************************************************************************/ ST_RET a_free_security_info (ACSE_AUTH_INFO *authInfo) { ST_RET ret = SD_SUCCESS; if (authInfo) { /* clear authentication info */ /* if there is an existing auth_value buf pointer then we have to free it */ if (authInfo->auth_pres && authInfo->mech_type != ACSE_AUTH_MECH_PASSWORD) if (authInfo->u.other_auth.auth_value.buf) { chk_free (authInfo->u.other_auth.auth_value.buf); authInfo->u.other_auth.auth_value.buf = NULL; authInfo->u.other_auth.auth_value.ptr = NULL; authInfo->u.other_auth.auth_value.len = 0; } authInfo->auth_pres = SD_FALSE; } return (ret); } /********************************************************************************/ /* a_free_part_security_info */ /*------------------------------------------------------------------------------*/ /* Releases partner authentication resources and resets the field in ACSE_CONN. */ /* Parameters: */ /* ST_LONG acse_conn_id indirect ptr to access security info */ /* Return: */ /* ST_RET SD_SUCCESS if free operation succeeded */ /* SD_FAILURE otherwise */ /********************************************************************************/ ST_RET a_free_part_security_info (ST_LONG acse_conn_id) { ST_RET ret = SD_SUCCESS; ACSE_CONN *acse_conn; if (acse_conn_id) { acse_conn= (ACSE_CONN *) acse_conn_id; if (acse_conn) ret = a_free_security_info (&acse_conn->part_auth_info); } return (ret); }