Merge branch 'master' into smgmaster

This commit is contained in:
Konrad Hammel 2010-10-18 15:08:03 -04:00
commit 1064818d9b
9 changed files with 466 additions and 23 deletions

View File

@ -265,10 +265,12 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
}
while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) {
/* find out why we returned from the interrupt queue */
ret_status = ftdm_interrupt_multiple_wait(ftdm_sangoma_isdn_int, 2, sleep);
/* Check if there are any timers to process */
ftdm_sched_run(signal_data->sched);
ret_status = ftdm_interrupt_multiple_wait(ftdm_sangoma_isdn_int, 2, sleep);
/* find out why we returned from the interrupt queue */
switch (ret_status) {
case FTDM_SUCCESS: /* there was a state change on the span */
/* process all pending state changes */
@ -289,13 +291,30 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
/* twiddle */
break;
case FTDM_FAIL:
ftdm_log(FTDM_LOG_ERROR,"ftdm_interrupt_wait returned error!\non span = %s\n", span->name);
ftdm_log(FTDM_LOG_ERROR,"%s:ftdm_interrupt_wait returned error!\n", span->name);
break;
default:
ftdm_log(FTDM_LOG_ERROR,"ftdm_interrupt_wait returned with unknown code on span = %s\n", span->name);
ftdm_log(FTDM_LOG_ERROR,"%s:ftdm_interrupt_wait returned with unknown code\n", span->name);
break;
}
/* Poll for events, e.g HW DTMF */
ret_status = ftdm_span_poll_event(span, 0);
switch(ret_status) {
case FTDM_SUCCESS:
{
ftdm_event_t *event;
while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS);
}
break;
case FTDM_TIMEOUT:
/* No events pending */
break;
default:
ftdm_log(FTDM_LOG_WARNING, "%s:Failed to poll span event\n", span->name);
}
if (ftdm_sched_get_time_to_next_timer(signal_data->sched, &sleep) == FTDM_SUCCESS) {
if (sleep < 0 || sleep > SNGISDN_EVENT_POLL_RATE) {
sleep = SNGISDN_EVENT_POLL_RATE;

View File

@ -188,11 +188,11 @@ ftdm_status_t cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPt
}
if (cdPtyNmb->nmbPlanId.pres == PRSNT_NODEF) {
ftdm->cid_num.plan = cdPtyNmb->nmbPlanId.val;
ftdm->dnis.plan = cdPtyNmb->nmbPlanId.val;
}
if (cdPtyNmb->typeNmb0.pres == PRSNT_NODEF) {
ftdm->cid_num.type = cdPtyNmb->typeNmb0.val;
ftdm->dnis.type = cdPtyNmb->typeNmb0.val;
}
if (cdPtyNmb->nmbDigits.pres == PRSNT_NODEF) {

View File

@ -616,8 +616,8 @@ static ftdm_status_t handle_print_usuage(ftdm_stream_handle_t *stream)
stream->write_function(stream, "Sangoma SS7 CLI usuage:\n\n");
stream->write_function(stream, "Ftmod_sangoma_ss7 general control:\n");
stream->write_function(stream, "ftdm ss7 set ftace X Y\n");
stream->write_function(stream, "ftdm ss7 set mtace X Y\n");
stream->write_function(stream, "ftdm ss7 set ftrace X Y\n");
stream->write_function(stream, "ftdm ss7 set mtrace X Y\n");
stream->write_function(stream, "\n");
stream->write_function(stream, "Ftmod_sangoma_ss7 information:\n");
stream->write_function(stream, "ftdm ss7 show status link X\n");
@ -1064,7 +1064,7 @@ static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span,
/* grab the signaling_status */
ftdm_channel_get_sig_status(ftdmchan, &sigstatus);
stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|sig_status=%s|state=%s|",
stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|sig_status=%4s|state=%s|",
ckt->span,
ckt->chan,
ckt->cic,
@ -1281,13 +1281,17 @@ static ftdm_status_t handle_status_link(ftdm_stream_handle_t *stream, char *name
(sta.t.ssta.s.snDLSAP.remBlkd) ? "Y":"N",
(sta.t.ssta.s.snDLSAP.locInhbt) ? "Y":"N",
(sta.t.ssta.s.snDLSAP.rmtInhbt) ? "Y":"N");
break;
goto success;
}
/* move to the next link */
x++;
} /* while (id != 0) */
stream->write_function(stream, "Failed to find link=\"%s\"\n", name);
success:
return FTDM_SUCCESS;
}
@ -1313,13 +1317,17 @@ static ftdm_status_t handle_status_linkset(ftdm_stream_handle_t *stream, char *n
name,
DECODE_LSN_LINKSET_STATUS(sta.t.ssta.s.snLnkSet.state),
sta.t.ssta.s.snLnkSet.nmbActLnks);
break;
goto success;
}
/* move to the next linkset */
x++;
} /* while (id != 0) */
stream->write_function(stream, "Failed to find link=\"%s\"\n", name);
success:
return FTDM_SUCCESS;
}
@ -1342,13 +1350,16 @@ static ftdm_status_t handle_set_inhibit(ftdm_stream_handle_t *stream, char *name
/* print the new status of the link */
handle_status_link(stream, &name[0]);
break;
goto success;
}
/* move to the next linkset */
x++;
} /* while (id != 0) */
stream->write_function(stream, "Failed to find link=\"%s\"\n", name);
success:
return FTDM_SUCCESS;
}
@ -1371,13 +1382,16 @@ static ftdm_status_t handle_set_uninhibit(ftdm_stream_handle_t *stream, char *na
/* print the new status of the link */
handle_status_link(stream, &name[0]);
break;
goto success;
}
/* move to the next linkset */
x++;
} /* while (id != 0) */
stream->write_function(stream, "Failed to find link=\"%s\"\n", name);
success:
return FTDM_SUCCESS;
}
@ -1440,6 +1454,10 @@ static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int c
/* go the next circuit */
x++;
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
/* print the status of channels */
handle_show_status(stream, span, chan, verbose);
return FTDM_SUCCESS;
@ -1505,6 +1523,24 @@ static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int c
x++;
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
x=1;
while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
ftdmchan = sngss7_info->ftdmchan;
sngss7_span = ftdmchan->span->mod_data;
if ((ftdmchan->physical_span_id == span) &&
((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) {
handle_show_status(stream, span, chan, verbose);
}
} /* if ( cic == voice) */
/* go the next circuit */
x++;
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
return FTDM_SUCCESS;
}
@ -1585,6 +1621,25 @@ static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int c
/* send the circuit group block */
ft_to_sngss7_cgb(main_chan);
x=1;
while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
ftdmchan = sngss7_info->ftdmchan;
sngss7_span = ftdmchan->span->mod_data;
if ((ftdmchan->physical_span_id == span) &&
((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) {
handle_show_status(stream, span, chan, verbose);
}
} /* if ( cic == voice) */
/* go the next circuit */
x++;
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
return FTDM_SUCCESS;
@ -1666,6 +1721,25 @@ static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int c
/* send the circuit group block */
ft_to_sngss7_cgu(main_chan);
x=1;
while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
ftdmchan = sngss7_info->ftdmchan;
sngss7_span = ftdmchan->span->mod_data;
if ((ftdmchan->physical_span_id == span) &&
((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) {
handle_show_status(stream, span, chan, verbose);
}
} /* if ( cic == voice) */
/* go the next circuit */
x++;
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
return FTDM_SUCCESS;

View File

@ -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) {
@ -1480,7 +1480,7 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init)
sngss7_id = 0;
cmbLinkSetId = 1;
cmbLinkSetId = 0;
/* initalize the global gen_config flag */
g_ftdm_sngss7_data.gen_config = 0;

View File

@ -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,15 @@ typedef enum {
SNGSS7_PAUSED = (1 << 7)
} sng_flag_t;
typedef enum {
SNGSS7_ACM_OBCI_BITA = (1 << 0) /* in-band indication */
} sng_intf_options_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;
@ -198,6 +209,7 @@ typedef struct sng_route {
typedef struct sng_isup_intf {
uint32_t id;
char name[MAX_NAME_LEN];
uint32_t options;
uint32_t flags;
uint32_t spc;
uint32_t dpc;
@ -579,6 +591,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);
@ -712,6 +726,11 @@ void handle_isup_t35(void *userdata);
#define sngss7_clear_flag(obj, flag) ((obj)->flags &= ~(flag))
#define sngss7_set_flag(obj, flag) ((obj)->flags |= (flag))
#define sngss7_test_options(obj, option) ((obj)->options & option)
#define sngss7_clear_options(obj, option) ((obj)->options &= ~(option))
#define sngss7_set_options(obj, option) ((obj)->options |= (option))
#ifdef SS7_PRODUCTION
# define SS7_ASSERT \
SS7_INFO_CHAN(ftdmchan,"Production Mode, continuing%s\n", "");

View File

@ -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,
@ -226,7 +308,8 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
sng_isup_inf_t *isup_intf = &g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId];
SiCnStEvnt acm;
memset (&acm, 0x0, sizeof (acm));
@ -255,7 +338,18 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
acm.bckCallInd.echoCtrlDevInd.val = 0x1; /* ec device present */
acm.bckCallInd.sccpMethInd.pres = PRSNT_NODEF;
acm.bckCallInd.sccpMethInd.val = SCCPMTH_NOIND;
/* fill in any optional parameters */
if (sngss7_test_options(isup_intf, SNGSS7_ACM_OBCI_BITA)) {
acm.optBckCalInd.eh.pres = PRSNT_NODEF;
acm.optBckCalInd.inbndInfoInd.pres = PRSNT_NODEF;
acm.optBckCalInd.inbndInfoInd.val = sngss7_test_options(isup_intf, SNGSS7_ACM_OBCI_BITA);
acm.optBckCalInd.caFwdMayOcc.pres = PRSNT_DEF;
acm.optBckCalInd.simpleSegmInd.pres = PRSNT_DEF;
acm.optBckCalInd.mlppUserInd.pres = PRSNT_DEF;
acm.optBckCalInd.usrNetIneractInd.pres = PRSNT_DEF;
} /* if (sngss7_test_options(isup_intf, SNGSS7_ACM_OBCI_BITA)) */
/* send the ACM request to LibSngSS7 */
sng_cc_con_status (1,
sngss7_info->suInstId,

View File

@ -50,27 +50,41 @@ int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm);
int ftmod_ss7_mtplink_sta(uint32_t id, SnMngmt *cfm)
{
SnMngmt sta;
Pst pst;
memset(&sta, 0x0, sizeof(sta));
/* initalize the post structure */
smPstInit(&pst);
/* insert the destination Entity */
pst.dstEnt = ENTSN;
sta.hdr.elmId.elmnt = STDLSAP;
sta.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLink[id].id;
return(sng_sta_mtp3(&sta, cfm));
return(sng_sta_mtp3(&pst, &sta, cfm));
}
/******************************************************************************/
int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm)
{
SnMngmt sta;
Pst pst;
memset(&sta, 0x0, sizeof(sta));
/* initalize the post structure */
smPstInit(&pst);
/* insert the destination Entity */
pst.dstEnt = ENTSN;
sta.hdr.elmId.elmnt = STLNKSET;
sta.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLinkSet[id].id;
sta.hdr.elmId.elmntInst2 = g_ftdm_sngss7_data.cfg.mtpLinkSet[id].links[0];
return(sng_sta_mtp3(&sta, cfm));
return(sng_sta_mtp3(&pst, &sta, cfm));
}
/******************************************************************************/

View File

@ -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:

View File

@ -1249,6 +1249,18 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
sng_isup.cld_nadi = atoi(parm->val);
SS7_DEBUG("\tFound default CLD_NADI value = %d\n", sng_isup.cld_nadi);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "obci_bita")) {
/**********************************************************************/
if (*parm->val == '1') {
sngss7_set_options(&sng_isup, SNGSS7_ACM_OBCI_BITA);
SS7_DEBUG("\tFound Optional Backwards Indicator: Bit A (early media) enable option\n");
} else if (*parm->val == '0') {
sngss7_clear_options(&sng_isup, SNGSS7_ACM_OBCI_BITA);
SS7_DEBUG("\tFound Optional Backwards Indicator: Bit A (early media) disable option\n");
} else {
SS7_DEBUG("\tInvalid value for \"obci_bita\" option\n");
}
/**********************************************************************/
} else {
SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val);
return FTDM_FAIL;
@ -1671,7 +1683,7 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup)
g_ftdm_sngss7_data.cfg.isupIntf[i].isap = sng_isup->isap;
g_ftdm_sngss7_data.cfg.isupIntf[i].cld_nadi = sng_isup->cld_nadi;
g_ftdm_sngss7_data.cfg.isupIntf[i].clg_nadi = sng_isup->clg_nadi;
g_ftdm_sngss7_data.cfg.isupIntf[i].options = sng_isup->options;
if (sng_isup->t4 != 0) {
g_ftdm_sngss7_data.cfg.isupIntf[i].t4 = sng_isup->t4;
} else {