From ea428669d3bb2711dc08432754292b65ef89974c Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Tue, 17 May 2011 17:13:38 -0400 Subject: [PATCH] chlog: freetdm - SS7: Support for Transparent IAM --- libs/freetdm/configure.ac | 13 + libs/freetdm/mod_freetdm/mod_freetdm.c | 30 +- libs/freetdm/src/ftdm_call_utils.c | 68 +++ libs/freetdm/src/ftdm_io.c | 4 +- .../ftmod_sangoma_isdn_support.c | 11 +- .../ftmod_sangoma_ss7_handle.c | 13 +- .../ftmod_sangoma_ss7_main.c | 6 +- .../ftmod_sangoma_ss7_main.h | 11 + .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c | 237 ++------ .../ftmod_sangoma_ss7_support.c | 526 +++++++++++++++++- .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c | 34 +- libs/freetdm/src/include/freetdm.h | 12 +- libs/freetdm/src/include/ftdm_call_utils.h | 19 + 13 files changed, 753 insertions(+), 231 deletions(-) diff --git a/libs/freetdm/configure.ac b/libs/freetdm/configure.ac index 55185cb10d..493f0da3b0 100644 --- a/libs/freetdm/configure.ac +++ b/libs/freetdm/configure.ac @@ -294,6 +294,19 @@ if test "${HAVE_SNG_SS7}" = "yes"; then fi fi + +## +# zlib (required for Sangoma SS7 Transparent IAM) +# +HAVE_ZLIB="no" +AC_MSG_RESULT([${as_nl}<<>> zlib]) +AC_CHECK_LIB([z], [compress], [HAVE_ZLIB="yes"]) +AC_MSG_RESULT([checking whether zlib is installed... ${HAVE_ZLIB}]) +AM_CONDITIONAL([HAVE_ZLIB], [test "{HAVE_ZLIB]" = "yes"]) +if test "${HAVE_ZLIB}" = "yes"; then + CFLAGS="$CFLAGS -DHAVE_ZLIB" +fi + ## # libisdn # diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 954a568e6f..75b500d0f6 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -1369,7 +1369,12 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-CPC"); if (sipvar) { - ftdm_set_calling_party_category(var, (uint8_t *)&caller_data.cpc); + ftdm_set_calling_party_category(sipvar, (uint8_t *)&caller_data.cpc); + } + + sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-IAM"); + if (sipvar) { + ftdm_usrmsg_add_var(&usrmsg, "ss7_iam", sipvar); } } @@ -1443,7 +1448,13 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi if (!strncasecmp(h->name, FREETDM_VAR_PREFIX, FREETDM_VAR_PREFIX_LEN)) { char *v = h->name + FREETDM_VAR_PREFIX_LEN; if (!zstr(v)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding outbound freetdm variable %s=%s to channel %d:%d\n", v, h->value, span_id, chan_id); + if (!strcasecmp(v, "ss7_iam")) { + /* Do not print the value of ss7_iam as it is very long */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding outbound freetdm variable %s to channel %d:%d\n", v, span_id, chan_id); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding outbound freetdm variable %s=%s to channel %d:%d\n", v, h->value, span_id, chan_id); + } + ftdm_usrmsg_add_var(&usrmsg, v, h->value); } } @@ -1633,6 +1644,8 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDNIS", "%s", channel_caller_data->rdnis.digits); switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDNIS-NADI", "%d", channel_caller_data->rdnis.type); switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDNIS-Plan", "%d", channel_caller_data->rdnis.plan); + switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-CPC", "%s", ftdm_calling_party_category2str(channel_caller_data->cpc)); + var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_rdnis_screen_ind"); if (!ftdm_strlen_zero(var_value)) { @@ -1678,10 +1691,10 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-GN-NumInComp", "%d", var_value); } } /* End - var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_gn_digits"); */ - - var_value = ftdm_sigmsg_get_var(sigmsg, "freetdm_calling_party_category"); + + var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_iam"); if (!ftdm_strlen_zero(var_value)) { - switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-CPC", "%s", var_value); + switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-IAM", "%s", var_value); } switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-Screen", "%d", channel_caller_data->screen); @@ -1694,7 +1707,12 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session ftdm_get_current_var(curr, &var_name, &var_value); snprintf(name, sizeof(name), FREETDM_VAR_PREFIX "%s", var_name); switch_channel_set_variable_printf(channel, name, "%s", var_value); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call Variable: %s = %s\n", name, var_value); + if (!strcasecmp(var_name, "ss7_iam")) { + /* Do not print freetdm_ss7_iam as it is a very long variable */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call Variable: %s is present\n", name); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call Variable: %s = %s\n", name, var_value); + } } ftdm_iterator_free(iter); diff --git a/libs/freetdm/src/ftdm_call_utils.c b/libs/freetdm/src/ftdm_call_utils.c index 2b72f05b77..d23c95af4e 100644 --- a/libs/freetdm/src/ftdm_call_utils.c +++ b/libs/freetdm/src/ftdm_call_utils.c @@ -42,6 +42,74 @@ #include + + +FT_DECLARE(char *) ftdm_url_encode(const char *url, char *buf, ftdm_size_t len) +{ + /* This implementation of url_encode is slightly different compared to the + * Freeswitch one. This is because this implementation accepts the full + * range of values (0x00 - 0xFF) compared to the Freeswitch implementation + * that does not accept 0x00 */ + + const char *p; + size_t x = 0,y = 0; + const char urlunsafe[] = "\r\n \"#%&+:;<=>?@[\\]^`{|}"; + const char hex[] = "0123456789ABCDEF"; + + if (!buf) { + return 0; + } + + if (!url) { + return 0; + } + + len--; + + for (p = url; y <= len; p++) { + if (*p < ' ' || *p > '~' || strchr(urlunsafe, *p)) { + buf[x++] = '%'; + buf[x++] = hex[(*p >> 4) & 0x0f]; + buf[x++] = hex[*p & 0x0f]; + } else { + buf[x++] = *p; + } + y++; + } + buf[x] = '\0'; + return buf; +} + + +FT_DECLARE(char *) ftdm_url_decode(char *s, ftdm_size_t *len) +{ + /* This implementation of url_decode is slightly different compared to the + * Freeswitch one. This is because this implementation accepts the full + * range of values (0x00 - 0xFF) compared to the Freeswitch implementation + * that does not accept 0x00 */ + + char *o; + unsigned int tmp; + ftdm_size_t mylen = 0; + + if (ftdm_strlen_zero(s)) { + return s; + } + + for (o = s; *s; s++, o++) { + if (*s == '%' && strlen(s) > 2 && sscanf(s + 1, "%2x", &tmp) == 1) { + *o = (char) tmp; + s += 2; + } else { + *o = *s; + } + mylen++; + } + *o = '\0'; + *len = mylen; + return s; +} + FT_DECLARE(ftdm_status_t) ftdm_set_npi(const char *string, uint8_t *target) { uint8_t val; diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 1d7a0d1eb1..c7a3ec48f4 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -411,13 +411,13 @@ FT_DECLARE(void) ftdm_set_echocancel_call_begin(ftdm_channel_t *chan) if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC)) { if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE)) { /* If the ec is disabled on idle, we need to enable it unless is a digital call */ - if (caller_data->bearer_capability != FTDM_BEARER_CAP_64K_UNRESTRICTED) { + if (caller_data->bearer_capability != FTDM_BEARER_CAP_UNRESTRICTED) { ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Enabling ec for call in channel state %s\n", ftdm_channel_state2str(chan->state)); ftdm_channel_command(chan, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL); } } else { /* If the ec is enabled on idle, we do nothing unless is a digital call that needs it disabled */ - if (caller_data->bearer_capability == FTDM_BEARER_CAP_64K_UNRESTRICTED) { + if (caller_data->bearer_capability == FTDM_BEARER_CAP_UNRESTRICTED) { ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Disabling ec for digital call in channel state %s\n", ftdm_channel_state2str(chan->state)); ftdm_channel_command(chan, FTDM_COMMAND_DISABLE_ECHOCANCEL, NULL); } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index a343809b4c..f4fee712c9 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -1069,18 +1069,20 @@ void get_memory_info(void) return; } + uint8_t sngisdn_get_infoTranCap_from_user(ftdm_bearer_cap_t bearer_capability) { switch(bearer_capability) { case FTDM_BEARER_CAP_SPEECH: return IN_ITC_SPEECH; - case FTDM_BEARER_CAP_64K_UNRESTRICTED: + case FTDM_BEARER_CAP_UNRESTRICTED: return IN_ITC_UNRDIG; case FTDM_BEARER_CAP_3_1KHZ_AUDIO: return IN_ITC_A31KHZ; case FTDM_BEARER_CAP_INVALID: return IN_ITC_SPEECH; - /* Do not put a default case here, so we can see compile warnings if we have unhandled cases */ + default: + return IN_ITC_SPEECH; } return FTDM_BEARER_CAP_SPEECH; } @@ -1096,7 +1098,8 @@ uint8_t sngisdn_get_usrInfoLyr1Prot_from_user(ftdm_user_layer1_prot_t layer1_pro return IN_UIL1_G711ALAW; case FTDM_USER_LAYER1_PROT_INVALID: return IN_UIL1_G711ULAW; - /* Do not put a default case here, so we can see compile warnings if we have unhandled cases */ + default: + return IN_UIL1_G711ULAW; } return IN_UIL1_G711ULAW; } @@ -1107,7 +1110,7 @@ ftdm_bearer_cap_t sngisdn_get_infoTranCap_from_stack(uint8_t bearer_capability) case IN_ITC_SPEECH: return FTDM_BEARER_CAP_SPEECH; case IN_ITC_UNRDIG: - return FTDM_BEARER_CAP_64K_UNRESTRICTED; + return FTDM_BEARER_CAP_UNRESTRICTED; case IN_ITC_A31KHZ: return FTDM_BEARER_CAP_3_1KHZ_AUDIO; default: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c index 596ae7c734..0520e9d163 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c @@ -33,12 +33,14 @@ /* INCLUDE ********************************************************************/ #include "ftmod_sangoma_ss7_main.h" + /******************************************************************************/ /* DEFINES ********************************************************************/ /******************************************************************************/ /* GLOBALS ********************************************************************/ + /******************************************************************************/ /* PROTOTYPES *****************************************************************/ @@ -79,14 +81,14 @@ ftdm_status_t handle_olm_msg(uint32_t suInstId, uint32_t spInstId, uint32_t circ /******************************************************************************/ /* FUNCTIONS ******************************************************************/ + ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt) { - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - sngss7_chan_data_t *sngss7_info = NULL; ftdm_channel_t *ftdmchan = NULL; char nadi[2]; - + + SS7_FUNC_TRACE_ENTER(__FUNCTION__); memset(nadi, '\0', sizeof(nadi)); /* get the ftdmchan and ss7_chan_data from the circuit */ @@ -208,6 +210,10 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ sprintf(nadi, "%d", siConEvnt->cdPtyNum.natAddrInd.val); sngss7_add_var(sngss7_info, "ss7_cld_nadi", nadi); + if (sngss7_info->circuit->transparent_iam) { + sngss7_save_iam(ftdmchan, siConEvnt); + } + /* check if a COT test is requested */ if ((siConEvnt->natConInd.eh.pres) && (siConEvnt->natConInd.contChkInd.pres) && @@ -231,7 +237,6 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ siConEvnt->cgPtyNum.natAddrInd.val, ftdmchan->caller_data.dnis.digits, siConEvnt->cdPtyNum.natAddrInd.val); - } /* if (channel is usable */ break; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c index 4f8c069b71..53062b9d56 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c @@ -42,6 +42,7 @@ static sng_isup_event_interface_t sng_event; static ftdm_io_interface_t g_ftdm_sngss7_interface; ftdm_sngss7_data_t g_ftdm_sngss7_data; + /******************************************************************************/ /* PROTOTYPES *****************************************************************/ @@ -509,11 +510,6 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) SS7_DEBUG_CHAN(ftdmchan, "ftmod_sangoma_ss7 processing state %s\n", ftdm_channel_state2str (ftdmchan->state)); -#if 0 - /* clear the state change flag...since we might be setting a new state */ - ftdm_channel_complete_state(ftdmchan); -#endif - /*check what state we are supposed to be in */ switch (ftdmchan->state) { /**************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h index 04723048f6..f88202b1a8 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h @@ -339,6 +339,7 @@ typedef struct sng_isup_ckt { uint32_t min_digits; uint8_t itx_auto_reply; + uint8_t transparent_iam; void *obj; uint16_t t3; uint16_t t12; @@ -406,6 +407,7 @@ typedef struct sng_ss7_cfg { uint32_t procId; char license[MAX_PATH]; char signature[MAX_PATH]; + uint32_t transparent_iam_max_size; uint32_t flags; sng_relay_t relay[MAX_RELAY_CHANNELS+1]; sng_mtp1_link_t mtp1Link[MAX_MTP_LINKS+1]; @@ -765,6 +767,10 @@ void sngss7_resm_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiR void sngss7_susp_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiSuspEvnt *siSuspEvnt); void sngss7_ssp_sta_cfm(uint32_t infId); +ftdm_status_t sngss7_bufferzero_iam(SiConEvnt *siConEvnt); +ftdm_status_t sngss7_retrieve_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt); +ftdm_status_t sngss7_save_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt); + /* in ftmod_sangoma_ss7_handle.c */ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType); @@ -815,6 +821,11 @@ ftdm_status_t copy_genNmb_to_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb); ftdm_status_t copy_genNmb_from_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb); ftdm_status_t copy_cgPtyCat_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyCat *cgPtyCat); ftdm_status_t copy_cgPtyCat_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyCat *cgPtyCat); +ftdm_status_t copy_accTrnspt_to_sngss7(ftdm_channel_t *ftdmchan, SiAccTrnspt *accTrnspt); +ftdm_status_t copy_natConInd_to_sngss7(ftdm_channel_t *ftdmchan, SiNatConInd *natConInd); +ftdm_status_t copy_fwdCallInd_to_sngss7(ftdm_channel_t *ftdmchan, SiFwdCallInd *fwdCallInd); +ftdm_status_t copy_txMedReq_to_sngss7(ftdm_channel_t *ftdmchan, SiTxMedReq *txMedReq); +ftdm_status_t copy_usrServInfoA_to_sngss7(ftdm_channel_t *ftdmchan, SiUsrServInfo *usrServInfoA); ftdm_status_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven); ftdm_status_t append_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c index e1944513d1..91b8900fef 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c @@ -36,10 +36,8 @@ /******************************************************************************/ /* DEFINES ********************************************************************/ -/******************************************************************************/ /* GLOBALS ********************************************************************/ -/******************************************************************************/ /* PROTOTYPES *****************************************************************/ void ft_to_sngss7_iam(ftdm_channel_t * ftdmchan); @@ -66,219 +64,70 @@ void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan); void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan); void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan); -/******************************************************************************/ /* FUNCTIONS ******************************************************************/ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) -{ - SS7_FUNC_TRACE_ENTER (__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;; - const char *clg_subAddr = NULL; - const char *cld_subAddr = NULL; - char subAddrIE[MAX_SIZEOF_SUBADDR_IE]; +{ SiConEvnt iam; + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;; + + SS7_FUNC_TRACE_ENTER (__FUNCTION__); sngss7_info->suInstId = get_unique_id (); sngss7_info->spInstId = 0; sngss7_info->spId = 1; memset (&iam, 0x0, sizeof (iam)); - - /* copy down the nature of connection indicators */ - iam.natConInd.eh.pres = PRSNT_NODEF; - iam.natConInd.satInd.pres = PRSNT_NODEF; - iam.natConInd.satInd.val = 0; /* no satellite circuit */ - iam.natConInd.contChkInd.pres = PRSNT_NODEF; - iam.natConInd.contChkInd.val = CONTCHK_NOTREQ; - iam.natConInd.echoCntrlDevInd.pres = PRSNT_NODEF; - iam.natConInd.echoCntrlDevInd.val = ECHOCDEV_INCL; - - /* copy down the forward call indicators */ - iam.fwdCallInd.eh.pres = PRSNT_NODEF; - iam.fwdCallInd.natIntCallInd.pres = PRSNT_NODEF; - iam.fwdCallInd.natIntCallInd.val = 0x00; - iam.fwdCallInd.end2EndMethInd.pres = PRSNT_NODEF; - iam.fwdCallInd.end2EndMethInd.val = E2EMTH_NOMETH; - iam.fwdCallInd.intInd.pres = PRSNT_NODEF; - iam.fwdCallInd.intInd.val = INTIND_NOINTW; - iam.fwdCallInd.end2EndInfoInd.pres = PRSNT_NODEF; - iam.fwdCallInd.end2EndInfoInd.val = E2EINF_NOINFO; - iam.fwdCallInd.isdnUsrPrtInd.pres = PRSNT_NODEF; - iam.fwdCallInd.isdnUsrPrtInd.val = ISUP_USED; - iam.fwdCallInd.isdnUsrPrtPrfInd.pres = PRSNT_NODEF; - iam.fwdCallInd.isdnUsrPrtPrfInd.val = PREF_PREFAW; - iam.fwdCallInd.isdnAccInd.pres = PRSNT_NODEF; - iam.fwdCallInd.isdnAccInd.val = ISDNACC_ISDN; - iam.fwdCallInd.sccpMethInd.pres = PRSNT_NODEF; - iam.fwdCallInd.sccpMethInd.val = SCCPMTH_NOIND; + + if (sngss7_info->circuit->transparent_iam && + sngss7_retrieve_iam(ftdmchan, &iam) == FTDM_SUCCESS) { + SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Transparent)\n", sngss7_info->circuit->cic); + } else { + /* Nature of Connection Indicators */ + copy_natConInd_to_sngss7(ftdmchan, &iam.natConInd); + + /* Forward Call Indicators */ + copy_fwdCallInd_to_sngss7(ftdmchan, &iam.fwdCallInd); + + /* Transmission medium requirements */ + copy_txMedReq_to_sngss7(ftdmchan, &iam.txMedReq); + + /* User Service Info A */ + copy_usrServInfoA_to_sngss7(ftdmchan, &iam.usrServInfoA); - /* copy down the transmission medium requirements */ - iam.txMedReq.eh.pres = PRSNT_NODEF; - iam.txMedReq.trMedReq.pres = PRSNT_NODEF; - iam.txMedReq.trMedReq.val = ftdmchan->caller_data.bearer_capability; - - if ((g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS88) || - (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS92) || - (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS95)) { - - /* include only if we're running ANSI */ - iam.fwdCallInd.transCallNInd.pres = PRSNT_NODEF; - iam.fwdCallInd.transCallNInd.val = 0x0; - - iam.usrServInfoA.eh.pres = PRSNT_NODEF; - - iam.usrServInfoA.infoTranCap.pres = PRSNT_NODEF; - switch (ftdmchan->caller_data.bearer_capability) { - /**********************************************************************/ - case (FTDM_BEARER_CAP_SPEECH): - iam.usrServInfoA.infoTranCap.val = 0x0; /* speech as per ATIS-1000113.3.2005 */ - break; - /**********************************************************************/ - case (FTDM_BEARER_CAP_64K_UNRESTRICTED): - iam.usrServInfoA.infoTranCap.val = 0x8; /* unrestricted digital as per ATIS-1000113.3.2005 */ - break; - /**********************************************************************/ - case (FTDM_BEARER_CAP_3_1KHZ_AUDIO): - iam.usrServInfoA.infoTranCap.val = 0x10; /* 3.1kHz audio as per ATIS-1000113.3.2005 */ - break; - /**********************************************************************/ - default: - SS7_ERROR_CHAN(ftdmchan, "Unknown Bearer capability falling back to speech%s\n", " "); - iam.usrServInfoA.infoTranCap.val = 0x0; /* speech as per ATIS-1000113.3.2005 */ - break; - /**********************************************************************/ - } /* switch (ftdmchan->caller_data.bearer_capability) */ - - iam.usrServInfoA.cdeStand.pres = PRSNT_NODEF; - iam.usrServInfoA.cdeStand.val = 0x0; /* ITU-T standardized coding */ - iam.usrServInfoA.tranMode.pres = PRSNT_NODEF; - iam.usrServInfoA.tranMode.val = 0x0; /* circuit mode */ - iam.usrServInfoA.infoTranRate0.pres = PRSNT_NODEF; - iam.usrServInfoA.infoTranRate0.val = 0x10; /* 64kbps origination to destination */ - iam.usrServInfoA.infoTranRate1.pres = PRSNT_NODEF; - iam.usrServInfoA.infoTranRate1.val = 0x10; /* 64kbps destination to origination */ - iam.usrServInfoA.chanStruct.pres = PRSNT_NODEF; - iam.usrServInfoA.chanStruct.val = 0x1; /* 8kHz integrity */ - iam.usrServInfoA.config.pres = PRSNT_NODEF; - iam.usrServInfoA.config.val = 0x0; /* point to point configuration */ - iam.usrServInfoA.establish.pres = PRSNT_NODEF; - iam.usrServInfoA.establish.val = 0x0; /* on demand */ - iam.usrServInfoA.symmetry.pres = PRSNT_NODEF; - iam.usrServInfoA.symmetry.val = 0x0; /* bi-directional symmetric */ - iam.usrServInfoA.usrInfLyr1Prot.pres = PRSNT_NODEF; - iam.usrServInfoA.usrInfLyr1Prot.val = 0x2; /* G.711 ulaw */ - iam.usrServInfoA.rateMultiplier.pres = PRSNT_NODEF; - iam.usrServInfoA.rateMultiplier.val = 0x1; /* 1x rate multipler */ - } /* if ANSI */ - - /* copy down the called number information */ - copy_cdPtyNum_to_sngss7 (ftdmchan, &iam.cdPtyNum); - - /* copy down the calling number information */ - copy_cgPtyNum_to_sngss7 (ftdmchan, &iam.cgPtyNum); - - /* copy down the generic number information */ - copy_genNmb_to_sngss7(ftdmchan, &iam.genNmb); - - /* copy down the calling party category */ - copy_cgPtyCat_to_sngss7(ftdmchan, &iam.cgPtyCat); - - /* TODO - move this to copy_clg_subAddr_to_sngss7 function */ - /* check if the user would like us to send a clg_sub-address */ - clg_subAddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_clg_subaddr"); - if (!ftdm_strlen_zero(clg_subAddr)) { - SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling Sub-Address value \"%s\"\n", clg_subAddr); + /* Called Number information */ + copy_cdPtyNum_to_sngss7(ftdmchan, &iam.cdPtyNum); - /* clean out the subAddrIE */ - memset(subAddrIE, 0x0, sizeof(subAddrIE)); + /* Calling Number information */ + copy_cgPtyNum_to_sngss7(ftdmchan, &iam.cgPtyNum); - /* check the first character in the sub-address to see what type of encoding to use */ - switch (clg_subAddr[0]) { - case '0': /* NSAP */ - encode_subAddrIE_nsap(&clg_subAddr[1], subAddrIE, SNG_CALLING); - break; - case '1': /* national variant */ - encode_subAddrIE_nat(&clg_subAddr[1], subAddrIE, SNG_CALLING); - break; - default: - SS7_ERROR_CHAN(ftdmchan,"Invalid Calling Sub-Address encoding requested: %c\n", clg_subAddr[0]); - break; - } /* switch (cld_subAddr[0]) */ + /* Generic Number information */ + copy_genNmb_to_sngss7(ftdmchan, &iam.genNmb); + /* Calling Party's Category */ + copy_cgPtyCat_to_sngss7(ftdmchan, &iam.cgPtyCat); - /* if subaddIE is still empty don't copy it in */ - if (subAddrIE[0] != '0') { - /* check if the clg_subAddr has already been added */ - if (iam.accTrnspt.eh.pres == PRSNT_NODEF) { - /* append the subAddrIE */ - memcpy(&iam.accTrnspt.infoElmts.val[iam.accTrnspt.infoElmts.len], subAddrIE, (subAddrIE[1] + 2)); - iam.accTrnspt.infoElmts.len = iam.accTrnspt.infoElmts.len +subAddrIE[1] + 2; - } else { - /* fill in from the beginning */ - iam.accTrnspt.eh.pres = PRSNT_NODEF; - iam.accTrnspt.infoElmts.pres = PRSNT_NODEF; - memcpy(iam.accTrnspt.infoElmts.val, subAddrIE, (subAddrIE[1] + 2)); - iam.accTrnspt.infoElmts.len = subAddrIE[1] + 2; - } /* if (iam.accTrnspt.eh.pres */ - } /* if (subAddrIE[0] != '0') */ + /* Redirecting Number */ + copy_redirgNum_to_sngss7(ftdmchan, &iam.redirgNum); + + /* Access Transport */ + copy_accTrnspt_to_sngss7(ftdmchan, &iam.accTrnspt); + + SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM clg = \"%s\" (NADI=%d), cld = \"%s\" (NADI=%d)\n", + sngss7_info->circuit->cic, + ftdmchan->caller_data.cid_num.digits, + iam.cgPtyNum.natAddrInd.val, + ftdmchan->caller_data.dnis.digits, + iam.cdPtyNum.natAddrInd.val); } - copy_redirgNum_to_sngss7(ftdmchan, &iam.redirgNum); - - /* check if the user would like us to send a cld_sub-address */ - cld_subAddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_cld_subaddr"); - if ((cld_subAddr != NULL) && (*cld_subAddr)) { - SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called Sub-Address value \"%s\"\n", cld_subAddr); - - /* clean out the subAddrIE */ - memset(subAddrIE, 0x0, sizeof(subAddrIE)); - - /* check the first character in the sub-address to see what type of encoding to use */ - switch (cld_subAddr[0]) { - case '0': /* NSAP */ - encode_subAddrIE_nsap(&cld_subAddr[1], subAddrIE, SNG_CALLED); - break; - case '1': /* national variant */ - encode_subAddrIE_nat(&cld_subAddr[1], subAddrIE, SNG_CALLED); - break; - default: - SS7_ERROR_CHAN(ftdmchan,"Invalid Called Sub-Address encoding requested: %c\n", cld_subAddr[0]); - break; - } /* switch (cld_subAddr[0]) */ - - /* if subaddIE is still empty don't copy it in */ - if (subAddrIE[0] != '0') { - /* check if the cld_subAddr has already been added */ - if (iam.accTrnspt.eh.pres == PRSNT_NODEF) { - /* append the subAddrIE */ - memcpy(&iam.accTrnspt.infoElmts.val[iam.accTrnspt.infoElmts.len], subAddrIE, (subAddrIE[1] + 2)); - iam.accTrnspt.infoElmts.len = iam.accTrnspt.infoElmts.len +subAddrIE[1] + 2; - } else { - /* fill in from the beginning */ - iam.accTrnspt.eh.pres = PRSNT_NODEF; - iam.accTrnspt.infoElmts.pres = PRSNT_NODEF; - memcpy(iam.accTrnspt.infoElmts.val, subAddrIE, (subAddrIE[1] + 2)); - iam.accTrnspt.infoElmts.len = subAddrIE[1] + 2; - } /* if (iam.accTrnspt.eh.pres */ - } /* if (subAddrIE[0] != '0') */ - } /* if ((cld_subAddr != NULL) && (*cld_subAddr)) */ - sng_cc_con_request (sngss7_info->spId, sngss7_info->suInstId, sngss7_info->spInstId, - sngss7_info->circuit->id, - &iam, + sngss7_info->circuit->id, + &iam, 0); - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM clg = \"%s\" (NADI=%d), cld = \"%s\" (NADI=%d)\n", - sngss7_info->circuit->cic, - ftdmchan->caller_data.cid_num.digits, - iam.cgPtyNum.natAddrInd.val, - ftdmchan->caller_data.dnis.digits, - iam.cdPtyNum.natAddrInd.val); - - SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; } @@ -319,7 +168,7 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan) acm.bckCallInd.echoCtrlDevInd.val = 0x1; break; /**********************************************************************/ - case (FTDM_BEARER_CAP_64K_UNRESTRICTED): + case (FTDM_BEARER_CAP_UNRESTRICTED): acm.bckCallInd.echoCtrlDevInd.val = 0x0; break; /**********************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c index 3ebd162f09..e61153c8e7 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c @@ -33,6 +33,9 @@ /* INCLUDE ********************************************************************/ #include "ftmod_sangoma_ss7_main.h" +#ifdef HAVE_ZLIB +#include +#endif /******************************************************************************/ /* DEFINES ********************************************************************/ @@ -111,6 +114,16 @@ ftdm2trillium_t cpc_codes[] = { {FTDM_CPC_PAYPHONE, CAT_PAYPHONE}, }; +ftdm2trillium_t bc_cap_codes[] = { + {FTDM_BEARER_CAP_SPEECH, ITC_SPEECH}, /* speech as per ATIS-1000113.3.2005 */ + {FTDM_BEARER_CAP_UNRESTRICTED, ITC_UNRDIG}, /* unrestricted digital as per ATIS-1000113.3.2005 */ + {FTDM_BEARER_CAP_RESTRICTED, ITC_UNRDIG}, /* Restricted Digital */ + {FTDM_BEARER_CAP_3_1KHZ_AUDIO, ITC_A31KHZ}, /* 3.1kHz audio as per ATIS-1000113.3.2005 */ + {FTDM_BEARER_CAP_7KHZ_AUDIO, ITC_A7KHZ}, /* 7Khz audio */ + {FTDM_BEARER_CAP_15KHZ_AUDIO, ITC_A15KHZ}, /* 15Khz audio */ + {FTDM_BEARER_CAP_VIDEO, ITC_VIDEO}, /* Video */ +}; + static uint8_t get_trillium_val(ftdm2trillium_t *vals, uint8_t ftdm_val, uint8_t default_val) { ftdm2trillium_t *val = vals; @@ -485,6 +498,187 @@ ftdm_status_t copy_cgPtyCat_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyCat *cg return FTDM_SUCCESS; } + +ftdm_status_t copy_accTrnspt_to_sngss7(ftdm_channel_t *ftdmchan, SiAccTrnspt *accTrnspt) +{ + const char *clg_subAddr = NULL; + const char *cld_subAddr = NULL; + char subAddrIE[MAX_SIZEOF_SUBADDR_IE]; + + /* check if the user would like us to send a clg_sub-address */ + clg_subAddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_clg_subaddr"); + if (!ftdm_strlen_zero(clg_subAddr)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Calling Sub-Address value \"%s\"\n", clg_subAddr); + + /* clean out the subAddrIE */ + memset(subAddrIE, 0x0, sizeof(subAddrIE)); + + /* check the first character in the sub-address to see what type of encoding to use */ + switch (clg_subAddr[0]) { + case '0': /* NSAP */ + encode_subAddrIE_nsap(&clg_subAddr[1], subAddrIE, SNG_CALLING); + break; + case '1': /* national variant */ + encode_subAddrIE_nat(&clg_subAddr[1], subAddrIE, SNG_CALLING); + break; + default: + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Invalid Calling Sub-Address encoding requested: %c\n", clg_subAddr[0]); + break; + } /* switch (cld_subAddr[0]) */ + + + /* if subaddIE is still empty don't copy it in */ + if (subAddrIE[0] != '0') { + /* check if the clg_subAddr has already been added */ + if (accTrnspt->eh.pres == PRSNT_NODEF) { + /* append the subAddrIE */ + memcpy(&accTrnspt->infoElmts.val[accTrnspt->infoElmts.len], subAddrIE, (subAddrIE[1] + 2)); + accTrnspt->infoElmts.len = accTrnspt->infoElmts.len +subAddrIE[1] + 2; + } else { + /* fill in from the beginning */ + accTrnspt->eh.pres = PRSNT_NODEF; + accTrnspt->infoElmts.pres = PRSNT_NODEF; + memcpy(accTrnspt->infoElmts.val, subAddrIE, (subAddrIE[1] + 2)); + accTrnspt->infoElmts.len = subAddrIE[1] + 2; + } + } + } + + /* check if the user would like us to send a cld_sub-address */ + cld_subAddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_cld_subaddr"); + if ((cld_subAddr != NULL) && (*cld_subAddr)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Called Sub-Address value \"%s\"\n", cld_subAddr); + + /* clean out the subAddrIE */ + memset(subAddrIE, 0x0, sizeof(subAddrIE)); + + /* check the first character in the sub-address to see what type of encoding to use */ + switch (cld_subAddr[0]) { + case '0': /* NSAP */ + encode_subAddrIE_nsap(&cld_subAddr[1], subAddrIE, SNG_CALLED); + break; + case '1': /* national variant */ + encode_subAddrIE_nat(&cld_subAddr[1], subAddrIE, SNG_CALLED); + break; + default: + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Invalid Called Sub-Address encoding requested: %c\n", cld_subAddr[0]); + break; + } /* switch (cld_subAddr[0]) */ + + /* if subaddIE is still empty don't copy it in */ + if (subAddrIE[0] != '0') { + /* check if the cld_subAddr has already been added */ + if (accTrnspt->eh.pres == PRSNT_NODEF) { + /* append the subAddrIE */ + memcpy(&accTrnspt->infoElmts.val[accTrnspt->infoElmts.len], subAddrIE, (subAddrIE[1] + 2)); + accTrnspt->infoElmts.len = accTrnspt->infoElmts.len +subAddrIE[1] + 2; + } else { + /* fill in from the beginning */ + accTrnspt->eh.pres = PRSNT_NODEF; + accTrnspt->infoElmts.pres = PRSNT_NODEF; + memcpy(accTrnspt->infoElmts.val, subAddrIE, (subAddrIE[1] + 2)); + accTrnspt->infoElmts.len = subAddrIE[1] + 2; + } + } + } /* if ((cld_subAddr != NULL) && (*cld_subAddr)) */ + return FTDM_SUCCESS; +} + +ftdm_status_t copy_natConInd_to_sngss7(ftdm_channel_t *ftdmchan, SiNatConInd *natConInd) +{ + /* copy down the nature of connection indicators */ + natConInd->eh.pres = PRSNT_NODEF; + natConInd->satInd.pres = PRSNT_NODEF; + natConInd->satInd.val = 0; /* no satellite circuit */ + natConInd->contChkInd.pres = PRSNT_NODEF; + natConInd->contChkInd.val = CONTCHK_NOTREQ; + natConInd->echoCntrlDevInd.pres = PRSNT_NODEF; + natConInd->echoCntrlDevInd.val = ECHOCDEV_INCL; + return FTDM_SUCCESS; +} + +ftdm_status_t copy_fwdCallInd_to_sngss7(ftdm_channel_t *ftdmchan, SiFwdCallInd *fwdCallInd) +{ + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; + + fwdCallInd->eh.pres = PRSNT_NODEF; + fwdCallInd->natIntCallInd.pres = PRSNT_NODEF; + fwdCallInd->natIntCallInd.val = 0x00; + fwdCallInd->end2EndMethInd.pres = PRSNT_NODEF; + fwdCallInd->end2EndMethInd.val = E2EMTH_NOMETH; + fwdCallInd->intInd.pres = PRSNT_NODEF; + fwdCallInd->intInd.val = INTIND_NOINTW; + fwdCallInd->end2EndInfoInd.pres = PRSNT_NODEF; + fwdCallInd->end2EndInfoInd.val = E2EINF_NOINFO; + fwdCallInd->isdnUsrPrtInd.pres = PRSNT_NODEF; + fwdCallInd->isdnUsrPrtInd.val = ISUP_USED; + fwdCallInd->isdnUsrPrtPrfInd.pres = PRSNT_NODEF; + fwdCallInd->isdnUsrPrtPrfInd.val = PREF_PREFAW; + fwdCallInd->isdnAccInd.pres = PRSNT_NODEF; + fwdCallInd->isdnAccInd.val = ISDNACC_ISDN; + fwdCallInd->sccpMethInd.pres = PRSNT_NODEF; + fwdCallInd->sccpMethInd.val = SCCPMTH_NOIND; + + if ((g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS88) || + (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS92) || + (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS95)) { + + /* include only if we're running ANSI */ + fwdCallInd->transCallNInd.pres = PRSNT_NODEF; + fwdCallInd->transCallNInd.val = 0x0; + } + return FTDM_SUCCESS; +} + +ftdm_status_t copy_txMedReq_to_sngss7(ftdm_channel_t *ftdmchan, SiTxMedReq *txMedReq) +{ + txMedReq->eh.pres = PRSNT_NODEF; + txMedReq->trMedReq.pres = PRSNT_NODEF; + txMedReq->trMedReq.val = ftdmchan->caller_data.bearer_capability; + + return FTDM_SUCCESS; +} + +ftdm_status_t copy_usrServInfoA_to_sngss7(ftdm_channel_t *ftdmchan, SiUsrServInfo *usrServInfoA) +{ + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; + + if ((g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS88) || + (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS92) || + (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS95)) { + + usrServInfoA->eh.pres = PRSNT_NODEF; + + usrServInfoA->infoTranCap.pres = PRSNT_NODEF; + + usrServInfoA->infoTranCap.val = get_trillium_val(bc_cap_codes, ftdmchan->caller_data.bearer_capability, ITC_SPEECH); + + usrServInfoA->cdeStand.pres = PRSNT_NODEF; + usrServInfoA->cdeStand.val = 0x0; /* ITU-T standardized coding */ + usrServInfoA->tranMode.pres = PRSNT_NODEF; + usrServInfoA->tranMode.val = 0x0; /* circuit mode */ + usrServInfoA->infoTranRate0.pres = PRSNT_NODEF; + usrServInfoA->infoTranRate0.val = 0x10; /* 64kbps origination to destination */ + usrServInfoA->infoTranRate1.pres = PRSNT_NODEF; + usrServInfoA->infoTranRate1.val = 0x10; /* 64kbps destination to origination */ + usrServInfoA->chanStruct.pres = PRSNT_NODEF; + usrServInfoA->chanStruct.val = 0x1; /* 8kHz integrity */ + usrServInfoA->config.pres = PRSNT_NODEF; + usrServInfoA->config.val = 0x0; /* point to point configuration */ + usrServInfoA->establish.pres = PRSNT_NODEF; + usrServInfoA->establish.val = 0x0; /* on demand */ + usrServInfoA->symmetry.pres = PRSNT_NODEF; + usrServInfoA->symmetry.val = 0x0; /* bi-directional symmetric */ + usrServInfoA->usrInfLyr1Prot.pres = PRSNT_NODEF; + usrServInfoA->usrInfLyr1Prot.val = 0x2; /* G.711 ulaw */ + usrServInfoA->rateMultiplier.pres = PRSNT_NODEF; + usrServInfoA->rateMultiplier.val = 0x1; /* 1x rate multipler */ + } /* if ANSI */ + return FTDM_SUCCESS; +} + + + ftdm_status_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven) { uint8_t i; @@ -1724,7 +1918,7 @@ void sngss7_set_sig_status(sngss7_chan_data_t *sngss7_info, ftdm_signaling_statu sig.ev_data.sigstatus.status = status; if (ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS) { - SS7_ERROR_CHAN(ftdmchan, "Failed to change channel status to %s\n", + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to change channel status to %s\n", ftdm_signaling_status2str(status)); } return; @@ -1899,6 +2093,336 @@ ftdm_status_t check_for_reconfig_flag(ftdm_span_t *ftdmspan) return FTDM_SUCCESS; } + +ftdm_status_t sngss7_bufferzero_iam(SiConEvnt *siConEvnt) +{ + if (siConEvnt->natConInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->natConInd, 0, sizeof(siConEvnt->natConInd)); + if (siConEvnt->fwdCallInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->fwdCallInd, 0, sizeof(siConEvnt->fwdCallInd)); + if (siConEvnt->cgPtyCat.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyCat, 0, sizeof(siConEvnt->cgPtyCat)); + if (siConEvnt->txMedReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->txMedReq, 0, sizeof(siConEvnt->txMedReq)); +#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL) + if (siConEvnt->usrServInfoA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usrServInfoA, 0, sizeof(siConEvnt->usrServInfoA)); +#endif + if (siConEvnt->cdPtyNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cdPtyNum, 0, sizeof(siConEvnt->cdPtyNum)); +#if TNS_ANSI +#if (SS7_ANS92 || SS7_ANS95 || SS7_BELL) + if (siConEvnt->tranNetSel1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->tranNetSel1, 0, sizeof(siConEvnt->tranNetSel1)); +#endif +#endif + if (siConEvnt->tranNetSel.eh.pres != PRSNT_NODEF) memset(&siConEvnt->tranNetSel, 0, sizeof(siConEvnt->tranNetSel)); +#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL || SS7_CHINA) + if (siConEvnt->callRefA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callRefA, 0, sizeof(siConEvnt->callRefA)); +#endif + if (siConEvnt->callRef.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callRef, 0, sizeof(siConEvnt->callRef)); + if (siConEvnt->cgPtyNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyNum, 0, sizeof(siConEvnt->cgPtyNum)); +#if SS7_BELL + if (siConEvnt->cgPtyNumB.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyNumB, 0, sizeof(siConEvnt->cgPtyNumB)); +#endif + if (siConEvnt->opFwdCalInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->opFwdCalInd, 0, sizeof(siConEvnt->opFwdCalInd)); +#if (SS7_Q767 || SS7_RUSSIA || SS7_NTT) + if (siConEvnt->opFwdCalIndQ.eh.pres != PRSNT_NODEF) memset(&siConEvnt->opFwdCalIndQ, 0, sizeof(siConEvnt->opFwdCalIndQ)); +#endif +#if SS7_Q767IT + if (siConEvnt->fwdVad.eh.pres != PRSNT_NODEF) memset(&siConEvnt->fwdVad, 0, sizeof(siConEvnt->fwdVad)); +#endif +#if SS7_ANS88 + if (siConEvnt->opFwdCalIndA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->opFwdCalIndA, 0, sizeof(siConEvnt->opFwdCalIndA)); +#endif + if (siConEvnt->redirgNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirgNum, 0, sizeof(siConEvnt->redirgNum)); + if (siConEvnt->redirInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirInfo, 0, sizeof(siConEvnt->redirInfo)); + if (siConEvnt->cugIntCode.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cugIntCode, 0, sizeof(siConEvnt->cugIntCode)); +#if SS7_ANS88 + if (siConEvnt->cugIntCodeA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cugIntCodeA, 0, sizeof(siConEvnt->cugIntCodeA)); +#endif +#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL || SS7_CHINA) + if (siConEvnt->connReqA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->connReqA, 0, sizeof(siConEvnt->connReqA)); +#endif +#if SS7_ANS88 + if (siConEvnt->usr2UsrInfoA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usr2UsrInfoA, 0, sizeof(siConEvnt->usr2UsrInfoA)); +#endif + if (siConEvnt->connReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->connReq, 0, sizeof(siConEvnt->connReq)); + if (siConEvnt->origCdNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->origCdNum, 0, sizeof(siConEvnt->origCdNum)); + if (siConEvnt->usr2UsrInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usr2UsrInfo, 0, sizeof(siConEvnt->usr2UsrInfo)); + if (siConEvnt->accTrnspt.eh.pres != PRSNT_NODEF) memset(&siConEvnt->accTrnspt, 0, sizeof(siConEvnt->accTrnspt)); + if (siConEvnt->echoControl.eh.pres != PRSNT_NODEF) memset(&siConEvnt->echoControl, 0, sizeof(siConEvnt->echoControl)); +#if SS7_ANS88 + if (siConEvnt->redirInfoA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirInfoA, 0, sizeof(siConEvnt->redirInfoA)); +#endif +#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL) + if (siConEvnt->chargeNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->chargeNum, 0, sizeof(siConEvnt->chargeNum)); + if (siConEvnt->origLineInf.eh.pres != PRSNT_NODEF) memset(&siConEvnt->origLineInf, 0, sizeof(siConEvnt->origLineInf)); +#endif + if (siConEvnt->usrServInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usrServInfo, 0, sizeof(siConEvnt->usrServInfo)); + if (siConEvnt->usr2UsrInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usr2UsrInd, 0, sizeof(siConEvnt->usr2UsrInd)); + if (siConEvnt->propDly.eh.pres != PRSNT_NODEF) memset(&siConEvnt->propDly, 0, sizeof(siConEvnt->propDly)); + if (siConEvnt->usrServInfo1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usrServInfo1, 0, sizeof(siConEvnt->usrServInfo1)); + if (siConEvnt->netFac.eh.pres != PRSNT_NODEF) memset(&siConEvnt->netFac, 0, sizeof(siConEvnt->netFac)); +#ifdef SS7_CHINA + if (siConEvnt->orgPteCdeA.eh.pres != PRSNT_NODEF) memset(&siConEvnt->orgPteCdeA, 0, sizeof(siConEvnt->orgPteCdeA)); +#endif + if (siConEvnt->orgPteCde.eh.pres != PRSNT_NODEF) memset(&siConEvnt->orgPteCde, 0, sizeof(siConEvnt->orgPteCde)); + if (siConEvnt->genDigits.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genDigits, 0, sizeof(siConEvnt->genDigits)); + if (siConEvnt->genDigitsR.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genDigitsR, 0, sizeof(siConEvnt->genDigitsR)); + if (siConEvnt->usrTSrvInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->usrTSrvInfo, 0, sizeof(siConEvnt->usrTSrvInfo)); + if (siConEvnt->remotOper.eh.pres != PRSNT_NODEF) memset(&siConEvnt->remotOper, 0, sizeof(siConEvnt->remotOper)); + if (siConEvnt->parmCom.eh.pres != PRSNT_NODEF) memset(&siConEvnt->parmCom, 0, sizeof(siConEvnt->parmCom)); +#if (SS7_ANS92 || SS7_ANS95) + if (siConEvnt->servCode.eh.pres != PRSNT_NODEF) memset(&siConEvnt->servCode, 0, sizeof(siConEvnt->servCode)); +#endif +#if SS7_ANS92 + if (siConEvnt->serviceAct1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->serviceAct1, 0, sizeof(siConEvnt->serviceAct1)); +#endif +#if SS7_CHINA + if (siConEvnt->serviceAct2.eh.pres != PRSNT_NODEF) memset(&siConEvnt->serviceAct2, 0, sizeof(siConEvnt->serviceAct2)); +#endif + if (siConEvnt->serviceAct2.eh.pres != PRSNT_NODEF) memset(&siConEvnt->serviceAct2, 0, sizeof(siConEvnt->serviceAct2)); + if (siConEvnt->serviceAct.eh.pres != PRSNT_NODEF) memset(&siConEvnt->serviceAct, 0, sizeof(siConEvnt->serviceAct)); + if (siConEvnt->mlppPrec.eh.pres != PRSNT_NODEF) memset(&siConEvnt->mlppPrec, 0, sizeof(siConEvnt->mlppPrec)); +#if (defined(SIT_PARAMETER) || defined(TDS_ROLL_UPGRADE_SUPPORT)) + if (siConEvnt->txMedUsPr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->txMedUsPr, 0, sizeof(siConEvnt->txMedUsPr)); +#endif + if (siConEvnt->bckCallInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->bckCallInd, 0, sizeof(siConEvnt->bckCallInd)); + if (siConEvnt->cgPtyNum1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyNum1, 0, sizeof(siConEvnt->cgPtyNum1)); + if (siConEvnt->optBckCalInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->optBckCalInd, 0, sizeof(siConEvnt->optBckCalInd)); +#if (SS7_Q767 || SS7_RUSSIA || SS7_NTT) + if (siConEvnt->optBckCalIndQ.eh.pres != PRSNT_NODEF) memset(&siConEvnt->optBckCalIndQ, 0, sizeof(siConEvnt->optBckCalIndQ)); +#endif + if (siConEvnt->connNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->connNum, 0, sizeof(siConEvnt->connNum)); +#if (defined(SIT_PARAMETER) || defined(TDS_ROLL_UPGRADE_SUPPORT)) + if (siConEvnt->connNum2.eh.pres != PRSNT_NODEF) memset(&siConEvnt->connNum2, 0, sizeof(siConEvnt->connNum2)); +#endif + if (siConEvnt->accDelInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->accDelInfo, 0, sizeof(siConEvnt->accDelInfo)); + if (siConEvnt->notifInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->notifInd, 0, sizeof(siConEvnt->notifInd)); + if (siConEvnt->notifIndR2.eh.pres != PRSNT_NODEF) memset(&siConEvnt->notifIndR2, 0, sizeof(siConEvnt->notifIndR2)); + if (siConEvnt->cllHstry.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cllHstry, 0, sizeof(siConEvnt->cllHstry)); + if (siConEvnt->genNmb.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genNmb, 0, sizeof(siConEvnt->genNmb)); + if (siConEvnt->genNmbR.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genNmbR, 0, sizeof(siConEvnt->genNmbR)); + if (siConEvnt->redirNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirNum, 0, sizeof(siConEvnt->redirNum)); + if (siConEvnt->redirRstr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirRstr, 0, sizeof(siConEvnt->redirRstr)); + +#if SS7_Q767IT + if (siConEvnt->backVad.eh.pres != PRSNT_NODEF) memset(&siConEvnt->backVad, 0, sizeof(siConEvnt->backVad)); +#endif +#if SS7_SINGTEL + if (siConEvnt->cgPtyNumS.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cgPtyNumS, 0, sizeof(siConEvnt->cgPtyNumS)); +#endif +#if (SS7_ANS92 || SS7_ANS95 || SS7_BELL) + if (siConEvnt->businessGrp.eh.pres != PRSNT_NODEF) memset(&siConEvnt->businessGrp, 0, sizeof(siConEvnt->businessGrp)); + if (siConEvnt->infoInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->infoInd, 0, sizeof(siConEvnt->infoInd)); + if (siConEvnt->carrierId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->carrierId, 0, sizeof(siConEvnt->carrierId)); + if (siConEvnt->carSelInf.eh.pres != PRSNT_NODEF) memset(&siConEvnt->carSelInf, 0, sizeof(siConEvnt->carSelInf)); + if (siConEvnt->egress.eh.pres != PRSNT_NODEF) memset(&siConEvnt->egress, 0, sizeof(siConEvnt->egress)); + if (siConEvnt->genAddr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genAddr, 0, sizeof(siConEvnt->genAddr)); + if (siConEvnt->genAddrR.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genAddrR, 0, sizeof(siConEvnt->genAddrR)); + if (siConEvnt->infoReqInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->infoReqInd, 0, sizeof(siConEvnt->infoReqInd)); + if (siConEvnt->jurisInf.eh.pres != PRSNT_NODEF) memset(&siConEvnt->jurisInf, 0, sizeof(siConEvnt->jurisInf)); + if (siConEvnt->netTransport.eh.pres != PRSNT_NODEF) memset(&siConEvnt->netTransport, 0, sizeof(siConEvnt->netTransport)); + if (siConEvnt->specProcReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->specProcReq, 0, sizeof(siConEvnt->specProcReq)); + if (siConEvnt->transReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->transReq, 0, sizeof(siConEvnt->transReq)); +#endif +#if (defined(SIT_PARAMETER) || defined(TDS_ROLL_UPGRADE_SUPPORT)) +#if (SS7_ANS92 || SS7_ANS95) + if (siConEvnt->notifInd1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->notifInd1, 0, sizeof(siConEvnt->notifInd1)); + if (siConEvnt->notifIndR1.eh.pres != PRSNT_NODEF) memset(&siConEvnt->notifIndR1, 0, sizeof(siConEvnt->notifIndR1)); +#endif /* SS7_ANS92 */ +#endif /* SIT_PARAMETER || TDS_ROLL_UPGRADE_SUPPORT */ +#if (SS7_BELL || SS7_ANS95) + if (siConEvnt->genName.eh.pres != PRSNT_NODEF) memset(&siConEvnt->genName, 0, sizeof(siConEvnt->genName)); +#endif +#if (SS7_ITU97 || SS7_RUSS2000 || SS7_ITU2000 || SS7_ETSIV3 || \ + SS7_BELL || SS7_ANS95 || SS7_INDIA || SS7_UK || SS7_NZL || SS7_KZ) + if (siConEvnt->hopCounter.eh.pres != PRSNT_NODEF) memset(&siConEvnt->hopCounter, 0, sizeof(siConEvnt->hopCounter)); +#endif +#if (SS7_BELL || SS7_ITU2000 || SS7_KZ) + if (siConEvnt->redirCap.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirCap, 0, sizeof(siConEvnt->redirCap)); + if (siConEvnt->redirCntr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->redirCntr, 0, sizeof(siConEvnt->redirCntr)); +#endif +#if (SS7_ETSI || SS7_FTZ) + if (siConEvnt->ccbsParam.eh.pres != PRSNT_NODEF) memset(&siConEvnt->ccbsParam, 0, sizeof(siConEvnt->ccbsParam)); + if (siConEvnt->freePhParam.eh.pres != PRSNT_NODEF) memset(&siConEvnt->freePhParam, 0, sizeof(siConEvnt->freePhParam)); +#endif +#ifdef SS7_FTZ + if (siConEvnt->naPaFF.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaFF, 0, sizeof(siConEvnt->naPaFF)); + if (siConEvnt->naPaFE.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaFE, 0, sizeof(siConEvnt->naPaFE)); + if (siConEvnt->naPaSSP.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaSSP, 0, sizeof(siConEvnt->naPaSSP)); + if (siConEvnt->naPaCdPNO.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaCdPNO, 0, sizeof(siConEvnt->naPaCdPNO)); + if (siConEvnt->naPaSPV.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaSPV, 0, sizeof(siConEvnt->naPaSPV)); + if (siConEvnt->naPaUKK.eh.pres != PRSNT_NODEF) memset(&siConEvnt->naPaUKK, 0, sizeof(siConEvnt->naPaUKK)); +#endif +#if SS7_NTT + if (siConEvnt->msgAreaInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->msgAreaInfo, 0, sizeof(siConEvnt->msgAreaInfo)); + if (siConEvnt->subsNumber.eh.pres != PRSNT_NODEF) memset(&siConEvnt->subsNumber, 0, sizeof(siConEvnt->subsNumber)); + if (siConEvnt->rpCllngNo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->rpCllngNo, 0, sizeof(siConEvnt->rpCllngNo)); + if (siConEvnt->supplUserType.eh.pres != PRSNT_NODEF) memset(&siConEvnt->supplUserType, 0, sizeof(siConEvnt->supplUserType)); + if (siConEvnt->carrierInfoTrans.eh.pres != PRSNT_NODEF) memset(&siConEvnt->carrierInfoTrans, 0, sizeof(siConEvnt->carrierInfoTrans)); + if (siConEvnt->nwFuncType.eh.pres != PRSNT_NODEF) memset(&siConEvnt->nwFuncType, 0, sizeof(siConEvnt->nwFuncType)); +#endif +#if SS7_ANS95 + if (siConEvnt->optrServicesInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->optrServicesInfo, 0, sizeof(siConEvnt->optrServicesInfo)); +#endif +#if (SS7_ANS95 || SS7_ITU97 || SS7_RUSS2000|| SS7_ITU2000 || SS7_NZL || SS7_KZ) + if (siConEvnt->cirAsgnMap.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cirAsgnMap, 0, sizeof(siConEvnt->cirAsgnMap)); +#endif +#if (SS7_ITU97 || SS7_RUSS2000 || SS7_ITU2000 || SS7_ETSIV3 || \ + SS7_INDIA || SS7_UK || SS7_NZL || SS7_KZ) + if (siConEvnt->displayInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->displayInfo, 0, sizeof(siConEvnt->displayInfo)); + if (siConEvnt->confTrtInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->confTrtInd, 0, sizeof(siConEvnt->confTrtInd)); + if (siConEvnt->netMgmtControls.eh.pres != PRSNT_NODEF) memset(&siConEvnt->netMgmtControls, 0, sizeof(siConEvnt->netMgmtControls)); + if (siConEvnt->correlationId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->correlationId, 0, sizeof(siConEvnt->correlationId)); + if (siConEvnt->callDivTrtInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callDivTrtInd, 0, sizeof(siConEvnt->callDivTrtInd)); + if (siConEvnt->callInNmb.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callInNmb, 0, sizeof(siConEvnt->callInNmb)); + if (siConEvnt->callOfferTrtInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->callOfferTrtInd, 0, sizeof(siConEvnt->callOfferTrtInd)); + if (siConEvnt->scfId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->scfId, 0, sizeof(siConEvnt->scfId)); + if (siConEvnt->uidCapInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->uidCapInd, 0, sizeof(siConEvnt->uidCapInd)); + if (siConEvnt->collCallReq.eh.pres != PRSNT_NODEF) memset(&siConEvnt->collCallReq, 0, sizeof(siConEvnt->collCallReq)); + if (siConEvnt->ccss.eh.pres != PRSNT_NODEF) memset(&siConEvnt->ccss, 0, sizeof(siConEvnt->ccss)); +#endif +#if (SS7_ITU97 || SS7_RUSS2000 || SS7_ITU2000 || SS7_UK || SS7_NZL || SS7_KZ) + if (siConEvnt->backGVNS.eh.pres != PRSNT_NODEF) memset(&siConEvnt->backGVNS, 0, sizeof(siConEvnt->backGVNS)); + if (siConEvnt->forwardGVNS.eh.pres != PRSNT_NODEF) memset(&siConEvnt->forwardGVNS, 0, sizeof(siConEvnt->forwardGVNS)); +#endif +#if (SS7_ETSIV3 || SS7_ITU97 || SS7_RUSS2000 || SS7_ITU2000 || \ + SS7_INDIA || SS7_UK || SS7_NZL || SS7_KZ) + if (siConEvnt->appTransParam.eh.pres != PRSNT_NODEF) memset(&siConEvnt->appTransParam, 0, sizeof(siConEvnt->appTransParam)); +#endif +#if (SS7_ITU2000 || SS7_UK || SS7_NZL || SS7_KZ) + if (siConEvnt->htrInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->htrInfo, 0, sizeof(siConEvnt->htrInfo)); + if (siConEvnt->pivotCap.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pivotCap, 0, sizeof(siConEvnt->pivotCap)); + if (siConEvnt->cadDirNmb.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cadDirNmb, 0, sizeof(siConEvnt->cadDirNmb)); + if (siConEvnt->origCallInNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->origCallInNum, 0, sizeof(siConEvnt->origCallInNum)); + if (siConEvnt->calgGeoLoc.eh.pres != PRSNT_NODEF) memset(&siConEvnt->calgGeoLoc, 0, sizeof(siConEvnt->calgGeoLoc)); + if (siConEvnt->netRoutNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->netRoutNum, 0, sizeof(siConEvnt->netRoutNum)); + if (siConEvnt->qonRelCap.eh.pres != PRSNT_NODEF) memset(&siConEvnt->qonRelCap, 0, sizeof(siConEvnt->qonRelCap)); + if (siConEvnt->pivotCntr.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pivotCntr, 0, sizeof(siConEvnt->pivotCntr)); + if (siConEvnt->pivotRtgFwInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pivotRtgFwInfo, 0, sizeof(siConEvnt->pivotRtgFwInfo)); + if (siConEvnt->pivotRtgBkInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pivotRtgBkInfo, 0, sizeof(siConEvnt->pivotRtgBkInfo)); + if (siConEvnt->numPortFwdInfo.eh.pres != PRSNT_NODEF) memset(&siConEvnt->numPortFwdInfo, 0, sizeof(siConEvnt->numPortFwdInfo)); +#endif +#ifdef SS7_UK + if (siConEvnt->natFwdCalInd.eh.pres != PRSNT_NODEF) memset(&siConEvnt->natFwdCalInd, 0, sizeof(siConEvnt->natFwdCalInd)); + if (siConEvnt->presntNum.eh.pres != PRSNT_NODEF) memset(&siConEvnt->presntNum, 0, sizeof(siConEvnt->presntNum)); + if (siConEvnt->lstDvrtLineId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->lstDvrtLineId, 0, sizeof(siConEvnt->lstDvrtLineId)); + if (siConEvnt->pcgLineId.eh.pres != PRSNT_NODEF) memset(&siConEvnt->pcgLineId, 0, sizeof(siConEvnt->pcgLineId)); + if (siConEvnt->natFwdCalIndLnk.eh.pres != PRSNT_NODEF) memset(&siConEvnt->natFwdCalIndLnk, 0, sizeof(siConEvnt->natFwdCalIndLnk)); + if (siConEvnt->cdBascSrvcMrk.eh.pres != PRSNT_NODEF) memset(&siConEvnt->cdBascSrvcMrk, 0, sizeof(siConEvnt->cdBascSrvcMrk)); +#endif /* SS7_UK */ +#if (defined(CGPN_CHK)) + if (siConEvnt->causeDgnCgPnChk.eh.pres != PRSNT_NODEF) memset(&siConEvnt->causeDgnCgPnChk, 0, sizeof(siConEvnt->causeDgnCgPnChk)); +#endif + return FTDM_SUCCESS; +} + +ftdm_status_t sngss7_save_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt) +{ +#ifndef HAVE_ZLIB + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Cannot perform transparent IAM because zlib is missing\n"); + return FTDM_FAIL; +#else + unsigned ret_val = FTDM_FAIL; + char *compressed_iam = NULL; + char *url_encoded_iam = NULL; + uLongf len = sizeof(*siConEvnt); + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; + + /* By default, Trillium does not memset their whole structure to zero for + * performance. But we want to memset all the IE's that are not present to + * optimize compressed size */ + sngss7_bufferzero_iam(siConEvnt); + + compressed_iam = ftdm_malloc(sizeof(*siConEvnt)); + if (!compressed_iam) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to allocate buffer for compressed_iam\n"); + goto done; + } + + /* Compress IAM structure to minimize buffer size */ + ret_val = compress((Bytef *)compressed_iam, &len, (const Bytef *)siConEvnt, (uLong)sizeof(*siConEvnt)); + if (ret_val != Z_OK) { + ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Failed to compress IAM (error:%d)\n", ret_val); + ret_val = FTDM_FAIL; + goto done; + } + + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Compressed IAM size:%d\n", len); + + /* Worst case: size will triple after url encode */ + url_encoded_iam = ftdm_malloc(3*sizeof(*siConEvnt)); + if (!url_encoded_iam) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to allocated buffer for url_encoded_iam\n"); + ret_val = FTDM_FAIL; + goto done; + } + memset(url_encoded_iam, 0, 2*sizeof(*siConEvnt)); + + /* URL encode buffer to that its safe to store it in a string */ + ftdm_url_encode((const char*)compressed_iam, url_encoded_iam, len); + + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "IAM variable length:%d\n", strlen(url_encoded_iam)); + + if (strlen(url_encoded_iam) > g_ftdm_sngss7_data.cfg.transparent_iam_max_size) { + ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "IAM variable length exceeds max size (len:%d max:%d) \n", strlen(url_encoded_iam), g_ftdm_sngss7_data.cfg.transparent_iam_max_size); + ret_val = FTDM_FAIL; + goto done; + } + + sngss7_add_var(sngss7_info, "ss7_iam", url_encoded_iam); +done: + ftdm_safe_free(compressed_iam); + ftdm_safe_free(url_encoded_iam); + return ret_val; +#endif +} + +ftdm_status_t sngss7_retrieve_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt) +{ +#ifndef HAVE_ZLIB + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Cannot perform transparent IAM because zlib is missing\n"); + return FTDM_FAIL; +#else + uLongf len = 3*sizeof(*siConEvnt); /* worst case: URL encoded buffer is 3x length of buffer */ + char *val = NULL; + unsigned ret_val = FTDM_FAIL; + void *uncompressed_buffer = NULL; + char *url_encoded_iam = NULL; + ftdm_size_t url_encoded_iam_len; + + val = (char*)ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_iam"); + if (ftdm_strlen_zero(val)) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No Transparent IAM info available\n"); + return FTDM_FAIL; + } + + url_encoded_iam = ftdm_strdup(val); + + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "IAM variable length:%d\n", strlen(val)); + ftdm_url_decode(url_encoded_iam, &url_encoded_iam_len); + + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Compressed IAM size:%d\n", url_encoded_iam_len); + + uncompressed_buffer = ftdm_malloc(sizeof(*siConEvnt)); + ftdm_assert_return(uncompressed_buffer, FTDM_FAIL, "Failed to allocate buffer for uncompressed buffer\n"); + + ret_val = uncompress(uncompressed_buffer, &len, (const Bytef *)url_encoded_iam, (uLong)url_encoded_iam_len); + if (ret_val != Z_OK) { + ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Failed to uncompress IAM (error:%d)\n", ret_val); + goto done; + } + + if (len != sizeof(*siConEvnt)) { + ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Incompatible IAM structure size (expected:%d size:%d)\n", sizeof(*siConEvnt), strlen(uncompressed_buffer)); + goto done; + } + + memcpy(siConEvnt, uncompressed_buffer, sizeof(*siConEvnt)); + ret_val = FTDM_SUCCESS; + +done: + ftdm_safe_free(uncompressed_buffer); + ftdm_safe_free(url_encoded_iam); + return ret_val; +#endif +} + /******************************************************************************/ /* For Emacs: * Local Variables: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c index 2df0a88edb..a891c50108 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c @@ -124,7 +124,8 @@ typedef struct sng_ccSpan uint32_t cld_nadi; uint32_t rdnis_nadi; uint32_t min_digits; - uint32_t itx_auto_reply; + uint8_t itx_auto_reply; + uint8_t transparent_iam; uint32_t t3; uint32_t t12; uint32_t t13; @@ -466,6 +467,9 @@ static int ftmod_ss7_parse_sng_gen(ftdm_conf_node_t *sng_gen) SS7_DEBUG("Found license file = %s\n", g_ftdm_sngss7_data.cfg.license); SS7_DEBUG("Found signature file = %s\n", g_ftdm_sngss7_data.cfg.signature); /**********************************************************************/ + } else if (!strcasecmp(parm->var, "transparent_iam_max_size")) { + g_ftdm_sngss7_data.cfg.transparent_iam_max_size = atoi(parm->val); + SS7_DEBUG("Found a transparent_iam max size = %d\n", g_ftdm_sngss7_data.cfg.transparent_iam_max_size); } else { /**********************************************************************/ SS7_ERROR("Found an invalid parameter \"%s\"!\n", parm->val); @@ -1896,6 +1900,13 @@ static int ftmod_ss7_parse_cc_span(ftdm_conf_node_t *cc_span) } else if (!strcasecmp(parm->var, "itx_auto_reply")) { sng_ccSpan.itx_auto_reply = ftdm_true(parm->val); SS7_DEBUG("Found itx_auto_reply %d\n", sng_ccSpan.itx_auto_reply); + } else if (!strcasecmp(parm->var, "transparent_iam")) { +#ifndef HAVE_ZLIB + SS7_CRIT("Cannot enable transparent IAM becauze zlib not installed\n"); +#else + sng_ccSpan.transparent_iam = ftdm_true(parm->val); + SS7_DEBUG("Found transparent_iam %d\n", sng_ccSpan.transparent_iam); +#endif } else if (!strcasecmp(parm->var, "cicbase")) { /**********************************************************************/ sng_ccSpan.cicbase = atoi(parm->val); @@ -2907,16 +2918,17 @@ static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan) g_ftdm_sngss7_data.cfg.isupCkt[x].cic = 0; } - g_ftdm_sngss7_data.cfg.isupCkt[x].infId = ccSpan->isupInf; - g_ftdm_sngss7_data.cfg.isupCkt[x].typeCntrl = ccSpan->typeCntrl; - g_ftdm_sngss7_data.cfg.isupCkt[x].ssf = ccSpan->ssf; - g_ftdm_sngss7_data.cfg.isupCkt[x].cld_nadi = ccSpan->cld_nadi; - g_ftdm_sngss7_data.cfg.isupCkt[x].clg_nadi = ccSpan->clg_nadi; - g_ftdm_sngss7_data.cfg.isupCkt[x].rdnis_nadi = ccSpan->rdnis_nadi; - g_ftdm_sngss7_data.cfg.isupCkt[x].options = ccSpan->options; - g_ftdm_sngss7_data.cfg.isupCkt[x].switchType = ccSpan->switchType; - g_ftdm_sngss7_data.cfg.isupCkt[x].min_digits = ccSpan->min_digits; - g_ftdm_sngss7_data.cfg.isupCkt[x].itx_auto_reply = ccSpan->itx_auto_reply; + g_ftdm_sngss7_data.cfg.isupCkt[x].infId = ccSpan->isupInf; + g_ftdm_sngss7_data.cfg.isupCkt[x].typeCntrl = ccSpan->typeCntrl; + g_ftdm_sngss7_data.cfg.isupCkt[x].ssf = ccSpan->ssf; + g_ftdm_sngss7_data.cfg.isupCkt[x].cld_nadi = ccSpan->cld_nadi; + g_ftdm_sngss7_data.cfg.isupCkt[x].clg_nadi = ccSpan->clg_nadi; + g_ftdm_sngss7_data.cfg.isupCkt[x].rdnis_nadi = ccSpan->rdnis_nadi; + g_ftdm_sngss7_data.cfg.isupCkt[x].options = ccSpan->options; + g_ftdm_sngss7_data.cfg.isupCkt[x].switchType = ccSpan->switchType; + g_ftdm_sngss7_data.cfg.isupCkt[x].min_digits = ccSpan->min_digits; + g_ftdm_sngss7_data.cfg.isupCkt[x].itx_auto_reply = ccSpan->itx_auto_reply; + g_ftdm_sngss7_data.cfg.isupCkt[x].transparent_iam = ccSpan->transparent_iam; if (ccSpan->t3 == 0) { g_ftdm_sngss7_data.cfg.isupCkt[x].t3 = 1200; diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 6b14d14524..1d27b946e3 100755 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -276,12 +276,16 @@ FTDM_STR2ENUM_P(ftdm_str2ftdm_screening, ftdm_screening2str, ftdm_screening_t) /*! \brief bearer capability */ typedef enum { - FTDM_BEARER_CAP_SPEECH = 0x00, - FTDM_BEARER_CAP_64K_UNRESTRICTED = 0x02, - FTDM_BEARER_CAP_3_1KHZ_AUDIO = 0x03, + FTDM_BEARER_CAP_SPEECH = 0x00, /* Speech */ + FTDM_BEARER_CAP_UNRESTRICTED, /* Unrestricted Digital */ + FTDM_BEARER_CAP_RESTRICTED, /* Restricted Digital */ + FTDM_BEARER_CAP_3_1KHZ_AUDIO, /* 3.1 Khz Audio */ + FTDM_BEARER_CAP_7KHZ_AUDIO, /* 7 Khz Audio or Unrestricted digital w tones */ + FTDM_BEARER_CAP_15KHZ_AUDIO, /* 15 Khz Audio */ + FTDM_BEARER_CAP_VIDEO, /* Video */ FTDM_BEARER_CAP_INVALID } ftdm_bearer_cap_t; -#define BEARER_CAP_STRINGS "speech", "unrestricted-digital-information", "3.1-Khz-audio", "invalid" +#define BEARER_CAP_STRINGS "speech", "unrestricted-digital-information", "restricted-digital-information", "3.1-Khz-audio", "7-Khz-audio", "15-Khz-audio", "video", "invalid" FTDM_STR2ENUM_P(ftdm_str2ftdm_bearer_cap, ftdm_bearer_cap2str, ftdm_bearer_cap_t) /*! \brief user information layer 1 protocol */ diff --git a/libs/freetdm/src/include/ftdm_call_utils.h b/libs/freetdm/src/include/ftdm_call_utils.h index 2418273343..975e73e729 100644 --- a/libs/freetdm/src/include/ftdm_call_utils.h +++ b/libs/freetdm/src/include/ftdm_call_utils.h @@ -131,5 +131,24 @@ FT_DECLARE(ftdm_status_t) ftdm_is_number(const char *number); */ FT_DECLARE(ftdm_status_t) ftdm_set_calling_party_category(const char *string, uint8_t *target); +/*! + * \brief URL encode a buffer + * + * \param url buffer to convert + * \param buf target to save converted string to + * \param len size of buffer + * + * \retval pointer to converted string + */ +FT_DECLARE(char *) ftdm_url_encode(const char *url, char *buf, ftdm_size_t len); + +/*! + * \param s buffer to convert + * \param len size of buffer + * + * \retval pointer to converted string + */ +FT_DECLARE(char *) ftdm_url_decode(char *s, ftdm_size_t *len); + #endif /* __FTDM_CALL_UTILS_H__ */