summaryrefslogtreecommitdiff
path: root/channels/chan_dahdi.c
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2014-06-16 18:27:51 +0000
committerRichard Mudgett <rmudgett@digium.com>2014-06-16 18:27:51 +0000
commit0c896d8b9b12e0eaacbe1b9d17060c59e6093d1d (patch)
treee00c8b6f34087a4243773a17d53e6193a069a3d4 /channels/chan_dahdi.c
parentbd0aa4fb04afe0d91b5fac2fc697fafd644cc907 (diff)
chan_dahdi: Adds support for major update to libss7.
* SS7 support now requires libss7 v2.0 or later. The new libss7 is not backwards compatible. * Added SS7 support for connected line and redirecting. * Most SS7 CLI commands are reworked as well as new SS7 commands added. See online CLI help. * Added several SS7 config option parameters described in chan_dahdi.conf.sample. * ISUP timer support reworked and now requires explicit configuration. See ss7.timers.sample. Special thanks to Kaloyan Kovachev for his support and persistence in getting the original patch by adomjan updated and ready for release. SS7-27 #close Reported by: adomjan git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@416416 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels/chan_dahdi.c')
-rw-r--r--channels/chan_dahdi.c877
1 files changed, 747 insertions, 130 deletions
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 71e5831e0..adc025ae0 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -81,7 +81,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#if defined(HAVE_SS7)
#include "sig_ss7.h"
-#if defined(LIBSS7_ABI_COMPATIBILITY)
+#if !defined(LIBSS7_ABI_COMPATIBILITY)
+#error "Upgrade your libss7"
+#elif LIBSS7_ABI_COMPATIBILITY != 2
#error "Your installed libss7 is not compatible"
#endif
#endif /* defined(HAVE_SS7) */
@@ -611,6 +613,7 @@ struct dahdi_ss7 {
static struct dahdi_ss7 linksets[NUM_SPANS];
static int cur_ss7type = -1;
+static int cur_slc = -1;
static int cur_linkset = -1;
static int cur_pointcode = -1;
static int cur_cicbeginswith = -1;
@@ -758,8 +761,8 @@ const char * const subnames[] = {
MEMBER(dahdi_pvt, mwimonitoractive, AST_DATA_BOOLEAN) \
MEMBER(dahdi_pvt, mwisendactive, AST_DATA_BOOLEAN) \
MEMBER(dahdi_pvt, inservice, AST_DATA_BOOLEAN) \
- MEMBER(dahdi_pvt, locallyblocked, AST_DATA_BOOLEAN) \
- MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_BOOLEAN) \
+ MEMBER(dahdi_pvt, locallyblocked, AST_DATA_UNSIGNED_INTEGER) \
+ MEMBER(dahdi_pvt, remotelyblocked, AST_DATA_UNSIGNED_INTEGER) \
MEMBER(dahdi_pvt, manages_span_alarms, AST_DATA_BOOLEAN) \
MEMBER(dahdi_pvt, use_smdi, AST_DATA_BOOLEAN) \
MEMBER(dahdi_pvt, context, AST_DATA_STRING) \
@@ -873,7 +876,8 @@ static struct dahdi_chan_conf dahdi_chan_conf_default(void)
.internationalprefix = "",
.nationalprefix = "",
.subscriberprefix = "",
- .unknownprefix = ""
+ .unknownprefix = "",
+ .networkroutedprefix = ""
},
#endif /* defined(HAVE_SS7) */
#ifdef HAVE_OPENR2
@@ -3022,6 +3026,34 @@ static void my_ss7_set_loopback(void *pvt, int enable)
#if defined(HAVE_SS7)
/*!
* \internal
+ * \brief Find the linkset to which SS7 belongs.
+ * \since 11.0
+ *
+ * \param ss7 structure to match on.
+ *
+ * \retval linkset if found.
+ * \retval NULL if not found.
+ */
+static struct sig_ss7_linkset *my_ss7_find_linkset(struct ss7 *ss7)
+{
+ int idx;
+
+ if (!ss7) {
+ return NULL;
+ }
+
+ for (idx = 0; idx < NUM_SPANS; ++idx) {
+ if (linksets[idx].ss7.ss7 == ss7) {
+ return &linksets[idx].ss7;
+ }
+ }
+ return NULL;
+}
+#endif /* defined(HAVE_SS7) */
+
+#if defined(HAVE_SS7)
+/*!
+ * \internal
* \brief Create a new asterisk channel structure for SS7.
* \since 1.8
*
@@ -3128,6 +3160,7 @@ struct sig_ss7_callback sig_ss7_callbacks =
.set_callerid = my_set_callerid,
.set_dnid = my_set_dnid,
.open_media = my_pri_ss7_open_media,
+ .find_linkset = my_ss7_find_linkset,
};
#endif /* defined(HAVE_SS7) */
@@ -10688,9 +10721,10 @@ static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
break;
case MWI_SEND_SPILL:
/* We read some number of bytes. Write an equal amount of data */
- if(0 < num_read) {
- if (num_read > pvt->cidlen - pvt->cidpos)
+ if (0 < num_read) {
+ if (num_read > pvt->cidlen - pvt->cidpos) {
num_read = pvt->cidlen - pvt->cidpos;
+ }
res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
if (res > 0) {
pvt->cidpos += res;
@@ -10741,7 +10775,7 @@ static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
switch (event) {
case DAHDI_EVENT_RINGEROFF:
- if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
+ if (pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
handled = 1;
if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
@@ -11946,6 +11980,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
ast_copy_string(ss7->ss7.nationalprefix, conf->ss7.ss7.nationalprefix, sizeof(ss7->ss7.nationalprefix));
ast_copy_string(ss7->ss7.subscriberprefix, conf->ss7.ss7.subscriberprefix, sizeof(ss7->ss7.subscriberprefix));
ast_copy_string(ss7->ss7.unknownprefix, conf->ss7.ss7.unknownprefix, sizeof(ss7->ss7.unknownprefix));
+ ast_copy_string(ss7->ss7.networkroutedprefix, conf->ss7.ss7.networkroutedprefix, sizeof(ss7->ss7.networkroutedprefix));
ss7->ss7.called_nai = conf->ss7.ss7.called_nai;
ss7->ss7.calling_nai = conf->ss7.ss7.calling_nai;
@@ -12452,12 +12487,12 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
tmp->named_pickupgroups = ast_ref_namedgroups(conf->chan.named_pickupgroups);
if (conf->chan.vars) {
struct ast_variable *v, *tmpvar;
- for (v = conf->chan.vars ; v ; v = v->next) {
- if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
- tmpvar->next = tmp->vars;
- tmp->vars = tmpvar;
- }
- }
+ for (v = conf->chan.vars ; v ; v = v->next) {
+ if ((tmpvar = ast_variable_new(v->name, v->value, v->file))) {
+ tmpvar->next = tmp->vars;
+ tmp->vars = tmpvar;
+ }
+ }
}
tmp->hwrxgain_enabled = conf->chan.hwrxgain_enabled;
tmp->hwtxgain_enabled = conf->chan.hwtxgain_enabled;
@@ -12566,6 +12601,9 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
#if defined(HAVE_SS7)
case SIG_SS7:
tmp->inservice = 0;
+ if (tmp->ss7->flags & LINKSET_FLAG_INITIALHWBLO) {
+ tmp->remotelyblocked |= SS7_BLOCKED_HARDWARE;
+ }
break;
#endif /* defined(HAVE_SS7) */
default:
@@ -12600,6 +12638,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
case SIG_SS7:
if (ss7_chan) {
ss7_chan->inalarm = tmp->inalarm;
+ ss7_chan->inservice = tmp->inservice;
ss7_chan->stripmsd = tmp->stripmsd;
ss7_chan->hidecallerid = tmp->hidecallerid;
@@ -14891,6 +14930,9 @@ static int dahdi_restart(void)
}
ss7_set_error(dahdi_ss7_error);
ss7_set_message(dahdi_ss7_message);
+ ss7_set_hangup(sig_ss7_cb_hangup);
+ ss7_set_notinservice(sig_ss7_cb_notinservice);
+ ss7_set_call_null(sig_ss7_cb_call_null);
#endif /* defined(HAVE_SS7) */
if (setup_dahdi(2) != 0) {
@@ -14943,9 +14985,8 @@ static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cl
ast_group_t targetnum = 0;
int filtertype = 0;
struct dahdi_pvt *tmp = NULL;
- char tmps[20] = "";
- char statestr[20] = "";
- char blockstr[20] = "";
+ char tmps[20];
+ char blockstr[20];
switch (cmd) {
case CLI_INIT:
@@ -14961,8 +15002,9 @@ static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cl
/* syntax: dahdi show channels [ group <group> | context <context> ] */
- if (!((a->argc == 3) || (a->argc == 5)))
+ if (!((a->argc == 3) || (a->argc == 5))) {
return CLI_SHOWUSAGE;
+ }
if (a->argc == 5) {
if (!strcasecmp(a->argv[3], "group")) {
@@ -14977,7 +15019,7 @@ static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cl
}
}
- ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "State", "Description");
+ ast_cli(a->fd, FORMAT2, "Chan", "Extension", "Context", "Language", "MOH Interpret", "Blocked", "In Service", "Description");
ast_mutex_lock(&iflock);
for (tmp = iflist; tmp; tmp = tmp->next) {
if (filtertype) {
@@ -14998,24 +15040,15 @@ static char *dahdi_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cl
}
if (tmp->channel > 0) {
snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
- } else
+ } else {
ast_copy_string(tmps, "pseudo", sizeof(tmps));
+ }
- if (tmp->locallyblocked)
- blockstr[0] = 'L';
- else
- blockstr[0] = ' ';
-
- if (tmp->remotelyblocked)
- blockstr[1] = 'R';
- else
- blockstr[1] = ' ';
-
+ blockstr[0] = tmp->locallyblocked ? 'L' : ' ';
+ blockstr[1] = tmp->remotelyblocked ? 'R' : ' ';
blockstr[2] = '\0';
- snprintf(statestr, sizeof(statestr), "%s", "In Service");
-
- ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, statestr, tmp->description);
+ ast_cli(a->fd, FORMAT, tmps, tmp->exten, tmp->context, tmp->language, tmp->mohinterpret, blockstr, tmp->inservice ? "Yes" : "No", tmp->description);
}
ast_mutex_unlock(&iflock);
return CLI_SUCCESS;
@@ -16023,7 +16056,7 @@ static int linkset_addsigchan(int sigchan)
(params.sigtype == DAHDI_SIG_MTP2)
? SS7_TRANSPORT_DAHDIMTP2
: SS7_TRANSPORT_DAHDIDCHAN,
- si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode);
+ si.alarms, cur_networkindicator, cur_pointcode, cur_adjpointcode, cur_slc);
if (res) {
dahdi_close_ss7_fd(link, curfd);
return -1;
@@ -16049,8 +16082,11 @@ static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_a
case CLI_GENERATE:
return NULL;
}
- if (a->argc < 6)
+
+ if (a->argc < 6) {
return CLI_SHOWUSAGE;
+ }
+
span = atoi(a->argv[5]);
if ((span < 1) || (span > NUM_SPANS)) {
ast_cli(a->fd, "Invalid linkset %s. Should be a number from %d to %d\n", a->argv[5], 1, NUM_SPANS);
@@ -16075,24 +16111,35 @@ static char *handle_ss7_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_a
#endif /* defined(HAVE_SS7) */
#if defined(HAVE_SS7)
-static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+static char *handle_ss7_cic_blocking(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
int linkset, cic;
- int blocked = -1, i;
+ int blocked, i;
+ int do_block = 0;
+ unsigned int dpc;
+
switch (cmd) {
case CLI_INIT:
- e->command = "ss7 block cic";
+ e->command = "ss7 {block|unblock} cic";
e->usage =
- "Usage: ss7 block cic <linkset> <CIC>\n"
- " Sends a remote blocking request for the given CIC on the specified linkset\n";
+ "Usage: ss7 {block|unblock} cic <linkset> <dpc> <CIC>\n"
+ " Sends a remote {blocking|unblocking} request for the given CIC on the specified linkset\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
- if (a->argc == 5)
+
+ if (a->argc == 6) {
linkset = atoi(a->argv[3]);
- else
+ } else {
return CLI_SHOWUSAGE;
+ }
+
+ if (!strcasecmp(a->argv[1], "block")) {
+ do_block = 1;
+ } else if (strcasecmp(a->argv[1], "unblock")) {
+ return CLI_SHOWUSAGE;
+ }
if ((linkset < 1) || (linkset > NUM_SPANS)) {
ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
@@ -16104,63 +16151,157 @@ static char *handle_ss7_block_cic(struct ast_cli_entry *e, int cmd, struct ast_c
return CLI_SUCCESS;
}
- cic = atoi(a->argv[4]);
-
+ cic = atoi(a->argv[5]);
if (cic < 1) {
ast_cli(a->fd, "Invalid CIC specified!\n");
return CLI_SUCCESS;
}
+ dpc = atoi(a->argv[4]);
+ if (dpc < 1) {
+ ast_cli(a->fd, "Invalid DPC specified!\n");
+ return CLI_SUCCESS;
+ }
+
for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
- if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
+ if (linksets[linkset-1].ss7.pvts[i] && linksets[linkset-1].ss7.pvts[i]->cic == cic && linksets[linkset-1].ss7.pvts[i]->dpc == dpc) {
blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
- if (!blocked) {
- ast_mutex_lock(&linksets[linkset-1].ss7.lock);
- isup_blo(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
- ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
+ if (!do_block ^ !(blocked & SS7_BLOCKED_MAINTENANCE)) {
+ if (sig_ss7_cic_blocking(&linksets[linkset-1].ss7, do_block, i) < 0) {
+ ast_cli(a->fd, "Unable to allocate new ss7call\n");
+ } else {
+ ast_cli(a->fd, "Sent %sblocking request for linkset %d on CIC %d DPC %d\n", (do_block) ? "" : "un", linkset, cic, dpc);
+ }
+ } else if (!do_block && blocked) {
+ ast_cli(a->fd, "CIC %d is hardware locally blocked!\n", cic);
+ } else {
+ ast_cli(a->fd, "CIC %d %s locally blocked\n", cic, do_block ? "already" : "is not");
}
+ return CLI_SUCCESS;
}
}
- if (blocked < 0) {
- ast_cli(a->fd, "Invalid CIC specified!\n");
+ ast_cli(a->fd, "Invalid CIC specified!\n");
+ return CLI_SUCCESS;
+}
+#endif /* defined(HAVE_SS7) */
+
+#if defined(HAVE_SS7)
+static char *handle_ss7_linkset_mng(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ int linkset, i;
+ enum {
+ DO_BLOCK,
+ DO_UNBLOCK,
+ DO_RESET,
+ } do_what;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "ss7 {reset|block|unblock} linkset";
+ e->usage =
+ "Usage: ss7 {reset|block|unblock} linkset <linkset number>\n"
+ " Sends a remote {reset|blocking|unblocking} request for all CICs on the given linkset\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if (a->argc == 4) {
+ linkset = atoi(a->argv[3]);
+ } else {
+ return CLI_SHOWUSAGE;
+ }
+
+ if (!strcasecmp(a->argv[1], "block")) {
+ do_what = DO_BLOCK;
+ } else if (!strcasecmp(a->argv[1], "unblock")) {
+ do_what = DO_UNBLOCK;
+ } else if (!strcasecmp(a->argv[1], "reset")) {
+ do_what = DO_RESET;
+ } else {
+ return CLI_SHOWUSAGE;
+ }
+
+ if ((linkset < 1) || (linkset > NUM_SPANS)) {
+ ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
return CLI_SUCCESS;
}
- if (!blocked)
- ast_cli(a->fd, "Sent blocking request for linkset %d on CIC %d\n", linkset, cic);
- else
- ast_cli(a->fd, "CIC %d already locally blocked\n", cic);
+ if (!linksets[linkset - 1].ss7.ss7) {
+ ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
+ return CLI_SUCCESS;
+ }
- /* Break poll on the linkset so it sends our messages */
- pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
+ for (i = 0; i < linksets[linkset - 1].ss7.numchans; i++) {
+ /* XXX Should be done with GRS/CGB/CGU instead - see ss7_reset_linkset() */
+ if (linksets[linkset - 1].ss7.pvts[i]) {
+ switch (do_what) {
+ case DO_BLOCK:
+ case DO_UNBLOCK:
+ if (sig_ss7_cic_blocking(&linksets[linkset - 1].ss7, do_what == DO_BLOCK, i)) {
+ ast_cli(a->fd, "Sent remote %s request on CIC %d\n",
+ (do_what == DO_BLOCK) ? "blocking" : "unblocking",
+ linksets[linkset - 1].ss7.pvts[i]->cic);
+ }
+ break;
+ case DO_RESET:
+ if (sig_ss7_reset_cic(&linksets[linkset - 1].ss7,
+ linksets[linkset - 1].ss7.pvts[i]->cic,
+ linksets[linkset - 1].ss7.pvts[i]->dpc)) {
+ ast_cli(a->fd, "Sent reset request on CIC %d\n",
+ linksets[linkset - 1].ss7.pvts[i]->cic);
+ }
+ break;
+ }
+ }
+ }
return CLI_SUCCESS;
}
#endif /* defined(HAVE_SS7) */
#if defined(HAVE_SS7)
-static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+static char *handle_ss7_group_blocking(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
- int linkset;
- int i;
+ int linkset, cic, range, chanpos;
+ int i, dpc, orient = 0;
+ int do_block = 0;
+ unsigned char state[255];
+
switch (cmd) {
case CLI_INIT:
- e->command = "ss7 block linkset";
+ e->command = "ss7 {block|unblock} group";
e->usage =
- "Usage: ss7 block linkset <linkset number>\n"
- " Sends a remote blocking request for all CICs on the given linkset\n";
+ "Usage: ss7 {block|unblock} group <linkset> <dpc> <1st. CIC> <range> [H]\n"
+ " Sends a remote {blocking|unblocking} request for CIC range on the specified linkset\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
- if (a->argc == 4)
+
+ if (a->argc == 7 || a->argc == 8) {
linkset = atoi(a->argv[3]);
- else
+ } else {
return CLI_SHOWUSAGE;
+ }
+
+ if (!strcasecmp(a->argv[1], "block")) {
+ do_block = 1;
+ } else if (strcasecmp(a->argv[1], "unblock")) {
+ return CLI_SHOWUSAGE;
+ }
+
+ if (a->argc == 8) {
+ if (!strcasecmp(a->argv[7], "H")) {
+ orient = 1;
+ } else {
+ return CLI_SHOWUSAGE;
+ }
+ }
if ((linkset < 1) || (linkset > NUM_SPANS)) {
- ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
+ ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
return CLI_SUCCESS;
}
@@ -16169,43 +16310,81 @@ static char *handle_ss7_block_linkset(struct ast_cli_entry *e, int cmd, struct a
return CLI_SUCCESS;
}
- for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
- ast_cli(a->fd, "Sending remote blocking request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
- ast_mutex_lock(&linksets[linkset-1].ss7.lock);
- isup_blo(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
+ cic = atoi(a->argv[5]);
+ if (cic < 1) {
+ ast_cli(a->fd, "Invalid CIC specified!\n");
+ return CLI_SUCCESS;
+ }
+
+ range = atoi(a->argv[6]);
+ /* ITU-T Q.763 3.43 - range 0 is reserved, which makes a range of 2 CICs a minimum group */
+ if (range < 1 || range > (linksets[linkset - 1].ss7.type == SS7_ANSI ? 24 : 31)) {
+ ast_cli(a->fd, "Invalid range specified!\n");
+ return CLI_SUCCESS;
+ }
+
+ dpc = atoi(a->argv[4]);
+ if (dpc < 1) {
+ ast_cli(a->fd, "Invalid DPC specified!\n");
+ return CLI_SUCCESS;
+ }
+
+ ast_mutex_lock(&linksets[linkset-1].ss7.lock);
+ if (!sig_ss7_find_cic_range(&linksets[linkset-1].ss7, cic, cic + range, dpc)) {
ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
+ ast_cli(a->fd, "Invalid CIC/RANGE\n");
+ return CLI_SHOWUSAGE;
}
- /* Break poll on the linkset so it sends our messages */
- pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
+ memset(state, 0, sizeof(state));
+ for (i = 0; i <= range; ++i) {
+ state[i] = 1;
+ }
+ /* We are guaranteed to find chanpos because of sig_ss7_find_cic_range() includes it. */
+ chanpos = sig_ss7_find_cic(&linksets[linkset-1].ss7, cic, dpc);
+ if (sig_ss7_group_blocking(&linksets[linkset-1].ss7, do_block, chanpos, cic + range, state, orient)) {
+ ast_cli(a->fd, "Unable allocate new ss7call\n");
+ } else {
+ ast_cli(a->fd, "Sending remote%s %sblocking request linkset %d on CIC %d range %d\n",
+ orient ? " hardware" : "", do_block ? "" : "un", linkset, cic, range);
+ }
+
+ ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
+
+ /* Break poll on the linkset so it sends our messages */
+ if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
+ pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
+ }
return CLI_SUCCESS;
}
#endif /* defined(HAVE_SS7) */
#if defined(HAVE_SS7)
-static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+static char *handle_ss7_group_reset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
- int linkset, cic;
- int i, blocked = -1;
+ int linkset, cic, range;
+ unsigned int dpc;
+
switch (cmd) {
case CLI_INIT:
- e->command = "ss7 unblock cic";
+ e->command = "ss7 reset group";
e->usage =
- "Usage: ss7 unblock cic <linkset> <CIC>\n"
- " Sends a remote unblocking request for the given CIC on the specified linkset\n";
+ "Usage: ss7 reset group <linkset> <dpc> <1st CIC> <range>\n"
+ " Send a GRS for the given CIC range on the specified linkset\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
- if (a->argc == 5)
+ if (a->argc == 7) {
linkset = atoi(a->argv[3]);
- else
+ } else {
return CLI_SHOWUSAGE;
+ }
if ((linkset < 1) || (linkset > NUM_SPANS)) {
- ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
+ ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[4], 1, NUM_SPANS);
return CLI_SUCCESS;
}
@@ -16214,54 +16393,69 @@ static char *handle_ss7_unblock_cic(struct ast_cli_entry *e, int cmd, struct ast
return CLI_SUCCESS;
}
- cic = atoi(a->argv[4]);
+ cic = atoi(a->argv[5]);
if (cic < 1) {
ast_cli(a->fd, "Invalid CIC specified!\n");
return CLI_SUCCESS;
}
- for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
- if (linksets[linkset-1].ss7.pvts[i]->cic == cic) {
- blocked = linksets[linkset-1].ss7.pvts[i]->locallyblocked;
- if (blocked) {
- ast_mutex_lock(&linksets[linkset-1].ss7.lock);
- isup_ubl(linksets[linkset-1].ss7.ss7, cic, linksets[linkset-1].ss7.pvts[i]->dpc);
- ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
- }
- }
+ range = atoi(a->argv[6]);
+ if (range < 1 || range > (linksets[linkset - 1].ss7.type == SS7_ANSI ? 24 : 31)) {
+ ast_cli(a->fd, "Invalid range specified!\n");
+ return CLI_SUCCESS;
}
- if (blocked > 0)
- ast_cli(a->fd, "Sent unblocking request for linkset %d on CIC %d\n", linkset, cic);
+ dpc = atoi(a->argv[4]);
+ if (dpc < 1) {
+ ast_cli(a->fd, "Invalid DPC specified!\n");
+ return CLI_SUCCESS;
+ }
- /* Break poll on the linkset so it sends our messages */
- pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
+ ast_mutex_lock(&linksets[linkset-1].ss7.lock);
+ if (!sig_ss7_find_cic_range(&linksets[linkset-1].ss7, cic, cic + range, dpc)) {
+ ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
+ ast_cli(a->fd, "Invalid CIC/RANGE\n");
+ return CLI_SHOWUSAGE;
+ }
+ if (sig_ss7_reset_group(&linksets[linkset-1].ss7, cic, dpc, range)) {
+ ast_cli(a->fd, "Unable to allocate new ss7call\n");
+ } else {
+ ast_cli(a->fd, "GRS sent ... \n");
+ }
+
+ ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
+
+ /* Break poll on the linkset so it sends our messages */
+ if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
+ pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
+ }
return CLI_SUCCESS;
}
#endif /* defined(HAVE_SS7) */
#if defined(HAVE_SS7)
-static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+static char *handle_ss7_show_calls(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
int linkset;
- int i;
+
switch (cmd) {
case CLI_INIT:
- e->command = "ss7 unblock linkset";
+ e->command = "ss7 show calls";
e->usage =
- "Usage: ss7 unblock linkset <linkset number>\n"
- " Sends a remote unblocking request for all CICs on the specified linkset\n";
+ "Usage: ss7 show calls <linkset>\n"
+ " Show SS7 calls on the specified linkset\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
- if (a->argc == 4)
+ if (a->argc == 4) {
linkset = atoi(a->argv[3]);
- else
+ } else {
return CLI_SHOWUSAGE;
+ }
if ((linkset < 1) || (linkset > NUM_SPANS)) {
ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
@@ -16273,15 +16467,164 @@ static char *handle_ss7_unblock_linkset(struct ast_cli_entry *e, int cmd, struct
return CLI_SUCCESS;
}
- for (i = 0; i < linksets[linkset-1].ss7.numchans; i++) {
- ast_cli(a->fd, "Sending remote unblock request on CIC %d\n", linksets[linkset-1].ss7.pvts[i]->cic);
- ast_mutex_lock(&linksets[linkset-1].ss7.lock);
- isup_ubl(linksets[linkset-1].ss7.ss7, linksets[linkset-1].ss7.pvts[i]->cic, linksets[linkset-1].ss7.pvts[i]->dpc);
- ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
+ ast_mutex_lock(&linksets[linkset-1].ss7.lock);
+ isup_show_calls(linksets[linkset-1].ss7.ss7, &ast_cli, a->fd);
+ ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
+
+ return CLI_SUCCESS;
+}
+#endif /* defined(HAVE_SS7) */
+
+#if defined(HAVE_SS7)
+static char *handle_ss7_reset_cic(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ int linkset, cic, res;
+ unsigned int dpc;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "ss7 reset cic";
+ e->usage =
+ "Usage: ss7 reset cic <linkset> <dpc> <CIC>\n"
+ " Send a RSC for the given CIC on the specified linkset\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if (a->argc == 6) {
+ linkset = atoi(a->argv[3]);
+ } else {
+ return CLI_SHOWUSAGE;
+ }
+
+ if ((linkset < 1) || (linkset > NUM_SPANS)) {
+ ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
+ return CLI_SUCCESS;
+ }
+
+ if (!linksets[linkset-1].ss7.ss7) {
+ ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
+ return CLI_SUCCESS;
+ }
+
+ cic = atoi(a->argv[5]);
+
+ if (cic < 1) {
+ ast_cli(a->fd, "Invalid CIC specified!\n");
+ return CLI_SUCCESS;
+ }
+
+ dpc = atoi(a->argv[4]);
+ if (dpc < 1) {
+ ast_cli(a->fd, "Invalid DPC specified!\n");
+ return CLI_SUCCESS;
+ }
+
+ res = sig_ss7_reset_cic(&linksets[linkset-1].ss7, cic, dpc);
+
+ ast_cli(a->fd, "%s RSC for linkset %d on CIC %d DPC %d\n", res ? "Sent" : "Failed", linkset, cic, dpc);
+
+ return CLI_SUCCESS;
+}
+#endif /* defined(HAVE_SS7) */
+
+#if defined(HAVE_SS7)
+static char *handle_ss7_net_mng(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ int linkset;
+ unsigned int slc;
+ unsigned int arg = 0;
+ const char *res;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "ss7 mtp3";
+ e->usage =
+ "Usage: ss7 mtp3 <linkset> <slc> coo|coa|cbd|cba|eco|eca|tfp|tfa|lin|lun|lia|lua|lid|lfu <arg>\n"
+ " Send a NET MNG message\n"
+ " WARNING!!! WARNING!!! We are not a STP, just for testing/development purposes\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if (a->argc < 5) {
+ return CLI_SHOWUSAGE;
}
+ linkset = atoi(a->argv[2]);
+ if ((linkset < 1) || (linkset > NUM_SPANS)) {
+ ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[2], 1, NUM_SPANS);
+ return CLI_SUCCESS;
+ }
+ if (!linksets[linkset-1].ss7.ss7) {
+ ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
+ return CLI_SUCCESS;
+ }
+
+ slc = atoi(a->argv[3]);
+
+ if (a->argc == 6) {
+ arg = atoi(a->argv[5]);
+ }
+
+ ast_mutex_lock(&linksets[linkset-1].ss7.lock);
+ res = mtp3_net_mng(linksets[linkset-1].ss7.ss7, slc, a->argv[4], arg);
+ ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
+
/* Break poll on the linkset so it sends our messages */
- pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
+ if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
+ pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
+ }
+
+ ast_cli(a->fd, "%s", res);
+
+ return CLI_SUCCESS;
+}
+#endif /* defined(HAVE_SS7) */
+
+#if defined(HAVE_SS7)
+static char *handle_ss7_mtp3_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ int linkset;
+ unsigned int slc = 0;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "ss7 restart mtp3";
+ e->usage =
+ "Usage: ss7 restart mtp3 <linkset> <slc>\n"
+ " Restart link\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if (a->argc < 5) {
+ return CLI_SHOWUSAGE;
+ }
+
+ linkset = atoi(a->argv[3]);
+ if ((linkset < 1) || (linkset > NUM_SPANS)) {
+ ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[2], 1, NUM_SPANS);
+ return CLI_SUCCESS;
+ }
+ if (!linksets[linkset-1].ss7.ss7) {
+ ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
+ return CLI_SUCCESS;
+ }
+
+ slc = atoi(a->argv[4]);
+
+ ast_mutex_lock(&linksets[linkset-1].ss7.lock);
+ mtp3_init_restart(linksets[linkset-1].ss7.ss7, slc);
+ ast_mutex_unlock(&linksets[linkset-1].ss7.lock);
+
+ /* Break poll on the linkset so it sends our messages */
+ if (linksets[linkset-1].ss7.master != AST_PTHREADT_NULL) {
+ pthread_kill(linksets[linkset-1].ss7.master, SIGURG);
+ }
return CLI_SUCCESS;
}
@@ -16303,8 +16646,10 @@ static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct as
return NULL;
}
- if (a->argc < 4)
+ if (a->argc < 4) {
return CLI_SHOWUSAGE;
+ }
+
linkset = atoi(a->argv[3]);
if ((linkset < 1) || (linkset > NUM_SPANS)) {
ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
@@ -16316,7 +16661,16 @@ static char *handle_ss7_show_linkset(struct ast_cli_entry *e, int cmd, struct as
return CLI_SUCCESS;
}
+ ast_cli(a->fd, "SS7 flags: 0x%x\n", ss7->flags);
ast_cli(a->fd, "SS7 linkset %d status: %s\n", linkset, (ss7->state == LINKSET_STATE_UP) ? "Up" : "Down");
+ ast_cli(a->fd, "SS7 calling nai: %i\n", ss7->calling_nai);
+ ast_cli(a->fd, "SS7 called nai: %i\n", ss7->called_nai);
+ ast_cli(a->fd, "SS7 nationalprefix: %s\n", ss7->nationalprefix);
+ ast_cli(a->fd, "SS7 internationalprefix: %s\n", ss7->internationalprefix);
+ ast_cli(a->fd, "SS7 unknownprefix: %s\n", ss7->unknownprefix);
+ ast_cli(a->fd, "SS7 networkroutedprefix: %s\n", ss7->networkroutedprefix);
+ ast_cli(a->fd, "SS7 subscriberprefix: %s\n", ss7->subscriberprefix);
+ ss7_show_linkset(ss7->ss7, &ast_cli, a->fd);
return CLI_SUCCESS;
}
@@ -16338,8 +16692,9 @@ static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct a
return NULL;
}
- if (a->argc != 3)
+ if (a->argc != 3) {
return CLI_SHOWUSAGE;
+ }
sig_ss7_cli_show_channels_header(a->fd);
for (linkset = 0; linkset < NUM_SPANS; ++linkset) {
@@ -16352,6 +16707,110 @@ static char *handle_ss7_show_channels(struct ast_cli_entry *e, int cmd, struct a
#endif /* defined(HAVE_SS7) */
#if defined(HAVE_SS7)
+static char *handle_ss7_show_cics(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+#define FORMAT "%5s %5s %6s %12s %-12s\n"
+#define FORMAT2 "%5i %5i %6i %12s %-12s\n"
+ int i, linkset, dpc = 0;
+ struct sig_ss7_linkset *ss7;
+ char *state;
+ char blocking[12];
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "ss7 show cics";
+ e->usage =
+ "Usage: ss7 show cics <linkset> [dpc]\n"
+ " Shows the cics of an SS7 linkset.\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if (a->argc < 4 || a->argc > 5) {
+ return CLI_SHOWUSAGE;
+ }
+
+ linkset = atoi(a->argv[3]);
+
+ if ((linkset < 1) || (linkset > NUM_SPANS)) {
+ ast_cli(a->fd, "Invalid linkset %s. Should be a number %d to %d\n", a->argv[3], 1, NUM_SPANS);
+ return CLI_SUCCESS;
+ }
+
+ if (!linksets[linkset-1].ss7.ss7) {
+ ast_cli(a->fd, "No SS7 running on linkset %d\n", linkset);
+ return CLI_SUCCESS;
+ }
+ ss7 = &linksets[linkset-1].ss7;
+
+ if (a->argc == 5) {
+ dpc = atoi(a->argv[4]);
+ if (dpc < 1) {
+ ast_cli(a->fd, "Invalid DPC specified!\n");
+ return CLI_SUCCESS;
+ }
+ }
+
+ ast_cli(a->fd, FORMAT, "CIC", "DPC", "DAHDI", "STATE", "BLOCKING");
+
+ for (i = 0; i < ss7->numchans; i++) {
+ if (!dpc || (ss7->pvts[i] && ss7->pvts[i]->dpc == dpc)) {
+ struct dahdi_pvt *p = ss7->pvts[i]->chan_pvt;
+
+ if (ss7->pvts[i]->owner) {
+ state = "Used";
+ } else if (ss7->pvts[i]->ss7call) {
+ state = "Pending";
+ } else if (!p->inservice) {
+ state = "NotInServ";
+ } else {
+ state = "Idle";
+ }
+
+ if (p->locallyblocked) {
+ strcpy(blocking, "L:");
+ if (p->locallyblocked & SS7_BLOCKED_MAINTENANCE) {
+ strcat(blocking, "M");
+ } else {
+ strcat(blocking, " ");
+ }
+
+ if (p->locallyblocked & SS7_BLOCKED_HARDWARE) {
+ strcat(blocking, "H");
+ } else {
+ strcat(blocking, " ");
+ }
+ } else {
+ strcpy(blocking, " ");
+ }
+
+ if (p->remotelyblocked) {
+ strcat(blocking, " R:");
+ if (p->remotelyblocked & SS7_BLOCKED_MAINTENANCE) {
+ strcat(blocking, "M");
+ } else {
+ strcat(blocking, " ");
+ }
+
+ if (p->remotelyblocked & SS7_BLOCKED_HARDWARE) {
+ strcat(blocking, "H");
+ } else {
+ strcat(blocking, " ");
+ }
+ }
+
+ ast_cli(a->fd, FORMAT2, ss7->pvts[i]->cic, ss7->pvts[i]->dpc, ss7->pvts[i]->channel, state, blocking);
+ }
+ }
+
+ return CLI_SUCCESS;
+#undef FORMAT
+#undef FORMAT2
+}
+#endif /* defined(HAVE_SS7) */
+
+#if defined(HAVE_SS7)
static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
switch (cmd) {
@@ -16374,12 +16833,17 @@ static char *handle_ss7_version(struct ast_cli_entry *e, int cmd, struct ast_cli
#if defined(HAVE_SS7)
static struct ast_cli_entry dahdi_ss7_cli[] = {
AST_CLI_DEFINE(handle_ss7_debug, "Enables SS7 debugging on a linkset"),
- AST_CLI_DEFINE(handle_ss7_block_cic, "Blocks the given CIC"),
- AST_CLI_DEFINE(handle_ss7_unblock_cic, "Unblocks the given CIC"),
- AST_CLI_DEFINE(handle_ss7_block_linkset, "Blocks all CICs on a linkset"),
- AST_CLI_DEFINE(handle_ss7_unblock_linkset, "Unblocks all CICs on a linkset"),
+ AST_CLI_DEFINE(handle_ss7_cic_blocking, "Blocks/Unblocks the given CIC"),
+ AST_CLI_DEFINE(handle_ss7_linkset_mng, "Resets/Blocks/Unblocks all CICs on a linkset"),
+ AST_CLI_DEFINE(handle_ss7_group_blocking, "Blocks/Unblocks the given CIC range"),
+ AST_CLI_DEFINE(handle_ss7_reset_cic, "Resets the given CIC"),
+ AST_CLI_DEFINE(handle_ss7_group_reset, "Resets the given CIC range"),
+ AST_CLI_DEFINE(handle_ss7_mtp3_restart, "Restart a link"),
+ AST_CLI_DEFINE(handle_ss7_net_mng, "Send an NET MNG message"),
AST_CLI_DEFINE(handle_ss7_show_linkset, "Shows the status of a linkset"),
AST_CLI_DEFINE(handle_ss7_show_channels, "Displays SS7 channel information"),
+ AST_CLI_DEFINE(handle_ss7_show_calls, "Show ss7 calls"),
+ AST_CLI_DEFINE(handle_ss7_show_cics, "Show cics on a linkset"),
AST_CLI_DEFINE(handle_ss7_version, "Displays libss7 version"),
};
#endif /* defined(HAVE_SS7) */
@@ -16581,6 +17045,10 @@ static int __unload_module(void)
for (j = 0; j < SIG_SS7_NUM_DCHANS; j++) {
dahdi_close_ss7_fd(&(linksets[i]), j);
}
+ if (linksets[i].ss7.ss7) {
+ ss7_destroy(linksets[i].ss7.ss7);
+ linksets[i].ss7.ss7 = NULL;
+ }
}
#endif /* defined(HAVE_SS7) */
ast_cond_destroy(&ss_thread_complete);
@@ -16856,7 +17324,7 @@ static void parse_busy_pattern(struct ast_variable *v, struct ast_dsp_busy_patte
for (; ;) {
/* Scans the string for the next value in the pattern. If none, it checks to see if any have been entered so far. */
- if(!sscanf(v->value, "%30d", &norval) && count_pattern == 0) {
+ if (!sscanf(v->value, "%30d", &norval) && count_pattern == 0) {
ast_log(LOG_ERROR, "busypattern= expects either busypattern=tonelength,quietlength or busypattern=t1length, q1length, t2length, q2length at line %d.\n", v->lineno);
break;
}
@@ -17220,23 +17688,23 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
#else
/* Default is fsk, to turn it off you must specify nofsk */
memset(&confp->chan.mwisend_setting, 0, sizeof(confp->chan.mwisend_setting));
- if (strcasestr(v->value, "nofsk")) { /* NoFSK */
+ if (strcasestr(v->value, "nofsk")) { /* NoFSK */
confp->chan.mwisend_fsk = 0;
} else { /* Default FSK */
confp->chan.mwisend_fsk = 1;
}
- if (strcasestr(v->value, "rpas")) { /* Ring Pulse Alert Signal, normally followed by FSK */
+ if (strcasestr(v->value, "rpas")) { /* Ring Pulse Alert Signal, normally followed by FSK */
confp->chan.mwisend_rpas = 1;
} else {
confp->chan.mwisend_rpas = 0;
}
- if (strcasestr(v->value, "lrev")) { /* Line Reversal */
+ if (strcasestr(v->value, "lrev")) { /* Line Reversal */
confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_LREV;
}
- if (strcasestr(v->value, "hvdc")) { /* HV 90VDC */
+ if (strcasestr(v->value, "hvdc")) { /* HV 90VDC */
confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVDC;
}
- if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ){ /* 90V DC pulses */
+ if ( (strcasestr(v->value, "neon")) || (strcasestr(v->value, "hvac")) ) { /* 90V DC pulses */
confp->chan.mwisend_setting.vmwi_type |= DAHDI_VMWI_HVAC;
}
#endif
@@ -17744,8 +18212,11 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
cur_ss7type = SS7_ITU;
} else if (!strcasecmp(v->value, "ansi")) {
cur_ss7type = SS7_ANSI;
- } else
+ } else {
ast_log(LOG_WARNING, "'%s' is an unknown ss7 switch type at line %d.!\n", v->value, v->lineno);
+ }
+ } else if (!strcasecmp(v->name, "slc")) {
+ cur_slc = atoi(v->value);
} else if (!strcasecmp(v->name, "linkset")) {
cur_linkset = atoi(v->value);
} else if (!strcasecmp(v->name, "pointcode")) {
@@ -17757,16 +18228,17 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
} else if (!strcasecmp(v->name, "cicbeginswith")) {
cur_cicbeginswith = atoi(v->value);
} else if (!strcasecmp(v->name, "networkindicator")) {
- if (!strcasecmp(v->value, "national"))
+ if (!strcasecmp(v->value, "national")) {
cur_networkindicator = SS7_NI_NAT;
- else if (!strcasecmp(v->value, "national_spare"))
+ } else if (!strcasecmp(v->value, "national_spare")) {
cur_networkindicator = SS7_NI_NAT_SPARE;
- else if (!strcasecmp(v->value, "international"))
+ } else if (!strcasecmp(v->value, "international")) {
cur_networkindicator = SS7_NI_INT;
- else if (!strcasecmp(v->value, "international_spare"))
+ } else if (!strcasecmp(v->value, "international_spare")) {
cur_networkindicator = SS7_NI_INT_SPARE;
- else
+ } else {
cur_networkindicator = -1;
+ }
} else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
ast_copy_string(confp->ss7.ss7.internationalprefix, v->value, sizeof(confp->ss7.ss7.internationalprefix));
} else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
@@ -17775,6 +18247,8 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
ast_copy_string(confp->ss7.ss7.subscriberprefix, v->value, sizeof(confp->ss7.ss7.subscriberprefix));
} else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
ast_copy_string(confp->ss7.ss7.unknownprefix, v->value, sizeof(confp->ss7.ss7.unknownprefix));
+ } else if (!strcasecmp(v->name, "ss7_networkroutedprefix")) {
+ ast_copy_string(confp->ss7.ss7.networkroutedprefix, v->value, sizeof(confp->ss7.ss7.networkroutedprefix));
} else if (!strcasecmp(v->name, "ss7_called_nai")) {
if (!strcasecmp(v->value, "national")) {
confp->ss7.ss7.called_nai = SS7_NAI_NATIONAL;
@@ -17807,9 +18281,9 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
int sigchan, res;
sigchan = atoi(v->value);
res = linkset_addsigchan(sigchan);
- if (res < 0)
+ if (res < 0) {
return -1;
-
+ }
} else if (!strcasecmp(v->name, "ss7_explicitacm")) {
struct dahdi_ss7 *link;
link = ss7_resolve_linkset(cur_linkset);
@@ -17817,8 +18291,148 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
return -1;
}
- if (ast_true(v->value))
+ if (ast_true(v->value)) {
link->ss7.flags |= LINKSET_FLAG_EXPLICITACM;
+ } else {
+ link->ss7.flags &= ~LINKSET_FLAG_EXPLICITACM;
+ }
+ } else if (!strcasecmp(v->name, "ss7_autoacm")) {
+ struct dahdi_ss7 *link;
+ link = ss7_resolve_linkset(cur_linkset);
+ if (!link) {
+ ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
+ return -1;
+ }
+ if (ast_true(v->value)) {
+ link->ss7.flags |= LINKSET_FLAG_AUTOACM;
+ } else {
+ link->ss7.flags &= ~LINKSET_FLAG_AUTOACM;
+ }
+ } else if (!strcasecmp(v->name, "ss7_initialhwblo")) {
+ struct dahdi_ss7 *link;
+ link = ss7_resolve_linkset(cur_linkset);
+ if (!link) {
+ ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
+ return -1;
+ }
+ if (ast_true(v->value)) {
+ link->ss7.flags |= LINKSET_FLAG_INITIALHWBLO;
+ } else {
+ link->ss7.flags &= ~LINKSET_FLAG_INITIALHWBLO;
+ }
+ } else if (!strcasecmp(v->name, "ss7_use_echocontrol")) {
+ struct dahdi_ss7 *link;
+ link = ss7_resolve_linkset(cur_linkset);
+ if (!link) {
+ ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
+ return -1;
+ }
+ if (ast_true(v->value)) {
+ link->ss7.flags |= LINKSET_FLAG_USEECHOCONTROL;
+ } else {
+ link->ss7.flags &= ~LINKSET_FLAG_USEECHOCONTROL;
+ }
+ } else if (!strcasecmp(v->name, "ss7_default_echocontrol")) {
+ struct dahdi_ss7 *link;
+ link = ss7_resolve_linkset(cur_linkset);
+ if (!link) {
+ ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
+ return -1;
+ }
+ if (ast_true(v->value)) {
+ link->ss7.flags |= LINKSET_FLAG_DEFAULTECHOCONTROL;
+ } else {
+ link->ss7.flags &= ~LINKSET_FLAG_DEFAULTECHOCONTROL;
+ }
+ } else if (!strncasecmp(v->name, "isup_timer.", 11)) {
+ struct dahdi_ss7 *link;
+ link = ss7_resolve_linkset(cur_linkset);
+ if (!link) {
+ ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
+ return -1;
+ }
+ if (!link->ss7.ss7) {
+ ast_log(LOG_ERROR, "Please specify isup timers after sigchan!\n");
+ } else if (!ss7_set_isup_timer(link->ss7.ss7, strstr(v->name, ".") + 1, atoi(v->value))) {
+ ast_log(LOG_ERROR, "Invalid isup timer %s\n", v->name);
+ }
+ } else if (!strncasecmp(v->name, "mtp3_timer.", 11)) {
+ struct dahdi_ss7 *link;
+ link = ss7_resolve_linkset(cur_linkset);
+ if (!link) {
+ ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
+ return -1;
+ }
+ if (!link->ss7.ss7) {
+ ast_log(LOG_ERROR, "Please specify mtp3 timers after sigchan!\n");
+ } else if (!ss7_set_mtp3_timer(link->ss7.ss7, strstr(v->name, ".") + 1, atoi(v->value))) {
+ ast_log(LOG_ERROR, "Invalid mtp3 timer %s\n", v->name);
+ }
+ } else if (!strcasecmp(v->name, "inr_if_no_calling")) {
+ struct dahdi_ss7 *link;
+ link = ss7_resolve_linkset(cur_linkset);
+ if (!link) {
+ ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
+ return -1;
+ }
+ if (!link->ss7.ss7) {
+ ast_log(LOG_ERROR, "Please specify inr_if_no_calling after sigchan!\n");
+ } else if (ast_true(v->value)) {
+ ss7_set_flags(link->ss7.ss7, SS7_INR_IF_NO_CALLING);
+ } else {
+ ss7_clear_flags(link->ss7.ss7, SS7_INR_IF_NO_CALLING);
+ }
+ } else if (!strcasecmp(v->name, "non_isdn_access")) {
+ struct dahdi_ss7 *link;
+ link = ss7_resolve_linkset(cur_linkset);
+ if (!link) {
+ ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
+ return -1;
+ }
+ if (!link->ss7.ss7) {
+ ast_log(LOG_ERROR, "Please specify non_isdn_access after sigchan!\n");
+ } else if (ast_true(v->value)) {
+ ss7_clear_flags(link->ss7.ss7, SS7_ISDN_ACCESS_INDICATOR);
+ } else {
+ ss7_set_flags(link->ss7.ss7, SS7_ISDN_ACCESS_INDICATOR);
+ }
+ } else if (!strcasecmp(v->name, "sls_shift")) {
+ struct dahdi_ss7 *link;
+ int sls_shift = atoi(v->value);
+
+ if (sls_shift < 0 || sls_shift > 7) {
+ ast_log(LOG_ERROR, "Invalid sls_shift value. Must be between 0 and 7\n");
+ return -1;
+ }
+
+ link = ss7_resolve_linkset(cur_linkset);
+ if (!link) {
+ ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
+ return -1;
+ }
+ if (!link->ss7.ss7) {
+ ast_log(LOG_ERROR, "Please specify sls_shift after sigchan!\n");
+ } else {
+ ss7_set_sls_shift(link->ss7.ss7, sls_shift);
+ }
+ } else if (!strcasecmp(v->name, "cause_location")) {
+ struct dahdi_ss7 *link;
+ int cause_location = atoi(v->value);
+
+ if (cause_location < 0 || cause_location > 15) {
+ ast_log(LOG_ERROR, "Invalid cause_location value. Must be between 0 and 15\n");
+ return -1;
+ }
+ link = ss7_resolve_linkset(cur_linkset);
+ if (!link) {
+ ast_log(LOG_ERROR, "Invalid linkset number. Must be between 1 and %d\n", NUM_SPANS + 1);
+ return -1;
+ }
+ if (!link->ss7.ss7) {
+ ast_log(LOG_ERROR, "Please specify cause_location after sigchan!\n");
+ } else {
+ ss7_set_cause_location(link->ss7.ss7, cause_location);
+ }
#endif /* defined(HAVE_SS7) */
#ifdef HAVE_OPENR2
} else if (!strcasecmp(v->name, "mfcr2_advanced_protocol_file")) {
@@ -17881,12 +18495,12 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
confp->mfcr2.call_files = ast_true(v->value) ? 1 : 0;
} else if (!strcasecmp(v->name, "mfcr2_max_ani")) {
confp->mfcr2.max_ani = atoi(v->value);
- if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION){
+ if (confp->mfcr2.max_ani >= AST_MAX_EXTENSION) {
confp->mfcr2.max_ani = AST_MAX_EXTENSION - 1;
}
} else if (!strcasecmp(v->name, "mfcr2_max_dnis")) {
confp->mfcr2.max_dnis = atoi(v->value);
- if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION){
+ if (confp->mfcr2.max_dnis >= AST_MAX_EXTENSION) {
confp->mfcr2.max_dnis = AST_MAX_EXTENSION - 1;
}
} else if (!strcasecmp(v->name, "mfcr2_category")) {
@@ -18677,6 +19291,9 @@ static int load_module(void)
}
ss7_set_error(dahdi_ss7_error);
ss7_set_message(dahdi_ss7_message);
+ ss7_set_hangup(sig_ss7_cb_hangup);
+ ss7_set_notinservice(sig_ss7_cb_notinservice);
+ ss7_set_call_null(sig_ss7_cb_call_null);
#endif /* defined(HAVE_SS7) */
res = setup_dahdi(0);
/* Make sure we can register our DAHDI channel type */