Compare commits

...

16 Commits

Author SHA1 Message Date
Sergey V. Lobanov
9ace221ca0 Makefile: Add the ability to build libpri on MacOS for Linux target.
This patch allows to redefine ar and ranlib tool using AR and
RANLIB make flags.

PRI-188 #close

Change-Id: I6554c57b6fab4d73bc752d4d9b878834aa86d1f1
2022-05-19 21:11:46 -05:00
bbabic
a7a2245b12 q931.c: Fix subaddress finding octet 4.
Some switches have extended subaddress ie octet 3 encoding to be
multi-octet.

* Update dump and receive helper functions to search for the end of octet
3 encoding to determine where octet 4 starts.

ASTERISK-27342

Change-Id: I5b2706f668e1a4664b020a58de41dad4cbc5c7e6
2017-10-23 12:27:42 -05:00
Tzafrir Cohen
c038af7892 Makefile: Use CPPFLAGS
* Include the value of CPPFLAGS in CFLAGS

Change-Id: Id8e6f3a231bf7581f3f37576b9ee6849ed59540a
2016-12-05 12:40:02 -06:00
Richard Mudgett
f8e6096bfe q931.c: Lucent switch implementation bug workaround (Part 2)
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.

PRI-183
Reported by: Richard Mudgett

Change-Id: I7eedbf68b7c3d9c868d9533012e4cea5142af281
2016-10-04 14:27:59 -05:00
Richard Mudgett
d2585d6da2 q931.c: Lucent switch implementation bug workaround.
A bug in a Lucent switch implementation sets the Connected Number
information element octet 3 extension bit.  When set that means octet 3 is
complete and thus there is no optional octet 3a.  However, the buggy
switch still sends octet 3a.  The unexpected octet 3a is interpreted as
the first octet 4 and thus the first character in the connected line
number is a garbage character.

* Work around the switch bug by checking octet 3 and the potential octet
3a extension bits.  If they are both set then assume that octet 3a is
actually present for the buggy switch types.

PRI-183 #close
Reported by: Richard Mudgett

Change-Id: I378af37bfd852737a0bfe6263ef3473ea6acfbad
2016-07-20 16:36:41 -05:00
Richard Mudgett
90019b935a q931.c: Add number ie specification references.
Change-Id: I0d15804963501d1e4063a581db756ff26513065b
2016-06-30 20:15:50 -05:00
Kevin Harwell
c71499df29 Adding .cleancount and .gitreview files
Change-Id: I0e5accd0e43c049578241b2841fc2efa821c24f4
2016-03-24 14:55:28 -05:00
Richard Mudgett
2952e95715 q931.c: Fix DISCONNECT Progress Indicator ie handling.
There are two scenarios that are exposed by DISCONNECT not initializing
the progress indicator value before processing the message when the
chan_dahdi.conf inbanddisconnect=yes option is set.

1) If a DISCONNECT comes in without a Progress Indicator ie and an earlier
message (such as SETUP-ACKNOWLEDGE or PROCEEDING) came in with the
indicator #8 (Inband audio present) then the DISCONNECT would not cause an
immediate hangup.  We would be letting the user hear the inband audio even
though there isn't any.

2) If a DISCONNECT message comes in with the indicator #8 (Inband audio
present) and then later the DISCONNECT message is repeated without a
Progress Indicator ie we would still ignore the second DISCONNECT to let
the user hear inband audio even though it likely isn't there anymore.

PRI-180 #close
Reported by: Alexandr Dranchuk

Change-Id: Ic88aafb45053146b5701d666e6212f7555573624
2016-03-17 11:43:10 -05:00
Richard Mudgett
7da3366cec q931.c: Substitute PROGRESS for DISCONNECT with progress indicator #8
When the pri_set_inbanddisconnect() option is enabled and the call has not
been answered when a DISCONNECT with progress indicator #8 (Inband audio
present) is received, then report the event as a PROGRESS with progress
indicator #8 (Inband audio present) instead.  Substituting a PROGRESS
event allows the upper layer to open the media path if it isn't already
open so the user can hear the inband audio message.

PRI-180
Reported by: Alexandr Dranchuk

Change-Id: I62313bf9cc1d2f3b0231f0c07a784717ddba0415
2016-03-17 11:43:10 -05:00
Richard Mudgett
734e922301 Add .gitignore
Change-Id: I11ac3b47a9d5d0a0c1ea4559280b75ef5d866d62
2016-03-16 16:09:24 -05:00
Richard Mudgett
a9722804c1 q931.c: Tighten mandatory ie checks.
Libpri was lax in checking if a missing channel identification ie is
mandatory for the SETUP ACKNOWLEDGE, PROCEEDING, ALERTING, and CONNECT
messages.  That ie is mandatory when those messages are the first response
to a SETUP message sent by the CPE side.

* Made those messages check if a missing channel identification ie is
mandatory and send a STATUS with cause 96 "Mandatory information element
is missing" in response.

Libpri did not care if a mandatory ie had a coding error.

* Made coding errors in mandatory ie's send a STATUS with cause 100
"Invalid information element contents" in response.

* Fixed detection of coding errors in channel identification ie.

SWP-8721
SWP-8722


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2337 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2016-02-17 20:21:18 +00:00
Richard Mudgett
6b2cc87b30 q931.c: Update ALERTING_NO_PROGRESS conditional code.
The conditional is to only remove the Progress Indicator ie from being
added to select messages.

* Made so the ALERTING message can have the User-User ie if needed when
ALERTING_NO_PROGRESS is defined.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2335 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2016-02-09 21:46:26 +00:00
Richard Mudgett
fc96191788 q931.c: Made not recognize ie 0x01 for switches other than 4ESS, 5ESS, NI2, and DMS-100.
An incoming SETUP message needs to reject the invalid ie 0x01 on switches
other than 4ESS, 5ESS, NI2, and DMS-100.

LIBPRI-74 #close
Reported by: Richard Mudgett


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2333 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2014-11-17 23:26:55 +00:00
Richard Mudgett
5fda3d8c68 q931.c: Send STATUS messages when receiving messages in the wrong call state.
* Add checks to send STATUS messages when receiving SETUP ACKNOWLEDGE,
ALERTING, and CONNECT ACKNOWLEDGE messages when in the wrong call state.

LIBPRI-76 #close
Reported by: Richard Mudgett


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2331 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2014-11-17 20:07:53 +00:00
Richard Mudgett
af8a550ff9 q921.c: Send DM and DISC frames with only three data octets instead of an extra fourth octet.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2329 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2014-11-04 22:19:02 +00:00
Richard Mudgett
a50516c1e4 q931.c: Make always post a PRI_EVENT_KEYPAD_DIGIT if keypad digits come in an INFO message.
Q.931 Section 3.1.6 INFORMATION message.  The keypad-facility or
called-party-number ie could be used to convey called party digits.  The
keypad-facility ie can also be used to convey supplementary service
information.

PRI-173 #close
Reported by: Gerald Schnabel
Patches:
      libpri_q931_keypad_digits.patch (license #6297) patch uploaded by Gerald Schnabel


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2327 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2014-08-18 22:44:04 +00:00
8 changed files with 439 additions and 106 deletions

1
.cleancount Normal file
View File

@@ -0,0 +1 @@
0

12
.gitignore vendored Normal file
View File

@@ -0,0 +1,12 @@
*.o
*.o.d
*.lo
*.so
*.a
libpri.so.*
pridump
pritest
rosetest
testprilib
version.c

4
.gitreview Normal file
View File

@@ -0,0 +1,4 @@
[gerrit]
host=gerrit.asterisk.org
port=29418
project=libpri.git

View File

@@ -27,6 +27,8 @@
CC=gcc
GREP=grep
AWK=awk
AR=ar
RANLIB=ranlib
OSARCH=$(shell uname -s)
PROC?=$(shell uname -m)
@@ -67,6 +69,7 @@ STATIC_OBJS= \
DYNAMIC_OBJS= \
$(STATIC_OBJS)
CFLAGS ?= -g
CFLAGS += $(CPPFLAGS)
CFLAGS += -Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
CFLAGS += -fPIC $(ALERTING) $(LIBPRI_OPT) $(COVERAGE_CFLAGS)
INSTALL_PREFIX=$(DESTDIR)
@@ -192,8 +195,8 @@ MAKE_DEPS= -MD -MT $@ -MF .$(subst /,_,$@).d -MP
$(CC) $(CFLAGS) $(MAKE_DEPS) -c -o $@ $<
$(STATIC_LIBRARY): $(STATIC_OBJS)
ar rcs $(STATIC_LIBRARY) $(STATIC_OBJS)
ranlib $(STATIC_LIBRARY)
$(AR) rcs $(STATIC_LIBRARY) $(STATIC_OBJS)
$(RANLIB) $(STATIC_LIBRARY)
$(DYNAMIC_LIBRARY): $(DYNAMIC_OBJS)
$(CC) $(SOFLAGS) -o $@ $(DYNAMIC_OBJS)

View File

@@ -647,10 +647,13 @@ struct q931_call {
unsigned char char_set;
} display;
/* AOC charge requesting on Setup */
/*! AOC charge requesting on Setup */
int aoc_charging_request;
unsigned int slotmap_size:1;/* TRUE if the slotmap is E1 (32 bits). */
/*! TRUE if the slotmap is E1 (32 bits). */
unsigned int slotmap_size:1;
/*! TRUE if need to see the channel id ie in first response to SETUP. */
unsigned int channel_id_ie_mandatory:1;
/*! Control the RESTART reception to the upper layer. */
struct {

View File

@@ -138,9 +138,6 @@ typedef struct q931_ie {
#define SERVICE_CHANGE_STATUS_REQCONTINUITYCHECK 3 /* not supported */
#define SERVICE_CHANGE_STATUS_SHUTDOWN 4 /* not supported */
/* Special codeset 0 IE */
#define NATIONAL_CHANGE_STATUS 0x1
/* Q.931 / National ISDN Information Elements */
#define Q931_LOCKING_SHIFT 0x90
#define Q931_NON_LOCKING_SHIFT 0x98

4
q921.c
View File

@@ -313,7 +313,7 @@ static void q921_send_dm(struct q921_link *link, int fbit)
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
pri_message(ctrl, "TEI=%d Sending DM\n", link->tei);
}
q921_transmit(ctrl, &h, 4);
q921_transmit(ctrl, &h, 3);
}
static void q921_send_disc(struct q921_link *link, int pbit)
@@ -342,7 +342,7 @@ static void q921_send_disc(struct q921_link *link, int pbit)
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
pri_message(ctrl, "TEI=%d Sending DISC\n", link->tei);
}
q921_transmit(ctrl, &h, 4);
q921_transmit(ctrl, &h, 3);
}
static void q921_send_ua(struct q921_link *link, int fbit)

507
q931.c
View File

@@ -40,6 +40,12 @@
#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 {
@@ -50,13 +56,27 @@ struct msgtype {
static struct msgtype msgs[] = {
/* Call establishment messages */
{ Q931_ALERTING, "ALERTING" },
{ Q931_CALL_PROCEEDING, "CALL PROCEEDING" },
{ Q931_CONNECT, "CONNECT" },
{ Q931_ALERTING, "ALERTING", { Q931_CHANNEL_IDENT } },
{ Q931_CALL_PROCEEDING, "CALL PROCEEDING", { Q931_CHANNEL_IDENT } },
{ Q931_CONNECT, "CONNECT", { Q931_CHANNEL_IDENT } },
{ 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_SETUP_ACKNOWLEDGE, "SETUP ACKNOWLEDGE", { Q931_CHANNEL_IDENT } },
/* Call disestablishment messages */
{ Q931_DISCONNECT, "DISCONNECT", { Q931_CAUSE } },
@@ -93,7 +113,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, int missingmand);
static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, enum mandatory_ie_status mand_status);
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[] = {
@@ -1258,6 +1278,14 @@ 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) {
@@ -1308,10 +1336,24 @@ static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, in
pos++;
if (ie->data[0] & 0x40) {
/* DS1 specified -- stop here */
call->ds1no = ie->data[1] & 0x7f;
/* 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;
call->ds1explicit = 1;
pos++;
/* Advance to 3.2 octet if present. */
do {
++pos;
} while (pos < ie->len && !(ie->data[pos - 1] & 0x80));
} else {
call->ds1explicit = 0;
}
@@ -1324,8 +1366,12 @@ static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, in
return 0;
}
if (need_extended_channel_octets && pos + 2 < len) {
/* More coming */
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 ((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);
@@ -1335,14 +1381,25 @@ 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) {
/* Expect Slot Map */
if (ie->data[pos++] & 0x10) {
/* Process 3.3 octets as a Slot Map */
call->slotmap = 0;
pos++;
call->slotmap_size = (ie->len - pos > 3) ? 1 : 0;
for (x = 0; x < (call->slotmap_size ? 4 : 3); ++x) {
/*
* 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--;) {
call->slotmap <<= 8;
call->slotmap |= ie->data[x + pos];
call->slotmap |= ie->data[pos++];
if (ie->len <= pos) {
/* No more ie contents. */
break;
}
}
if (msgtype == Q931_RESTART) {
@@ -1357,8 +1414,11 @@ static int receive_channel_id(int full_ie, struct pri *ctrl, q931_call *call, in
}
}
} else {
pos++;
/* Only expect a particular channel */
/*
* Process 3.3 octets as either a single channel or a channel list
*
* Get single channel
*/
call->channelno = ie->data[pos] & 0x7f;
if (ctrl->chan_mapping_logical && call->channelno > 15) {
call->channelno++;
@@ -1385,6 +1445,9 @@ 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;
}
@@ -1518,21 +1581,29 @@ 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] >> 3) & 0x04)]);
prefix, msg_chan_sel[(ie->data[0] & 0x03) | ((ie->data[0] & 0x20) >> 3)]);
pos = 1;
len -= 2;
if (ie->data[0] & 0x40) {
/* 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);
/* 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);
}
} else {
/* Implicitly defined DS1 */
}
if (pos < len) {
/* Still more information here */
/* Octet 3.2 present */
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,
@@ -1540,6 +1611,7 @@ 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 {
@@ -2124,17 +2196,33 @@ 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;
/* 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_subaddress->length = len - i;
q931_memget(q931_subaddress->data, sizeof(q931_subaddress->data),
ie->data + offset, len);
ie->data + offset + i, len - i);
return 0;
}
@@ -2142,13 +2230,22 @@ 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, datalen);
q931_strget(cnum, sizeof(cnum), ie->data + offset + i, datalen - i);
} else {
/* User Specified */
q931_get_subaddr_specific(cnum, sizeof(cnum), ie->data + offset, datalen,
q931_get_subaddr_specific(cnum, sizeof(cnum), ie->data + offset + i, datalen - i,
ie->data[0] & 0x08);
}
@@ -2268,6 +2365,7 @@ 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 =
@@ -2278,7 +2376,39 @@ 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;
break;
/*
* 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 */
case 1:
/* Keep only the presentation and screening fields */
call->remote_id.number.presentation =
@@ -2320,7 +2450,44 @@ 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);
break;
/*
* 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 */
case 1: /* Octet 3a */
pri_message(ctrl, "\n");
pri_message(ctrl, "%c Ext: %d Presentation: %s (%d)",
@@ -2357,6 +2524,7 @@ 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 =
@@ -2435,6 +2603,7 @@ 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;
@@ -2578,6 +2747,7 @@ 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;
@@ -2681,10 +2851,33 @@ 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;
}
@@ -2841,7 +3034,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));
break;
return -1;
}
return 0;
}
@@ -3955,8 +4148,11 @@ 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 },
@@ -3988,7 +4184,6 @@ 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 },
@@ -4000,7 +4195,6 @@ 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 },
@@ -4792,7 +4986,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 an IE %s (%d)\n", ie2str(ie), ie);
pri_error(ctrl, "!! Don't know how to add IE %d (%s)\n", ie, ie2str(ie));
return -1;
}
}
@@ -5613,11 +5807,12 @@ int q931_notify(struct pri *ctrl, q931_call *c, int channel, int info)
return q931_notify_redirection(ctrl, c, info, NULL, NULL);
}
#ifdef ALERTING_NO_PROGRESS
static int call_progress_ies[] = { -1 };
#else
static int call_progress_ies[] = { Q931_PROGRESS_INDICATOR, -1 };
static int call_progress_ies[] = {
#ifndef ALERTING_NO_PROGRESS
Q931_PROGRESS_INDICATOR,
#endif
-1
};
int q931_call_progress(struct pri *ctrl, q931_call *c, int channel, int info)
{
@@ -5645,11 +5840,13 @@ int q931_call_progress(struct pri *ctrl, q931_call *c, int channel, int info)
return send_message(ctrl, c, Q931_PROGRESS, call_progress_ies);
}
#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 };
static int call_progress_with_cause_ies[] = {
Q931_CAUSE,
#ifndef ALERTING_NO_PROGRESS
Q931_PROGRESS_INDICATOR,
#endif
-1
};
int q931_call_progress_with_cause(struct pri *ctrl, q931_call *c, int channel, int info, int cause)
{
@@ -5681,11 +5878,13 @@ 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);
}
#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 };
static int call_proceeding_ies[] = {
Q931_CHANNEL_IDENT,
#ifndef ALERTING_NO_PROGRESS
Q931_PROGRESS_INDICATOR,
#endif
-1
};
int q931_call_proceeding(struct pri *ctrl, q931_call *c, int channel, int info)
{
@@ -5716,11 +5915,15 @@ 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
static int alerting_ies[] = { Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, Q931_IE_USER_USER, -1 };
#else
static int alerting_ies[] = { Q931_IE_FACILITY, -1 };
Q931_PROGRESS_INDICATOR,
#endif
Q931_IE_USER_USER,
-1
};
int q931_alerting(struct pri *ctrl, q931_call *c, int channel, int info)
{
@@ -6283,6 +6486,9 @@ 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;
@@ -7273,6 +7479,8 @@ 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;
@@ -7477,12 +7685,13 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
int res;
int r;
int mandies[MAX_MAND_IES];
int missingmand;
int is_mandatory;
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));
@@ -7562,7 +7771,7 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
q931_clr_subcommands(ctrl);
q931_display_clear(c);
/* Handle IEs */
/* Determine which ies are mandatory for this message. */
memset(mandies, 0, sizeof(mandies));
for (x = 0; x < ARRAY_LEN(msgs); ++x) {
if (msgs[x].msgnum == mh->msg) {
@@ -7570,6 +7779,25 @@ 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;
@@ -7586,10 +7814,16 @@ 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:
@@ -7632,6 +7866,15 @@ 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)) {
/*
@@ -7648,19 +7891,21 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
break;
}
}
missingmand = 0;
/* Check for missing mandatory ies. */
for (x = 0; x < ARRAY_LEN(mandies); ++x) {
if (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++;
}
/* 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]));
}
}
if (!missingmand) {
if (mand_status == MAND_STATUS_OK) {
switch (mh->msg) {
case Q931_SETUP:
case Q931_CONNECT:
@@ -7696,7 +7941,7 @@ int q931_receive(struct q921_link *link, q931_h *h, int len)
}
if (allow_posthandle) {
res = post_handle_q931_message(ctrl, mh, c, missingmand);
res = post_handle_q931_message(ctrl, mh, c, mand_status);
if (res == Q931_RES_HAVEEVENT && !allow_event) {
res = 0;
}
@@ -8566,7 +8811,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 missingmand Number of missing mandatory ie's.
* \param mand_status Mandatory ie status
*
* \note
* When this function returns c may be destroyed so you can no
@@ -8576,19 +8821,33 @@ 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, int missingmand)
static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct q931_call *c, enum mandatory_ie_status mand_status)
{
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 (missingmand) {
q931_status(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
if (mand_status != MAND_STATUS_OK) {
q931_status(ctrl, c, mand_cause);
pri_destroycall(ctrl, c);
break;
}
@@ -8646,9 +8905,8 @@ 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 (missingmand) {
q931_release_complete(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
if (mand_status != MAND_STATUS_OK) {
q931_release_complete(ctrl, c, mand_cause);
break;
}
/* Must be new call */
@@ -8691,11 +8949,24 @@ 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;
@@ -8727,6 +8998,10 @@ 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));
@@ -8805,16 +9080,15 @@ 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) {
@@ -8866,11 +9140,8 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
}
switch (c->ourcallstate) {
default:
if (ctrl->localtype == PRI_NETWORK || ctrl->switchtype == PRI_SWITCH_QSIG) {
q931_status(ctrl, c, PRI_CAUSE_WRONG_MESSAGE);
break;
}
/* Fall through */
q931_status(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
return 0;
case Q931_CALL_STATE_CONNECT_REQUEST:
case Q931_CALL_STATE_ACTIVE:
UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_ACTIVE);
@@ -8887,9 +9158,8 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
break;
case Q931_STATUS:
q931_display_subcmd(ctrl, c);
if (missingmand) {
q931_status(ctrl, c, PRI_CAUSE_MANDATORY_IE_MISSING);
pri_destroycall(ctrl, c);
if (mand_status != MAND_STATUS_OK) {
q931_status(ctrl, c, mand_cause);
break;
}
if (c->newcall) {
@@ -8995,9 +9265,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 (missingmand) {
/* Force cause to be mandatory IE missing */
c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
if (mand_status != MAND_STATUS_OK) {
/* Force mandatory ie cause */
c->cause = mand_cause;
}
/*
@@ -9041,9 +9311,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 (missingmand) {
if (mand_status != MAND_STATUS_OK) {
/* Still let user call release */
c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
c->cause = mand_cause;
}
if (c->newcall) {
q931_release_complete(ctrl, c, newcall_rel_comp_cause(c));
@@ -9096,14 +9366,46 @@ 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))
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.
*/
break;
}
/* Return such an event */
ctrl->ev.e = PRI_EVENT_HANGUP_REQ;
@@ -9170,7 +9472,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 (c->ourcallstate != Q931_CALL_STATE_OVERLAP_RECEIVING) {
if (strlen(c->keypad_digits)) {
ctrl->ev.e = PRI_EVENT_KEYPAD_DIGIT;
ctrl->ev.digit.subcmds = &ctrl->subcmds;
ctrl->ev.digit.call = c->master_call;
@@ -9203,11 +9505,22 @@ 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;
@@ -9421,9 +9734,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 (missingmand) {
if (mand_status != MAND_STATUS_OK) {
/* Still, let hold rejection continue. */
c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
c->cause = mand_cause;
}
ctrl->ev.e = PRI_EVENT_HOLD_REJ;
ctrl->ev.hold_rej.channel = q931_encode_channel(c);
@@ -9545,9 +9858,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 (missingmand) {
if (mand_status != MAND_STATUS_OK) {
/* Still, let retrive rejection continue. */
c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
c->cause = mand_cause;
}
ctrl->ev.e = PRI_EVENT_RETRIEVE_REJ;
ctrl->ev.retrieve_rej.channel = q931_encode_channel(c);