|
|
|
|
@@ -40,12 +40,6 @@
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <limits.h>
|
|
|
|
|
|
|
|
|
|
enum mandatory_ie_status {
|
|
|
|
|
MAND_STATUS_OK,
|
|
|
|
|
MAND_STATUS_CONTENT_ERROR,
|
|
|
|
|
MAND_STATUS_MISSING,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define MAX_MAND_IES 10
|
|
|
|
|
|
|
|
|
|
struct msgtype {
|
|
|
|
|
@@ -56,27 +50,13 @@ struct msgtype {
|
|
|
|
|
|
|
|
|
|
static struct msgtype msgs[] = {
|
|
|
|
|
/* Call establishment messages */
|
|
|
|
|
{ Q931_ALERTING, "ALERTING", { Q931_CHANNEL_IDENT } },
|
|
|
|
|
{ Q931_CALL_PROCEEDING, "CALL PROCEEDING", { Q931_CHANNEL_IDENT } },
|
|
|
|
|
{ Q931_CONNECT, "CONNECT", { Q931_CHANNEL_IDENT } },
|
|
|
|
|
{ Q931_ALERTING, "ALERTING" },
|
|
|
|
|
{ Q931_CALL_PROCEEDING, "CALL PROCEEDING" },
|
|
|
|
|
{ Q931_CONNECT, "CONNECT" },
|
|
|
|
|
{ Q931_CONNECT_ACKNOWLEDGE, "CONNECT ACKNOWLEDGE" },
|
|
|
|
|
/*
|
|
|
|
|
* Very early in libpri SVN history (SVN -r154) a change was explicitly
|
|
|
|
|
* made to not care about a missing Progress Indicator ie. There is no
|
|
|
|
|
* explanation in the commit message why this was done even though
|
|
|
|
|
* Q.931 and ECMA-143 clearly show that the ie is mandatory for a
|
|
|
|
|
* PROGRESS message.
|
|
|
|
|
*
|
|
|
|
|
* Hazzarding a guess, I think it was because of the
|
|
|
|
|
* ALERTING_NO_PROGRESS support for Mitel switches. (SVN -r44)
|
|
|
|
|
*/
|
|
|
|
|
#ifdef ALERTING_NO_PROGRESS
|
|
|
|
|
{ Q931_PROGRESS, "PROGRESS" },
|
|
|
|
|
#else
|
|
|
|
|
{ Q931_PROGRESS, "PROGRESS", { Q931_PROGRESS_INDICATOR } },
|
|
|
|
|
#endif
|
|
|
|
|
{ Q931_SETUP, "SETUP", { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT } },
|
|
|
|
|
{ Q931_SETUP_ACKNOWLEDGE, "SETUP ACKNOWLEDGE", { Q931_CHANNEL_IDENT } },
|
|
|
|
|
{ Q931_SETUP_ACKNOWLEDGE, "SETUP ACKNOWLEDGE" },
|
|
|
|
|
|
|
|
|
|
/* Call disestablishment messages */
|
|
|
|
|
{ Q931_DISCONNECT, "DISCONNECT", { Q931_CAUSE } },
|
|
|
|
|
@@ -113,7 +93,7 @@ static struct msgtype msgs[] = {
|
|
|
|
|
{ Q931_ANY_MESSAGE, "ANY MESSAGE" },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, enum mandatory_ie_status mand_status);
|
|
|
|
|
static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, int missingmand);
|
|
|
|
|
static void nt_ptmp_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, int *allow_event, int *allow_posthandle);
|
|
|
|
|
|
|
|
|
|
struct msgtype att_maintenance_msgs[] = {
|
|
|
|
|
@@ -1278,14 +1258,6 @@ static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, in
|
|
|
|
|
int pos = 0;
|
|
|
|
|
int need_extended_channel_octets;/*!< TRUE if octets 3.2 and 3.3 need to be present. */
|
|
|
|
|
|
|
|
|
|
call->channel_id_ie_mandatory = 0;
|
|
|
|
|
|
|
|
|
|
if (ie->len < 1) {
|
|
|
|
|
/* Must have at least one payload octet. */
|
|
|
|
|
pri_error(ctrl, "!! Channel Identification ie too short\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
call->restart.count = 0;
|
|
|
|
|
|
|
|
|
|
if (ie->data[0] & 0x08) {
|
|
|
|
|
@@ -1336,24 +1308,10 @@ static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, in
|
|
|
|
|
|
|
|
|
|
pos++;
|
|
|
|
|
if (ie->data[0] & 0x40) {
|
|
|
|
|
/* Explicitly defined DS1 (One or more 3.1 octets expected) */
|
|
|
|
|
if (ctrl->switchtype == PRI_SWITCH_QSIG) {
|
|
|
|
|
pri_error(ctrl, "!! Q.SIG does not support Channel Identification octet 3.1\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (ie->len <= pos) {
|
|
|
|
|
pri_error(ctrl, "!! Missing expected Channel Identification octet 3.1\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Extract explicit DS1 reference. */
|
|
|
|
|
call->ds1no = ie->data[pos] & 0x7f;
|
|
|
|
|
/* DS1 specified -- stop here */
|
|
|
|
|
call->ds1no = ie->data[1] & 0x7f;
|
|
|
|
|
call->ds1explicit = 1;
|
|
|
|
|
|
|
|
|
|
/* Advance to 3.2 octet if present. */
|
|
|
|
|
do {
|
|
|
|
|
++pos;
|
|
|
|
|
} while (pos < ie->len && !(ie->data[pos - 1] & 0x80));
|
|
|
|
|
pos++;
|
|
|
|
|
} else {
|
|
|
|
|
call->ds1explicit = 0;
|
|
|
|
|
}
|
|
|
|
|
@@ -1366,12 +1324,8 @@ static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, in
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (need_extended_channel_octets && pos + 2 <= ie->len) {
|
|
|
|
|
/*
|
|
|
|
|
* Octet 3.2 and at least one octet 3.3 are present.
|
|
|
|
|
*
|
|
|
|
|
* Process octet 3.2
|
|
|
|
|
*/
|
|
|
|
|
if (need_extended_channel_octets && pos + 2 < len) {
|
|
|
|
|
/* More coming */
|
|
|
|
|
if ((ie->data[pos] & 0x0f) != 3) {
|
|
|
|
|
/* Channel type/mapping is not for B channel units. */
|
|
|
|
|
pri_error(ctrl, "!! Unexpected Channel Type %d\n", ie->data[pos] & 0x0f);
|
|
|
|
|
@@ -1381,25 +1335,14 @@ static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, in
|
|
|
|
|
pri_error(ctrl, "!! Invalid CCITT coding %d\n", (ie->data[pos] & 0x60) >> 5);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (ie->data[pos++] & 0x10) {
|
|
|
|
|
/* Process 3.3 octets as a Slot Map */
|
|
|
|
|
if (ie->data[pos] & 0x10) {
|
|
|
|
|
/* Expect Slot Map */
|
|
|
|
|
call->slotmap = 0;
|
|
|
|
|
pos++;
|
|
|
|
|
call->slotmap_size = (ie->len - pos > 3) ? 1 : 0;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We will be tolerant of partial slot maps that do not
|
|
|
|
|
* specify the upper channels. We will assume they
|
|
|
|
|
* are not requested.
|
|
|
|
|
*
|
|
|
|
|
* We will only read up to 24 or 32 bit channel maps.
|
|
|
|
|
*/
|
|
|
|
|
for (x = call->slotmap_size ? 4 : 3; x--;) {
|
|
|
|
|
for (x = 0; x < (call->slotmap_size ? 4 : 3); ++x) {
|
|
|
|
|
call->slotmap <<= 8;
|
|
|
|
|
call->slotmap |= ie->data[pos++];
|
|
|
|
|
if (ie->len <= pos) {
|
|
|
|
|
/* No more ie contents. */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
call->slotmap |= ie->data[x + pos];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (msgtype == Q931_RESTART) {
|
|
|
|
|
@@ -1414,11 +1357,8 @@ static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, in
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/*
|
|
|
|
|
* Process 3.3 octets as either a single channel or a channel list
|
|
|
|
|
*
|
|
|
|
|
* Get single channel
|
|
|
|
|
*/
|
|
|
|
|
pos++;
|
|
|
|
|
/* Only expect a particular channel */
|
|
|
|
|
call->channelno = ie->data[pos] & 0x7f;
|
|
|
|
|
if (ctrl->chan_mapping_logical && call->channelno > 15) {
|
|
|
|
|
call->channelno++;
|
|
|
|
|
@@ -1445,9 +1385,6 @@ static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, in
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (need_extended_channel_octets) {
|
|
|
|
|
pri_error(ctrl, "!! Missing expected Channel Identification octets 3.2 or 3.3\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
@@ -1581,29 +1518,21 @@ static void dump_channel_id(int full_ie, struct pri *ctrl, q931_ie *ie, int len,
|
|
|
|
|
(ie->data[0] & 0x08) ? "Exclusive" : "Preferred",
|
|
|
|
|
(ie->data[0] & 0x04) ? 1 : 0);
|
|
|
|
|
pri_message(ctrl, "%c ChanSel: %s\n",
|
|
|
|
|
prefix, msg_chan_sel[(ie->data[0] & 0x03) | ((ie->data[0] & 0x20) >> 3)]);
|
|
|
|
|
prefix, msg_chan_sel[(ie->data[0] & 0x03) | ((ie->data[0] >> 3) & 0x04)]);
|
|
|
|
|
pos = 1;
|
|
|
|
|
len -= 2;
|
|
|
|
|
if (ie->data[0] & 0x40) {
|
|
|
|
|
/* Explicitly defined DS1 (One or more 3.1 octets expected) */
|
|
|
|
|
if (ctrl->switchtype == PRI_SWITCH_QSIG) {
|
|
|
|
|
pri_message(ctrl, "%c Octet 3.1 specified when Q.SIG!\n",
|
|
|
|
|
prefix);
|
|
|
|
|
}
|
|
|
|
|
if (pos < len) {
|
|
|
|
|
do {
|
|
|
|
|
pri_message(ctrl, "%c Ext: %d DS1 Identifier: %d\n",
|
|
|
|
|
prefix, (ie->data[pos] & 0x80) >> 7, ie->data[pos] & 0x7f);
|
|
|
|
|
++pos;
|
|
|
|
|
} while (!(ie->data[pos - 1] & 0x80) && pos < len);
|
|
|
|
|
} else {
|
|
|
|
|
pri_message(ctrl, "%c Octet 3.1 is missing!\n", prefix);
|
|
|
|
|
}
|
|
|
|
|
/* Explicitly defined DS1 */
|
|
|
|
|
do {
|
|
|
|
|
pri_message(ctrl, "%c Ext: %d DS1 Identifier: %d \n",
|
|
|
|
|
prefix, (ie->data[pos] & 0x80) >> 7, ie->data[pos] & 0x7f);
|
|
|
|
|
++pos;
|
|
|
|
|
} while (!(ie->data[pos - 1] & 0x80) && pos < len);
|
|
|
|
|
} else {
|
|
|
|
|
/* Implicitly defined DS1 */
|
|
|
|
|
}
|
|
|
|
|
if (pos < len) {
|
|
|
|
|
/* Octet 3.2 present */
|
|
|
|
|
/* Still more information here */
|
|
|
|
|
pri_message(ctrl,
|
|
|
|
|
"%c Ext: %d Coding: %d %s Specified Channel Type: %d\n",
|
|
|
|
|
prefix, (ie->data[pos] & 0x80) >> 7, (ie->data[pos] & 60) >> 5,
|
|
|
|
|
@@ -1611,7 +1540,6 @@ static void dump_channel_id(int full_ie, struct pri *ctrl, q931_ie *ie, int len,
|
|
|
|
|
++pos;
|
|
|
|
|
}
|
|
|
|
|
if (pos < len) {
|
|
|
|
|
/* One or more 3.3 octets present */
|
|
|
|
|
if (!(ie->data[pos - 1] & 0x10)) {
|
|
|
|
|
/* Number specified */
|
|
|
|
|
do {
|
|
|
|
|
@@ -2196,33 +2124,17 @@ static int transmit_subaddr_helper(int full_ie, struct pri *ctrl, struct q931_pa
|
|
|
|
|
|
|
|
|
|
static int receive_subaddr_helper(int full_ie, struct pri *ctrl, struct q931_party_subaddress *q931_subaddress, int msgtype, q931_ie *ie, int offset, int len)
|
|
|
|
|
{
|
|
|
|
|
int i = -1;
|
|
|
|
|
|
|
|
|
|
if (len <= 0) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* To follow Q.931 (4.5.1), we must search for start of octet 4 by
|
|
|
|
|
* walking through all bytes until one with ext bit (8) set to 1
|
|
|
|
|
*/
|
|
|
|
|
do {
|
|
|
|
|
++i;
|
|
|
|
|
switch (i) {
|
|
|
|
|
case 0: /* Octet 3 */
|
|
|
|
|
/* type: 0 = NSAP, 2 = User Specified */
|
|
|
|
|
q931_subaddress->type = ((ie->data[0] & 0x70) >> 4);
|
|
|
|
|
q931_subaddress->odd_even_indicator = (ie->data[0] & 0x08) ? 1 : 0;
|
|
|
|
|
break;
|
|
|
|
|
default: /* Octet 3* extra */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} while (!(ie->data[i] & 0x80) && len - i);
|
|
|
|
|
|
|
|
|
|
q931_subaddress->valid = 1;
|
|
|
|
|
q931_subaddress->length = len - i;
|
|
|
|
|
q931_subaddress->length = len;
|
|
|
|
|
/* type: 0 = NSAP, 2 = User Specified */
|
|
|
|
|
q931_subaddress->type = ((ie->data[0] & 0x70) >> 4);
|
|
|
|
|
q931_subaddress->odd_even_indicator = (ie->data[0] & 0x08) ? 1 : 0;
|
|
|
|
|
q931_memget(q931_subaddress->data, sizeof(q931_subaddress->data),
|
|
|
|
|
ie->data + offset + i, len - i);
|
|
|
|
|
ie->data + offset, len);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
@@ -2230,22 +2142,13 @@ static int receive_subaddr_helper(int full_ie, struct pri *ctrl, struct q931_par
|
|
|
|
|
static void dump_subaddr_helper(int full_ie, struct pri *ctrl, q931_ie *ie, int offset, int len, int datalen, char prefix)
|
|
|
|
|
{
|
|
|
|
|
unsigned char cnum[256];
|
|
|
|
|
int i = -1;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* To follow Q.931 (4.5.1), we must search for start of octet 4 by
|
|
|
|
|
* walking through all bytes until one with ext bit (8) set to 1
|
|
|
|
|
*/
|
|
|
|
|
do {
|
|
|
|
|
++i;
|
|
|
|
|
} while (!(ie->data[i] & 0x80) && datalen - i);
|
|
|
|
|
|
|
|
|
|
if (!(ie->data[0] & 0x70)) {
|
|
|
|
|
/* NSAP Get it as a string for dump display purposes only. */
|
|
|
|
|
q931_strget(cnum, sizeof(cnum), ie->data + offset + i, datalen - i);
|
|
|
|
|
q931_strget(cnum, sizeof(cnum), ie->data + offset, datalen);
|
|
|
|
|
} else {
|
|
|
|
|
/* User Specified */
|
|
|
|
|
q931_get_subaddr_specific(cnum, sizeof(cnum), ie->data + offset + i, datalen - i,
|
|
|
|
|
q931_get_subaddr_specific(cnum, sizeof(cnum), ie->data + offset, datalen,
|
|
|
|
|
ie->data[0] & 0x08);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2365,7 +2268,6 @@ static int receive_connected_number(int full_ie, struct pri *ctrl, q931_call *ca
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
/* Reference Q.951 Section 5.4.1 for ie */
|
|
|
|
|
call->connected_number_in_message = 1;
|
|
|
|
|
call->remote_id.number.valid = 1;
|
|
|
|
|
call->remote_id.number.presentation =
|
|
|
|
|
@@ -2376,39 +2278,7 @@ static int receive_connected_number(int full_ie, struct pri *ctrl, q931_call *ca
|
|
|
|
|
switch (i) {
|
|
|
|
|
case 0:
|
|
|
|
|
call->remote_id.number.plan = ie->data[i] & 0x7f;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Work around a bug in a Lucent switch implementation that
|
|
|
|
|
* sets the extension bit in octet 3 even though octet 3a
|
|
|
|
|
* is present.
|
|
|
|
|
*
|
|
|
|
|
* The same issue was seen in a NI2 switch implementation.
|
|
|
|
|
* It was probably a Lucent switch configured for NI2
|
|
|
|
|
* operation. To avoid further surprises, I'm going to
|
|
|
|
|
* enable the work around for all North American switch
|
|
|
|
|
* types.
|
|
|
|
|
*/
|
|
|
|
|
if (ie->data[i] & 0x80) {
|
|
|
|
|
/* Octet 3 extension bit is set */
|
|
|
|
|
if (ctrl->switchtype != PRI_SWITCH_LUCENT5E
|
|
|
|
|
&& ctrl->switchtype != PRI_SWITCH_ATT4ESS
|
|
|
|
|
&& ctrl->switchtype != PRI_SWITCH_NI1
|
|
|
|
|
&& ctrl->switchtype != PRI_SWITCH_NI2
|
|
|
|
|
&& ctrl->switchtype != PRI_SWITCH_DMS100) {
|
|
|
|
|
/* Not a potentially buggy switch type. */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!(ie->data[i + 1] & 0x80)) {
|
|
|
|
|
/*
|
|
|
|
|
* The possible octet 3a doesn't have the extension
|
|
|
|
|
* bit set. It is likely not the erroneous octet 3a.
|
|
|
|
|
*/
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Octet 3a is present */
|
|
|
|
|
++i;
|
|
|
|
|
/* Fall through */
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
/* Keep only the presentation and screening fields */
|
|
|
|
|
call->remote_id.number.presentation =
|
|
|
|
|
@@ -2450,44 +2320,7 @@ static void dump_connected_number(int full_ie, struct pri *ctrl, q931_ie *ie, in
|
|
|
|
|
prefix, ie2str(full_ie), len, ie->data[0] >> 7,
|
|
|
|
|
ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07,
|
|
|
|
|
npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Work around a bug in a Lucent switch implementation that
|
|
|
|
|
* sets the extension bit in octet 3 even though octet 3a
|
|
|
|
|
* is present.
|
|
|
|
|
*
|
|
|
|
|
* The same issue was seen in a NI2 switch implementation.
|
|
|
|
|
* It was probably a Lucent switch configured for NI2
|
|
|
|
|
* operation. To avoid further surprises, I'm going to
|
|
|
|
|
* enable the work around for all North American switch
|
|
|
|
|
* types.
|
|
|
|
|
*/
|
|
|
|
|
if (ie->data[i] & 0x80) {
|
|
|
|
|
/* Octet 3 extension bit is set */
|
|
|
|
|
if (ctrl->switchtype != PRI_SWITCH_LUCENT5E
|
|
|
|
|
&& ctrl->switchtype != PRI_SWITCH_ATT4ESS
|
|
|
|
|
&& ctrl->switchtype != PRI_SWITCH_NI1
|
|
|
|
|
&& ctrl->switchtype != PRI_SWITCH_NI2
|
|
|
|
|
&& ctrl->switchtype != PRI_SWITCH_DMS100) {
|
|
|
|
|
/* Not a potentially buggy switch type. */
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!(ie->data[i + 1] & 0x80)) {
|
|
|
|
|
/*
|
|
|
|
|
* The possible octet 3a doesn't have the extension
|
|
|
|
|
* bit set. It is likely not the erroneous octet 3a.
|
|
|
|
|
*/
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
pri_message(ctrl, "\n");
|
|
|
|
|
pri_message(ctrl, "%c Switch bug workaround.\n",
|
|
|
|
|
prefix);
|
|
|
|
|
pri_message(ctrl, "%c Assuming octet 3a is present.",
|
|
|
|
|
prefix);
|
|
|
|
|
}
|
|
|
|
|
/* Octet 3a is present */
|
|
|
|
|
++i;
|
|
|
|
|
/* Fall through */
|
|
|
|
|
break;
|
|
|
|
|
case 1: /* Octet 3a */
|
|
|
|
|
pri_message(ctrl, "\n");
|
|
|
|
|
pri_message(ctrl, "%c Ext: %d Presentation: %s (%d)",
|
|
|
|
|
@@ -2524,7 +2357,6 @@ static int receive_redirecting_number(int full_ie, struct pri *ctrl, q931_call *
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
/* Reference Q.952 Section 4.1.2 for ie */
|
|
|
|
|
call->redirecting_number_in_message = 1;
|
|
|
|
|
call->redirecting.from.number.valid = 1;
|
|
|
|
|
call->redirecting.from.number.presentation =
|
|
|
|
|
@@ -2603,7 +2435,6 @@ static int receive_redirection_number(int full_ie, struct pri *ctrl, q931_call *
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
|
|
/* Reference Q.952 Section 4.1.3 for ie */
|
|
|
|
|
call->redirection_number.valid = 1;
|
|
|
|
|
call->redirection_number.presentation =
|
|
|
|
|
PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
|
|
|
|
|
@@ -2747,7 +2578,6 @@ static int receive_calling_party_number(int full_ie, struct pri *ctrl, q931_call
|
|
|
|
|
int i = 0;
|
|
|
|
|
struct q931_party_number number;
|
|
|
|
|
|
|
|
|
|
/* Reference Q.931 Section 4.5.10 for ie */
|
|
|
|
|
q931_party_number_init(&number);
|
|
|
|
|
number.valid = 1;
|
|
|
|
|
number.presentation = PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED;
|
|
|
|
|
@@ -2851,33 +2681,10 @@ static void dump_change_status(int full_ie, struct pri *ctrl, q931_ie *ie, int l
|
|
|
|
|
pri_message(ctrl, " %02x", ie->data[x] & 0x7f);
|
|
|
|
|
}
|
|
|
|
|
pri_message(ctrl, " ]\n");
|
|
|
|
|
|
|
|
|
|
switch (ctrl->switchtype) {
|
|
|
|
|
case PRI_SWITCH_NI2:
|
|
|
|
|
case PRI_SWITCH_DMS100:
|
|
|
|
|
case PRI_SWITCH_LUCENT5E:
|
|
|
|
|
case PRI_SWITCH_ATT4ESS:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
/* ie not supported by this switch type */
|
|
|
|
|
pri_message(ctrl, "%c %s is treated as unknown by current switch type.\n",
|
|
|
|
|
prefix, ie2str(full_ie));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int receive_change_status(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
|
|
|
|
|
{
|
|
|
|
|
switch (ctrl->switchtype) {
|
|
|
|
|
case PRI_SWITCH_NI2:
|
|
|
|
|
case PRI_SWITCH_DMS100:
|
|
|
|
|
case PRI_SWITCH_LUCENT5E:
|
|
|
|
|
case PRI_SWITCH_ATT4ESS:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
/* ie not supported by this switch type */
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
call->changestatus = ie->data[0] & 0x0f;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
@@ -3034,7 +2841,7 @@ static int receive_progress_indicator(int full_ie, struct pri *ctrl, q931_call *
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
pri_error(ctrl, "XXX Invalid Progress indicator value received: %02x\n",(ie->data[1] & 0x7f));
|
|
|
|
|
return -1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
@@ -4148,11 +3955,8 @@ static int transmit_reverse_charging_indication(int full_ie, struct pri *ctrl, q
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct ie ies[] = {
|
|
|
|
|
/* Codeset 0 - Comprehension required ie's with varying support. */
|
|
|
|
|
{ 1, Q931_IE_SEGMENTED_MSG, "Segmented Message" }, /* Not supported. Just ie name is available for message decode. */
|
|
|
|
|
{ 1, Q931_IE_CHANGE_STATUS, "Change Status Information", dump_change_status, receive_change_status, transmit_change_status },
|
|
|
|
|
|
|
|
|
|
/* Codeset 0 - Common */
|
|
|
|
|
{ 1, NATIONAL_CHANGE_STATUS, "Change Status Information", dump_change_status, receive_change_status, transmit_change_status },
|
|
|
|
|
{ 0, Q931_LOCKING_SHIFT, "Locking Shift", dump_shift },
|
|
|
|
|
{ 0, Q931_BEARER_CAPABILITY, "Bearer Capability", dump_bearer_capability, receive_bearer_capability, transmit_bearer_capability },
|
|
|
|
|
{ 0, Q931_CAUSE, "Cause", dump_cause, receive_cause, transmit_cause },
|
|
|
|
|
@@ -4184,6 +3988,7 @@ static struct ie ies[] = {
|
|
|
|
|
{ 1, Q931_IE_FEATURE_ACTIVATE, "Feature Activation" },
|
|
|
|
|
{ 1, Q931_IE_INFO_REQUEST, "Feature Request" },
|
|
|
|
|
{ 1, Q931_IE_FEATURE_IND, "Feature Indication" },
|
|
|
|
|
{ 1, Q931_IE_SEGMENTED_MSG, "Segmented Message" },
|
|
|
|
|
{ 1, Q931_IE_CALL_IDENTITY, "Call Identity", dump_call_identity },
|
|
|
|
|
{ 1, Q931_IE_ENDPOINT_ID, "Endpoint Identification" },
|
|
|
|
|
{ 1, Q931_IE_NOTIFY_IND, "Notification Indicator", dump_notify, receive_notify, transmit_notify },
|
|
|
|
|
@@ -4195,6 +4000,7 @@ static struct ie ies[] = {
|
|
|
|
|
{ 1, Q931_IE_USER_USER, "User-User Information", dump_user_user, receive_user_user, transmit_user_user },
|
|
|
|
|
{ 1, Q931_IE_ESCAPE_FOR_EXT, "Escape for Extension" },
|
|
|
|
|
{ 1, Q931_IE_CALL_STATUS, "Call Status" },
|
|
|
|
|
{ 1, Q931_IE_CHANGE_STATUS, "Change Status Information", dump_change_status, receive_change_status, transmit_change_status },
|
|
|
|
|
{ 1, Q931_IE_CONNECTED_ADDR, "Connected Address", dump_connected_number, receive_connected_number, transmit_connected_number },
|
|
|
|
|
{ 1, Q931_IE_CONNECTED_NUM, "Connected Number", dump_connected_number, receive_connected_number, transmit_connected_number },
|
|
|
|
|
{ 1, Q931_IE_CONNECTED_SUBADDR, "Connected Subaddress", dump_connected_subaddr, receive_connected_subaddr, transmit_connected_subaddr },
|
|
|
|
|
@@ -4986,7 +4792,7 @@ static int add_ie(struct pri *ctrl, q931_call *call, int msgtype, int ie, q931_i
|
|
|
|
|
}
|
|
|
|
|
return total_res;
|
|
|
|
|
} else {
|
|
|
|
|
pri_error(ctrl, "!! Don't know how to add IE %d (%s)\n", ie, ie2str(ie));
|
|
|
|
|
pri_error(ctrl, "!! Don't know how to add an IE %s (%d)\n", ie2str(ie), ie);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -5807,12 +5613,11 @@ int q931_notify(struct pri *ctrl, q931_call *c, int channel, int info)
|
|
|
|
|
return q931_notify_redirection(ctrl, c, info, NULL, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int call_progress_ies[] = {
|
|
|
|
|
#ifndef ALERTING_NO_PROGRESS
|
|
|
|
|
Q931_PROGRESS_INDICATOR,
|
|
|
|
|
#ifdef ALERTING_NO_PROGRESS
|
|
|
|
|
static int call_progress_ies[] = { -1 };
|
|
|
|
|
#else
|
|
|
|
|
static int call_progress_ies[] = { Q931_PROGRESS_INDICATOR, -1 };
|
|
|
|
|
#endif
|
|
|
|
|
-1
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int q931_call_progress(struct pri *ctrl, q931_call *c, int channel, int info)
|
|
|
|
|
{
|
|
|
|
|
@@ -5840,13 +5645,11 @@ int q931_call_progress(struct pri *ctrl, q931_call *c, int channel, int info)
|
|
|
|
|
return send_message(ctrl, c, Q931_PROGRESS, call_progress_ies);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int call_progress_with_cause_ies[] = {
|
|
|
|
|
Q931_CAUSE,
|
|
|
|
|
#ifndef ALERTING_NO_PROGRESS
|
|
|
|
|
Q931_PROGRESS_INDICATOR,
|
|
|
|
|
#ifdef ALERTING_NO_PROGRESS
|
|
|
|
|
static int call_progress_with_cause_ies[] = { Q931_CAUSE, -1 };
|
|
|
|
|
#else
|
|
|
|
|
static int call_progress_with_cause_ies[] = { Q931_CAUSE, Q931_PROGRESS_INDICATOR, -1 };
|
|
|
|
|
#endif
|
|
|
|
|
-1
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int q931_call_progress_with_cause(struct pri *ctrl, q931_call *c, int channel, int info, int cause)
|
|
|
|
|
{
|
|
|
|
|
@@ -5878,13 +5681,11 @@ int q931_call_progress_with_cause(struct pri *ctrl, q931_call *c, int channel, i
|
|
|
|
|
return send_message(ctrl, c, Q931_PROGRESS, call_progress_with_cause_ies);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int call_proceeding_ies[] = {
|
|
|
|
|
Q931_CHANNEL_IDENT,
|
|
|
|
|
#ifndef ALERTING_NO_PROGRESS
|
|
|
|
|
Q931_PROGRESS_INDICATOR,
|
|
|
|
|
#ifdef ALERTING_NO_PROGRESS
|
|
|
|
|
static int call_proceeding_ies[] = { Q931_CHANNEL_IDENT, -1 };
|
|
|
|
|
#else
|
|
|
|
|
static int call_proceeding_ies[] = { Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, -1 };
|
|
|
|
|
#endif
|
|
|
|
|
-1
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int q931_call_proceeding(struct pri *ctrl, q931_call *c, int channel, int info)
|
|
|
|
|
{
|
|
|
|
|
@@ -5915,15 +5716,11 @@ int q931_call_proceeding(struct pri *ctrl, q931_call *c, int channel, int info)
|
|
|
|
|
c->alive = 1;
|
|
|
|
|
return send_message(ctrl, c, Q931_CALL_PROCEEDING, call_proceeding_ies);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int alerting_ies[] = {
|
|
|
|
|
Q931_IE_FACILITY,
|
|
|
|
|
#ifndef ALERTING_NO_PROGRESS
|
|
|
|
|
Q931_PROGRESS_INDICATOR,
|
|
|
|
|
static int alerting_ies[] = { Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, Q931_IE_USER_USER, -1 };
|
|
|
|
|
#else
|
|
|
|
|
static int alerting_ies[] = { Q931_IE_FACILITY, -1 };
|
|
|
|
|
#endif
|
|
|
|
|
Q931_IE_USER_USER,
|
|
|
|
|
-1
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
int q931_alerting(struct pri *ctrl, q931_call *c, int channel, int info)
|
|
|
|
|
{
|
|
|
|
|
@@ -6486,9 +6283,6 @@ int q931_setup(struct pri *ctrl, q931_call *c, struct pri_sr *req)
|
|
|
|
|
c->chanflags = FLAG_PREFERRED;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (ctrl->localtype == PRI_CPE) {
|
|
|
|
|
c->channel_id_ie_mandatory = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c->slotmap = -1;
|
|
|
|
|
c->nonisdn = req->nonisdn;
|
|
|
|
|
@@ -7479,8 +7273,6 @@ static int prepare_to_handle_q931_message(struct pri *ctrl, q931_mh *mh, q931_ca
|
|
|
|
|
c->cause = -1;
|
|
|
|
|
c->causecode = -1;
|
|
|
|
|
c->causeloc = -1;
|
|
|
|
|
c->progress = -1;
|
|
|
|
|
c->progressmask = 0;
|
|
|
|
|
c->aoc_units = -1;
|
|
|
|
|
pri_schedule_del(ctrl, c->retranstimer);
|
|
|
|
|
c->retranstimer = 0;
|
|
|
|
|
@@ -7685,13 +7477,12 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
|
|
|
|
|
int res;
|
|
|
|
|
int r;
|
|
|
|
|
int mandies[MAX_MAND_IES];
|
|
|
|
|
int is_mandatory;
|
|
|
|
|
int missingmand;
|
|
|
|
|
int codeset, cur_codeset;
|
|
|
|
|
int last_ie[8];
|
|
|
|
|
int cref;
|
|
|
|
|
int allow_event;
|
|
|
|
|
int allow_posthandle;
|
|
|
|
|
enum mandatory_ie_status mand_status;
|
|
|
|
|
|
|
|
|
|
ctrl = link->ctrl;
|
|
|
|
|
memset(last_ie, 0, sizeof(last_ie));
|
|
|
|
|
@@ -7771,7 +7562,7 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
|
|
|
|
|
q931_clr_subcommands(ctrl);
|
|
|
|
|
q931_display_clear(c);
|
|
|
|
|
|
|
|
|
|
/* Determine which ies are mandatory for this message. */
|
|
|
|
|
/* Handle IEs */
|
|
|
|
|
memset(mandies, 0, sizeof(mandies));
|
|
|
|
|
for (x = 0; x < ARRAY_LEN(msgs); ++x) {
|
|
|
|
|
if (msgs[x].msgnum == mh->msg) {
|
|
|
|
|
@@ -7779,25 +7570,6 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (x = 0; x < ARRAY_LEN(mandies); ++x) {
|
|
|
|
|
if (mandies[x]) {
|
|
|
|
|
/* Check mandatory channel identification ie exceptions */
|
|
|
|
|
if (mandies[x] != Q931_CHANNEL_IDENT
|
|
|
|
|
/* Always mandatory for RESUME_ACKNOWLEDGE */
|
|
|
|
|
|| mh->msg == Q931_RESUME_ACKNOWLEDGE
|
|
|
|
|
/* Mandatory in Net -> CPE direction for SETUP */
|
|
|
|
|
|| (mh->msg == Q931_SETUP && ctrl->localtype == PRI_CPE)
|
|
|
|
|
/* Mandatory for first SETUP response message in Net -> CPE direction. */
|
|
|
|
|
|| c->channel_id_ie_mandatory) {
|
|
|
|
|
/* ie is mandatory for this message */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
/* ie is not mandatory for this message */
|
|
|
|
|
mandies[x] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
mand_status = MAND_STATUS_OK;
|
|
|
|
|
|
|
|
|
|
/* Do real IE processing */
|
|
|
|
|
len -= (h->crlen + 3);
|
|
|
|
|
codeset = cur_codeset = 0;
|
|
|
|
|
@@ -7814,16 +7586,10 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
|
|
|
|
|
q931_display_clear(c);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check if processing a mandatory ie. */
|
|
|
|
|
is_mandatory = 0;
|
|
|
|
|
for (y = 0; y < ARRAY_LEN(mandies); ++y) {
|
|
|
|
|
if (mandies[y] == Q931_FULL_IE(cur_codeset, ie->ie)) {
|
|
|
|
|
if (mandies[y] == Q931_FULL_IE(cur_codeset, ie->ie))
|
|
|
|
|
mandies[y] = 0;
|
|
|
|
|
is_mandatory = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Special processing for codeset shifts */
|
|
|
|
|
switch (ie->ie & 0xf8) {
|
|
|
|
|
case Q931_LOCKING_SHIFT:
|
|
|
|
|
@@ -7866,15 +7632,6 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
|
|
|
|
|
/* Fall through */
|
|
|
|
|
default:
|
|
|
|
|
y = q931_handle_ie(cur_codeset, ctrl, c, mh->msg, ie);
|
|
|
|
|
if (y < 0 && is_mandatory) {
|
|
|
|
|
/* Error processing mandatory ie. */
|
|
|
|
|
mand_status = MAND_STATUS_CONTENT_ERROR;
|
|
|
|
|
pri_error(ctrl, "%s: Error in mandatory IE %d (cs%d, %s)\n",
|
|
|
|
|
msg2str(mh->msg),
|
|
|
|
|
ie->ie,
|
|
|
|
|
cur_codeset,
|
|
|
|
|
ie2str(Q931_FULL_IE(codeset, ie->ie)));
|
|
|
|
|
}
|
|
|
|
|
/* XXX Applicable to codeset 0 only? XXX */
|
|
|
|
|
if (!cur_codeset && !(ie->ie & 0xf0) && (y < 0)) {
|
|
|
|
|
/*
|
|
|
|
|
@@ -7891,21 +7648,19 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Check for missing mandatory ies. */
|
|
|
|
|
missingmand = 0;
|
|
|
|
|
for (x = 0; x < ARRAY_LEN(mandies); ++x) {
|
|
|
|
|
if (mandies[x]) {
|
|
|
|
|
/* This mandatory ie was not processed. */
|
|
|
|
|
mand_status = MAND_STATUS_MISSING;
|
|
|
|
|
pri_error(ctrl, "%s: Missing mandatory IE %d (cs%d, %s)\n",
|
|
|
|
|
msg2str(mh->msg),
|
|
|
|
|
Q931_IE_IE(mandies[x]),
|
|
|
|
|
Q931_IE_CODESET(mandies[x]),
|
|
|
|
|
ie2str(mandies[x]));
|
|
|
|
|
/* check if there is no channel identification when we're configured as network -> that's not an error */
|
|
|
|
|
if (((ctrl->localtype != PRI_NETWORK) || (mh->msg != Q931_SETUP) || (mandies[x] != Q931_CHANNEL_IDENT)) &&
|
|
|
|
|
((mh->msg != Q931_PROGRESS) || (mandies[x] != Q931_PROGRESS_INDICATOR))) {
|
|
|
|
|
pri_error(ctrl, "XXX Missing handling for mandatory IE %d (cs%d, %s) XXX\n", Q931_IE_IE(mandies[x]), Q931_IE_CODESET(mandies[x]), ie2str(mandies[x]));
|
|
|
|
|
missingmand++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mand_status == MAND_STATUS_OK) {
|
|
|
|
|
if (!missingmand) {
|
|
|
|
|
switch (mh->msg) {
|
|
|
|
|
case Q931_SETUP:
|
|
|
|
|
case Q931_CONNECT:
|
|
|
|
|
@@ -7941,7 +7696,7 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (allow_posthandle) {
|
|
|
|
|
res = post_handle_q931_message(ctrl, mh, c, mand_status);
|
|
|
|
|
res = post_handle_q931_message(ctrl, mh, c, missingmand);
|
|
|
|
|
if (res == Q931_RES_HAVEEVENT && !allow_event) {
|
|
|
|
|
res = 0;
|
|
|
|
|
}
|
|
|
|
|
@@ -8811,7 +8566,7 @@ static void q931_restart_notify(struct q931_call *call)
|
|
|
|
|
* \param ctrl D channel controller.
|
|
|
|
|
* \param mh Q.931 message header.
|
|
|
|
|
* \param c Q.931 call leg.
|
|
|
|
|
* \param mand_status Mandatory ie status
|
|
|
|
|
* \param missingmand Number of missing mandatory ie's.
|
|
|
|
|
*
|
|
|
|
|
* \note
|
|
|
|
|
* When this function returns c may be destroyed so you can no
|
|
|
|
|
@@ -8821,33 +8576,19 @@ static void q931_restart_notify(struct q931_call *call)
|
|
|
|
|
* \retval Q931_RES_HAVEEVENT if have an event.
|
|
|
|
|
* \retval -1 on error.
|
|
|
|
|
*/
|
|
|
|
|
static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, enum mandatory_ie_status mand_status)
|
|
|
|
|
static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, int missingmand)
|
|
|
|
|
{
|
|
|
|
|
int res;
|
|
|
|
|
int changed;
|
|
|
|
|
int mand_cause;
|
|
|
|
|
enum Q931_CALL_STATE ourcallstate_orig;
|
|
|
|
|
struct apdu_event *cur = NULL;
|
|
|
|
|
struct pri_subcommand *subcmd;
|
|
|
|
|
struct q931_call *master_call;
|
|
|
|
|
|
|
|
|
|
mand_cause = 0;
|
|
|
|
|
switch (mand_status) {
|
|
|
|
|
case MAND_STATUS_OK:
|
|
|
|
|
break;
|
|
|
|
|
case MAND_STATUS_CONTENT_ERROR:
|
|
|
|
|
mand_cause = PRI_CAUSE_INVALID_IE_CONTENTS;
|
|
|
|
|
break;
|
|
|
|
|
case MAND_STATUS_MISSING:
|
|
|
|
|
mand_cause = PRI_CAUSE_MANDATORY_IE_MISSING;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch(mh->msg) {
|
|
|
|
|
case Q931_RESTART:
|
|
|
|
|
q931_display_subcmd(ctrl, c);
|
|
|
|
|
if (mand_status != MAND_STATUS_OK) {
|
|
|
|
|
q931_status(ctrl, c, mand_cause);
|
|
|
|
|
if (missingmand) {
|
|
|
|
|
q931_status(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
|
|
|
|
|
pri_destroycall(ctrl, c);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
@@ -8905,8 +8646,9 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
|
|
|
|
return Q931_RES_HAVEEVENT;
|
|
|
|
|
case Q931_SETUP:
|
|
|
|
|
q931_display_subcmd(ctrl, c);
|
|
|
|
|
if (mand_status != MAND_STATUS_OK) {
|
|
|
|
|
q931_release_complete(ctrl, c, mand_cause);
|
|
|
|
|
|
|
|
|
|
if (missingmand) {
|
|
|
|
|
q931_release_complete(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* Must be new call */
|
|
|
|
|
@@ -8949,24 +8691,11 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
|
|
|
|
return Q931_RES_HAVEEVENT;
|
|
|
|
|
case Q931_ALERTING:
|
|
|
|
|
q931_display_subcmd(ctrl, c);
|
|
|
|
|
if (mand_status != MAND_STATUS_OK) {
|
|
|
|
|
q931_status(ctrl, c, mand_cause);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
stop_t303(c->master_call);
|
|
|
|
|
if (c->newcall) {
|
|
|
|
|
q931_release_complete(ctrl, c, newcall_rel_comp_cause(c));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
switch (c->ourcallstate) {
|
|
|
|
|
default:
|
|
|
|
|
q931_status(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
|
|
|
|
|
return 0;
|
|
|
|
|
case Q931_CALL_STATE_CALL_INITIATED:
|
|
|
|
|
case Q931_CALL_STATE_OVERLAP_SENDING:
|
|
|
|
|
case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_CALL_DELIVERED);
|
|
|
|
|
c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED;
|
|
|
|
|
ctrl->ev.e = PRI_EVENT_RINGING;
|
|
|
|
|
@@ -8998,10 +8727,6 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
|
|
|
|
return Q931_RES_HAVEEVENT;
|
|
|
|
|
case Q931_CONNECT:
|
|
|
|
|
q931_display_subcmd(ctrl, c);
|
|
|
|
|
if (mand_status != MAND_STATUS_OK) {
|
|
|
|
|
q931_status(ctrl, c, mand_cause);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
stop_t303(c->master_call);
|
|
|
|
|
if (c->newcall) {
|
|
|
|
|
q931_release_complete(ctrl, c, newcall_rel_comp_cause(c));
|
|
|
|
|
@@ -9080,15 +8805,16 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case Q931_PROGRESS:
|
|
|
|
|
if (missingmand) {
|
|
|
|
|
q931_status(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
|
|
|
|
|
pri_destroycall(ctrl, c);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
ctrl->ev.e = PRI_EVENT_PROGRESS;
|
|
|
|
|
ctrl->ev.proceeding.cause = c->cause;
|
|
|
|
|
/* Fall through */
|
|
|
|
|
case Q931_CALL_PROCEEDING:
|
|
|
|
|
q931_display_subcmd(ctrl, c);
|
|
|
|
|
if (mand_status != MAND_STATUS_OK) {
|
|
|
|
|
q931_status(ctrl, c, mand_cause);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
stop_t303(c->master_call);
|
|
|
|
|
ctrl->ev.proceeding.subcmds = &ctrl->subcmds;
|
|
|
|
|
if (c->newcall) {
|
|
|
|
|
@@ -9140,8 +8866,11 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
|
|
|
|
}
|
|
|
|
|
switch (c->ourcallstate) {
|
|
|
|
|
default:
|
|
|
|
|
q931_status(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
|
|
|
|
|
return 0;
|
|
|
|
|
if (ctrl->localtype == PRI_NETWORK || ctrl->switchtype == PRI_SWITCH_QSIG) {
|
|
|
|
|
q931_status(ctrl, c, PRI_CAUSE_WRONG_MESSAGE);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* Fall through */
|
|
|
|
|
case Q931_CALL_STATE_CONNECT_REQUEST:
|
|
|
|
|
case Q931_CALL_STATE_ACTIVE:
|
|
|
|
|
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_ACTIVE);
|
|
|
|
|
@@ -9158,8 +8887,9 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
|
|
|
|
break;
|
|
|
|
|
case Q931_STATUS:
|
|
|
|
|
q931_display_subcmd(ctrl, c);
|
|
|
|
|
if (mand_status != MAND_STATUS_OK) {
|
|
|
|
|
q931_status(ctrl, c, mand_cause);
|
|
|
|
|
if (missingmand) {
|
|
|
|
|
q931_status(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
|
|
|
|
|
pri_destroycall(ctrl, c);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (c->newcall) {
|
|
|
|
|
@@ -9265,9 +8995,9 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
|
|
|
|
case Q931_RELEASE:
|
|
|
|
|
q931_display_subcmd(ctrl, c);
|
|
|
|
|
c->hangupinitiated = 1;
|
|
|
|
|
if (mand_status != MAND_STATUS_OK) {
|
|
|
|
|
/* Force mandatory ie cause */
|
|
|
|
|
c->cause = mand_cause;
|
|
|
|
|
if (missingmand) {
|
|
|
|
|
/* Force cause to be mandatory IE missing */
|
|
|
|
|
c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
@@ -9311,9 +9041,9 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
|
|
|
|
case Q931_DISCONNECT:
|
|
|
|
|
q931_display_subcmd(ctrl, c);
|
|
|
|
|
c->hangupinitiated = 1;
|
|
|
|
|
if (mand_status != MAND_STATUS_OK) {
|
|
|
|
|
if (missingmand) {
|
|
|
|
|
/* Still let user call release */
|
|
|
|
|
c->cause = mand_cause;
|
|
|
|
|
c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
|
|
|
|
|
}
|
|
|
|
|
if (c->newcall) {
|
|
|
|
|
q931_release_complete(ctrl, c, newcall_rel_comp_cause(c));
|
|
|
|
|
@@ -9366,46 +9096,14 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ourcallstate_orig = c->ourcallstate;
|
|
|
|
|
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_DISCONNECT_INDICATION);
|
|
|
|
|
c->peercallstate = Q931_CALL_STATE_DISCONNECT_REQUEST;
|
|
|
|
|
c->sendhangupack = 1;
|
|
|
|
|
|
|
|
|
|
/* wait for a RELEASE so that sufficient time has passed
|
|
|
|
|
for the inband audio to be heard */
|
|
|
|
|
if (ctrl->acceptinbanddisconnect
|
|
|
|
|
&& (c->progressmask & PRI_PROG_INBAND_AVAILABLE)) {
|
|
|
|
|
switch (ourcallstate_orig) {
|
|
|
|
|
case Q931_CALL_STATE_CALL_INITIATED:
|
|
|
|
|
case Q931_CALL_STATE_OVERLAP_SENDING:
|
|
|
|
|
case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
|
|
|
|
|
case Q931_CALL_STATE_CALL_DELIVERED:
|
|
|
|
|
/*
|
|
|
|
|
* Open the media path if it isn't already open so
|
|
|
|
|
* the user can hear the inband audio.
|
|
|
|
|
*/
|
|
|
|
|
if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
|
|
|
|
|
pri_message(ctrl, "Report the DISCONNECT as a PROGRESS instead.\n");
|
|
|
|
|
}
|
|
|
|
|
ctrl->ev.e = PRI_EVENT_PROGRESS;
|
|
|
|
|
ctrl->ev.proceeding.cause = c->cause;
|
|
|
|
|
ctrl->ev.proceeding.subcmds = &ctrl->subcmds;
|
|
|
|
|
ctrl->ev.proceeding.channel = q931_encode_channel(c);
|
|
|
|
|
ctrl->ev.proceeding.progress = c->progress;
|
|
|
|
|
ctrl->ev.proceeding.progressmask = c->progressmask;
|
|
|
|
|
ctrl->ev.proceeding.cref = c->cr;
|
|
|
|
|
ctrl->ev.proceeding.call = c->master_call;
|
|
|
|
|
return Q931_RES_HAVEEVENT;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* Suppress reporting DISCONNECT to the upper layer. The
|
|
|
|
|
* media path should already be open and we cannot report
|
|
|
|
|
* a PROGRESS at this time anyway.
|
|
|
|
|
*/
|
|
|
|
|
if (ctrl->acceptinbanddisconnect && (c->progressmask & PRI_PROG_INBAND_AVAILABLE))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return such an event */
|
|
|
|
|
ctrl->ev.e = PRI_EVENT_HANGUP_REQ;
|
|
|
|
|
@@ -9472,7 +9170,7 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
|
|
|
|
q931_release_complete(ctrl, c, newcall_rel_comp_cause(c));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (strlen(c->keypad_digits)) {
|
|
|
|
|
if (c->ourcallstate != Q931_CALL_STATE_OVERLAP_RECEIVING) {
|
|
|
|
|
ctrl->ev.e = PRI_EVENT_KEYPAD_DIGIT;
|
|
|
|
|
ctrl->ev.digit.subcmds = &ctrl->subcmds;
|
|
|
|
|
ctrl->ev.digit.call = c->master_call;
|
|
|
|
|
@@ -9505,22 +9203,11 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
|
|
|
|
break;
|
|
|
|
|
case Q931_SETUP_ACKNOWLEDGE:
|
|
|
|
|
q931_display_subcmd(ctrl, c);
|
|
|
|
|
if (mand_status != MAND_STATUS_OK) {
|
|
|
|
|
q931_status(ctrl, c, mand_cause);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
stop_t303(c->master_call);
|
|
|
|
|
if (c->newcall) {
|
|
|
|
|
q931_release_complete(ctrl, c, newcall_rel_comp_cause(c));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
switch (c->ourcallstate) {
|
|
|
|
|
default:
|
|
|
|
|
q931_status(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
|
|
|
|
|
return 0;
|
|
|
|
|
case Q931_CALL_STATE_CALL_INITIATED:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_OVERLAP_SENDING);
|
|
|
|
|
c->peercallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
|
|
|
|
|
ctrl->ev.e = PRI_EVENT_SETUP_ACK;
|
|
|
|
|
@@ -9734,9 +9421,9 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
|
|
|
|
master_call = c->master_call;
|
|
|
|
|
switch (master_call->hold_state) {
|
|
|
|
|
case Q931_HOLD_STATE_HOLD_REQ:
|
|
|
|
|
if (mand_status != MAND_STATUS_OK) {
|
|
|
|
|
if (missingmand) {
|
|
|
|
|
/* Still, let hold rejection continue. */
|
|
|
|
|
c->cause = mand_cause;
|
|
|
|
|
c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
|
|
|
|
|
}
|
|
|
|
|
ctrl->ev.e = PRI_EVENT_HOLD_REJ;
|
|
|
|
|
ctrl->ev.hold_rej.channel = q931_encode_channel(c);
|
|
|
|
|
@@ -9858,9 +9545,9 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
|
|
|
|
pri_schedule_del(ctrl, master_call->hold_timer);
|
|
|
|
|
master_call->hold_timer = 0;
|
|
|
|
|
|
|
|
|
|
if (mand_status != MAND_STATUS_OK) {
|
|
|
|
|
if (missingmand) {
|
|
|
|
|
/* Still, let retrive rejection continue. */
|
|
|
|
|
c->cause = mand_cause;
|
|
|
|
|
c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
|
|
|
|
|
}
|
|
|
|
|
ctrl->ev.e = PRI_EVENT_RETRIEVE_REJ;
|
|
|
|
|
ctrl->ev.retrieve_rej.channel = q931_encode_channel(c);
|
|
|
|
|
|