diff options
Diffstat (limited to 'channels/chan_dahdi.c')
-rw-r--r-- | channels/chan_dahdi.c | 877 |
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 */ |