Properly handle PRI TON and allow changing number (bug #3493, with mods)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4963 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.2-netsec
Mark Spencer 21 years ago
parent 403d010294
commit e75a91556c

@ -144,7 +144,6 @@ static char *config = "zapata.conf";
#define NUM_SPANS 32 #define NUM_SPANS 32
#define NUM_DCHANS 4 /* No more than 4 d-channels */ #define NUM_DCHANS 4 /* No more than 4 d-channels */
#define MAX_CHANNELS 672 /* No more than a DS3 per trunk group */ #define MAX_CHANNELS 672 /* No more than a DS3 per trunk group */
#define RESET_INTERVAL 3600 /* How often (in seconds) to reset unused channels */
#define CHAN_PSEUDO -2 #define CHAN_PSEUDO -2
@ -248,6 +247,12 @@ static int minidle = 0;
static char idleext[AST_MAX_EXTENSION]; static char idleext[AST_MAX_EXTENSION];
static char idledial[AST_MAX_EXTENSION]; static char idledial[AST_MAX_EXTENSION];
static int overlapdial = 0; static int overlapdial = 0;
static char internationalprefix[10] = "";
static char nationalprefix[10] = "";
static char localprefix[20] = "";
static char privateprefix[20] = "";
static char unknownprefix[20] = "";
static long resetinterval = 3600; /* How often (in seconds) to reset unused channels. Default 1 hour. */
static struct ast_channel inuse = { "GR-303InUse" }; static struct ast_channel inuse = { "GR-303InUse" };
#ifdef PRI_GETSET_TIMERS #ifdef PRI_GETSET_TIMERS
static int pritimers[PRI_MAX_TIMERS]; static int pritimers[PRI_MAX_TIMERS];
@ -351,6 +356,11 @@ struct zt_pri {
int nsf; /* Network-Specific Facilities */ int nsf; /* Network-Specific Facilities */
int dialplan; /* Dialing plan */ int dialplan; /* Dialing plan */
int localdialplan; /* Local dialing plan */ int localdialplan; /* Local dialing plan */
char internationalprefix[10]; /* country access code ('00' for european dialplans) */
char nationalprefix[10]; /* area access code ('0' for european dialplans) */
char localprefix[20]; /* area access code + area code ('0'+area code for european dialplans) */
char privateprefix[20]; /* for private dialplans */
char unknownprefix[20]; /* for unknown dialplans */
int dchannels[NUM_DCHANS]; /* What channel are the dchannels on */ int dchannels[NUM_DCHANS]; /* What channel are the dchannels on */
int trunkgroup; /* What our trunkgroup is */ int trunkgroup; /* What our trunkgroup is */
int mastertrunkgroup; /* What trunk group is our master */ int mastertrunkgroup; /* What trunk group is our master */
@ -366,7 +376,8 @@ struct zt_pri {
int span; int span;
int resetting; int resetting;
int resetpos; int resetpos;
time_t lastreset; time_t lastreset; /* time when unused channels were last reset */
long resetinterval; /* Interval (in seconds) for resetting unused channels */
struct zt_pvt *pvts[MAX_CHANNELS]; /* Member channel pvt structs */ struct zt_pvt *pvts[MAX_CHANNELS]; /* Member channel pvt structs */
struct zt_pvt *crvs; /* Member CRV structs */ struct zt_pvt *crvs; /* Member CRV structs */
struct zt_pvt *crvend; /* Pointer to end of CRV structs */ struct zt_pvt *crvend; /* Pointer to end of CRV structs */
@ -475,6 +486,7 @@ static struct zt_pvt {
char language[MAX_LANGUAGE]; char language[MAX_LANGUAGE];
char musicclass[MAX_LANGUAGE]; char musicclass[MAX_LANGUAGE];
char cid_num[AST_MAX_EXTENSION]; char cid_num[AST_MAX_EXTENSION];
int cid_ton; /* Type Of Number (TON) */
char cid_name[AST_MAX_EXTENSION]; char cid_name[AST_MAX_EXTENSION];
char lastcid_num[AST_MAX_EXTENSION]; char lastcid_num[AST_MAX_EXTENSION];
char lastcid_name[AST_MAX_EXTENSION]; char lastcid_name[AST_MAX_EXTENSION];
@ -581,7 +593,7 @@ static struct zt_pvt {
int logicalspan; int logicalspan;
int alreadyhungup; int alreadyhungup;
int proceeding; int proceeding;
int setup_ack; /* wheter we received SETUP_ACKNOWLEDGE or not */ int setup_ack; /* whether we received SETUP_ACKNOWLEDGE or not */
int dsp_features; int dsp_features;
#endif #endif
#ifdef ZAPATA_R2 #ifdef ZAPATA_R2
@ -4636,6 +4648,7 @@ static struct ast_channel *zt_new(struct zt_pvt *i, int state, int startpbx, int
ast_set_callerid(tmp, i->cid_num, i->cid_name, i->cid_num); ast_set_callerid(tmp, i->cid_num, i->cid_name, i->cid_num);
tmp->cid.cid_pres = i->callingpres; tmp->cid.cid_pres = i->callingpres;
tmp->cid.cid_ton = i->cid_ton;
#ifdef ZAPATA_PRI #ifdef ZAPATA_PRI
set_calltype(tmp, ctype); set_calltype(tmp, ctype);
/* Assume calls are not idle calls unless we're told differently */ /* Assume calls are not idle calls unless we're told differently */
@ -6476,6 +6489,12 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_p
pris[span].overlapdial = overlapdial; pris[span].overlapdial = overlapdial;
strncpy(pris[span].idledial, idledial, sizeof(pris[span].idledial) - 1); strncpy(pris[span].idledial, idledial, sizeof(pris[span].idledial) - 1);
strncpy(pris[span].idleext, idleext, sizeof(pris[span].idleext) - 1); strncpy(pris[span].idleext, idleext, sizeof(pris[span].idleext) - 1);
strncpy(pris[span].internationalprefix, internationalprefix, sizeof(pris[span].internationalprefix)-1);
strncpy(pris[span].nationalprefix, nationalprefix, sizeof(pris[span].nationalprefix)-1);
strncpy(pris[span].localprefix, localprefix, sizeof(pris[span].localprefix)-1);
strncpy(pris[span].privateprefix, privateprefix, sizeof(pris[span].privateprefix)-1);
strncpy(pris[span].unknownprefix, unknownprefix, sizeof(pris[span].unknownprefix)-1);
pris[span].resetinterval = resetinterval;
tmp->pri = &pris[span]; tmp->pri = &pris[span];
tmp->prioffset = offset; tmp->prioffset = offset;
@ -6638,6 +6657,7 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_p
strncpy(tmp->musicclass, musicclass, sizeof(tmp->musicclass)-1); strncpy(tmp->musicclass, musicclass, sizeof(tmp->musicclass)-1);
strncpy(tmp->context, context, sizeof(tmp->context)-1); strncpy(tmp->context, context, sizeof(tmp->context)-1);
strncpy(tmp->cid_num, cid_num, sizeof(tmp->cid_num)-1); strncpy(tmp->cid_num, cid_num, sizeof(tmp->cid_num)-1);
tmp->cid_ton = 0;
strncpy(tmp->cid_name, cid_name, sizeof(tmp->cid_name)-1); strncpy(tmp->cid_name, cid_name, sizeof(tmp->cid_name)-1);
strncpy(tmp->mailbox, mailbox, sizeof(tmp->mailbox)-1); strncpy(tmp->mailbox, mailbox, sizeof(tmp->mailbox)-1);
tmp->msgstate = -1; tmp->msgstate = -1;
@ -7358,6 +7378,8 @@ static void *pri_dchannel(void *vpri)
pthread_t threadid; pthread_t threadid;
pthread_attr_t attr; pthread_attr_t attr;
char ani2str[6]; char ani2str[6];
char plancallingnum[256];
char calledtonstr[10];
pthread_attr_init(&attr); pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
@ -7395,7 +7417,7 @@ static void *pri_dchannel(void *vpri)
if (pri->resetpos < 0) if (pri->resetpos < 0)
pri_check_restart(pri); pri_check_restart(pri);
} else { } else {
if (!pri->resetting && ((t - pri->lastreset) >= RESET_INTERVAL)) { if (!pri->resetting && (t - pri->lastreset) >= pri->resetinterval) {
pri->resetting = 1; pri->resetting = 1;
pri->resetpos = -1; pri->resetpos = -1;
} }
@ -7566,7 +7588,7 @@ static void *pri_dchannel(void *vpri)
time(&pri->lastreset); time(&pri->lastreset);
/* Restart in 5 seconds */ /* Restart in 5 seconds */
pri->lastreset -= RESET_INTERVAL; pri->lastreset -= pri->resetinterval;
pri->lastreset += 5; pri->lastreset += 5;
pri->resetting = 0; pri->resetting = 0;
/* Take the channels from inalarm condition */ /* Take the channels from inalarm condition */
@ -7727,13 +7749,35 @@ static void *pri_dchannel(void *vpri)
} }
pri->pvts[chanpos]->call = e->ring.call; pri->pvts[chanpos]->call = e->ring.call;
/* Get caller ID */ /* Get caller ID */
switch (e->ring.callingplan) {
case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
snprintf(plancallingnum, sizeof(plancallingnum), "%s%s", pri->internationalprefix, e->ring.callingnum);
break;
case PRI_NATIONAL_ISDN: /* Q.931 dialplan == 0x21 national dialplan => prepend national prefix digits */
snprintf(plancallingnum, sizeof(plancallingnum), "%s%s", pri->nationalprefix, e->ring.callingnum);
break;
case PRI_LOCAL_ISDN: /* Q.931 dialplan == 0x41 local dialplan => prepend local prefix digits */
snprintf(plancallingnum, sizeof(plancallingnum), "%s%s", pri->localprefix, e->ring.callingnum);
break;
case PRI_PRIVATE: /* Q.931 dialplan == 0x49 private dialplan => prepend private prefix digits */
snprintf(plancallingnum, sizeof(plancallingnum), "%s%s", pri->privateprefix, e->ring.callingnum);
break;
case PRI_UNKNOWN: /* Q.931 dialplan == 0x00 unknown dialplan => prepend unknown prefix digits */
snprintf(plancallingnum, sizeof(plancallingnum), "%s%s", pri->unknownprefix, e->ring.callingnum);
break;
default: /* other Q.931 dialplan => don't twiddle with callingnum */
snprintf(plancallingnum, sizeof(plancallingnum), "%s", e->ring.callingnum);
break;
}
if (pri->pvts[chanpos]->use_callerid) { if (pri->pvts[chanpos]->use_callerid) {
ast_shrink_phone_number(e->ring.callingnum); ast_shrink_phone_number(plancallingnum);
strncpy(pri->pvts[chanpos]->cid_num, e->ring.callingnum, sizeof(pri->pvts[chanpos]->cid_num)-1); strncpy(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num)-1);
strncpy(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name)-1); strncpy(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name)-1);
pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
} else { } else {
pri->pvts[chanpos]->cid_num[0] = '\0'; pri->pvts[chanpos]->cid_num[0] = '\0';
pri->pvts[chanpos]->cid_name[0] = '\0'; pri->pvts[chanpos]->cid_name[0] = '\0';
pri->pvts[chanpos]->cid_ton = 0;
} }
strncpy(pri->pvts[chanpos]->rdnis, e->ring.redirectingnum, sizeof(pri->pvts[chanpos]->rdnis) - 1); strncpy(pri->pvts[chanpos]->rdnis, e->ring.redirectingnum, sizeof(pri->pvts[chanpos]->rdnis) - 1);
/* If immediate=yes go to s|1 */ /* If immediate=yes go to s|1 */
@ -7788,6 +7832,7 @@ static void *pri_dchannel(void *vpri)
} }
/* Get the use_callingpres state */ /* Get the use_callingpres state */
pri->pvts[chanpos]->callingpres = e->ring.callingpres; pri->pvts[chanpos]->callingpres = e->ring.callingpres;
/* Start PBX */ /* Start PBX */
if (pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) { if (pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
/* Release the PRI lock while we create the channel */ /* Release the PRI lock while we create the channel */
@ -7808,27 +7853,30 @@ static void *pri_dchannel(void *vpri)
snprintf(ani2str, 5, "%.2d", e->ring.ani2); snprintf(ani2str, 5, "%.2d", e->ring.ani2);
pbx_builtin_setvar_helper(c, "ANI2", ani2str); pbx_builtin_setvar_helper(c, "ANI2", ani2str);
} }
if (!ast_strlen_zero(e->ring.useruserinfo)) {
pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
}
snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
if (e->ring.redirectingreason >= 0) { if (e->ring.redirectingreason >= 0) {
char redirstr[20] = ""; char redirstr[20] = "";
switch (e->ring.redirectingreason) { switch (e->ring.redirectingreason) {
case 0: case 0:
snprintf(redirstr, 20, "UNKNOWN"); snprintf(redirstr, sizeof(redirstr), "UNKNOWN");
break; break;
case 1: case 1:
snprintf(redirstr, 20, "BUSY"); snprintf(redirstr, sizeof(redirstr), "BUSY");
break; break;
case 2: case 2:
snprintf(redirstr, 20, "NO_REPLY"); snprintf(redirstr, sizeof(redirstr), "NO_REPLY");
break; break;
case 0xF: case 0xF:
snprintf(redirstr, 20, "UNCONDITIONAL"); /* Other reason */ snprintf(redirstr, sizeof(redirstr), "UNCONDITIONAL"); /* Other reason */
break; break;
default: default:
snprintf(redirstr, 20, "NOREDIRECT"); snprintf(redirstr, sizeof(redirstr), "NOREDIRECT");
break; break;
} }
pbx_builtin_setvar_helper(c, "PRIREDIRECTCAUSE", redirstr); pbx_builtin_setvar_helper(c, "PRIREDIRECTCAUSE", redirstr);
} }
@ -7836,7 +7884,7 @@ static void *pri_dchannel(void *vpri)
if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) { if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
if (option_verbose > 2) if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n", ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
e->ring.callingnum, !ast_strlen_zero(pri->pvts[chanpos]->exten) ? pri->pvts[chanpos]->exten : "<unspecified>", plancallingnum, !ast_strlen_zero(pri->pvts[chanpos]->exten) ? pri->pvts[chanpos]->exten : "<unspecified>",
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
} else { } else {
ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n", ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
@ -7858,9 +7906,15 @@ static void *pri_dchannel(void *vpri)
snprintf(ani2str, 5, "%d", e->ring.ani2); snprintf(ani2str, 5, "%d", e->ring.ani2);
pbx_builtin_setvar_helper(c, "ANI2", ani2str); pbx_builtin_setvar_helper(c, "ANI2", ani2str);
} }
if (!ast_strlen_zero(e->ring.useruserinfo)) {
pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
}
char calledtonstr[10];
snprintf(calledtonstr, sizeof(calledtonstr)-1, "%d", e->ring.calledplan);
pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
if (option_verbose > 2) if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n", ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
e->ring.callingnum, pri->pvts[chanpos]->exten, plancallingnum, pri->pvts[chanpos]->exten,
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span); pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
zt_enable_ec(pri->pvts[chanpos]); zt_enable_ec(pri->pvts[chanpos]);
} else { } else {
@ -8791,6 +8845,7 @@ static int zap_show_channel(int fd, int argc, char **argv)
ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no"); ast_cli(fd, "Dialing: %s\n", tmp->dialing ? "yes" : "no");
ast_cli(fd, "Context: %s\n", tmp->context); ast_cli(fd, "Context: %s\n", tmp->context);
ast_cli(fd, "Caller ID: %s\n", tmp->cid_num); ast_cli(fd, "Caller ID: %s\n", tmp->cid_num);
ast_cli(fd, "Calling TON: %d\n", tmp->cid_ton);
ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name); ast_cli(fd, "Caller ID name: %s\n", tmp->cid_name);
ast_cli(fd, "Destroy: %d\n", tmp->destroy); ast_cli(fd, "Destroy: %d\n", tmp->destroy);
ast_cli(fd, "InAlarm: %d\n", tmp->inalarm); ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
@ -9772,6 +9827,22 @@ static int setup_zap(int reload)
else else
ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n", ast_log(LOG_WARNING, "'%s' is not a valid pri indication value, should be 'inband' or 'outofband' at line %d\n",
v->value, v->lineno); v->value, v->lineno);
} else if (!strcasecmp(v->name, "internationalprefix")) {
strncpy(internationalprefix, v->value, sizeof(internationalprefix)-1);
} else if (!strcasecmp(v->name, "nationalprefix")) {
strncpy(nationalprefix, v->value, sizeof(nationalprefix)-1);
} else if (!strcasecmp(v->name, "localprefix")) {
strncpy(localprefix, v->value, sizeof(localprefix)-1);
} else if (!strcasecmp(v->name, "privateprefix")) {
strncpy(privateprefix, v->value, sizeof(privateprefix)-1);
} else if (!strcasecmp(v->name, "unknownprefix")) {
strncpy(unknownprefix, v->value, sizeof(unknownprefix)-1);
} else if (!strcasecmp(v->name, "resetinterval")) {
if( atoi(v->value) >= 60 )
resetinterval = atoi(v->value);
else
ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds at line %d\n",
v->value, v->lineno);
} else if (!strcasecmp(v->name, "minunused")) { } else if (!strcasecmp(v->name, "minunused")) {
minunused = atoi(v->value); minunused = atoi(v->value);
} else if (!strcasecmp(v->name, "idleext")) { } else if (!strcasecmp(v->name, "idleext")) {

@ -76,6 +76,29 @@ switchtype=national
; ;
;prilocaldialplan=national ;prilocaldialplan=national
; ;
; PRI callerid prefixes based on the given TON/NPI (dialplan)
; This is especially needed for euroisdn E1-PRIs
;
; sample 1 for Germany
;internationalprefix = 00
;nationalprefix = 0
;localprefix = 0711
;privateprefix = 07115678
;unknownprefix =
;
; sample 2 for Germany
;internationalprefix = +
;nationalprefix = +49
;localprefix = +49711
;privateprefix = +497115678
;unknownprefix =
;
; PRI resetinterval: sets the time in seconds between restart of unused channels, defaults to 3600
; minimum 60 seconds
; some PBXs don't like channel restarts. so set the interval to a very long interval e.g. 100000000
;
;resetinterval = 3600
;
; Overlap dialing mode (sending overlap digits) ; Overlap dialing mode (sending overlap digits)
; ;
;overlapdial=yes ;overlapdial=yes

Loading…
Cancel
Save