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 30cb31691d..cff9711814 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 @@ -1332,7 +1332,7 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span) sngss7_clear_flag(sngss7_info, FLAG_INFID_PAUSED); sngss7_set_flag(sngss7_info, FLAG_INFID_RESUME); } -#if 1 +#if 0 /* throw the grp reset flag */ sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX); if (x == 1) { 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 a358236ed0..5de237dcbf 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 @@ -58,6 +58,8 @@ #define SNGSS7_EVENT_QUEUE_SIZE 100 +#define MAX_SIZEOF_SUBADDR_IE 24 /* as per Q931 4.5.9 */ + typedef enum { SNGSS7_CON_IND_EVENT = 0, SNGSS7_CON_CFM_EVENT, @@ -83,6 +85,11 @@ typedef enum { SNGSS7_PAUSED = (1 << 7) } sng_flag_t; +typedef enum { + SNG_CALLED = 1, + SNG_CALLING = 2 +} sng_addr_type_t; + typedef struct sng_mtp_link { char name[MAX_NAME_LEN]; uint32_t id; @@ -579,6 +586,8 @@ ftdm_status_t clear_rx_grs_data(sngss7_chan_data_t *sngss7_info); ftdm_status_t clear_rx_gra_data(sngss7_chan_data_t *sngss7_info); ftdm_status_t clear_tx_grs_data(sngss7_chan_data_t *sngss7_info); +ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type); +ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type); /* in ftmod_sangoma_ss7_timers.c */ void handle_isup_t35(void *userdata); 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 973fbf47c7..3571a9ef0a 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 @@ -76,6 +76,9 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;; const char *clg_nadi = NULL; const char *cld_nadi = NULL; + const char *clg_subAddr = NULL; + const char *cld_subAddr = NULL; + char subAddrIE[MAX_SIZEOF_SUBADDR_IE]; SiConEvnt iam; sngss7_info->suInstId = get_unique_id (); @@ -186,7 +189,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) /* check if the user would like a custom NADI value for the calling Pty Num */ clg_nadi = ftdm_channel_get_var(ftdmchan, "ss7_clg_nadi"); if ((clg_nadi != NULL) && (*clg_nadi)) { - SS7_DEBUG_CHAN(ftdmchan,"Found user supplied NADI value \"%s\"\n", clg_nadi); + SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling NADI value \"%s\"\n", clg_nadi); iam.cgPtyNum.natAddrInd.val = atoi(clg_nadi); } else { iam.cgPtyNum.natAddrInd.val = g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].clg_nadi; @@ -195,14 +198,93 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) cld_nadi = ftdm_channel_get_var(ftdmchan, "ss7_cld_nadi"); if ((cld_nadi != NULL) && (*cld_nadi)) { - SS7_DEBUG_CHAN(ftdmchan,"Found user supplied NADI value \"%s\"\n", cld_nadi); + SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called NADI value \"%s\"\n", cld_nadi); iam.cdPtyNum.natAddrInd.val = atoi(cld_nadi); } else { iam.cdPtyNum.natAddrInd.val = g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].cld_nadi; SS7_DEBUG_CHAN(ftdmchan,"No user supplied NADI value found for CLD, using \"%d\"\n", iam.cdPtyNum.natAddrInd.val); - } + /* check if the user would like us to send a clg_sub-address */ + clg_subAddr = ftdm_channel_get_var(ftdmchan, "ss7_clg_subaddr"); + if ((clg_subAddr != NULL) && (*clg_subAddr)) { + SS7_DEBUG_CHAN(ftdmchan,"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: + SS7_ERROR_CHAN(ftdmchan,"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 (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') */ + } + + /* check if the user would like us to send a cld_sub-address */ + cld_subAddr = ftdm_channel_get_var(ftdmchan, "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, 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 41db1fe140..718663950a 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 @@ -71,6 +71,9 @@ ftdm_status_t clear_tx_rsc_flags(sngss7_chan_data_t *sngss7_info); ftdm_status_t clear_rx_grs_data(sngss7_chan_data_t *sngss7_info); ftdm_status_t clear_rx_gra_data(sngss7_chan_data_t *sngss7_info); ftdm_status_t clear_tx_grs_data(sngss7_chan_data_t *sngss7_info); + +ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type); +ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type); /******************************************************************************/ /* FUNCTIONS ******************************************************************/ @@ -884,6 +887,214 @@ ftdm_status_t clear_tx_rsc_flags(sngss7_chan_data_t *sngss7_info) } /******************************************************************************/ +ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type) +{ + /* Q931 4.5.9 + * 8 7 6 5 4 3 2 1 (octet) + * + * 0 1 1 1 0 0 0 1 (spare 8) ( IE id 1-7) + * X X X X X X X X (length of IE contents) + * 1 0 0 0 Z 0 0 0 (ext 8) (NSAP type 5-7) (odd/even 4) (spare 1-3) + * X X X X X X X X (sub address encoded in ia5) + */ + + int x = 0; + int p = 0; + int len = 0; + char tmp[2]; + + /* initalize the second element of tmp to \0 so that atoi doesn't go to far */ + tmp[1]='\0'; + + /* set octet 1 aka IE id */ + p = 0; + switch(type) { + /**************************************************************************/ + case SNG_CALLED: /* called party sub address */ + subAddrIE[p] = 0x71; + break; + /**************************************************************************/ + case SNG_CALLING: /* calling party sub address */ + subAddrIE[p] = 0x6d; + break; + /**************************************************************************/ + default: /* not good */ + SS7_ERROR("Sub-Address type is invalid: %d\n", type); + return FTDM_FAIL; + break; + /**************************************************************************/ + } /* switch(type) */ + + /* set octet 3 aka type and o/e */ + p = 2; + subAddrIE[p] = 0x80; + + /* set the subAddrIE pointer octet 4 */ + p = 3; + + /* loop through all digits in subAddr and insert them into subAddrIE */ + while (subAddr[x] != '\0') { + + /* grab a character */ + tmp[0] = subAddr[x]; + + /* confirm it is a digit */ + if (!isdigit(tmp[0])) { + /* move to the next character in subAddr */ + x++; + + /* restart the loop */ + continue; + } + + /* convert the character to IA5 encoding and write into subAddrIE */ + subAddrIE[p] = atoi(&tmp[0]); /* lower nibble is the digit */ + subAddrIE[p] |= 0x3 << 4; /* upper nibble is 0x3 */ + + /* increment address length counter */ + len++; + + /* increment the subAddrIE pointer */ + p++; + + /* move to the next character in subAddr */ + x++; + + } /* while (subAddr[x] != '\0') */ + + /* set octet 2 aka length of subaddr */ + p = 1; + subAddrIE[p] = len + 1; + + + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type) +{ + /* Q931 4.5.9 + * 8 7 6 5 4 3 2 1 (octet) + * + * 0 1 1 1 0 0 0 1 (spare 8) ( IE id 1-7) + * X X X X X X X X (length of IE contents) + * 1 0 0 0 Z 0 0 0 (ext 8) (NSAP type 5-7) (odd/even 4) (spare 1-3) + * X X X X X X X X (sub address encoded in ia5) + */ + + int x = 0; + int p = 0; + int len = 0; + char tmp[2]; + int flag = 0; + int odd = 0; + uint8_t lower = 0x0; + uint8_t upper = 0x0; + + /* initalize the second element of tmp to \0 so that atoi doesn't go to far */ + tmp[1]='\0'; + + /* set octet 1 aka IE id */ + p = 0; + switch(type) { + /**************************************************************************/ + case SNG_CALLED: /* called party sub address */ + subAddrIE[p] = 0x71; + break; + /**************************************************************************/ + case SNG_CALLING: /* calling party sub address */ + subAddrIE[p] = 0x6d; + break; + /**************************************************************************/ + default: /* not good */ + SS7_ERROR("Sub-Address type is invalid: %d\n", type); + return FTDM_FAIL; + break; + /**************************************************************************/ + } /* switch(type) */ + + /* set the subAddrIE pointer octet 4 */ + p = 3; + + /* loop through all digits in subAddr and insert them into subAddrIE */ + while (1) { + + /* grab a character */ + tmp[0] = subAddr[x]; + + /* confirm it is a hex digit */ + while ((!isxdigit(tmp[0])) && (tmp[0] != '\0')) { + /* move to the next character in subAddr */ + x++; + tmp[0] = subAddr[x]; + } + + /* check if tmp is null or a digit */ + if (tmp[0] != '\0') { + /* push it into the lower nibble using strtol to allow a-f chars */ + lower = strtol(&tmp[0], (char **)NULL, 16); + /* move to the next digit */ + x++; + /* grab a digit from the ftdm digits */ + tmp[0] = subAddr[x]; + + /* check if the digit is a hex digit and that is not null */ + while (!(isxdigit(tmp[0])) && (tmp[0] != '\0')) { + x++; + tmp[0] = subAddr[x]; + } /* while(!(isdigit(tmp))) */ + + /* check if tmp is null or a digit */ + if (tmp[0] != '\0') { + /* push the digit into the upper nibble using strtol to allow a-f chars */ + upper = (strtol(&tmp[0], (char **)NULL, 16)) << 4; + } else { + /* there is no upper ... fill in spare */ + upper = 0x00; + /* throw the odd flag since we need to buffer */ + odd = 1; + /* throw the end flag */ + flag = 1; + } /* if (tmp != '\0') */ + } else { + /* keep the odd flag down */ + odd = 0; + + /* throw the flag */ + flag = 1; + + /* bounce out right away */ + break; + } + + /* fill in the octet */ + subAddrIE[p] = upper | lower; + + /* increment address length counter */ + len++; + + /* if the flag is we're through all the digits */ + if (flag) break; + + /* increment the subAddrIE pointer */ + p++; + + /* move to the next character in subAddr */ + x++; + + } /* while (subAddr[x] != '\0') */ + + /* set octet 2 aka length of subaddr */ + p = 1; + subAddrIE[p] = len + 1; + + /* set octet 3 aka type and o/e */ + p = 2; + subAddrIE[p] = 0xa0 | (odd << 3); + + + return FTDM_SUCCESS; +} /******************************************************************************/ /* For Emacs: