aboutsummaryrefslogtreecommitdiffstats
path: root/main/libpri/libpri-1.4.9-i14292.patch
diff options
context:
space:
mode:
Diffstat (limited to 'main/libpri/libpri-1.4.9-i14292.patch')
-rw-r--r--main/libpri/libpri-1.4.9-i14292.patch5668
1 files changed, 0 insertions, 5668 deletions
diff --git a/main/libpri/libpri-1.4.9-i14292.patch b/main/libpri/libpri-1.4.9-i14292.patch
deleted file mode 100644
index 27ed1b8d43..0000000000
--- a/main/libpri/libpri-1.4.9-i14292.patch
+++ /dev/null
@@ -1,5668 +0,0 @@
-Index: .version
-===================================================================
---- a/.version (.../tags/1.4.9) (revision 700)
-+++ b/.version (.../team/group/issue14292) (revision 700)
-@@ -1 +1 @@
--1.4.9
-+1.4.9-issue14292
-Index: pri_facility.c
-===================================================================
---- a/pri_facility.c (.../tags/1.4.9) (revision 700)
-+++ b/pri_facility.c (.../team/group/issue14292) (revision 700)
-@@ -171,7 +171,7 @@
-
- struct addressingdataelements_presentednumberunscreened {
- char partyaddress[21];
-- char partysubaddress[21];
-+ char notused[21];
- int npi; /* Numbering Plan Indicator */
- int ton; /* Type Of Number */
- int pres; /* Presentation */
-@@ -179,6 +179,15 @@
-
- struct addressingdataelements_presentednumberscreened {
- char partyaddress[21];
-+ char notused[21];
-+ int npi; /* Numbering Plan Indicator */
-+ int ton; /* Type Of Number */
-+ int pres; /* Presentation */
-+ int scrind; /* Screening Indicator */
-+};
-+
-+struct addressingdataelements_presentedaddressscreened {
-+ char partyaddress[21];
- char partysubaddress[21];
- int npi; /* Numbering Plan Indicator */
- int ton; /* Type Of Number */
-@@ -186,6 +195,35 @@
- int scrind; /* Screening Indicator */
- };
-
-+struct addressingdataelements_addressscreened {
-+ char partyaddress[21];
-+ char partysubaddress[21];
-+ int npi; /* Numbering Plan Indicator */
-+ int ton; /* Type Of Number */
-+ int notused;
-+ int scrind; /* Screening Indicator */
-+};
-+
-+struct addressingdataelements_partysubaddress {
-+ char notused[21];
-+ char partysubaddress[21];
-+};
-+
-+struct nameelements_name {
-+ char name[51];
-+ int characterset;
-+ int namepres;
-+};
-+
-+struct nameelements_nameset {
-+ char name[51];
-+ int characterset;
-+};
-+
-+struct nameelements_namedata {
-+ char name[51];
-+};
-+
- #define PRI_CHECKOVERFLOW(size) \
- if (msgptr - message + (size) >= sizeof(message)) { \
- *msgptr = '\0'; \
-@@ -225,6 +263,92 @@
- }
- #undef PRI_CHECKOVERFLOW
-
-+static const char *namepres_to_str(int namepres)
-+{
-+ return (namepres == 0) ? "Restricted" : "Allowed";
-+}
-+
-+static const char *characterset_to_str(int characterset)
-+{
-+ switch (characterset) {
-+ case CHARACTER_SET_UNKNOWN:
-+ return "Unknown";
-+ case CHARACTER_SET_ISO8859_1:
-+ return "ISO8859-1";
-+ case CHARACTER_SET_ISO8859_2:
-+ return "ISO8859-2";
-+ case CHARACTER_SET_ISO8859_3:
-+ return "ISO8859-3";
-+ case CHARACTER_SET_ISO8859_4:
-+ return "ISO8859-4";
-+ case CHARACTER_SET_ISO8859_5:
-+ return "ISO8859-5";
-+ case CHARACTER_SET_ISO8859_7:
-+ return "ISO8859-7";
-+ default:
-+ return "illegal value";
-+ }
-+}
-+
-+static const char *diversionreason_to_str(struct pri *pri, int diversionreason)
-+{
-+ if (pri->switchtype == PRI_SWITCH_QSIG) {
-+ switch (diversionreason) {
-+ case QSIG_DIVERT_REASON_UNKNOWN:
-+ return "Unknown";
-+ case QSIG_DIVERT_REASON_CFU:
-+ return "Call Forwarding Unconditional";
-+ case QSIG_DIVERT_REASON_CFB:
-+ return "Call Forwarding Busy";
-+ case QSIG_DIVERT_REASON_CFNR:
-+ return "Call Forwarding No Reply";
-+ default:
-+ return "invalid value";
-+ }
-+ } else {
-+ switch(diversionreason) {
-+ case Q952_DIVERT_REASON_UNKNOWN:
-+ return "Unknown";
-+ case Q952_DIVERT_REASON_CFU:
-+ return "Call Forwarding Unconditional";
-+ case Q952_DIVERT_REASON_CFB:
-+ return "Call Forwarding Busy";
-+ case Q952_DIVERT_REASON_CFNR:
-+ return "Call Forwarding No Reply";
-+ case Q952_DIVERT_REASON_CD:
-+ return "Call Deflection";
-+ case Q952_DIVERT_REASON_IMMEDIATE:
-+ return "Call Deflection Immediate";
-+ default:
-+ return "invalid value";
-+ }
-+ }
-+}
-+
-+static const char *callstatus_to_str(int callstatus)
-+{
-+ switch (callstatus) {
-+ case 0:
-+ return "answered";
-+ case 1:
-+ return "alerting";
-+ default:
-+ return "illegal value";
-+ }
-+}
-+
-+static const char *enddesignation_to_str(int enddesignation)
-+{
-+ switch (enddesignation) {
-+ case 0:
-+ return "primaryEnd";
-+ case 1:
-+ return "secondaryEnd";
-+ default:
-+ return "illegal value";
-+ }
-+}
-+
- int redirectingreason_from_q931(struct pri *pri, int redirectingreason)
- {
- switch(pri->switchtype) {
-@@ -350,8 +474,25 @@
- }
- }
-
--int asn1_name_decode(void * data, int len, char *namebuf, int buflen)
-+static int presentation_to_subscription(struct pri *pri, int presentation)
- {
-+ /* derive subscription value from presentation value */
-+
-+ switch (presentation & PRES_RESTRICTION) {
-+ case PRES_ALLOWED:
-+ return QSIG_NOTIFICATION_WITH_DIVERTED_TO_NR;
-+ case PRES_RESTRICTED:
-+ return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR;
-+ case PRES_UNAVAILABLE: /* Number not available due to interworking */
-+ return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR; /* ?? QSIG_NO_NOTIFICATION */
-+ default:
-+ pri_message(pri, "!! Unknown Q.SIG presentationIndicator 0x%02x\n", presentation);
-+ return QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR;
-+ }
-+}
-+
-+int asn1_name_decode(void *data, int len, char *namebuf, int buflen)
-+{
- struct rose_component *comp = (struct rose_component*)data;
- int datalen = 0, res = 0;
-
-@@ -361,11 +502,13 @@
- } else
- datalen = res = comp->len;
-
-- if (datalen > buflen) {
-+ if (datalen > buflen - 1) {
- /* Truncate */
- datalen = buflen;
- }
- memcpy(namebuf, comp->data, datalen);
-+ namebuf[datalen] = '\0';
-+
- return res + 2;
- }
-
-@@ -407,42 +550,230 @@
- return res;
- }
-
--static int rose_number_digits_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
-+static int rose_namedata_decode(struct pri *pri, unsigned char *data, int len, int implicit, struct nameelements_namedata *value)
- {
- int i = 0;
- struct rose_component *comp = NULL;
- unsigned char *vdata = data;
-- int datalen = 0;
-- int res = 0;
-+ int res;
-
- do {
-+ /* NameData */
-+ if (!implicit) {
-+ GET_COMPONENT(comp, i, vdata, len);
-+ CHECK_COMPONENT(comp, ASN1_OCTETSTRING, "Don't know what to do if NameData is of type 0x%x\n");
-+
-+ data = comp->data;
-+ if (comp->len == ASN1_LEN_INDEF) {
-+ len = strlen((char *)comp->data);
-+ res = len + 2 + 2;
-+ } else {
-+ len = comp->len;
-+ res = len + 2;
-+ }
-+ } else
-+ res = len;
-+
-+ if (len > sizeof(value->name)-1) {
-+ pri_message(pri, "!! Oversized NameData component (%d)\n", len);
-+ return -1;
-+ }
-+
-+ memcpy(value->name, data, len);
-+ value->name[len] = '\0';
-+
-+ return res;
-+ }
-+ while(0);
-+
-+ return -1;
-+}
-+
-+static int rose_namedata_encode(struct pri *pri, unsigned char *dst, int implicit, char *name)
-+{
-+ int size = 0;
-+ struct rose_component *comp;
-+ int namesize;
-+
-+ namesize = strlen(name);
-+ if (namesize > 50 ) {
-+ pri_message(pri, "!! Encoding of oversized NameData component failed (%d)\n", namesize);
-+ return -1;
-+ } else if (namesize == 0){
-+ pri_message(pri, "!! Encoding of undersized NameData component failed (%d)\n", namesize);
-+ return -1;
-+ }
-+
-+ if (!implicit) {
-+ /* constructor component (0x04,len) */
-+ comp = (struct rose_component *)dst;
-+ comp->type = ASN1_OCTETSTRING;
-+ comp->len = 2 + namesize;
-+ size += 2;
-+ dst += 2;
-+ }
-+
-+ memcpy(dst, name, namesize);
-+ size += namesize;
-+
-+ return size;
-+}
-+
-+static int rose_nameset_decode(struct pri *pri, unsigned char *data, int len, int implicit, struct nameelements_nameset *value)
-+{
-+ int size;
-+ int i = 0;
-+ struct rose_component *comp = NULL;
-+ unsigned char *vdata = data;
-+ int characterset;
-+
-+ value->characterset = CHARACTER_SET_ISO8859_1;
-+
-+ do {
-+ /* NameSet */
-+ if (!implicit) {
-+ GET_COMPONENT(comp, i, vdata, len);
-+ CHECK_COMPONENT(comp, ASN1_SEQUENCE, "Don't know what to do if NameSet is of type 0x%x\n");
-+ SUB_COMPONENT(comp, i);
-+ }
-+
-+ /* nameData NameData */
- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_NUMERICSTRING, "Don't know what to do with PublicPartyNumber ROSE component type 0x%x\n");
-- if(comp->len > 20 && comp->len != ASN1_LEN_INDEF) {
-- pri_message(pri, "!! Oversized NumberDigits component (%d)\n", comp->len);
-+ size = rose_namedata_decode(pri, (u_int8_t *)comp, len, 0, (struct nameelements_namedata *)value);
-+ if (size < 0)
- return -1;
-+ i += size;
-+
-+ if (i < len) {
-+ /* characterSet CharacterSet OPTIONAL */
-+ GET_COMPONENT(comp, i, vdata, len);
-+ CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if CharacterSet is of type 0x%x\n");
-+ ASN1_GET_INTEGER(comp, characterset);
-+ NEXT_COMPONENT(comp, i);
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " NameSet: Received characterSet=%s(%d)\n", characterset_to_str(characterset), characterset);
-+ value->characterset = characterset;
- }
-- if (comp->len == ASN1_LEN_INDEF) {
-- datalen = strlen((char *)comp->data);
-- res = datalen + 2;
-- } else
-- res = datalen = comp->len;
--
-- memcpy(value->partyaddress, comp->data, datalen);
-- value->partyaddress[datalen] = '\0';
-
-- return res + 2;
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " NameSet: '%s', characterSet=%s(%d) i=%d len=%d\n", value->name, characterset_to_str(value->characterset), value->characterset, i, len);
-+
-+ return i;
- }
- while(0);
-
- return -1;
- }
-
--static int rose_public_party_number_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
-+static int rose_name_decode(struct pri *pri, unsigned char *data, int len, struct nameelements_name *value)
- {
- int i = 0;
-+ int size = 0;
- struct rose_component *comp = NULL;
- unsigned char *vdata = data;
-+
-+ value->name[0] = '\0';
-+ value->characterset = CHARACTER_SET_UNKNOWN;
-+ value->namepres = -1;
-+
-+ do {
-+ GET_COMPONENT(comp, i, vdata, len);
-+
-+ switch(comp->type) {
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0): /* [0] namePresentationAllowedSimple */
-+ size = rose_namedata_decode(pri, comp->data, comp->len, 1, (struct nameelements_namedata *)value);
-+ if (size < 0)
-+ return -1;
-+ i += (size + 2);
-+ value->characterset = CHARACTER_SET_ISO8859_1;
-+ value->namepres = 1;
-+ break;
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] namePresentationAllowedExtended */
-+ size = rose_nameset_decode(pri, comp->data, comp->len, 1, (struct nameelements_nameset *)value);
-+ if (size < 0)
-+ return -1;
-+ i += (size + 2);
-+ value->namepres = 1;
-+ break;
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2): /* [2] namePresentationRestrictedSimple */
-+ size = rose_namedata_decode(pri, comp->data, comp->len, 1, (struct nameelements_namedata *)value);
-+ if (size < 0)
-+ return -1;
-+ i += (size + 2);
-+ value->characterset = CHARACTER_SET_ISO8859_1;
-+ value->namepres = 0;
-+ break;
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] namePresentationRestrictedExtended */
-+ size = rose_nameset_decode(pri, comp->data, comp->len, 1, (struct nameelements_nameset *)value);
-+ if (size < 0)
-+ return -1;
-+ i += (size + 2);
-+ value->namepres = 0;
-+ break;
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_4): /* [4] nameNotAvailable */
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_7): /* [7] namePresentationRestrictedNull */
-+ i += (comp->len + 2);
-+ value->name[0] = '\0';
-+ value->characterset = CHARACTER_SET_UNKNOWN;
-+ value->namepres = 0;
-+ break;
-+ default:
-+ pri_message(pri, "!! Unknown Name component received 0x%x\n", comp->type);
-+ return -1;
-+ }
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Name: '%s' i=%d len=%d\n", value->name, i, len);
-+ return i;
-+ }
-+ while (0);
-+
-+ return -1;
-+}
-+
-+static int rose_number_digits_decode(struct pri *pri, unsigned char *data, int len, int implicit, struct addressingdataelements_presentednumberunscreened *value)
-+{
-+ int i = 0;
-+ struct rose_component *comp = NULL;
-+ unsigned char *vdata = data;
-+ int res = 0;
-+
-+ do {
-+ if (!implicit) {
-+ GET_COMPONENT(comp, i, vdata, len);
-+ CHECK_COMPONENT(comp, ASN1_NUMERICSTRING, "Don't know what to do with NumberDigits ROSE component type 0x%x\n");
-+
-+ data = comp->data;
-+ if (comp->len == ASN1_LEN_INDEF) {
-+ len = strlen((char *)comp->data);
-+ res = len + 2 + 2;
-+ } else {
-+ len = comp->len;
-+ res = len + 2;
-+ }
-+ } else
-+ res = len;
-+
-+ if (len > sizeof(value->partyaddress)-1) {
-+ pri_message(pri, "!! Oversized NumberDigits component (%d)\n", len);
-+ return -1;
-+ }
-+
-+ memcpy(value->partyaddress, data, len);
-+ value->partyaddress[len] = '\0';
-+
-+ return res;
-+ }
-+ while(0);
-+
-+ return -1;
-+}
-+
-+static int rose_public_party_number_decode(struct pri *pri, unsigned char *data, int len, int implicit, struct addressingdataelements_presentednumberunscreened *value)
-+{
-+ int i = 0;
-+ struct rose_component *comp = NULL;
-+ unsigned char *vdata = data;
- int ton;
- int res = 0;
-
-@@ -450,13 +781,19 @@
- return -1;
-
- do {
-+ if (!implicit) {
-+ GET_COMPONENT(comp, i, vdata, len);
-+ CHECK_COMPONENT(comp, ASN1_SEQUENCE, "Don't know what to do if PublicPartyNumber is of type 0x%x\n");
-+ SUB_COMPONENT(comp, i);
-+ }
-+
- GET_COMPONENT(comp, i, vdata, len);
- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with PublicPartyNumber ROSE component type 0x%x\n");
- ASN1_GET_INTEGER(comp, ton);
- NEXT_COMPONENT(comp, i);
- ton = typeofnumber_for_q931(pri, ton);
-
-- res = rose_number_digits_decode(pri, call, &vdata[i], len-i, value);
-+ res = rose_number_digits_decode(pri, &vdata[i], len-i, 0, value);
- if (res < 0)
- return -1;
- value->ton = ton;
-@@ -467,8 +804,48 @@
- return -1;
- }
-
--static int rose_private_party_number_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
-+static int rose_public_party_number_encode(struct pri *pri, unsigned char *dst, int implicit, unsigned char ton, char *num)
- {
-+ int i = 0, compsp = 0;
-+ struct rose_component *comp, *compstk[10];
-+ int numsize;
-+
-+ numsize = strlen(num);
-+ if (numsize > 20 ) {
-+ pri_message(pri, "!! Encoding of oversized PublicPartyNumber component failed (%d)\n", numsize);
-+ return -1;
-+ }
-+
-+ if (!implicit) {
-+ /* constructor component (0x30,len) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), dst, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+ } else
-+ comp = (struct rose_component *)dst;
-+
-+ /* publicTypeOfNumber (0x0a,0x01,ton)*/
-+ ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, dst, i, ton);
-+
-+ /* publicNumberDigits */
-+
-+ /* tag component NumericString (0x12,len) */
-+ ASN1_ADD_SIMPLE(comp, ASN1_NUMERICSTRING, dst, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* NumericString */
-+ memcpy(comp->data, num, numsize);
-+ i += numsize;
-+
-+ ASN1_FIXUP(compstk, compsp, dst, i);
-+
-+ if (!implicit)
-+ ASN1_FIXUP(compstk, compsp, dst, i);
-+
-+ return i;
-+}
-+
-+static int rose_private_party_number_decode(struct pri *pri, unsigned char *data, int len, int implicit, struct addressingdataelements_presentednumberunscreened *value)
-+{
- int i = 0;
- struct rose_component *comp = NULL;
- unsigned char *vdata = data;
-@@ -476,18 +853,24 @@
- int res = 0;
-
- if (len < 2)
-- return -1;
-+ return -1;
-
- do {
-+ if (!implicit) {
-+ GET_COMPONENT(comp, i, vdata, len);
-+ CHECK_COMPONENT(comp, ASN1_SEQUENCE, "Don't know what to do if PrivatePartyNumber is of type 0x%x\n");
-+ SUB_COMPONENT(comp, i);
-+ }
-+
- GET_COMPONENT(comp, i, vdata, len);
- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with PrivatePartyNumber ROSE component type 0x%x\n");
- ASN1_GET_INTEGER(comp, ton);
- NEXT_COMPONENT(comp, i);
- ton = typeofnumber_for_q931(pri, ton);
-
-- res = rose_number_digits_decode(pri, call, &vdata[i], len-i, value);
-+ res = rose_number_digits_decode(pri, &vdata[i], len-i, 0, value);
- if (res < 0)
-- return -1;
-+ return -1;
- value->ton = ton;
-
- return res + 3;
-@@ -496,7 +879,7 @@
- return -1;
- }
-
--static int rose_address_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
-+static int rose_address_decode(struct pri *pri, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
- {
- int i = 0;
- struct rose_component *comp = NULL;
-@@ -506,65 +889,59 @@
- do {
- GET_COMPONENT(comp, i, vdata, len);
-
-+ /* PartyNumber */
- switch(comp->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] unknownPartyNumber */
-- res = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0): /* [0] unknownPartyNumber, IMPLICIT NumberDigits */
-+ res = rose_number_digits_decode(pri, comp->data, comp->len, 1, value);
- if (res < 0)
- return -1;
- value->npi = PRI_NPI_UNKNOWN;
- value->ton = PRI_TON_UNKNOWN;
- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0): /* [0] unknownPartyNumber */
-- res = asn1_copy_string(value->partyaddress, sizeof(value->partyaddress), comp);
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] publicPartyNumber, IMPLICIT PublicPartyNumber */
-+ res = rose_public_party_number_decode(pri, comp->data, comp->len, 1, value);
- if (res < 0)
- return -1;
-- value->npi = PRI_NPI_UNKNOWN;
-- value->ton = PRI_TON_UNKNOWN;
-+ value->npi = PRI_NPI_E163_E164;
- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] publicPartyNumber */
-- res = rose_public_party_number_decode(pri, call, comp->data, comp->len, value);
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_3): /* [3] dataPartyNumber, IMPLICIT NumberDigits */
-+ res = rose_number_digits_decode(pri, comp->data, comp->len, 1, value);
- if (res < 0)
- return -1;
-- value->npi = PRI_NPI_E163_E164;
-- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2): /* [2] nsapEncodedNumber */
-- pri_message(pri, "!! NsapEncodedNumber isn't handled\n");
-- return -1;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] dataPartyNumber */
-- if(rose_number_digits_decode(pri, call, comp->data, comp->len, value))
-- return -1;
- value->npi = PRI_NPI_X121 /* ??? */;
- value->ton = PRI_TON_UNKNOWN /* ??? */;
- pri_message(pri, "!! dataPartyNumber isn't handled\n");
- return -1;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4): /* [4] telexPartyNumber */
-- res = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_4): /* [4] telexPartyNumber, IMPLICIT NumberDigits */
-+ res = rose_number_digits_decode(pri, comp->data, comp->len, 1, value);
- if (res < 0)
- return -1;
- value->npi = PRI_NPI_F69 /* ??? */;
- value->ton = PRI_TON_UNKNOWN /* ??? */;
- pri_message(pri, "!! telexPartyNumber isn't handled\n");
- return -1;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] priavePartyNumber */
-- res = rose_private_party_number_decode(pri, call, comp->data, comp->len, value);
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] privatePartyNumber, IMPLICIT PrivatePartyNumber */
-+ res = rose_private_party_number_decode(pri, comp->data, comp->len, 1, value);
- if (res < 0)
-- return -1;
-+ return -1;
- value->npi = PRI_NPI_PRIVATE;
- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_8): /* [8] nationalStandardPartyNumber */
-- res = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_8): /* [8] nationalStandardPartyNumber, IMPLICIT NumberDigits */
-+ res = rose_number_digits_decode(pri, comp->data, comp->len, 1, value);
- if (res < 0)
- return -1;
- value->npi = PRI_NPI_NATIONAL;
- value->ton = PRI_TON_NATIONAL;
- break;
- default:
-- pri_message(pri, "!! Unknown Party number component received 0x%X\n", comp->type);
-+ pri_message(pri, "!! Unknown PartyNumber component received 0x%X\n", comp->type);
- return -1;
- }
- ASN1_FIXUP_LEN(comp, res);
- NEXT_COMPONENT(comp, i);
-- if(i < len)
-+
-+ /* PartySubaddress OPTIONAL */
-+ if (i < len)
- pri_message(pri, "!! not all information is handled from Address component\n");
- return res + 2;
- }
-@@ -573,14 +950,176 @@
- return -1;
- }
-
--static int rose_presented_number_unscreened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
-+static int rose_party_number_encode(struct pri *pri, unsigned char *dst, unsigned char ton, char *num)
- {
-+ int i = 0, compsp = 0;
-+ struct rose_component *comp, *compstk[10];
-+ int numsize, size;
-+
-+ numsize = strlen(num);
-+ if (numsize > 20 ) {
-+ pri_message(pri, "!! Encoding of oversized PartyNumber component failed (%d)\n", numsize);
-+ return -1;
-+ }
-+
-+#if 0
-+ /* tag component unknownPartyNumber (0x80,len) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), dst, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* unknownPartyNumber, implicid NumberDigits */
-+ memcpy(comp->data, num, numsize);
-+ i += numsize;
-+
-+ ASN1_FIXUP(compstk, compsp, dst, i);
-+#endif
-+
-+ /* tag component publicPartyNumber (0xa1,len) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), dst, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* publicPartyNumber, implicid PublicPartyNumber */
-+ size = rose_public_party_number_encode(pri, comp->data, 1, ton, num);
-+ if (size < 0)
-+ return -1;
-+ i += size;
-+
-+ ASN1_FIXUP(compstk, compsp, dst, i);
-+
-+ return i;
-+}
-+
-+static int rose_party_number_decode(struct pri *pri, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
-+{
- int i = 0;
- int size = 0;
- struct rose_component *comp = NULL;
- unsigned char *vdata = data;
-
-+ do {
-+ GET_COMPONENT(comp, i, vdata, len);
-+
-+ switch(comp->type) {
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0): /* [0] IMPLICIT NumberDigits -- default: unknownPartyNumber */
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " PartyNumber: UnknownPartyNumber len=%d\n", len);
-+ size = rose_number_digits_decode(pri, comp->data, comp->len, 1, value);
-+ if (size < 0)
-+ return -1;
-+ value->npi = PRI_NPI_UNKNOWN;
-+ value->ton = PRI_TON_UNKNOWN;
-+ break;
-+
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] IMPLICIT PublicPartyNumber */
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " PartyNumber: PublicPartyNumber len=%d\n", len);
-+ size = rose_public_party_number_decode(pri, comp->data, comp->len, 1, value);
-+ if (size < 0)
-+ return -1;
-+ value->npi = PRI_NPI_E163_E164;
-+ break;
-+
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_3): /* [3] IMPLICIT NumberDigits -- not used: dataPartyNumber */
-+ pri_message(pri, "!! PartyNumber: dataPartyNumber is reserved!\n");
-+ size = rose_number_digits_decode(pri, comp->data, comp->len, 1, value);
-+ if (size < 0)
-+ return -1;
-+ value->npi = PRI_NPI_X121 /* ??? */;
-+ value->ton = PRI_TON_UNKNOWN /* ??? */;
-+ break;
-+
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_4): /* [4] IMPLICIT NumberDigits -- not used: telexPartyNumber */
-+ pri_message(pri, "!! PartyNumber: telexPartyNumber is reserved!\n");
-+ size = rose_number_digits_decode(pri, comp->data, comp->len, 1, value);
-+ if (size < 0)
-+ return -1;
-+ value->npi = PRI_NPI_F69 /* ??? */;
-+ value->ton = PRI_TON_UNKNOWN /* ??? */;
-+ break;
-+
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] IMPLICIT PrivatePartyNumber */
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " PartyNumber: PrivatePartyNumber len=%d\n", len);
-+ size = rose_private_party_number_decode(pri, comp->data, comp->len, 1, value);
-+ if (size < 0)
-+ return -1;
-+ value->npi = PRI_NPI_PRIVATE;
-+ break;
-+
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_8): /* [8] IMPLICIT NumberDigits -- not used: nationalStandatdPartyNumber */
-+ pri_message(pri, "!! PartyNumber: nationalStandardPartyNumber is reserved!\n");
-+ size = rose_number_digits_decode(pri, comp->data, comp->len, 1, value);
-+ if (size < 0)
-+ return -1;
-+ value->npi = PRI_NPI_NATIONAL;
-+ value->ton = PRI_TON_NATIONAL;
-+ break;
-+
-+ default:
-+ pri_message(pri, "Invalid PartyNumber component 0x%X\n", comp->type);
-+ return -1;
-+ }
-+ ASN1_FIXUP_LEN(comp, size);
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " PartyNumber: '%s' size=%d len=%d\n", value->partyaddress, size, len);
-+ return size;
-+ }
-+ while (0);
-+
-+ return -1;
-+}
-+
-+static int rose_presented_number_unscreened_encode(struct pri *pri, unsigned char *dst, unsigned char presentation, unsigned char ton, char *num)
-+{
-+ int i = 0, compsp = 0;
-+ struct rose_component *comp, *compstk[10];
-+ int numsize, size;
-+
-+ numsize = strlen(num);
-+ if (numsize > 20 ) {
-+ pri_message(pri, "!! Encoding of oversized PresentedNumberUnscreened component failed (%d)\n", numsize);
-+ return -1;
-+ }
-+
-+ switch (presentation & PRES_RESTRICTION) {
-+ case PRES_ALLOWED:
-+ /* tag component [0] presentationAllowedAddress (0xa0,len) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), dst, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* PartyNumber */
-+ size = rose_party_number_encode(pri, comp->data, ton, num);
-+ if (size < 0)
-+ return -1;
-+ i += size;
-+ ASN1_FIXUP(compstk, compsp, dst, i);
-+ break;
-+ case PRES_RESTRICTED:
-+ /* tag component [1] presentationRestricted (0x81,len) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), dst, i);
-+ break;
-+ case PRES_UNAVAILABLE:
-+ /* tag component [2] numberNotAvailableDueToInterworking (0x82,len) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), dst, i);
-+ /* ASN1_FIXUP(compstk, compsp, dst, i); */
-+ break;
-+ default:
-+ pri_message(pri, "!! Undefined presentation value for PresentedNumberUnscreened: 0x%x\n", presentation);
-+ return -1;
-+ }
-+
-+ return i;
-+}
-+
-+static int rose_presented_number_unscreened_decode(struct pri *pri, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
-+{
-+ int i = 0;
-+ int size = 0;
-+ struct rose_component *comp = NULL;
-+ unsigned char *vdata = data;
-+
- /* Fill in default values */
-+ value->partyaddress[0] = '\0';
- value->ton = PRI_TON_UNKNOWN;
- value->npi = PRI_NPI_E163_E164;
- value->pres = -1; /* Data is not available */
-@@ -591,7 +1130,7 @@
- switch(comp->type) {
- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] presentationAllowedNumber */
- value->pres = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
-- size = rose_address_decode(pri, call, comp->data, comp->len, value);
-+ size = rose_address_decode(pri, comp->data, comp->len, value);
- ASN1_FIXUP_LEN(comp, size);
- return size + 2;
- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* [1] IMPLICIT presentationRestricted */
-@@ -610,7 +1149,7 @@
- return 2;
- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] presentationRestrictedNumber */
- value->pres = PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
-- size = rose_address_decode(pri, call, comp->data, comp->len, value) + 2;
-+ size = rose_address_decode(pri, comp->data, comp->len, value) + 2;
- ASN1_FIXUP_LEN(comp, size);
- return size + 2;
- default:
-@@ -623,17 +1162,482 @@
- return -1;
- }
-
-+static int rose_number_screened_encode(struct pri *pri, unsigned char *dst, int implicit, unsigned char ton, unsigned char screenind, char *num)
-+{
-+ int i = 0, compsp = 0;
-+ struct rose_component *comp, *compstk[10];
-+ int numsize, size;
-+
-+ numsize = strlen(num);
-+ if (numsize > 20 ) {
-+ pri_message(pri, "!! Encoding of oversized NumberScreened component failed (%d)\n", numsize);
-+ return -1;
-+ }
-+
-+ if (!implicit) {
-+ /* constructor component (0x30,len) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), dst, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+ } else
-+ comp = (struct rose_component *)dst;
-+
-+ /* PartyNumber */
-+ size = rose_party_number_encode(pri, (u_int8_t *)comp, ton, num);
-+ if (size < 0)
-+ return -1;
-+ i += size;
-+
-+ /* ScreeningIndicator (0x0a,0x01,screenind) */
-+ ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, dst, i, screenind);
-+
-+ if (!implicit)
-+ ASN1_FIXUP(compstk, compsp, dst, i);
-+
-+ return i;
-+}
-+
-+static int rose_number_screened_decode(struct pri *pri, unsigned char *data, int len, struct addressingdataelements_presentednumberscreened *value)
-+{
-+ int i = 0;
-+ int size = 0;
-+ struct rose_component *comp = NULL;
-+ unsigned char *vdata = data;
-+
-+ int scrind = -1;
-+
-+ do {
-+ /* Party Number */
-+ GET_COMPONENT(comp, i, vdata, len);
-+ size = rose_party_number_decode(pri, (u_int8_t *)comp, comp->len + 2, (struct addressingdataelements_presentednumberunscreened*) value);
-+ if (size < 0)
-+ return -1;
-+ comp->len = size;
-+ NEXT_COMPONENT(comp, i);
-+
-+ /* Screening Indicator */
-+ GET_COMPONENT(comp, i, vdata, len);
-+ CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with NumberScreened ROSE component type 0x%x\n");
-+ ASN1_GET_INTEGER(comp, scrind);
-+ // Todo: scrind = screeningindicator_for_q931(pri, scrind);
-+ NEXT_COMPONENT(comp, i);
-+
-+ value->scrind = scrind;
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " NumberScreened: '%s' ScreeningIndicator=%d i=%d len=%d\n", value->partyaddress, scrind, i, len);
-+
-+ return i-2; // We do not have a sequence header here.
-+ }
-+ while (0);
-+
-+ return -1;
-+}
-+
-+static int rose_presented_number_screened_decode(struct pri *pri, unsigned char *data, int len, struct addressingdataelements_presentednumberscreened *value)
-+{
-+ int i = 0;
-+ int size = 0;
-+ struct rose_component *comp = NULL;
-+ unsigned char *vdata = data;
-+
-+ /* Fill in default values */
-+ value->partyaddress[0] = '\0';
-+ value->ton = PRI_TON_UNKNOWN;
-+ value->npi = PRI_NPI_UNKNOWN;
-+ value->pres = -1; /* Data is not available */
-+ value->scrind = 0;
-+
-+ do {
-+ GET_COMPONENT(comp, i, vdata, len);
-+
-+ switch(comp->type) {
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] IMPLICIT presentationAllowedNumber */
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " PresentedNumberScreened: presentationAllowedNumber comp->len=%d\n", comp->len);
-+ value->pres = PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
-+ size = rose_number_screened_decode(pri, comp->data, comp->len, value);
-+ if (size < 0)
-+ return -1;
-+ ASN1_FIXUP_LEN(comp, size);
-+ return size + 2;
-+
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* [1] IMPLICIT presentationRestricted */
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " PresentedNumberScreened: presentationRestricted comp->len=%d\n", comp->len);
-+ if (comp->len != 0) { /* must be NULL */
-+ pri_error(pri, "!! Invalid PresentationRestricted component received (len != 0)\n");
-+ return -1;
-+ }
-+ value->pres = PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
-+ return 2;
-+
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2): /* [2] IMPLICIT numberNotAvailableDueToInterworking */
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " PresentedNumberScreened: NumberNotAvailableDueToInterworking comp->len=%d\n", comp->len);
-+ if (comp->len != 0) { /* must be NULL */
-+ pri_error(pri, "!! Invalid NumberNotAvailableDueToInterworking component received (len != 0)\n");
-+ return -1;
-+ }
-+ value->pres = PRES_NUMBER_NOT_AVAILABLE;
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " PresentedNumberScreened: numberNotAvailableDueToInterworking Type=0x%X i=%d len=%d size=%d\n", comp->type, i, len);
-+ return 2;
-+
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] IMPLICIT presentationRestrictedNumber */
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " PresentedNumberScreened: presentationRestrictedNumber comp->len=%d\n", comp->len);
-+ value->pres = PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
-+ size = rose_number_screened_decode(pri, comp->data, comp->len, value);
-+ if (size < 0)
-+ return -1;
-+ ASN1_FIXUP_LEN(comp, size);
-+ return size + 2;
-+
-+ default:
-+ pri_message(pri, "Invalid PresentedNumberScreened component 0x%X\n", comp->type);
-+ }
-+ return -1;
-+ }
-+ while (0);
-+
-+ return -1;
-+}
-+
-+static int rose_partysubaddress_decode(struct pri *pri, unsigned char *data, int len, struct addressingdataelements_partysubaddress *value)
-+{
-+ int i = 0;
-+ int size = 0;
-+ struct rose_component *comp = NULL;
-+ unsigned char *vdata = data;
-+
-+ int odd_count_indicator = -1;
-+ value->partysubaddress[0] = '\0';
-+
-+ do {
-+ GET_COMPONENT(comp, i, vdata, len);
-+
-+ switch(comp->type) {
-+ case (ASN1_CONSTRUCTOR | ASN1_SEQUENCE): /* UserSpecifiedSubaddress */
-+ /* SubaddressInformation */
-+ SUB_COMPONENT(comp, i);
-+ GET_COMPONENT(comp, i, vdata, len);
-+ CHECK_COMPONENT(comp, ASN1_OCTETSTRING, "Don't know what to do if SubaddressInformation is of type 0x%x\n");
-+ size = asn1_name_decode(comp->data, comp->len, value->partysubaddress, sizeof(value->partysubaddress));
-+ if (size < 0)
-+ return -1;
-+ i += size;
-+
-+ /* oddCountIndicator BOOLEAN OPTIONAL */
-+ if (i < len) {
-+ GET_COMPONENT(comp, i, vdata, len);
-+ CHECK_COMPONENT(comp, ASN1_BOOLEAN, "Don't know what to do if SubaddressInformation is of type 0x%x\n");
-+
-+ ASN1_GET_INTEGER(comp, odd_count_indicator);
-+ NEXT_COMPONENT(comp, i);
-+ }
-+ case (ASN1_OCTETSTRING): /* NSAPSubaddress */
-+ size = asn1_name_decode((u_int8_t *)comp, comp->len + 2, value->partysubaddress, sizeof(value->partysubaddress));
-+ if (size < 0)
-+ return -1;
-+ i += size;
-+ break;
-+ default:
-+ pri_message(pri, "Invalid PartySubaddress component 0x%X\n", comp->type);
-+ return -1;
-+ }
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " PartySubaddress: '%s', oddCountIndicator=%d, i=%d len=%d\n", value->partysubaddress, odd_count_indicator, i, len);
-+
-+ return i;
-+ }
-+ while (0);
-+
-+ return -1;
-+}
-+
-+static int rose_address_screened_decode(struct pri *pri, unsigned char *data, int len, struct addressingdataelements_addressscreened *value)
-+{
-+ int i = 0;
-+ int size = 0;
-+ struct rose_component *comp = NULL;
-+ unsigned char *vdata = data;
-+
-+ int scrind;
-+ value->partysubaddress[0] = '\0';
-+
-+ /* SEQUENCE AddressScreened */
-+ do {
-+ /* PartyNumber */
-+ GET_COMPONENT(comp, i, vdata, len);
-+ size = rose_party_number_decode(pri, (u_int8_t *)comp, comp->len + 2, (struct addressingdataelements_presentednumberunscreened *)value);
-+ if (size < 0)
-+ return -1;
-+ comp->len = size;
-+ NEXT_COMPONENT(comp, i);
-+
-+ /* ScreeningIndicator */
-+ GET_COMPONENT(comp, i, vdata, len);
-+ CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with AddressScreened ROSE component type 0x%x\n");
-+ ASN1_GET_INTEGER(comp, scrind);
-+ NEXT_COMPONENT(comp, i);
-+
-+ if (i < len) {
-+ /* PartySubaddress OPTIONAL */
-+ GET_COMPONENT(comp, i, vdata, len);
-+ size = rose_partysubaddress_decode(pri, (u_int8_t *)comp, comp->len + 2, (struct addressingdataelements_partysubaddress *)value);
-+ if (size < 0)
-+ return -1;
-+ i += size;
-+ }
-+
-+ value->scrind = scrind;
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " AddressScreened: '%s' ScreeningIndicator=%d i=%d len=%d\n", value->partyaddress, scrind, i, len);
-+
-+ return i-2;
-+ }
-+ while (0);
-+
-+ return -1;
-+}
-+
-+static int rose_presented_address_screened_decode(struct pri *pri, unsigned char *data, int len, struct addressingdataelements_presentedaddressscreened *value)
-+{
-+ int i = 0;
-+ int size = 0;
-+ struct rose_component *comp = NULL;
-+ unsigned char *vdata = data;
-+
-+ /* Fill in default values */
-+ value->partyaddress[0] = '\0';
-+ value->partysubaddress[0] = '\0';
-+ value->npi = PRI_NPI_UNKNOWN;
-+ value->ton = PRI_TON_UNKNOWN;
-+ value->pres = -1; /* Data is not available */
-+ value->scrind = 0;
-+
-+ do {
-+ GET_COMPONENT(comp, i, vdata, len);
-+
-+ switch(comp->type) {
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] IMPLICIT presentationAllowedAddress */
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " PresentedAddressScreened: presentationAllowedAddress comp->len=%d\n", comp->len);
-+ value->pres = PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
-+ size = rose_address_screened_decode(pri, comp->data, comp->len, (struct addressingdataelements_addressscreened *)value);
-+ if (size < 0)
-+ return -1;
-+ ASN1_FIXUP_LEN(comp, size);
-+ return size + 2;
-+
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* [1] IMPLICIT presentationRestricted */
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " PresentedAddressScreened: presentationRestricted comp->len=%d\n", comp->len);
-+ if (comp->len != 0) { /* must be NULL */
-+ pri_error(pri, "!! Invalid PresentationRestricted component received (len != 0)\n");
-+ return -1;
-+ }
-+ value->pres = PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
-+ return 2;
-+
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2): /* [2] IMPLICIT numberNotAvailableDueToInterworking */
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " PresentedAddressScreened: NumberNotAvailableDueToInterworking comp->len=%d\n", comp->len);
-+ if (comp->len != 0) { /* must be NULL */
-+ pri_error(pri, "!! Invalid NumberNotAvailableDueToInterworking component received (len != 0)\n");
-+ return -1;
-+ }
-+ value->pres = PRES_NUMBER_NOT_AVAILABLE;
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " PresentedAddressScreened: numberNotAvailableDueToInterworking Type=0x%X i=%d len=%d size=%d\n", comp->type, i, len);
-+ return 2;
-+
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] IMPLICIT presentationRestrictedAddress */
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " PresentedAddressScreened: presentationRestrictedAddress comp->len=%d\n", comp->len);
-+ value->pres = PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
-+ size = rose_address_screened_decode(pri, comp->data, comp->len, (struct addressingdataelements_addressscreened *)value);
-+ if (size < 0)
-+ return -1;
-+ ASN1_FIXUP_LEN(comp, size);
-+ return size + 2;
-+
-+ default:
-+ pri_message(pri, "Invalid PresentedAddressScreened component 0x%X\n", comp->type);
-+ }
-+ return -1;
-+ }
-+ while (0);
-+
-+ return -1;
-+}
-+
-+static int rose_diverting_leg_information1_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
-+{
-+ int i = 0;
-+ struct addressingdataelements_presentednumberunscreened nominatednr;
-+ int diversion_reason;
-+ int subscription_option;
-+ struct rose_component *comp = NULL;
-+ unsigned char *vdata = sequence->data;
-+ int size = 0;
-+ memset(&nominatednr, 0, sizeof(nominatednr));
-+
-+ /* Data checks */
-+ if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
-+ pri_message(pri, "Invalid DivertingLegInformation1Type argument\n");
-+ return -1;
-+ }
-+
-+ if (sequence->len == ASN1_LEN_INDEF) {
-+ len -= 4; /* For the 2 extra characters at the end
-+ and two characters of header */
-+ } else
-+ len -= 2;
-+
-+ do {
-+ /* diversionReason DiversionReason */
-+ GET_COMPONENT(comp, i, vdata, len);
-+ CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Invalid diversionReason type 0x%X of ROSE divertingLegInformation1 component received\n");
-+ ASN1_GET_INTEGER(comp, diversion_reason);
-+ NEXT_COMPONENT(comp, i);
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Received diversionReason: %s(%d)\n", diversionreason_to_str(pri, diversion_reason), diversion_reason);
-+
-+ diversion_reason = redirectingreason_for_q931(pri, diversion_reason);
-+
-+ /* subscriptionOption SubscriptionOption */
-+ GET_COMPONENT(comp, i, vdata, len);
-+ CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Invalid subscriptionOption type 0x%X of ROSE divertingLegInformation1 component received\n");
-+ ASN1_GET_INTEGER(comp, subscription_option);
-+ NEXT_COMPONENT(comp, i);
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Received subscriptionOption: %d\n", subscription_option);
-+
-+ /* nominatedNr PartyNumber */
-+ GET_COMPONENT(comp, i, vdata, len);
-+ size = rose_party_number_decode(pri, (u_int8_t *)comp, comp->len + 2, &nominatednr);
-+ if (size < 0)
-+ return -1;
-+
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, " Received nominatedNr '%s'\n", nominatednr.partyaddress);
-+ pri_message(pri, " ton = %d, npi = %d\n\n", nominatednr.ton, nominatednr.npi);
-+ }
-+
-+ call->divleginfo1activeflag = 1;
-+ if (subscription_option == QSIG_NOTIFICATION_WITH_DIVERTED_TO_NR) {
-+ libpri_copy_string(call->divertedtonum, nominatednr.partyaddress, sizeof(call->divertedtonum));
-+ } else {
-+ call->divertedtonum[0] = '\0';
-+ }
-+ call->divertedtopres = (subscription_option == QSIG_NOTIFICATION_WITH_DIVERTED_TO_NR) ? PRES_ALLOWED_USER_NUMBER_NOT_SCREENED : PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
-+ call->divertedtoplan = ((nominatednr.ton & 0x07) << 4) | (nominatednr.npi & 0x0f);
-+ call->divertedtoreason = diversion_reason;
-+ call->divertedtocount++;
-+
-+ return 0;
-+ }
-+ while (0);
-+
-+ return -1;
-+}
-+
-+int rose_diverting_leg_information1_encode(struct pri *pri, q931_call *call)
-+{
-+ int i = 0, compsp = 0;
-+ struct rose_component *comp, *compstk[10];
-+ unsigned char buffer[256];
-+ int size;
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Encode divertingLegInformation1\n");
-+
-+ /* Protocol Profile = 0x1f (Networking Extensions) (0x9f) */
-+ buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
-+
-+ /* Network Facility Extension */
-+ if (pri->switchtype == PRI_SWITCH_QSIG) {
-+ /* tag component NetworkFacilityExtension (0xaa, len ) */
-+ ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* sourceEntity (0x80,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0); /* endPINX(0) */
-+
-+ /* destinationEntity (0x82,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0); /* endPINX(0) */
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+ }
-+
-+ /* Network Protocol Profile */
-+ /* - not included - */
-+
-+ /* Interpretation APDU (0x8b,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0); /* discardAnyUnrecognisedInvokePdu(0) */
-+
-+ /* Service APDU(s): */
-+
-+ /* ROSE InvokePDU (0xa1,len) */
-+ ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* ROSE InvokeID (0x02,0x01,invokeid) */
-+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
-+
-+ /* ROSE operationId (0x02,0x01,0x14)*/
-+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, ROSE_DIVERTING_LEG_INFORMATION1);
-+
-+ /* constructor component (0x30,len) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* diversionReason (0x0a,0x01,diversionreason) */
-+ ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, redirectingreason_from_q931(pri, call->divertedtoreason));
-+
-+ /* subscriptionOption (0x0a,0x01,subscriptionoption) */
-+ ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, presentation_to_subscription(pri, call->divertedtopres));
-+
-+ /* nominatedNr */
-+
-+ /* tag component publicPartyNumber (0xa1,len) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* publicPartyNumber, implicid PublicPartyNumber */
-+ size = rose_public_party_number_encode(pri, &buffer[i], 1, (call->divertedtoplan & 0x70) >> 4, call->divertedtonum);
-+ if (size < 0)
-+ return -1;
-+ i += size;
-+
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+
-+ if (pri_call_apdu_queue(call, Q931_FACILITY, buffer, i, NULL, NULL))
-+ return -1;
-+
-+ return 0;
-+}
-+
- static int rose_diverting_leg_information2_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
- {
- int i = 0;
-+ struct rose_component *comp = NULL;
-+ unsigned char *vdata = sequence->data;
-+ int size = 0;
-+
- int diversion_counter;
- int diversion_reason;
-- char origcalledname[50] = "", redirectingname[50] = "";
-+ int original_diversion_reason = QSIG_DIVERT_REASON_UNKNOWN;
-+ struct nameelements_name redirectingname = { "", CHARACTER_SET_UNKNOWN, 0 };
-+ struct nameelements_name origcalledname = { "", CHARACTER_SET_UNKNOWN, 0 };;
- struct addressingdataelements_presentednumberunscreened divertingnr;
-- struct addressingdataelements_presentednumberunscreened originalcallednr;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = sequence->data;
-- int res = 0;
-+ struct addressingdataelements_presentednumberunscreened originalcallednr;
- memset(&divertingnr, 0, sizeof(divertingnr));
- memset(&originalcallednr, 0, sizeof(originalcallednr));
-
-@@ -644,249 +1648,429 @@
- }
-
- if (sequence->len == ASN1_LEN_INDEF) {
-- len -= 4; /* For the 2 extra characters at the end
-- * and two characters of header */
-+ len -= 4; /* For the 2 extra characters at the end
-+ and two characters of header */
- } else
- len -= 2;
-
- do {
-- /* diversionCounter stuff */
-+ /* diversionCounter */
- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do it diversionCounter is of type 0x%x\n");
-+ CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if diversionCounter is of type 0x%x\n");
- ASN1_GET_INTEGER(comp, diversion_counter);
- NEXT_COMPONENT(comp, i);
-
-- /* diversionReason stuff */
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Received diversionCounter: %d\n", diversion_counter);
-+
-+ /* diversionReason DiversionReason */
- GET_COMPONENT(comp, i, vdata, len);
- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Invalid diversionReason type 0x%X of ROSE divertingLegInformation2 component received\n");
- ASN1_GET_INTEGER(comp, diversion_reason);
- NEXT_COMPONENT(comp, i);
-
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Received diversionReason: %s(%d)\n", diversionreason_to_str(pri, diversion_reason), diversion_reason);
-+
- diversion_reason = redirectingreason_for_q931(pri, diversion_reason);
--
-- if(pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Redirection reason: %d, total diversions: %d\n", diversion_reason, diversion_counter);
-- pri_message(NULL, "Length of message is %d\n", len);
-
-- for(; i < len; NEXT_COMPONENT(comp, i)) {
-+ /* Type SEQUENCE specifies an ordered list of component types. *
-+ * We decode all components but for simplicity we don't check the order. */
-+ while (i < len) {
- GET_COMPONENT(comp, i, vdata, len);
-+
- switch(comp->type) {
- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0):
-- call->origredirectingreason = redirectingreason_for_q931(pri, comp->data[0]);
-+ /* originalDiversionReason */
-+ ASN1_GET_INTEGER(comp, original_diversion_reason);
-+ NEXT_COMPONENT(comp,i);
- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Received reason for original redirection %d\n", call->origredirectingreason);
-+ pri_message(pri, " Received originalDiversionReason: %s(%d)\n", diversionreason_to_str(pri, original_diversion_reason), original_diversion_reason);
-+ original_diversion_reason = redirectingreason_for_q931(pri, original_diversion_reason);
- break;
- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1):
-- res = rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &divertingnr);
-- /* TODO: Fix indefinite length form hacks */
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-- if (res < 0)
-+ /* divertingNr */
-+ size = rose_presented_number_unscreened_decode(pri, comp->data, comp->len, &divertingnr);
-+ if (size < 0)
- return -1;
-+ ASN1_FIXUP_LEN(comp, size);
-+ comp->len = size;
-+ NEXT_COMPONENT(comp,i);
- if (pri->debug & PRI_DEBUG_APDU) {
- pri_message(pri, " Received divertingNr '%s'\n", divertingnr.partyaddress);
- pri_message(pri, " ton = %d, pres = %d, npi = %d\n", divertingnr.ton, divertingnr.pres, divertingnr.npi);
- }
- break;
- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2):
-- res = rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &originalcallednr);
-- if (res < 0)
-+ /* originalCalledNr */
-+ size = rose_presented_number_unscreened_decode(pri, comp->data, comp->len, &originalcallednr);
-+ if (size < 0)
- return -1;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-+ ASN1_FIXUP_LEN(comp, size);
-+ comp->len = size;
-+ NEXT_COMPONENT(comp,i);
- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, " Received originalcallednr '%s'\n", originalcallednr.partyaddress);
-+ pri_message(pri, " Received originalCalledNr '%s'\n", originalcallednr.partyaddress);
- pri_message(pri, " ton = %d, pres = %d, npi = %d\n", originalcallednr.ton, originalcallednr.pres, originalcallednr.npi);
- }
- break;
- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3):
-- res = asn1_name_decode(comp->data, comp->len, redirectingname, sizeof(redirectingname));
-- if (res < 0)
-+ /* redirectingName */
-+ size = rose_name_decode(pri, comp->data, comp->len, &redirectingname);
-+ if (size < 0)
- return -1;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-+ i += (size + 2);
- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Received RedirectingName '%s'\n", redirectingname);
-+ pri_message(pri, " Received RedirectingName '%s', namepres %s(%d), characterset %s(%d)\n",
-+ redirectingname.name, namepres_to_str(redirectingname.namepres), redirectingname.namepres,
-+ characterset_to_str(redirectingname.characterset), redirectingname.characterset);
- break;
- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4):
-- res = asn1_name_decode(comp->data, comp->len, origcalledname, sizeof(origcalledname));
-- if (res < 0)
-+ /* originalCalledName */
-+ size = rose_name_decode(pri, comp->data, comp->len, &origcalledname);
-+ if (size < 0)
- return -1;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-+ i += (size + 2);
- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Received Originally Called Name '%s'\n", origcalledname);
-+ pri_message(pri, " Received OriginalCalledName '%s', namepres %s(%d), characterset %s(%d)\n",
-+ origcalledname.name, namepres_to_str(origcalledname.namepres), origcalledname.namepres,
-+ characterset_to_str(origcalledname.characterset), origcalledname.characterset);
- break;
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5):
-- pri_message(pri, "!! Ignoring DivertingLegInformation2 component 0x%X\n", comp->type);
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] IMPLICIT Extension */
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_6): /* [6] IMPLICIT SEQUENCE OF Extension */
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "!! Ignoring DivertingLegInformation2 component 0x%X\n", comp->type);
-+ NEXT_COMPONENT(comp, i);
- break;
- default:
-- if (comp->type == 0 && comp->len == 0) {
-- break; /* Found termination characters */
-- }
-- pri_message(pri, "!! Invalid DivertingLegInformation2 component received 0x%X\n", comp->type);
-+ pri_message(pri, "!! Invalid DivertingLegInformation2 component received 0x%X\n", comp->type);
- return -1;
- }
- }
-
- if (divertingnr.pres >= 0) {
-- call->redirectingplan = divertingnr.npi;
-+ call->redirectingplan = ((divertingnr.ton & 0x07) << 4) | (divertingnr.npi & 0x0f);
- call->redirectingpres = divertingnr.pres;
- call->redirectingreason = diversion_reason;
- libpri_copy_string(call->redirectingnum, divertingnr.partyaddress, sizeof(call->redirectingnum));
-- pri_message(pri, " Received redirectingnum '%s' (%d)\n", call->redirectingnum, (int)call->redirectingnum[0]);
- }
- if (originalcallednr.pres >= 0) {
-- call->origcalledplan = originalcallednr.npi;
-+ call->origcalledplan = ((originalcallednr.ton & 0x07) << 4) | (originalcallednr.npi & 0x0f);
- call->origcalledpres = originalcallednr.pres;
- libpri_copy_string(call->origcallednum, originalcallednr.partyaddress, sizeof(call->origcallednum));
-- pri_message(pri, " Received origcallednum '%s' (%d)\n", call->origcallednum, (int)call->origcallednum[0]);
- }
-- libpri_copy_string(call->redirectingname, redirectingname, sizeof(call->redirectingname));
-- libpri_copy_string(call->origcalledname, origcalledname, sizeof(call->origcalledname));
-+
-+ if (redirectingname.namepres != 0) {
-+ libpri_copy_string(call->redirectingname, redirectingname.name, sizeof(call->redirectingname));
-+ } else {
-+ call->redirectingname[0] = '\0';
-+ }
-+
-+ if (origcalledname.namepres != 0) {
-+ libpri_copy_string(call->origcalledname, origcalledname.name, sizeof(call->origcalledname));
-+ } else {
-+ call->origcalledname[0] = '\0';
-+ }
-+
-+ call->origredirectingreason = original_diversion_reason;
-+ call->redirectingcount = diversion_counter;
-+
- return 0;
- }
- while (0);
-
- return -1;
- }
--
-+
- static int rose_diverting_leg_information2_encode(struct pri *pri, q931_call *call)
- {
-- int i = 0, j, compsp = 0;
-+ int i = 0, compsp = 0;
- struct rose_component *comp, *compstk[10];
- unsigned char buffer[256];
-- int len = 253;
--
--#if 0 /* This is not required by specifications */
-- if (!strlen(call->callername)) {
-- return -1;
-+ int size;
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Encode divertingLegInformation2\n");
-+
-+ /* Protocol Profile = 0x1f (Networking Extensions) (0x9f) */
-+ buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
-+
-+ /* Network Facility Extension */
-+ if (pri->switchtype == PRI_SWITCH_QSIG) {
-+ /* tag component NetworkFacilityExtension (0xaa, len ) */
-+ ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* sourceEntity (0x80,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0); /* endPINX(0) */
-+
-+ /* destinationEntity (0x82,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0); /* endPINX(0) */
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
- }
--#endif
-
-- buffer[i] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
-- i++;
-- /* Interpretation component */
-- ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0x00 /* Discard unrecognized invokes */);
--
-+ /* Network Protocol Profile */
-+ /* - not included - */
-+
-+ /* Interpretation APDU (0x8b,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0); /* discardAnyUnrecognisedInvokePdu(0) */
-+
-+ /* Service APDU(s): */
-+
-+ /* ROSE InvokePDU (0xa1,len) */
- ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
--
- ASN1_PUSH(compstk, compsp, comp);
-- /* Invoke component contents */
-- /* Invoke ID */
-+
-+ /* ROSE InvokeID (0x02,0x01,invokeid) */
- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
-- /* Operation Tag */
--
-- /* ROSE operationId component */
-+
-+ /* ROSE operationId (0x02,0x01,0x15)*/
- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, ROSE_DIVERTING_LEG_INFORMATION2);
-
-- /* ROSE ARGUMENT component */
-+ /* constructor component (0x30,len) */
- ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
- ASN1_PUSH(compstk, compsp, comp);
-- /* ROSE DivertingLegInformation2.diversionCounter component */
-- /* Always is 1 because other isn't available in the current design */
-+
-+ /* diversionCounter always is 1 because other isn't available in the current design */
-+ /* diversionCounter (0x02,0x01,0x01) */
- ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, 1);
--
-- /* ROSE DivertingLegInformation2.diversionReason component */
-+
-+ /* diversionReason (0x0a,0x01,redirectingreason) */
- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, redirectingreason_from_q931(pri, call->redirectingreason));
--
-- /* ROSE DivertingLegInformation2.divertingNr component */
-+
-+ /* originalDiversionReason */
-+ /* - not included - */
-+
-+ /* divertingNr */
-+
-+ /* tag component divertingNr (0xa1,len) */
- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
--
- ASN1_PUSH(compstk, compsp, comp);
-- /* Redirecting information always not screened */
--
-- switch(call->redirectingpres) {
-- case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
-- case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
-- if (call->redirectingnum && strlen(call->redirectingnum)) {
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- /* NPI of redirected number is not supported in the current design */
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, typeofnumber_from_q931(pri, call->redirectingplan >> 4));
-- j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, call->redirectingnum, strlen(call->redirectingnum));
-- if (j < 0)
-- return -1;
--
-- i += j;
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- break;
-- }
-- /* fall through */
-- case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
-- case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
-- break;
-- /* Don't know how to handle this */
-- case PRES_ALLOWED_NETWORK_NUMBER:
-- case PRES_PROHIB_NETWORK_NUMBER:
-- case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
-- case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
-- break;
-- default:
-- pri_message(pri, "!! Undefined presentation value for redirecting number: %d\n", call->redirectingpres);
-- case PRES_NUMBER_NOT_AVAILABLE:
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i);
-- break;
-- }
-+
-+ size = rose_presented_number_unscreened_encode(pri, &buffer[i], call->redirectingpres, typeofnumber_from_q931(pri, (call->redirectingplan & 0x70) >> 4), call->redirectingnum);
-+ if (size < 0)
-+ return -1;
-+ i += size;
- ASN1_FIXUP(compstk, compsp, buffer, i);
-
-- /* ROSE DivertingLegInformation2.originalCalledNr component */
-- /* This information isn't supported by current design - duplicate divertingNr */
-+ /* originalCalledNr */
-+ /* - not included - */
-+
-+#if 0
-+ /* The originalCalledNr is unknown here. Its the same as divertingNr if the call *
-+ * is diverted only once but we don't know if its diverted one ore more times. */
-+
-+ /* originalCalledNr */
-+
-+ /* tag component originalCalledNr (0xa2,len) */
- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2), buffer, i);
- ASN1_PUSH(compstk, compsp, comp);
-- /* Redirecting information always not screened */
-- switch(call->redirectingpres) {
-- case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
-- case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
-- if (call->redirectingnum && strlen(call->redirectingnum)) {
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
-- ASN1_PUSH(compstk, compsp, comp);
-- ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, typeofnumber_from_q931(pri, call->redirectingplan >> 4));
--
-- j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, call->redirectingnum, strlen(call->redirectingnum));
-- if (j < 0)
-+
-+ size = rose_presented_number_unscreened_encode(pri, &buffer[i], call->redirectingpres, typeofnumber_from_q931(pri, (call->redirectingplan & 0x70) >> 4), call->redirectingnum);
-+ if (size < 0)
-+ return -1;
-+ i += size;
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+#endif
-+
-+ /* redirectingName */
-+ if (call->redirectingname[0]) {
-+ /* tag component redirectingName (0xa3,len) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3), buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* tag component namePresentationAllowedSimple (0x80,len) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* namePresentationAllowedSimple, implicid NameData */
-+ size = rose_namedata_encode(pri, &buffer[i], 1, call->redirectingname);
-+ if (size < 0)
-+ return -1;
-+ i += size;
-+
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+ }
-+
-+ /* originalCalledName */
-+ /* - not included - */
-+
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+
-+ if (pri_call_apdu_queue(call, Q931_SETUP, buffer, i, NULL, NULL))
-+ return -1;
-+
-+ return 0;
-+}
-+
-+static int rose_diverting_leg_information3_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
-+{
-+ int i = 0;
-+ struct nameelements_name redirectionname = { "", CHARACTER_SET_UNKNOWN, 0 };
-+ int presentation_allowed_indicator;
-+ struct rose_component *comp = NULL;
-+ unsigned char *vdata = sequence->data;
-+ int size = 0;
-+
-+ /* Data checks */
-+ if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
-+ pri_message(pri, "Invalid DivertingLegInformation3Type argument\n");
-+ return -1;
-+ }
-+
-+ if (sequence->len == ASN1_LEN_INDEF) {
-+ len -= 4; /* For the 2 extra characters at the end
-+ and two characters of header */
-+ } else
-+ len -= 2;
-+
-+ do {
-+ /* presentationAllowedIndicator */
-+ GET_COMPONENT(comp, i, vdata, len);
-+ CHECK_COMPONENT(comp, ASN1_BOOLEAN, "Don't know what to do if presentationAllowedIndicator is of type 0x%x\n");
-+ ASN1_GET_INTEGER(comp, presentation_allowed_indicator);
-+ NEXT_COMPONENT(comp, i);
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Received presentationAllowedIndicator: %d\n", presentation_allowed_indicator);
-+
-+ /* Type SEQUENCE specifies an ordered list of component types. *
-+ * We decode all components but for simplicity we don't check the order. */
-+ while (i < len) {
-+ GET_COMPONENT(comp, i, vdata, len);
-+
-+ switch(comp->type) {
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0):
-+ /* redirectionName */
-+ size = rose_name_decode(pri, comp->data, comp->len, &redirectionname);
-+ if (size < 0)
- return -1;
--
-- i += j;
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-- ASN1_FIXUP(compstk, compsp, buffer, i);
-+ i += (size + 2);
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Received RedirectionName '%s', namepres %s(%d), characterset %s(%d)\n",
-+ redirectionname.name, namepres_to_str(redirectionname.namepres), redirectionname.namepres,
-+ characterset_to_str(redirectionname.characterset), redirectionname.characterset);
- break;
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] IMPLICIT Extension */
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2): /* [2] IMPLICIT SEQUENCE OF Extension */
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "!! Ignoring DivertingLegInformation3 component 0x%X\n", comp->type);
-+ NEXT_COMPONENT(comp, i);
-+ break;
-+ default:
-+ pri_message(pri, "!! Invalid DivertingLegInformation3 component received 0x%X\n", comp->type);
-+ return -1;
- }
-- /* fall through */
-- case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
-- case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
-- break;
-- /* Don't know how to handle this */
-- case PRES_ALLOWED_NETWORK_NUMBER:
-- case PRES_PROHIB_NETWORK_NUMBER:
-- case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
-- case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
-- break;
-- default:
-- pri_message(pri, "!! Undefined presentation value for redirecting number: %d\n", call->redirectingpres);
-- case PRES_NUMBER_NOT_AVAILABLE:
-- ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i);
-- break;
-+ }
-+
-+ call->divleginfo3activeflag = 1;
-+ if ((redirectionname.namepres != 0) && (presentation_allowed_indicator != 0)) {
-+ libpri_copy_string(call->divertedtoname, redirectionname.name, sizeof(call->divertedtoname));
-+ } else {
-+ call->divertedtoname[0] = '\0';
-+ }
-+
-+ return 0;
- }
-- ASN1_FIXUP(compstk, compsp, buffer, i);
--
-- /* Fix length of stacked components */
-- while(compsp > 0) {
-+ while (0);
-+
-+ return -1;
-+}
-+
-+int rose_diverting_leg_information3_encode(struct pri *pri, q931_call *call, int messagetype)
-+{
-+ int i = 0, compsp = 0;
-+ struct rose_component *comp, *compstk[10];
-+ unsigned char buffer[256];
-+ int size;
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Encode divertingLegInformation3\n");
-+
-+ /* Protocol Profile = 0x1f (Networking Extensions) (0x9f) */
-+ buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
-+
-+ /* Network Facility Extension */
-+ if (pri->switchtype == PRI_SWITCH_QSIG) {
-+ /* tag component NetworkFacilityExtension (0xaa, len ) */
-+ ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* sourceEntity (0x80,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0); /* endPINX(0) */
-+
-+ /* destinationEntity (0x82,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0); /* endPINX(0) */
- ASN1_FIXUP(compstk, compsp, buffer, i);
- }
--
-- if (pri_call_apdu_queue(call, Q931_SETUP, buffer, i, NULL, NULL))
-+
-+ /* Network Protocol Profile */
-+ /* - not included - */
-+
-+ /* Interpretation APDU (0x8b,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0); /* discardAnyUnrecognisedInvokePdu(0) */
-+
-+ /* Service APDU(s): */
-+
-+ /* ROSE InvokePDU (0xa1,len) */
-+ ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* ROSE InvokeID (0x02,0x01,invokeid) */
-+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
-+
-+ /* ROSE operationId (0x02,0x01,0x16)*/
-+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, ROSE_DIVERTING_LEG_INFORMATION3);
-+
-+ /* constructor component (0x30,len) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* 'connectedpres' also indicates if name presentation is allowed */
-+ if (((call->divertedtopres & 0x60) >> 5) == 0) {
-+ /* presentation allowed */
-+
-+ /* presentationAllowedIndicator (0x01,0x01,0xff) */
-+ ASN1_ADD_BYTECOMP(comp, ASN1_BOOLEAN, buffer, i, 0xff); /* true(255) */
-+
-+ /* redirectionName */
-+
-+ /* tag component redirectionName (0xa0,len) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ if (call->divertedtoname[0]) {
-+ /* tag component namePresentationAllowedSimple (0x80,len) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* namePresentationAllowedSimple, implicid NameData */
-+ size = rose_namedata_encode(pri, &buffer[i], 1, call->divertedtoname);
-+ if (size < 0)
-+ return -1;
-+ i += size;
-+
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+ }
-+
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+ } else {
-+ /* presentation restricted */
-+
-+ /* presentationAllowedIndicator (0x01,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, ASN1_BOOLEAN, buffer, i, 0); /* false(0) */
-+
-+ /* - don't include redirectionName, component is optional - */
-+ }
-+
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+
-+ if (pri_call_apdu_queue(call, messagetype, buffer, i, NULL, NULL))
- return -1;
--
-+
- return 0;
- }
-
-@@ -1644,7 +2828,7 @@
- switch (comp1->type) {
- /* TODO: charged number is untested - please report! */
- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* chargedNumber (0xA0) */
-- if(rose_presented_number_unscreened_decode(pri, call, comp1->data, comp1->len, &chargednr) != 0)
-+ if(rose_presented_number_unscreened_decode(pri, comp1->data, comp1->len, &chargednr) != 0)
- return -1;
- pri_message(pri, "!! not handled: Received ChargedNr '%s' \n", chargednr.partyaddress);
- pri_message(pri, " ton = %d, pres = %d, npi = %d\n", chargednr.ton, chargednr.pres, chargednr.npi);
-@@ -1740,302 +2924,407 @@
- }
- /* End AOC */
-
--static int rose_calling_name_decode(struct pri *pri, q931_call *call, struct rose_component *choice, int len)
-+/* ===== Call Transfer Supplementary Service (ECMA-178) ===== */
-+
-+static int rose_call_transfer_complete_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
- {
- int i = 0;
- struct rose_component *comp = NULL;
-- unsigned char *vdata = choice->data;
-- int characterSet = 1;
-- switch (choice->type) {
-- case ROSE_NAME_PRESENTATION_ALLOWED_SIMPLE:
-- memcpy(call->callername, choice->data, choice->len);
-- call->callername[choice->len] = 0;
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Received simple calling name '%s'\n", call->callername);
-- return 0;
-+ unsigned char *vdata = sequence->data;
-+ int size = 0;
-
-- case ROSE_NAME_PRESENTATION_ALLOWED_EXTENDED:
-- do {
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_OCTETSTRING, "Don't know what to do if nameData is of type 0x%x\n");
-- memcpy(call->callername, comp->data, comp->len);
-- call->callername[comp->len] = 0;
-- NEXT_COMPONENT(comp, i);
-+ struct addressingdataelements_presentednumberscreened redirection_number;
-+ struct nameelements_name redirectionname = { "", CHARACTER_SET_UNKNOWN, 0 };
-+ char basiccallinfoelements[257] = "";
-+ int call_status = 0; /* answered(0) */
-+ int end_designation;
-
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if CharacterSet is of type 0x%x\n");
-- ASN1_GET_INTEGER(comp, characterSet);
-- }
-- while (0);
--
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Received extended calling name '%s', characterset %d\n", call->callername, characterSet);
-- return 0;
-- case ROSE_NAME_PRESENTATION_RESTRICTED_SIMPLE:
-- case ROSE_NAME_PRESENTATION_RESTRICTED_EXTENDED:
-- case ROSE_NAME_PRESENTATION_RESTRICTED_NULL:
-- case ROSE_NAME_NOT_AVAIL:
-- default:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "Do not handle argument of type 0x%X\n", choice->type);
-- return -1;
-+ /* Data checks */
-+ if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
-+ pri_message(pri, "Invalid callTransferComplete argument. (Not a sequence)\n");
-+ return -1;
- }
--}
--/* ===== Call Transfer Supplementary Service (ECMA-178) ===== */
-
--static int rose_party_number_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
--{
-- int i = 0;
-- int size = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = data;
-+ if (sequence->len == ASN1_LEN_INDEF) {
-+ len -= 4; /* For the 2 extra characters at the end
-+ and two characters of header */
-+ } else
-+ len -= 2;
-
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " CT-Complete: len=%d\n", len);
-
-+ /* CTCompleteArg SEQUENCE */
- do {
-+ /* endDesignation EndDesignation */
- GET_COMPONENT(comp, i, vdata, len);
-+ CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Invalid endDesignation type 0x%X of ROSE callTransferComplete component received\n");
-+ ASN1_GET_INTEGER(comp, end_designation);
-+ NEXT_COMPONENT(comp, i);
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " CT-Complete: Received endDesignation=%s(%d)\n", enddesignation_to_str(end_designation), end_designation);
-
-- switch(comp->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] IMPLICIT NumberDigits -- default: unknownPartyNumber */
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PartyNumber: UnknownPartyNumber len=%d\n", len);
-- size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- value->npi = PRI_NPI_UNKNOWN;
-- value->ton = PRI_TON_UNKNOWN;
-- break;
-+ /* redirectionNumber PresentedNumberScreened */
-+ GET_COMPONENT(comp, i, vdata, len);
-+ size = rose_presented_number_screened_decode(pri, (u_int8_t *)comp, comp->len + 2, &redirection_number);
-+ if (size < 0)
-+ return -1;
-+ comp->len = size;
-+ NEXT_COMPONENT(comp, i);
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " CT-Complete: Received redirectionNumber=%s\n", redirection_number.partyaddress);
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] IMPLICIT PublicPartyNumber */
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PartyNumber: PublicPartyNumber len=%d\n", len);
-- size = rose_public_party_number_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- value->npi = PRI_NPI_E163_E164;
-- break;
-+ /* Type SEQUENCE specifies an ordered list of component types. *
-+ * We decode all components but for simplicity we don't check the order. */
-+ while (i < len) {
-+ GET_COMPONENT(comp, i, vdata, len);
-
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] IMPLICIT NumberDigits -- not used: dataPartyNumber */
-- pri_message(pri, "!! PartyNumber: dataPartyNumber is reserved!\n");
-- size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-+ switch(comp->type) {
-+ case (ASN1_APPLICATION):
-+ /* basicCallInfoElements PSS1InformationElement OPTIONAL */
-+ size = asn1_name_decode((u_int8_t *)comp, comp->len + 2, basiccallinfoelements, sizeof(basiccallinfoelements));
- if (size < 0)
- return -1;
-- value->npi = PRI_NPI_X121 /* ??? */;
-- value->ton = PRI_TON_UNKNOWN /* ??? */;
-+ i += size;
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ int j;
-+ pri_message(pri, " CT-Complete: Received basicCallInfoElements\n");
-+ pri_message(pri, " ");
-+ for (j = 0; basiccallinfoelements[j] != '\0'; j++)
-+ pri_message(pri, "%02x ", (u_int8_t)basiccallinfoelements[j]);
-+ pri_message(pri, "\n");
-+ }
- break;
--
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4): /* [4] IMPLICIT NumberDigits -- not used: telexPartyNumber */
-- pri_message(pri, "!! PartyNumber: telexPartyNumber is reserved!\n");
-- size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0): /* [0] namePresentationAllowedSimple */
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] namePresentationAllowedExtended */
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2): /* [2] namePresentationRestrictedSimple */
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] namePresentationRestrictedExtended */
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_4): /* [4] nameNotAvailable */
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_7): /* [7] namePresentationRestrictedNull */
-+ /* redirectionName Name OPTIONAL */
-+ size = rose_name_decode(pri, (u_int8_t *)comp, comp->len + 2, &redirectionname);
- if (size < 0)
- return -1;
-- value->npi = PRI_NPI_F69 /* ??? */;
-- value->ton = PRI_TON_UNKNOWN /* ??? */;
-+ i += size;
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " CT-Complete: Received RedirectionName '%s', namepres %s(%d), characterset %s(%d)\n",
-+ redirectionname.name, namepres_to_str(redirectionname.namepres), redirectionname.namepres,
-+ characterset_to_str(redirectionname.characterset), redirectionname.characterset);
- break;
--
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] IMPLICIT PrivatePartyNumber */
-+ case (ASN1_ENUMERATED):
-+ /* callStatus CallStatus DEFAULT answered */
-+ ASN1_GET_INTEGER(comp, call_status);
-+ NEXT_COMPONENT(comp,i);
- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PartyNumber: PrivatePartyNumber len=%d\n", len);
-- size = rose_private_party_number_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- value->npi = PRI_NPI_PRIVATE;
-+ pri_message(pri, " CT-Complete: Received callStatus=%s(%d)\n", callstatus_to_str(call_status), call_status);
- break;
--
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_8): /* [8] IMPLICIT NumberDigits -- not used: nationalStandatdPartyNumber */
-- pri_message(pri, "!! PartyNumber: nationalStandardPartyNumber is reserved!\n");
-- size = rose_number_digits_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- value->npi = PRI_NPI_NATIONAL;
-- value->ton = PRI_TON_NATIONAL;
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_9): /* [9] IMPLICIT Extension */
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_10): /* [10] IMPLICIT SEQUENCE OF Extension */
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "!! CT-Complete: Ignoring CallTransferComplete component 0x%X\n", comp->type);
-+ NEXT_COMPONENT(comp, i);
- break;
--
- default:
-- pri_message(pri, "Invalid PartyNumber component 0x%X\n", comp->type);
-+ pri_message(pri, "!! CT-Complete: Invalid CallTransferComplete component received 0x%X\n", comp->type);
- return -1;
-+ }
- }
-- ASN1_FIXUP_LEN(comp, size);
-+
- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PartyNumber: '%s' size=%d len=%d\n", value->partyaddress, size, len);
-- return size;
-+ pri_message(pri, " CT-Complete: callStatus=%s(%d)\n", callstatus_to_str(call_status), call_status);
-+
-+ call->ctcompleteflag = 1;
-+ if ((redirection_number.pres & PRES_RESTRICTION) == PRES_ALLOWED) {
-+ libpri_copy_string(call->ctcompletenum, redirection_number.partyaddress, sizeof(call->ctcompletenum));
-+ } else {
-+ call->ctcompletenum[0] = '\0';
-+ }
-+ call->ctcompletepres = redirection_number.pres;
-+ call->ctcompleteplan = ((redirection_number.ton & 0x07) << 4) | (redirection_number.npi & 0x0f);
-+ call->ctcompletecallstatus = call_status;
-+
-+ if (redirectionname.namepres != 0) {
-+ libpri_copy_string(call->ctcompletename, redirectionname.name, sizeof(call->ctcompletename));
-+ } else {
-+ call->ctcompletename[0] = '\0';
-+ }
-+
-+ return 0;
- }
- while (0);
-
- return -1;
- }
-
--
--static int rose_number_screened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberscreened *value)
-+static int rose_call_transfer_complete_encode(struct pri *pri, q931_call *call, int call_status)
- {
-- int i = 0;
-- int size = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = data;
-+ int i = 0, compsp = 0;
-+ struct rose_component *comp, *compstk[10];
-+ unsigned char buffer[256];
-+ int size;
-
-- int scrind = -1;
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Encode CallTransferComplete\n");
-
-- do {
-- /* Party Number */
-- GET_COMPONENT(comp, i, vdata, len);
-- size = rose_party_number_decode(pri, call, (u_int8_t *)comp, comp->len + 2, (struct addressingdataelements_presentednumberunscreened*) value);
-+ /* Protocol Profile = 0x1f (Networking Extensions) (0x9f) */
-+ buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
-+
-+ /* Network Facility Extension */
-+ if (pri->switchtype == PRI_SWITCH_QSIG) {
-+ /* tag component NetworkFacilityExtension (0xaa, len ) */
-+ ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* sourceEntity (0x80,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0); /* endPINX(0) */
-+
-+ /* destinationEntity (0x82,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0); /* endPINX(0) */
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+ }
-+
-+ /* Network Protocol Profile */
-+ /* - not included - */
-+
-+ /* Interpretation APDU (0x8b,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0); /* discardAnyUnrecognisedInvokePdu(0) */
-+
-+ /* Service APDU(s): */
-+
-+ /* ROSE InvokePDU (0xa1,len) */
-+ ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* ROSE InvokeID (0x02,0x01,invokeid) */
-+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
-+
-+ /* ROSE operationId (0x02,0x01,0x0c)*/
-+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, ROSE_CALL_TRANSFER_COMPLETE);
-+
-+
-+ /* CTCompleteArg */
-+
-+ /* constructor component (0x30,len) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+
-+ /* endDesignation (0x0a,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0); /* primaryEnd(0) */
-+
-+
-+ /* redirectionNumber PresentedNumberScreened */
-+
-+ /* tag component presentationAllowedAddress (0xa0,len) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* presentationAllowedAddress, implicit NumberScreened */
-+ size = rose_number_screened_encode(pri, &buffer[i], 1, typeofnumber_from_q931(pri, (call->connectedplan & 0x70) >> 4), call->connectedpres & 0x03, call->connectednum);
-+ if (size < 0)
-+ return -1;
-+ i += size;
-+
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+
-+ /* basicCallInfoElements */
-+ /* - not included - */
-+
-+#if 0
-+ /* basicCallInfoElements (0x40,0x00) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_APPLICATION| ASN1_TAG_0), buffer, i);
-+#endif
-+
-+ /* redirectionName */
-+ if (call->connectedname[0]) {
-+ /* tag component namePresentationAllowedSimple (0x80,len) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* namePresentationAllowedSimple, implicid NameData */
-+ size = rose_namedata_encode(pri, &buffer[i], 1, call->connectedname);
- if (size < 0)
- return -1;
-- comp->len = size;
-- NEXT_COMPONENT(comp, i);
-+ i += size;
-
-- /* Screening Indicator */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with NumberScreened ROSE component type 0x%x\n");
-- ASN1_GET_INTEGER(comp, scrind);
-- // Todo: scrind = screeningindicator_for_q931(pri, scrind);
-- NEXT_COMPONENT(comp, i);
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+ }
-
-- value->scrind = scrind;
-+ if (call_status) {
-+ /* callStatus (0x0a,0x01,0x01) */
-+ ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 1); /* alerting(1) */
-+ } else {
-+ /* callStatus */
-+ /* - not included, default: answered(0) - */
-+#if 0
-+ /* callStatus (0x0a,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0); /* answered(0) */
-+#endif
-+ }
-
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " NumberScreened: '%s' ScreeningIndicator=%d i=%d len=%d\n", value->partyaddress, scrind, i, len);
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-
-- return i-2; // We do not have a sequence header here.
-- }
-- while (0);
-+ if (pri_call_apdu_queue(call, Q931_FACILITY, buffer, i, NULL, NULL))
-+ return -1;
-
-- return -1;
-+ return 0;
- }
-
--
--static int rose_presented_number_screened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberscreened *value)
-+static int rose_call_transfer_active_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
- {
- int i = 0;
-+ struct rose_component *comp = NULL;
-+ unsigned char *vdata = sequence->data;
- int size = 0;
-- struct rose_component *comp = NULL;
-- unsigned char *vdata = data;
-
-- /* Fill in default values */
-- value->ton = PRI_TON_UNKNOWN;
-- value->npi = PRI_NPI_UNKNOWN;
-- value->pres = -1; /* Data is not available */
-+ struct addressingdataelements_presentedaddressscreened connectedaddress;
-+ struct nameelements_name connectedname = { "", CHARACTER_SET_UNKNOWN, 0 };
-+ char basiccallinfoelements[257] = "";
-
-+ /* Data checks */
-+ if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
-+ pri_message(pri, "Invalid callTransferActive argument. (Not a sequence)\n");
-+ return -1;
-+ }
-+
-+ if (sequence->len == ASN1_LEN_INDEF) {
-+ len -= 4; /* For the 2 extra characters at the end
-+ and two characters of header */
-+ } else
-+ len -= 2;
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " CT-Active: len=%d\n", len);
-+
-+ /* CTActiveArg SEQUENCE */
- do {
-+ /* connectedAddress PresentedAddressScreened */
- GET_COMPONENT(comp, i, vdata, len);
-+ size = rose_presented_address_screened_decode(pri, (u_int8_t *)comp, comp->len + 2, &connectedaddress);
-+ if (size < 0)
-+ return -1;
-+ comp->len = size;
-+ NEXT_COMPONENT(comp, i);
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, " CT-Active: Received connectedAddress=%s\n", connectedaddress.partyaddress);
-+ }
-
-- switch(comp->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] IMPLICIT presentationAllowedNumber */
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PresentedNumberScreened: presentationAllowedNumber comp->len=%d\n", comp->len);
-- value->pres = PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN;
-- size = rose_number_screened_decode(pri, call, comp->data, comp->len, value);
-+ /* Type SEQUENCE specifies an ordered list of component types. *
-+ * We decode all components but for simplicity we don't check the order. */
-+ while (i < len) {
-+ GET_COMPONENT(comp, i, vdata, len);
-+
-+ switch(comp->type) {
-+ case (ASN1_APPLICATION):
-+ /* basiccallinfoelements PSS1InformationElement OPTIONAL */
-+ size = asn1_name_decode((u_int8_t *)comp, comp->len + 2, basiccallinfoelements, sizeof(basiccallinfoelements));
- if (size < 0)
- return -1;
-- ASN1_FIXUP_LEN(comp, size);
-- return size + 2;
--
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* [1] IMPLICIT presentationRestricted */
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PresentedNumberScreened: presentationRestricted comp->len=%d\n", comp->len);
-- if (comp->len != 0) { /* must be NULL */
-- pri_error(pri, "!! Invalid PresentationRestricted component received (len != 0)\n");
-- return -1;
-+ i += size;
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ int j;
-+ pri_message(pri, " CT-Active: Received basicCallInfoElements\n");
-+ pri_message(pri, " ");
-+ for (j = 0; basiccallinfoelements[j] != '\0'; j++)
-+ pri_message(pri, "%02x ", (u_int8_t)basiccallinfoelements[j]);
-+ pri_message(pri, "\n");
- }
-- value->pres = PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
-- return 2;
--
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2): /* [2] IMPLICIT numberNotAvailableDueToInterworking */
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PresentedNumberScreened: NumberNotAvailableDueToInterworking comp->len=%d\n", comp->len);
-- if (comp->len != 0) { /* must be NULL */
-- pri_error(pri, "!! Invalid NumberNotAvailableDueToInterworking component received (len != 0)\n");
-+ break;
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0): /* [0] namePresentationAllowedSimple */
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] namePresentationAllowedExtended */
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2): /* [2] namePresentationRestrictedSimple */
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] namePresentationRestrictedExtended */
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_4): /* [4] nameNotAvailable */
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_7): /* [7] namePresentationRestrictedNull */
-+ /* connectedName Name OPTIONAL */
-+ size = rose_name_decode(pri, (u_int8_t *)comp, comp->len + 2, &connectedname);
-+ if (size < 0)
- return -1;
-- }
-- value->pres = PRES_NUMBER_NOT_AVAILABLE;
-+ i += size;
- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PresentedNumberScreened: numberNotAvailableDueToInterworking Type=0x%X i=%d len=%d size=%d\n", comp->type, i, len);
-- return 2;
--
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] IMPLICIT presentationRestrictedNumber */
-+ pri_message(pri, " CT-Active: Received ConnectedName '%s', namepres %s(%d), characterset %s(%d)\n",
-+ connectedname.name, namepres_to_str(connectedname.namepres), connectedname.namepres,
-+ characterset_to_str(connectedname.characterset), connectedname.characterset);
-+ break;
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_9): /* [9] IMPLICIT Extension */
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_10): /* [10] IMPLICIT SEQUENCE OF Extension */
- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " PresentedNumberScreened: presentationRestrictedNumber comp->len=%d\n", comp->len);
-- value->pres = PRES_PROHIB_USER_NUMBER_PASSED_SCREEN;
-- size = rose_number_screened_decode(pri, call, comp->data, comp->len, value);
-- if (size < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, size);
-- return size + 2;
-+ pri_message(pri, "!! CT-Active: Ignoring CallTransferActive component 0x%X\n", comp->type);
-+ NEXT_COMPONENT(comp, i);
-+ break;
-+ default:
-+ pri_message(pri, "!! CT-Active: Invalid CallTransferActive component received 0x%X\n", comp->type);
-+ return -1;
-+ }
-+ }
-
-- default:
-- pri_message(pri, "Invalid PresentedNumberScreened component 0x%X\n", comp->type);
-+ call->ctactiveflag = 1;
-+ if ((connectedaddress.pres & PRES_RESTRICTION) == PRES_ALLOWED) {
-+ libpri_copy_string(call->ctactivenum, connectedaddress.partyaddress, sizeof(call->ctactivenum));
-+ } else {
-+ call->ctactivenum[0] = '\0';
- }
-- return -1;
-+ call->ctactivepres = connectedaddress.pres;
-+ call->ctactiveplan = ((connectedaddress.ton & 0x07) << 4) | (connectedaddress.npi & 0x0f);
-+
-+ if (connectedname.namepres != 0) {
-+ libpri_copy_string(call->ctactivename, connectedname.name, sizeof(call->ctactivename));
-+ } else {
-+ call->ctactivename[0] = '\0';
-+ }
-+
-+ return 0;
- }
- while (0);
-
- return -1;
- }
-
--
--static int rose_call_transfer_complete_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
-+#if 0
-+static int rose_call_transfer_update_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
- {
- int i = 0;
- struct rose_component *comp = NULL;
- unsigned char *vdata = sequence->data;
- int res = 0;
-
-- int end_designation = 0;
- struct addressingdataelements_presentednumberscreened redirection_number;
-- char redirection_name[50] = "";
-- int call_status = 0;
- redirection_number.partyaddress[0] = 0;
-- redirection_number.partysubaddress[0] = 0;
-+ char redirection_name[51] = "";
- call->callername[0] = 0;
- call->callernum[0] = 0;
-
--
- /* Data checks */
- if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
-- pri_message(pri, "Invalid callTransferComplete argument. (Not a sequence)\n");
-+ pri_message(pri, "Invalid callTransferUpdate argument. (Not a sequence)\n");
- return -1;
- }
-
- if (sequence->len == ASN1_LEN_INDEF) {
-- len -= 4; /* For the 2 extra characters at the end
-- * and two characters of header */
-+ len -= 4; /* For the 2 extra characters at the end
-+ and two characters of header */
- } else
- len -= 2;
-
- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: len=%d\n", len);
-+ pri_message(pri, " CT-Update: len=%d\n", len);
-
- do {
-- /* End Designation */
-- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Invalid endDesignation type 0x%X of ROSE callTransferComplete component received\n");
-- ASN1_GET_INTEGER(comp, end_designation);
-- NEXT_COMPONENT(comp, i);
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: Received endDesignation=%d\n", end_designation);
--
--
- /* Redirection Number */
- GET_COMPONENT(comp, i, vdata, len);
-- res = rose_presented_number_screened_decode(pri, call, (u_int8_t *)comp, comp->len + 2, &redirection_number);
-+ res = rose_presented_number_screened_decode(pri, (u_int8_t *)comp, comp->len + 2, &redirection_number);
- if (res < 0)
- return -1;
- comp->len = res;
- if (res > 2) {
- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: Received redirectionNumber=%s\n", redirection_number.partyaddress);
-+ pri_message(pri, " CT-Update: Received redirectionNumber=%s\n", redirection_number.partyaddress);
- strncpy(call->callernum, redirection_number.partyaddress, 20);
- call->callernum[20] = 0;
- }
- NEXT_COMPONENT(comp, i);
-
--
--#if 0 /* This one is optional. How do we check if it is there? */
-- /* Basic Call Info Elements */
-- GET_COMPONENT(comp, i, vdata, len);
-- NEXT_COMPONENT(comp, i);
--#endif
--
--
- /* Redirection Name */
- GET_COMPONENT(comp, i, vdata, len);
- res = asn1_name_decode((u_int8_t *)comp, comp->len + 2, redirection_name, sizeof(redirection_name));
-@@ -2047,16 +3336,14 @@
- comp->len = res;
- NEXT_COMPONENT(comp, i);
- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: Received redirectionName '%s'\n", redirection_name);
-+ pri_message(pri, " CT-Update: Received redirectionName '%s'\n", redirection_name);
-
-
-- /* Call Status */
-+#if 0 /* This one is optional. How do we check if it is there? */
-+ /* Basic Call Info Elements */
- GET_COMPONENT(comp, i, vdata, len);
-- CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Invalid callStatus type 0x%X of ROSE callTransferComplete component received\n");
-- ASN1_GET_INTEGER(comp, call_status);
- NEXT_COMPONENT(comp, i);
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: Received callStatus=%d\n", call_status);
-+#endif
-
-
- /* Argument Extension */
-@@ -2078,8 +3365,8 @@
- comp->len = res;
-
- default:
-- pri_message(pri, " CT-Complete: !! Unknown argumentExtension received 0x%X\n", comp->type);
-- return -1;
-+ pri_message(pri, " CT-Update: !! Unknown argumentExtension received 0x%X\n", comp->type);
-+ return -1;
- }
- #else
- GET_COMPONENT(comp, i, vdata, len);
-@@ -2088,7 +3375,7 @@
- #endif
-
- if(i < len)
-- pri_message(pri, " CT-Complete: !! not all information is handled !! i=%d / len=%d\n", i, len);
-+ pri_message(pri, " CT-Update: !! not all information is handled !! i=%d / len=%d\n", i, len);
-
- return 0;
- }
-@@ -2096,26 +3383,422 @@
-
- return -1;
- }
-+#endif
-
-+/* ===== End Call Transfer Supplementary Service (ECMA-178) ===== */
-
--static int rose_call_transfer_update_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
-+
-+
-+static int rose_calling_name_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
- {
-+ struct nameelements_name callingname;
-+ int res;
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Handle callingName\n");
-+
-+ res = rose_name_decode(pri, (u_int8_t *)sequence, sequence->len + 2, &callingname);
-+ if (res < 0)
-+ return -1;
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Received CallingName '%s', namepres: %s(%d), characterset %s(%d)\n",
-+ callingname.name, namepres_to_str(callingname.namepres), callingname.namepres,
-+ characterset_to_str(callingname.characterset), callingname.characterset);
-+
-+ if (callingname.namepres >= 0) {
-+ libpri_copy_string(call->callername, callingname.name, sizeof(call->callername));
-+ }
-+
-+ return 0;
-+}
-+
-+static int rose_called_name_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
-+{
-+ struct nameelements_name calledname;
-+ int res;
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Handle calledName\n");
-+
-+ res = rose_name_decode(pri, (u_int8_t *)sequence, sequence->len + 2, &calledname);
-+ if (res < 0)
-+ return -1;
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Received CalledName '%s', namepres %s(%d), characterset %s(%d)\n",
-+ calledname.name, namepres_to_str(calledname.namepres), calledname.namepres,
-+ characterset_to_str(calledname.characterset), calledname.characterset);
-+
-+ if (calledname.namepres != 0) {
-+ libpri_copy_string(call->calledname, calledname.name, sizeof(call->calledname));
-+ } else {
-+ call->calledname[0] = '\0';
-+ }
-+
-+ return 0;
-+}
-+
-+int rose_called_name_encode(struct pri *pri, q931_call *call, int messagetype)
-+{
-+ int i = 0, compsp = 0;
-+ struct rose_component *comp, *compstk[10];
-+ unsigned char buffer[256];
-+ int size;
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Encode calledName\n");
-+
-+ /* Protocol Profile = 0x1f (Networking Extensions) (0x9f) */
-+ buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
-+
-+ /* Network Facility Extension */
-+ if (pri->switchtype == PRI_SWITCH_QSIG) {
-+ /* tag component NetworkFacilityExtension (0xaa, len ) */
-+ ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* sourceEntity (0x80,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0); /* endPINX(0) */
-+
-+ /* destinationEntity (0x82,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0); /* endPINX(0) */
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+ }
-+
-+ /* Network Protocol Profile */
-+ /* - not included - */
-+
-+ /* Interpretation APDU (0x8b,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0); /* discardAnyUnrecognisedInvokePdu(0) */
-+
-+ /* Service APDU(s): */
-+
-+ /* ROSE InvokePDU (0xa1,len) */
-+ ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* ROSE InvokeID (0x02,0x01,invokeid) */
-+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
-+
-+ /* ROSE operationId (0x02,0x01,0x02)*/
-+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, SS_CNOP_CALLEDNAME);
-+
-+ /* tag component namePresentationAllowedSimple (0x80,len) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* namePresentationAllowedSimple, implicid NameData */
-+ size = rose_namedata_encode(pri, &buffer[i], 1, call->connectedname);
-+ if (size < 0)
-+ return -1;
-+ i += size;
-+
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+
-+ if (pri_call_apdu_queue(call, messagetype, buffer, i, NULL, NULL))
-+ return -1;
-+
-+ return 0;
-+}
-+
-+static int rose_connected_name_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
-+{
-+ struct nameelements_name connectedname;
-+ int res;
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Handle connectedName\n");
-+
-+ res = rose_name_decode(pri, (u_int8_t *)sequence, sequence->len + 2, &connectedname);
-+ if (res < 0)
-+ return -1;
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Received ConnectedName '%s', namepres %s(%d), characterset %s(%d)\n",
-+ connectedname.name, namepres_to_str(connectedname.namepres), connectedname.namepres,
-+ characterset_to_str(connectedname.characterset), connectedname.characterset);
-+
-+ if (connectedname.namepres != 0) {
-+ libpri_copy_string(call->connectedname, connectedname.name, sizeof(call->connectedname));
-+ } else {
-+ call->connectedname[0] = '\0';
-+ }
-+
-+ return 0;
-+}
-+
-+int rose_connected_name_encode(struct pri *pri, q931_call *call, int messagetype)
-+{
-+ int i = 0, compsp = 0;
-+ struct rose_component *comp, *compstk[10];
-+ unsigned char buffer[256];
-+ int size;
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Encode connectedName\n");
-+
-+ /* Protocol Profile = 0x1f (Networking Extensions) (0x9f) */
-+ buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
-+
-+ /* Network Facility Extension */
-+ if (pri->switchtype == PRI_SWITCH_QSIG) {
-+ /* tag component NetworkFacilityExtension (0xaa, len ) */
-+ ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* sourceEntity (0x80,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0); /* endPINX(0) */
-+
-+ /* destinationEntity (0x82,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0); /* endPINX(0) */
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+ }
-+
-+ /* Network Protocol Profile */
-+ /* - not included - */
-+
-+ /* Interpretation APDU (0x8b,0x01,0x00) */
-+ ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0); /* discardAnyUnrecognisedInvokePdu(0) */
-+
-+ /* Service APDU(s): */
-+
-+ /* ROSE InvokePDU (0xa1,len) */
-+ ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* ROSE InvokeID (0x02,0x01,invokeid) */
-+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
-+
-+ /* ROSE operationId (0x02,0x01,0x02)*/
-+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, SS_CNOP_CONNECTEDNAME);
-+
-+ /* tag component namePresentationAllowedSimple (0x80,len) */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* namePresentationAllowedSimple, implicid NameData */
-+ size = rose_namedata_encode(pri, &buffer[i], 1, call->connectedname);
-+ if (size < 0)
-+ return -1;
-+ i += size;
-+
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+
-+ if (pri_call_apdu_queue(call, messagetype, buffer, i, NULL, NULL))
-+ return -1;
-+
-+ return 0;
-+}
-+
-+/* ===== Begin Call Completion Supplementary Service (ETS 300 366/ECMA 186) ===== */
-+/* operationId e.g. QSIG_CCBSRINGOUT, QSIG_CC_CANCEL */
-+int add_qsigCcInv_facility_ie (struct pri *pri, q931_call *c, int messagetype)
-+{
- int i = 0;
-+ unsigned char buffer[256];
-+ struct rose_component *comp = NULL, *compstk[10];
-+ int compsp = 0;
-+ u_int8_t operationId = c->ccoperation;
-+
-+ /* 1 Byte 0x80 | 0x1F = 9F Protocol Profile */
-+ buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
-+
-+ /* Interpretation component */
-+ ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i); /* 2. Byte NEtwork Facility Extension 0xAA = ASN1_CONTEXT_SPECIFIC(0x80) | (ASN1_CONSTRUCTOR 0x20) 0x0A (Tag laut Standard) */
-+ ASN1_PUSH(compstk, compsp, comp);
-+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0); /* (0x80, 0x01(len), 0x00) endPTNX */
-+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0); /* (0x82, 0x01(len), 0x00) endPTNX */
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+
-+ ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0); /* 0x8B, 0x01(len), 0x00 discard */
-+ ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i); /* 0xA1, 0xXX (len of Invoke Sequenz) invoke APDU */
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* Invoke ID */
-+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri)); /* 0x02 0x01 0xXX */
-+
-+ /* Operation ID: QSIG_CCBSRINGOUT, QSIG_CC_CANCEL */
-+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, operationId); /* 0x02 0x01 0x1f/0x1c */
-+
-+ /* CcExtension */
-+ ASN1_ADD_SIMPLE(comp, ASN1_NULL, buffer, i); /* 0x05 0x00 */
-+
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+
-+ if (pri_call_apdu_queue(c, messagetype, buffer, i, NULL, NULL))
-+ return -1;
-+
-+ return 0;
-+}
-+
-+static int rose_cc_ringout_inv_decode(struct pri *pri, struct qsig_cc_extension *cc_extension, struct rose_component *choice, int len) {
-+ int i = 0;
-+ cc_extension->cc_extension_tag = 0;
-+
-+ do {
-+ switch(choice->type) {
-+ case (ASN1_NULL): /* none NULL */
-+ cc_extension->cc_extension_tag = ASN1_NULL;
-+ return 0;
-+
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_14): /* single [14] IMPLICIT Extension */
-+ cc_extension->cc_extension_tag = ASN1_TAG_14;
-+ return 0;
-+
-+
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_15): /* multiple [15] IMPLICIT SEQUENCE OF Extension */
-+ cc_extension->cc_extension_tag = ASN1_TAG_15;
-+ return 0;
-+
-+ default:
-+ if (choice->type == 0 && choice->len == 0) {
-+ return 0;
-+ }
-+ pri_message(pri, "!! Invalid ss-cc-optional-Arg component received 0x%X\n", choice->type);
-+ return -1;
-+ }
-+
-+ if (i < len)
-+ pri_message(pri, " ss-cc-extension: !! not all information is handled !! i=%d / len=%d\n", i, len);
-+
-+ return 0;
-+ }
-+ while (0);
-+
-+ return -1;
-+}
-+
-+static int rose_cc_optional_arg_decode(struct pri *pri, q931_call *call, struct qsig_cc_optional_arg *cc_optional_arg , struct rose_component *choice, int len) {
-+ int i = 0;
-+ int res = 0;
- struct rose_component *comp = NULL;
-+ unsigned char *vdata = choice->data;
-+ struct addressingdataelements_presentednumberunscreened numberA;
-+ struct addressingdataelements_presentednumberunscreened numberB;
-+
-+ cc_optional_arg->cc_extension.cc_extension_tag = 0;
-+ cc_optional_arg->number_A[0] = '\0';
-+ cc_optional_arg->number_B[0] = '\0';
-+
-+ do {
-+ switch(choice->type) {
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* fullArg [0] IMPLICIT SEQUENCE */
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " ss-cc-optional-Arg: len=%d\n", len);
-+
-+ numberA.partyaddress[0] = '\0';
-+
-+ /* numberA */
-+ GET_COMPONENT(comp, i, vdata, len);
-+ res += rose_party_number_decode(pri, (u_int8_t *)comp, comp->len + 2, &numberA);
-+ if (res < 0)
-+ return -1;
-+ comp->len = res;
-+ if (res > 2) {
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " ss-cc-optional-Arg: Received numberA=%s\n", numberA.partyaddress);
-+ strncpy(cc_optional_arg->number_A, numberA.partyaddress, 20);
-+ cc_optional_arg->number_A[20] = '\0';
-+ }
-+ NEXT_COMPONENT(comp, i);
-+
-+ numberB.partyaddress[0] = '\0';
-+
-+ /* numberB */
-+ GET_COMPONENT(comp, i, vdata, len);
-+ res = rose_party_number_decode(pri, (u_int8_t *)comp, comp->len + 2, &numberB);
-+ if (res < 0)
-+ return -1;
-+ comp->len = res;
-+ if (res > 2) {
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " ss-cc-optional-Arg: Received numberB=%s\n", numberB.partyaddress);
-+ strncpy(cc_optional_arg->number_B, numberB.partyaddress, 20);
-+ cc_optional_arg->number_B[20] = '\0';
-+ }
-+ NEXT_COMPONENT(comp, i);
-+
-+ /* service */ /* PSS1InformationElement */
-+ GET_COMPONENT(comp, i, vdata, len);
-+ NEXT_COMPONENT(comp, i);
-+
-+ /* optional */
-+ for (; i < len; NEXT_COMPONENT(comp, i)) {
-+ GET_COMPONENT(comp, i, vdata, len);
-+ switch(comp->type) {
-+ case (ASN1_NULL): /* */
-+ cc_optional_arg->cc_extension.cc_extension_tag = ASN1_NULL;
-+ NEXT_COMPONENT(comp, i);
-+ break;
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_14): /* */
-+ NEXT_COMPONENT(comp, i);
-+ break;
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_15): /* */
-+ NEXT_COMPONENT(comp, i);
-+ break;
-+ default:
-+ if (comp->type == 0 && comp->len == 0) {
-+ return 0;
-+ break; /* Found termination characters */
-+ }
-+ pri_message(pri, "!! Invalid ss-cc-optional-Arg component received 0x%X\n", comp->type);
-+ return -1;
-+ }
-+ }
-+
-+ if (i < len)
-+ pri_message(pri, " ss-cc-optional-Arg: !! not all information is handled !! i=%d / len=%d\n", i, len);
-+
-+ return 0;
-+
-+ /* extArg CcExtension */
-+ case (ASN1_NULL): /* none NULL */
-+ cc_optional_arg->cc_extension.cc_extension_tag = ASN1_NULL;
-+ return 0;
-+
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_14): /* single [14] IMPLICIT Extension */
-+ cc_optional_arg->cc_extension.cc_extension_tag = ASN1_TAG_14;
-+ return 0;
-+
-+
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_15): /* multiple [15] IMPLICIT SEQUENCE OF Extension */
-+ cc_optional_arg->cc_extension.cc_extension_tag = ASN1_TAG_15;
-+ return 0;
-+
-+ default:
-+ if (choice->type == 0 && choice->len == 0) {
-+ return 0;
-+ }
-+ pri_message(pri, "!! Invalid ss-cc-optional-Arg component received 0x%X\n", choice->type);
-+ return -1;
-+ }
-+
-+ if (i < len)
-+ pri_message(pri, " ss-cc-optional-Arg: !! not all information is handled !! i=%d / len=%d\n", i, len);
-+
-+ return 0;
-+ }
-+ while (0);
-+
-+ return -1;
-+}
-+
-+static int rose_cc_request_result_decode(struct pri *pri, struct qsig_cc_request_res *cc_request_res , struct rose_component *sequence, int len)
-+{
-+ int i = 0;
-+ struct rose_component *comp = NULL;
- unsigned char *vdata = sequence->data;
-- int res = 0;
-
-- struct addressingdataelements_presentednumberscreened redirection_number;
-- redirection_number.partyaddress[0] = 0;
-- redirection_number.partysubaddress[0] = 0;
-- char redirection_name[50] = "";
-- call->callername[0] = 0;
-- call->callernum[0] = 0;
-+ cc_request_res->no_path_reservation = 0; /* Default FALSE */
-+ cc_request_res->retain_service = 0; /* Default FALSE */
-+ cc_request_res->cc_extension.cc_extension_tag = 0;
-
--
- /* Data checks */
- if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
-- pri_message(pri, "Invalid callTransferComplete argument. (Not a sequence)\n");
-+ pri_message(pri, "Invalid cc request result argument. (Not a sequence)\n");
- return -1;
- }
-
-@@ -2126,75 +3809,55 @@
- len -= 2;
-
- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: len=%d\n", len);
-+ pri_message(pri, " CC-request-Return-Result: len=%d\n", len);
-
- do {
-- /* Redirection Number */
-- GET_COMPONENT(comp, i, vdata, len);
-- res = rose_presented_number_screened_decode(pri, call, (u_int8_t *)comp, comp->len + 2, &redirection_number);
-- if (res < 0)
-- return -1;
-- comp->len = res;
-- if (res > 2) {
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: Received redirectionNumber=%s\n", redirection_number.partyaddress);
-- strncpy(call->callernum, redirection_number.partyaddress, 20);
-- call->callernum[20] = 0;
-- }
-- NEXT_COMPONENT(comp, i);
-+ /* defaults and optional */
-+ for (; i < len; NEXT_COMPONENT(comp, i)) {
-+ GET_COMPONENT(comp, i, vdata, len);
-+ switch(comp->type) {
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0):
-+ /* no-path-reservation */
-+ ASN1_GET_INTEGER(comp, cc_request_res->no_path_reservation);
-+ NEXT_COMPONENT(comp, i);
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " cc request result: Received noPathReservation=%d\n", cc_request_res->no_path_reservation);
-+ break;
-
-- /* Redirection Name */
-- GET_COMPONENT(comp, i, vdata, len);
-- res = asn1_name_decode((u_int8_t *)comp, comp->len + 2, redirection_name, sizeof(redirection_name));
-- if (res < 0)
-- return -1;
-- memcpy(call->callername, comp->data, comp->len);
-- call->callername[comp->len] = 0;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
-- NEXT_COMPONENT(comp, i);
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " CT-Complete: Received redirectionName '%s'\n", redirection_name);
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1):
-+ /* retain_service */
-+ ASN1_GET_INTEGER(comp, cc_request_res->retain_service);
-+ NEXT_COMPONENT(comp, i);
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " cc request result: Received retainService=%d\n", cc_request_res->retain_service);
-+ break;
-
-+ case (ASN1_NULL): /* */
-+ cc_request_res->cc_extension.cc_extension_tag = ASN1_NULL;
-+ NEXT_COMPONENT(comp, i);
-+ break;
-
--#if 0 /* This one is optional. How do we check if it is there? */
-- /* Basic Call Info Elements */
-- GET_COMPONENT(comp, i, vdata, len);
-- NEXT_COMPONENT(comp, i);
--#endif
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_14):
-+ cc_request_res->cc_extension.cc_extension_tag = ASN1_TAG_14;
-+ NEXT_COMPONENT(comp, i);
-+ break;
-
-+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_15):
-+ cc_request_res->cc_extension.cc_extension_tag = ASN1_TAG_15;
-+ NEXT_COMPONENT(comp, i);
-+ break;
-
-- /* Argument Extension */
--#if 0 /* Not supported */
-- GET_COMPONENT(comp, i, vdata, len);
-- switch (comp->type) {
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_9): /* [9] IMPLICIT Extension */
-- res = rose_extension_decode(pri, call, comp->data, comp->len, &redirection_number);
-- if (res < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
--
-- case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_10): /* [10] IMPLICIT SEQUENCE OF Extension */
-- res = rose_sequence_of_extension_decode(pri, call, comp->data, comp->len, &redirection_number);
-- if (res < 0)
-- return -1;
-- ASN1_FIXUP_LEN(comp, res);
-- comp->len = res;
--
- default:
-- pri_message(pri, " CT-Complete: !! Unknown argumentExtension received 0x%X\n", comp->type);
-+ if (comp->type == 0 && comp->len == 0) {
-+ break; /* Found termination characters */
-+ }
-+ pri_message(pri, "!! Invalid ss-cc-optional-Arg component received 0x%X\n", comp->type);
- return -1;
-+ }
- }
--#else
-- GET_COMPONENT(comp, i, vdata, len);
-- ASN1_FIXUP_LEN(comp, res);
-- NEXT_COMPONENT(comp, i);
--#endif
-
-- if(i < len)
-- pri_message(pri, " CT-Complete: !! not all information is handled !! i=%d / len=%d\n", i, len);
--
-+ if (i < len)
-+ pri_message(pri, " ss-cc-optional-Arg: !! not all information is handled !! i=%d / len=%d\n", i, len);
- return 0;
- }
- while (0);
-@@ -2202,11 +3865,18 @@
- return -1;
- }
-
-+static int rose_ccbs_request_result_decode(struct pri *pri, struct qsig_cc_request_res *cc_request_res , struct rose_component *sequence, int len)
-+{
-+ return rose_cc_request_result_decode(pri, cc_request_res , sequence, len);
-+}
-
--/* ===== End Call Transfer Supplementary Service (ECMA-178) ===== */
-+static int rose_ccnr_request_result_decode(struct pri *pri, struct qsig_cc_request_res *cc_request_res , struct rose_component *sequence, int len)
-+{
-+ return rose_cc_request_result_decode(pri, cc_request_res , sequence, len);
-+}
-+/* ===== End Call Completion Supplementary Service (ETS 300 366/ECMA 186) ===== */
-
-
--
- int rose_reject_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
- {
- int i = 0;
-@@ -2267,7 +3937,7 @@
-
- return 0;
- } else {
-- pri_message(pri, "Unable to handle return result on switchtype %d!\n", pri->switchtype);
-+ pri_message(pri, "Unable to handle reject on switchtype %d!\n", pri->switchtype);
- return -1;
- }
-
-@@ -2275,6 +3945,20 @@
-
- return -1;
- }
-+
-+
-+static struct subcommand *get_ptr_subcommand(struct subcommands *sub)
-+{
-+ if (sub->counter_subcmd < MAX_SUBCOMMANDS) {
-+ int count = sub->counter_subcmd;
-+ sub->counter_subcmd++;
-+ return &sub->subcmd[count];
-+ }
-+
-+ return NULL;
-+}
-+
-+
- int rose_return_error_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
- {
- int i = 0;
-@@ -2283,6 +3967,7 @@
- unsigned char *vdata = data;
- struct rose_component *comp = NULL;
- char *invokeidstr, *errorstr;
-+ struct subcommand *c_subcmd;
-
- do {
- /* Invoke ID stuff */
-@@ -2329,9 +4014,39 @@
- pri_error(pri, "\tERROR: %s\n", errorstr);
-
- return 0;
-+ } else if (pri->switchtype == PRI_SWITCH_QSIG) {
-+ switch (errorvalue) {
-+ case 1008:
-+ errorstr = "Unspecified";
-+ break;
-+ case 1012:
-+ errorstr = "Remote user busy again";
-+ break;
-+ case 1013:
-+ errorstr = "Failure to match";
-+ break;
-+ default:
-+ errorstr = "Unknown";
-+ }
-+
-+ c_subcmd = get_ptr_subcommand(&call->subcmds);
-+ if (!c_subcmd) {
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE RETURN ERROR %i - more than %d facilities !\n", errorvalue, MAX_SUBCOMMANDS);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ return -1;
-+ }
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ {
-+ pri_message(pri, "ROSE RETURN RESULT %i: %s\n", errorvalue, errorstr);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ c_subcmd->cmd = CMD_CC_ERROR;
-+ c_subcmd->cc_error.error_value = errorvalue;
-+ return 0;
- } else {
-- pri_message(pri, "Unable to handle return result on switchtype %d!\n", pri->switchtype);
-- return -1;
-+ pri_message(pri, "Unable to handle return error on switchtype %d!\n", pri->switchtype);
- }
-
- } while(0);
-@@ -2346,6 +4061,8 @@
- int invokeidvalue = -1;
- unsigned char *vdata = data;
- struct rose_component *comp = NULL;
-+ int res;
-+ struct subcommand *c_subcmd;
-
- do {
- /* Invoke ID stuff */
-@@ -2392,11 +4109,90 @@
- return -1;
- }
- } else if (pri->switchtype == PRI_SWITCH_QSIG) {
-- switch (invokeidvalue) {
-- case 0x13:
-- if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Successfully completed QSIG CF callRerouting!\n");
-+ int operation_tag;
-+
-+ /* sequence is optional */
-+ if (i >= len)
- return 0;
-+
-+ /* Data checks, sequence is optional */
-+ GET_COMPONENT(comp, i, vdata, len);
-+ if (comp->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
-+ pri_message(pri, "No arguments on cc-return result\n");
-+ return 0;
- }
-+
-+ if (comp->len == ASN1_LEN_INDEF) {
-+ len -= 2; /* For the 2 extra characters at the end*/
-+ }
-+
-+ /* Traverse the contents of this sequence */
-+ SUB_COMPONENT(comp, i);
-+
-+ /* Operation Tag */
-+ GET_COMPONENT(comp, i, vdata, len);
-+ CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if second ROSE component is of type 0x%x\n");
-+ ASN1_GET_INTEGER(comp, operation_tag);
-+ NEXT_COMPONENT(comp, i);
-+
-+ /* No argument - return with error */
-+ if (i >= len)
-+ return -1;
-+
-+ /* Arguement Tag */
-+ GET_COMPONENT(comp, i, vdata, len);
-+ if (!comp->type)
-+ return -1;
-+
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " [ Handling operation %d ]\n", operation_tag);
-+ switch (operation_tag) {
-+ case QSIG_CF_CALLREROUTING:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "Successfully completed QSIG CF callRerouting!\n");
-+ return 0;
-+
-+ case QSIG_CC_CCBSREQUEST:
-+ c_subcmd = get_ptr_subcommand(&call->subcmds);
-+ if (!c_subcmd) {
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: return_result CcCcbsRequest - more than %d facilities !\n", operation_tag, MAX_SUBCOMMANDS);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ return -1;
-+ }
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ {
-+ pri_message(pri, "ROSE %i: Handle CcCcbsRequest\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ c_subcmd->cmd = CMD_CC_CCBSREQUEST_RR;
-+ res = rose_ccbs_request_result_decode(pri, &c_subcmd->cc_ccbs_rr.cc_request_res, comp, len-i);
-+ return res;
-+
-+ case QSIG_CC_CCNRREQUEST:
-+ c_subcmd = get_ptr_subcommand(&call->subcmds);
-+ if (!c_subcmd) {
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: return_result CcCcnrRequest - more than %d facilities !\n", operation_tag, MAX_SUBCOMMANDS);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ return -1;
-+ }
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ {
-+ pri_message(pri, "ROSE %i: Handle CcCcnrRequest\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ c_subcmd->cmd = CMD_CC_CCNRREQUEST_RR;
-+ res = rose_ccnr_request_result_decode(pri, &c_subcmd->cc_ccnr_rr.cc_request_res, comp, len-i);
-+ return res;
-+
-+ default:
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "!! Unable to handle ROSE operation %d", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ return -1;
-+ }
- } else {
- pri_message(pri, "Unable to handle return result on switchtype %d!\n", pri->switchtype);
- return -1;
-@@ -2414,6 +4210,7 @@
- int operation_tag;
- unsigned char *vdata = data;
- struct rose_component *comp = NULL, *invokeid = NULL, *operationid = NULL;
-+ struct subcommand *c_subcmd;
-
- do {
- /* Invoke ID stuff */
-@@ -2444,126 +4241,294 @@
-
- if (pri->debug & PRI_DEBUG_APDU)
- pri_message(pri, " [ Handling operation %d ]\n", operation_tag);
-- switch (operation_tag) {
-- case SS_CNID_CALLINGNAME:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, " Handle Name display operation\n");
-- return rose_calling_name_decode(pri, call, comp, len-i);
-- case ROSE_CALL_TRANSFER_IDENTIFY:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "ROSE %i: CallTransferIdentify - not handled!\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- return -1;
-- case ROSE_CALL_TRANSFER_ABANDON:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "ROSE %i: CallTransferAbandon - not handled!\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- return -1;
-- case ROSE_CALL_TRANSFER_INITIATE:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "ROSE %i: CallTransferInitiate - not handled!\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- return -1;
-- case ROSE_CALL_TRANSFER_SETUP:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "ROSE %i: CallTransferSetup - not handled!\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- return -1;
-- case ROSE_CALL_TRANSFER_ACTIVE:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "ROSE %i: CallTransferActive - not handled!\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- return -1;
-- case ROSE_CALL_TRANSFER_COMPLETE:
-- if (pri->debug & PRI_DEBUG_APDU)
-- {
-- pri_message(pri, "ROSE %i: Handle CallTransferComplete\n", operation_tag);
-+
-+ if (pri->switchtype == PRI_SWITCH_QSIG) {
-+
-+ switch (operation_tag) {
-+ case SS_CNID_CALLINGNAME:
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "ROSE %i: Handle CallingName\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ return rose_calling_name_decode(pri, call, comp, len-i);
-+ case SS_CNOP_CALLEDNAME:
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "ROSE %i: Handle CalledName\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ return rose_called_name_decode(pri, call, comp, len-i);
-+ case SS_CNOP_CONNECTEDNAME:
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "ROSE %i: Handle ConnectedName\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ return rose_connected_name_decode(pri, call, comp, len-i);
-+ case ROSE_CALL_TRANSFER_IDENTIFY:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: CallTransferIdentify - not handled!\n", operation_tag);
- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return rose_call_transfer_complete_decode(pri, call, comp, len-i);
-- case ROSE_CALL_TRANSFER_UPDATE:
-- if (pri->debug & PRI_DEBUG_APDU)
-- {
-- pri_message(pri, "ROSE %i: Handle CallTransferUpdate\n", operation_tag);
-+ return -1;
-+ case ROSE_CALL_TRANSFER_ABANDON:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: CallTransferAbandon - not handled!\n", operation_tag);
- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return rose_call_transfer_update_decode(pri, call, comp, len-i);
-- case ROSE_SUBADDRESS_TRANSFER:
-- if (pri->debug & PRI_DEBUG_APDU)
-- pri_message(pri, "ROSE %i: SubaddressTransfer - not handled!\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- return -1;
-- case ROSE_DIVERTING_LEG_INFORMATION2:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: Handle CallingName\n", operation_tag);
-- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return rose_diverting_leg_information2_decode(pri, call, comp, len-i);
-- case ROSE_AOC_NO_CHARGING_INFO_AVAILABLE:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC No Charging Info Available - not handled!", operation_tag);
-- dump_apdu (pri, comp->data, comp->len);
-- }
-- return -1;
-- case ROSE_AOC_CHARGING_REQUEST:
-- return aoc_aoce_charging_request_decode(pri, call, (u_int8_t *)comp, comp->len + 2);
-- case ROSE_AOC_AOCS_CURRENCY:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC-S Currency - not handled!", operation_tag);
-+ return -1;
-+ case ROSE_CALL_TRANSFER_INITIATE:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: CallTransferInitiate - not handled!\n", operation_tag);
- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return -1;
-- case ROSE_AOC_AOCS_SPECIAL_ARR:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC-S Special Array - not handled!", operation_tag);
-+ return -1;
-+ case ROSE_CALL_TRANSFER_SETUP:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: CallTransferSetup - not handled!\n", operation_tag);
- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return -1;
-- case ROSE_AOC_AOCD_CURRENCY:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC-D Currency - not handled!", operation_tag);
-+ return -1;
-+ case ROSE_CALL_TRANSFER_ACTIVE:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: Handle CallTransferActive\n", operation_tag);
- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return -1;
-- case ROSE_AOC_AOCD_CHARGING_UNIT:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC-D Charging Unit - not handled!", operation_tag);
-+ return rose_call_transfer_active_decode(pri, call, comp, len-i);
-+ case ROSE_CALL_TRANSFER_COMPLETE:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ {
-+ pri_message(pri, "ROSE %i: Handle CallTransferComplete\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ return rose_call_transfer_complete_decode(pri, call, comp, len-i);
-+ case ROSE_CALL_TRANSFER_UPDATE:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: CallTransferUpdate - not handled!\n", operation_tag);
- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return -1;
-- case ROSE_AOC_AOCE_CURRENCY:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC-E Currency - not handled!", operation_tag);
-+ return -1;
-+ case ROSE_SUBADDRESS_TRANSFER:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: SubaddressTransfer - not handled!\n", operation_tag);
- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-- }
-- return -1;
-- case ROSE_AOC_AOCE_CHARGING_UNIT:
-- return aoc_aoce_charging_unit_decode(pri, call, (u_int8_t *)comp, comp->len + 2);
-- if (0) { /* the following function is currently not used - just to make the compiler happy */
-- aoc_aoce_charging_unit_encode(pri, call, call->aoc_units); /* use this function to forward the aoc-e on a bridged channel */
-+ return -1;
-+ case ROSE_DIVERTING_LEG_INFORMATION1:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Handle DivertingLegInformation1\n");
-+ return rose_diverting_leg_information1_decode(pri, call, comp, len-i);
-+ case ROSE_DIVERTING_LEG_INFORMATION2:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Handle DivertingLegInformation2\n");
-+ return rose_diverting_leg_information2_decode(pri, call, comp, len-i);
-+ case ROSE_DIVERTING_LEG_INFORMATION3:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Handle DivertingLegInformation3\n");
-+ return rose_diverting_leg_information3_decode(pri, call, comp, len-i);
-+ case SS_ANFPR_PATHREPLACEMENT:
-+ /* Clear Queue */
-+ res = pri_call_apdu_queue_cleanup(call->bridged_call);
-+ if (res) {
-+ pri_message(pri, "Could not Clear queue ADPU\n");
-+ return -1;
-+ }
-+ anfpr_pathreplacement_respond(pri, call, ie);
-+ break;
-+ case QSIG_CC_CCBSREQUEST:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: invoke CcbsRequest - not handled!\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ return -1;
-+ case QSIG_CC_CCNRREQUEST:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: invoke CcnrRequest - not handled!\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ return -1;
-+ case QSIG_CC_CANCEL:
-+ c_subcmd = get_ptr_subcommand(&call->subcmds);
-+ if (!c_subcmd) {
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: invoke CcCancel - more than %d facilities !\n", operation_tag, MAX_SUBCOMMANDS);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ return -1;
-+ }
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ {
-+ pri_message(pri, "ROSE %i: Handle CcCancel\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ c_subcmd->cmd = CMD_CC_CANCEL_INV;
-+ res = rose_cc_optional_arg_decode(pri, call, &c_subcmd->cc_cancel_inv.cc_optional_arg, comp, len-i);
-+ return res;
-+ case QSIG_CC_EXECPOSIBLE:
-+ c_subcmd = get_ptr_subcommand(&call->subcmds);
-+ if (!c_subcmd) {
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: invoke CcExecposible - more than %d facilities !\n", operation_tag, MAX_SUBCOMMANDS);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ return -1;
-+ }
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ {
-+ pri_message(pri, "ROSE %i: Handle CcExecposible\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ c_subcmd->cmd = CMD_CC_EXECPOSIBLE_INV;
-+ res = rose_cc_optional_arg_decode(pri, call, &c_subcmd->cc_execposible_inv.cc_optional_arg, comp, len-i);
-+ return res;
-+ case QSIG_CC_PATHRESERVE:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: invoke CcPathreserve - not handled!\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ return -1;
-+ case QSIG_CC_RINGOUT:
-+ c_subcmd = get_ptr_subcommand(&call->subcmds);
-+ if (!c_subcmd) {
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: invoke CcRingout - more than %d facilities !\n", operation_tag, MAX_SUBCOMMANDS);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ return -1;
-+ }
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ {
-+ pri_message(pri, "ROSE %i: Handle CcRingout\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ c_subcmd->cmd = CMD_CC_RINGOUT_INV;
-+ res = rose_cc_ringout_inv_decode(pri, &c_subcmd->cc_ringout_inv.cc_extension, comp, len-i);
-+ return res;
-+ case QSIG_CC_SUSPEND:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ {
-+ pri_message(pri, "ROSE %i: Handle CcSuspend\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
- return 0;
-- }
-- case ROSE_AOC_IDENTIFICATION_OF_CHARGE:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "ROSE %i: AOC Identification Of Charge - not handled!", operation_tag);
-+ case QSIG_CC_RESUME:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: invoke CcResume - not handled!\n", operation_tag);
- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ return -1;
-+ default:
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "!! Unable to handle ROSE operation %d", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ return -1;
- }
-- return -1;
-- case SS_ANFPR_PATHREPLACEMENT:
-- /* Clear Queue */
-- res = pri_call_apdu_queue_cleanup(call->bridged_call);
-- if (res) {
-- pri_message(pri, "Could not Clear queue ADPU\n");
-- return -1;
-- }
-- anfpr_pathreplacement_respond(pri, call, ie);
-- break;
-- default:
-- if (pri->debug & PRI_DEBUG_APDU) {
-- pri_message(pri, "!! Unable to handle ROSE operation %d", operation_tag);
-+ } else { /* pri->switchtype == PRI_SWITCH_QSIG */
-+
-+ switch (operation_tag) {
-+ case SS_CNID_CALLINGNAME:
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "ROSE %i: Handle CallingName\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ return rose_calling_name_decode(pri, call, comp, len-i);
-+ case ROSE_CALL_TRANSFER_IDENTIFY:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: CallTransferIdentify - not handled!\n", operation_tag);
- dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ return -1;
-+ case ROSE_CALL_TRANSFER_ABANDON:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: CallTransferAbandon - not handled!\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ return -1;
-+ case ROSE_CALL_TRANSFER_INITIATE:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: CallTransferInitiate - not handled!\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ return -1;
-+ case ROSE_CALL_TRANSFER_SETUP:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: CallTransferSetup - not handled!\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ return -1;
-+ case ROSE_CALL_TRANSFER_ACTIVE:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: Handle CallTransferActive\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ return rose_call_transfer_active_decode(pri, call, comp, len-i);
-+ case ROSE_CALL_TRANSFER_COMPLETE:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ {
-+ pri_message(pri, "ROSE %i: Handle CallTransferComplete\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ return rose_call_transfer_complete_decode(pri, call, comp, len-i);
-+ case ROSE_CALL_TRANSFER_UPDATE:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: CallTransferUpdate - not handled!\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ return -1;
-+ case ROSE_SUBADDRESS_TRANSFER:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "ROSE %i: SubaddressTransfer - not handled!\n", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ return -1;
-+ case ROSE_DIVERTING_LEG_INFORMATION2:
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, " Handle DivertingLegInformation2\n");
-+ return rose_diverting_leg_information2_decode(pri, call, comp, len-i);
-+ case ROSE_AOC_NO_CHARGING_INFO_AVAILABLE:
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "ROSE %i: AOC No Charging Info Available - not handled!", operation_tag);
-+ dump_apdu (pri, comp->data, comp->len);
-+ }
-+ return -1;
-+ case ROSE_AOC_CHARGING_REQUEST:
-+ return aoc_aoce_charging_request_decode(pri, call, (u_int8_t *)comp, comp->len + 2);
-+ case ROSE_AOC_AOCS_CURRENCY:
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "ROSE %i: AOC-S Currency - not handled!", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ return -1;
-+ case ROSE_AOC_AOCS_SPECIAL_ARR:
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "ROSE %i: AOC-S Special Array - not handled!", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ return -1;
-+ case ROSE_AOC_AOCD_CURRENCY:
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "ROSE %i: AOC-D Currency - not handled!", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ return -1;
-+ case ROSE_AOC_AOCD_CHARGING_UNIT:
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "ROSE %i: AOC-D Charging Unit - not handled!", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ return -1;
-+ case ROSE_AOC_AOCE_CURRENCY:
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "ROSE %i: AOC-E Currency - not handled!", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ return -1;
-+ case ROSE_AOC_AOCE_CHARGING_UNIT:
-+ return aoc_aoce_charging_unit_decode(pri, call, (u_int8_t *)comp, comp->len + 2);
-+ if (0) { /* the following function is currently not used - just to make the compiler happy */
-+ aoc_aoce_charging_unit_encode(pri, call, call->aoc_units); /* use this function to forward the aoc-e on a bridged channel */
-+ return 0;
-+ }
-+ case ROSE_AOC_IDENTIFICATION_OF_CHARGE:
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "ROSE %i: AOC Identification Of Charge - not handled!", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ return -1;
-+ case SS_ANFPR_PATHREPLACEMENT:
-+ /* Clear Queue */
-+ res = pri_call_apdu_queue_cleanup(call->bridged_call);
-+ if (res) {
-+ pri_message(pri, "Could not Clear queue ADPU\n");
-+ return -1;
-+ }
-+ anfpr_pathreplacement_respond(pri, call, ie);
-+ break;
-+ default:
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "!! Unable to handle ROSE operation %d", operation_tag);
-+ dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
-+ }
-+ return -1;
- }
-- return -1;
- }
- } while(0);
-
-@@ -2619,15 +4584,119 @@
- return 0;
- }
-
-+/* ===== Begin Call Completion Supplementary Service (ETS 300 366/ECMA 186) ===== */
-+/* operationId e.g. QSIG_CC_CCBS_REQUEST and QSIG_CC_CCNR_REQUEST */
-+static int add_qsigCcRequestArg_facility_ie (struct pri *pri, q931_call *c)
-+{
-+ int size = 0;
-+ int i = 0;
-+ unsigned char buffer[256];
-+ struct rose_component *comp = NULL, *compstk[10];
-+ int compsp = 0;
-+ u_int8_t operationId = c->ccoperation;
-+ char *numberA = c->callernum;
-+ char *numberB = c->callednum;
-+
-+ /* 1 Byte 0x80 | 0x1F = 9F Protocol Profile (0x93 wäre altes QSIG oder DDS1) */
-+ buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
-+
-+ /* Interpretation component */
-+ ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i); /* 2. Byte NEtwork Facility Extension 0xAA = ASN1_CONTEXT_SPECIFIC(0x80) | (ASN1_CONSTRUCTOR 0x20) 0x0A (Tag laut Standard) */
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0); /* (0x80, 0x01(len), 0x00) endPTNX */
-+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0); /* (0x82, 0x01(len), 0x00) endPTNX */
-+
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+
-+#if 0
-+ ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0); /* 0x8B, 0x01(len), 0x00 discard */
-+#endif
-+ ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i); /* 0xA1, 0xXX (len of Invoke Sequenz) invoke APDU */
-+ ASN1_PUSH(compstk, compsp, comp);
-+
-+ /* Invoke ID */
-+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri)); /* InvokeID 0x02 0x01 0xXX */
-+
-+ /*CcbsRequest ::= 40 or CcnrRequest ::= 27 */
-+ /* Operation ID: CCBS/CCNR */
-+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, operationId); /* 0x02 0x01 0x28/0x1b */
-+
-+ /* ccbs/ccnr request argument */
-+ /* PresentedNumberUnscreened */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i); /*0x30 0xXX (len)*/
-+ ASN1_PUSH(compstk, compsp, comp);
-+ /* (0xA0, 0x01(len)) presentationAlloweAddress [0] PartyNumber */
-+ /* (0xA1, 0xXX (len) publicPartyNumber [1] IMPLICIT PublicPartyNumber */
-+ /* (0x0A, 0x01, 0x00 ) type of public party number = subscriber number */
-+ /* (0x12, 0xXX (len), 0xXX .. 0xXX) numeric string */
-+ size = rose_presented_number_unscreened_encode(pri, &buffer[i], PRES_ALLOWED, Q932_TON_UNKNOWN, numberA);
-+ if (size < 0)
-+ return -1;
-+ i += size;
-+
-+ /* (0xA1, 0xXX (len) [1] IMPLICIT PublicPartyNumber */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+ /* (0x0A, 0x01, 0x00 ) type of public party number = subscriber number */
-+ /* (0x12, 0xXX (len), 0xXX .. 0xXX) numeric string */
-+ size = rose_public_party_number_encode(pri, comp->data, 1, Q932_TON_UNKNOWN, numberB);
-+ if (size < 0)
-+ return -1;
-+ i += size;
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+
-+ /* (0x40, 0xXX (len), 0xXX .. 0xXX) pSS1InfoElement */
-+ ASN1_ADD_SIMPLE(comp, (ASN1_APPLICATION | ASN1_TAG_0 ), buffer, i);
-+ ASN1_PUSH(compstk, compsp, comp);
-+ buffer[i++] = (0x04); /* add Bearer Capability IE */
-+ buffer[i++] = (0x03); /* len*/
-+ buffer[i++] = (0x80); /* ETSI Standard, Speech */
-+ buffer[i++] = (0x90); /* circuit mode, 64kbit/s */
-+ buffer[i++] = (0xa3); /* level1 protocol, a-law */
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+#if 0
-+ /* can-retain-service [12] IMPLICIT BOOLEAN DEFAULT FALSE,*/
-+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_12), buffer, i, 0); /* 0x1C, 0x01(len), 0x00 false */
-+#endif
-+ /* retain-sig-connection [13] IMPLICIT BOOLEAN OPTIONAL, --TRUE: sign. connection to be retained */
-+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_13), buffer, i, 1); /* 0x1D, 0x01(len), 0x01 true */
-+
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+
-+ ASN1_FIXUP(compstk, compsp, buffer, i);
-+
-+ if (pri_call_apdu_queue(c, Q931_SETUP, buffer, i, NULL, NULL))
-+ return -1;
-+
-+ return 0;
-+}
-+/* ===== End Call Completion Supplementary Service (ETS 300 366/ECMA 186) ===== */
-+
- int pri_call_add_standard_apdus(struct pri *pri, q931_call *call)
- {
- if (!pri->sendfacility)
- return 0;
-
- if (pri->switchtype == PRI_SWITCH_QSIG) { /* For Q.SIG it does network and cpe operations */
-- if (call->redirectingnum[0])
-+ if (call->redirectingnum[0])
- rose_diverting_leg_information2_encode(pri, call);
- add_callername_facility_ies(pri, call, 1);
-+ if (call->ccoperation) {
-+ switch(call->ccoperation) {
-+ case 0:
-+ break;
-+ case QSIG_CC_CCBSREQUEST:
-+ case QSIG_CC_CCNRREQUEST:
-+ add_qsigCcRequestArg_facility_ie(pri, call);
-+ break;
-+ case QSIG_CC_RINGOUT:
-+ add_qsigCcInv_facility_ie(pri, call, Q931_SETUP);
-+ break;
-+ default:
-+ break;
-+ }
-+ }
- return 0;
- }
-
-@@ -2665,3 +4734,26 @@
- return 0;
- }
-
-+int qsig_initiate_diverting_leg_information1(struct pri *pri, q931_call *call)
-+{
-+ rose_diverting_leg_information1_encode(pri, call);
-+
-+ if (q931_facility(pri, call)) {
-+ pri_message(pri, "Could not schedule facility message for divertingLegInfo1\n");
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-+
-+int qsig_initiate_call_transfer_complete(struct pri *pri, q931_call *call, int call_status)
-+{
-+ rose_call_transfer_complete_encode(pri, call, call_status);
-+
-+ if (q931_facility(pri, call)) {
-+ pri_message(pri, "Could not schedule facility message for callTransferComplete\n");
-+ return -1;
-+ }
-+
-+ return 0;
-+}
-Index: pri_timers.h
-===================================================================
---- a/pri_timers.h (.../tags/1.4.9) (revision 700)
-+++ b/pri_timers.h (.../team/group/issue14292) (revision 700)
-@@ -62,6 +62,7 @@
- -1, /* T322 */ \
- 2500, /* TM20 - Q.921 Appendix IV */ \
- 3, /* NM20 - Q.921 Appendix IV */ \
-+ 45*60*1000 /* CC-Timer2 45 min */\
- }
-
- /* XXX Only our default timers are setup now XXX */
-Index: pri_facility.h
-===================================================================
---- a/pri_facility.h (.../tags/1.4.9) (revision 700)
-+++ b/pri_facility.h (.../team/group/issue14292) (revision 700)
-@@ -38,14 +38,6 @@
- #define Q932_PROTOCOL_GAT 0x16
- #define Q932_PROTOCOL_EXTENSIONS 0x1F
-
--/* Argument values */
--#define ROSE_NAME_PRESENTATION_ALLOWED_SIMPLE 0x80
--#define ROSE_NAME_PRESENTATION_RESTRICTED_NULL 0x87
--#define ROSE_NAME_PRESENTATION_ALLOWED_EXTENDED 0xA1
--#define ROSE_NAME_PRESENTATION_RESTRICTED_SIMPLE 0xA2
--#define ROSE_NAME_PRESENTATION_RESTRICTED_EXTENDED 0xA3
--#define ROSE_NAME_NOT_AVAIL 0x84
--
- /* Component types */
- #define COMP_TYPE_INTERPRETATION 0x8B
- #define COMP_TYPE_NETWORK_PROTOCOL_PROFILE 0x92
-@@ -65,10 +57,11 @@
- #define ROSE_CALL_TRANSFER_COMPLETE 12
- #define ROSE_CALL_TRANSFER_UPDATE 13
- #define ROSE_SUBADDRESS_TRANSFER 14
-+#define QSIG_CF_CALLREROUTING 19
- /* Q.952 ROSE operations (Diverting) */
--#define ROSE_DIVERTING_LEG_INFORMATION1 18
--#define ROSE_DIVERTING_LEG_INFORMATION2 0x15
--#define ROSE_DIVERTING_LEG_INFORMATION3 19
-+#define ROSE_DIVERTING_LEG_INFORMATION1 20
-+#define ROSE_DIVERTING_LEG_INFORMATION2 21
-+#define ROSE_DIVERTING_LEG_INFORMATION3 22
- /* Q.956 ROSE operations (Advice Of Charge) */
- #define ROSE_AOC_NO_CHARGING_INFO_AVAILABLE 26
- #define ROSE_AOC_CHARGING_REQUEST 30
-@@ -81,12 +74,27 @@
- #define ROSE_AOC_IDENTIFICATION_OF_CHARGE 37
- /* Q.SIG operations */
- #define SS_CNID_CALLINGNAME 0
-+#define SS_CNOP_CALLEDNAME 1
-+#define SS_CNOP_CONNECTEDNAME 2
- #define SS_ANFPR_PATHREPLACEMENT 4
--#define SS_DIVERTING_LEG_INFORMATION2 21
- #define SS_MWI_ACTIVATE 80
- #define SS_MWI_DEACTIVATE 81
- #define SS_MWI_INTERROGATE 82
-
-+/* ECMA 186 */
-+#define QSIG_CC_CCNRREQUEST PRI_CC_CCNRREQUEST /* 27 */
-+#define QSIG_CC_CANCEL PRI_CC_CANCEL /* 28 */
-+#define QSIG_CC_EXECPOSIBLE 29
-+#define QSIG_CC_PATHRESERVE 30
-+#define QSIG_CC_RINGOUT 31
-+#define QSIG_CC_SUSPEND 32
-+#define QSIG_CC_RESUME 33
-+#define QSIG_CC_CCBSREQUEST PRI_CC_CCBSREQUEST /* 40 */
-+
-+#define QSIG_CC_UNSPECIFIED 1008
-+#define QSIG_CC_REMOTE_USER_BUSY_AGAIN 1012
-+#define QSIG_CC_FAILURE_TO_MATCH 1013
-+
- /* ROSE definitions and data structures */
- #define INVOKE_IDENTIFIER 0x02
- #define INVOKE_LINKED_IDENTIFIER 0x80
-@@ -128,6 +136,12 @@
- #define ASN1_TAG_7 0x07
- #define ASN1_TAG_8 0x08
- #define ASN1_TAG_9 0x09
-+#define ASN1_TAG_10 0x0a
-+#define ASN1_TAG_11 0x0b
-+#define ASN1_TAG_12 0x0c
-+#define ASN1_TAG_13 0x0d
-+#define ASN1_TAG_14 0x0e
-+#define ASN1_TAG_15 0x0f
-
- /* ASN.1 Identifier Octet - Primitive/Constructor Bit */
- #define ASN1_PC_MASK 0x20
-@@ -169,6 +183,20 @@
- #define Q932_TON_SUBSCRIBER 0x04
- #define Q932_TON_ABBREVIATED 0x06
-
-+/* Q.SIG Character Sets. Listed in ISO/IEC 8859 */
-+#define CHARACTER_SET_UNKNOWN 0x00
-+#define CHARACTER_SET_ISO8859_1 0x01
-+#define CHARACTER_SET_ISO8859_2 0x03
-+#define CHARACTER_SET_ISO8859_3 0x04
-+#define CHARACTER_SET_ISO8859_4 0x05
-+#define CHARACTER_SET_ISO8859_5 0x06
-+#define CHARACTER_SET_ISO8859_7 0x07
-+
-+/* Q.SIG Subscription Option. Listed in ECMA-174 */
-+#define QSIG_NO_NOTIFICATION 0x00
-+#define QSIG_NOTIFICATION_WITHOUT_DIVERTED_TO_NR 0x01
-+#define QSIG_NOTIFICATION_WITH_DIVERTED_TO_NR 0x02
-+
- /* RLT related Operations */
- #define RLT_SERVICE_ID 0x3e
- #define RLT_OPERATION_IND 0x01
-@@ -314,6 +342,18 @@
- /* starts a QSIG Path Replacement */
- int anfpr_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
-
-+int qsig_initiate_diverting_leg_information1(struct pri *pri, q931_call *call);
-+
-+int qsig_initiate_call_transfer_complete(struct pri *pri, q931_call *call, int call_status);
-+
-+int rose_diverting_leg_information1_encode(struct pri *pri, q931_call *call);
-+
-+int rose_diverting_leg_information3_encode(struct pri *pri, q931_call *call, int messagetype);
-+
-+int rose_connected_name_encode(struct pri *pri, q931_call *call, int messagetype);
-+
-+int rose_called_name_encode(struct pri *pri, q931_call *call, int messagetype);
-+
- /* Use this function to queue a facility-IE born APDU onto a call
- * call is the call to use, messagetype is any one of the Q931 messages,
- * apdu is the apdu data, apdu_len is the length of the apdu data */
-@@ -325,6 +365,8 @@
- /* Adds the "standard" APDUs to a call */
- int pri_call_add_standard_apdus(struct pri *pri, q931_call *call);
-
-+int add_qsigCcInv_facility_ie (struct pri *pri, q931_call *c, int messagetype);
-+
- int asn1_dump(struct pri *pri, void *comp, int len);
-
- #endif /* _PRI_FACILITY_H */
-Index: libpri.h
-===================================================================
---- a/libpri.h (.../tags/1.4.9) (revision 700)
-+++ b/libpri.h (.../team/group/issue14292) (revision 700)
-@@ -81,6 +81,7 @@
- #define PRI_EVENT_NOTIFY 16 /* Notification received */
- #define PRI_EVENT_PROGRESS 17 /* When we get CALL_PROCEEDING or PROGRESS */
- #define PRI_EVENT_KEYPAD_DIGIT 18 /* When we receive during ACTIVE state */
-+#define PRI_EVENT_FACILITY 19 /* Facility received */
-
- /* Simple states */
- #define PRI_STATE_DOWN 0
-@@ -135,16 +136,45 @@
- #define PRI_UNKNOWN 0x0
-
- /* Presentation */
--#define PRES_ALLOWED_USER_NUMBER_NOT_SCREENED 0x00
--#define PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN 0x01
--#define PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN 0x02
--#define PRES_ALLOWED_NETWORK_NUMBER 0x03
--#define PRES_PROHIB_USER_NUMBER_NOT_SCREENED 0x20
--#define PRES_PROHIB_USER_NUMBER_PASSED_SCREEN 0x21
--#define PRES_PROHIB_USER_NUMBER_FAILED_SCREEN 0x22
--#define PRES_PROHIB_NETWORK_NUMBER 0x23
--#define PRES_NUMBER_NOT_AVAILABLE 0x43
-+#define PRES_NUMBER_TYPE 0x03
-+#define PRES_USER_NUMBER_UNSCREENED 0x00
-+#define PRES_USER_NUMBER_PASSED_SCREEN 0x01
-+#define PRES_USER_NUMBER_FAILED_SCREEN 0x02
-+#define PRES_NETWORK_NUMBER 0x03
-
-+#define PRES_RESTRICTION 0x60
-+#define PRES_ALLOWED 0x00
-+#define PRES_RESTRICTED 0x20
-+#define PRES_UNAVAILABLE 0x40
-+#define PRES_RESERVED 0x60
-+
-+#define PRES_ALLOWED_USER_NUMBER_NOT_SCREENED \
-+ (PRES_ALLOWED | PRES_USER_NUMBER_UNSCREENED)
-+
-+#define PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN \
-+ (PRES_ALLOWED | PRES_USER_NUMBER_PASSED_SCREEN)
-+
-+#define PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN \
-+ (PRES_ALLOWED | PRES_USER_NUMBER_FAILED_SCREEN)
-+
-+#define PRES_ALLOWED_NETWORK_NUMBER \
-+ (PRES_ALLOWED | PRES_NETWORK_NUMBER)
-+
-+#define PRES_PROHIB_USER_NUMBER_NOT_SCREENED \
-+ (PRES_RESTRICTED | PRES_USER_NUMBER_UNSCREENED)
-+
-+#define PRES_PROHIB_USER_NUMBER_PASSED_SCREEN \
-+ (PRES_RESTRICTED | PRES_USER_NUMBER_PASSED_SCREEN)
-+
-+#define PRES_PROHIB_USER_NUMBER_FAILED_SCREEN \
-+ (PRES_RESTRICTED | PRES_USER_NUMBER_FAILED_SCREEN)
-+
-+#define PRES_PROHIB_NETWORK_NUMBER \
-+ (PRES_RESTRICTED | PRES_NETWORK_NUMBER)
-+
-+#define PRES_NUMBER_NOT_AVAILABLE \
-+ (PRES_UNAVAILABLE | PRES_NETWORK_NUMBER)
-+
- /* Causes for disconnection */
- #define PRI_CAUSE_UNALLOCATED 1
- #define PRI_CAUSE_NO_ROUTE_TRANSIT_NET 2 /* !Q.SIG */
-@@ -303,8 +333,141 @@
- #define PRI_NSF_ATT_MULTIQUEST 0xF0
- #define PRI_NSF_CALL_REDIRECTION_SERVICE 0xF7
-
-+/* ECMA 186 */
-+#define PRI_CC_CCNRREQUEST 27
-+#define PRI_CC_CANCEL 28
-+#define PRI_CC_CCBSREQUEST 40
-+
- typedef struct q931_call q931_call;
-
-+/* Connected line update source code */
-+enum PRI_CONNECTED_LINE_UPDATE_SOURCE {
-+ PRI_CONNECTED_LINE_UPDATE_SOURCE_UNKNOWN, /* Update for unknown reason (May be interpreted to mean from answer) */
-+ PRI_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, /* Update from normal call answering */
-+ PRI_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, /* Update from call transfer(active) (Party has already answered) */
-+ PRI_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING /* Update from call transfer(alerting) (Party has not answered yet) */
-+};
-+
-+/* Information needed to identify an endpoint in a call. */
-+struct pri_party_id {
-+ char number[256]; /* Subscriber phone number */
-+ char name[256]; /* Subscriber name */
-+ int number_type; /* Q.931 encoded "type of number" and "numbering plan identification" */
-+ int number_presentation; /* Q.931 encoded "presentation indicator" and "screening indicator" */
-+};
-+
-+/* Connected Line/Party information */
-+struct pri_party_connected_line {
-+ struct pri_party_id id; /* Connected party ID */
-+ int source; /* Information about the source of an update .
-+ * enum PRI_CONNECTED_LINE_UPDATE_SOURCE values
-+ * for Normal-Answer, Call-transfer */
-+};
-+
-+/* Redirecting Line information.
-+ * RDNIS (Redirecting Directory Number Information Service)
-+ * Where a call diversion or transfer was invoked. */
-+struct pri_party_redirecting {
-+ struct pri_party_id from; /* Who is redirecting the call (Sent to the party the call is redirected toward) */
-+ struct pri_party_id to; /* Call is redirecting to a new party (Sent to the caller) */
-+ int count; /* Number of times the call was redirected */
-+ int reason; /* Redirection reasons */
-+};
-+
-+/* Structures for qsig_cc_facilities */
-+struct qsig_cc_extension {
-+ int cc_extension_tag;
-+ char extension[256];
-+};
-+
-+struct qsig_cc_optional_arg {
-+ char number_A[256];
-+ char number_B[256];
-+ int service;
-+ struct qsig_cc_extension cc_extension;
-+};
-+
-+struct qsig_cc_request_res {
-+ int no_path_reservation;
-+ int retain_service;
-+ struct qsig_cc_extension cc_extension;
-+};
-+
-+/* Command derived from Facility */
-+#define CMD_REDIRECTING 1
-+#define CMD_CONNECTEDLINE 2
-+#define CMD_CC_CCBSREQUEST_RR 3
-+#define CMD_CC_CCNRREQUEST_RR 4
-+#define CMD_CC_CANCEL_INV 5
-+#define CMD_CC_EXECPOSIBLE_INV 6
-+#define CMD_CC_RINGOUT_INV 7
-+#define CMD_CC_SUSPEND_INV 8
-+#define CMD_CC_ERROR 9
-+
-+#define CCERROR_UNSPECIFIED 1008
-+#define CCERROR_REMOTE_USER_BUSY_AGAIN 1012
-+#define CCERROR_FAILURE_TO_MATCH 1013
-+
-+struct cmd_connectedline {
-+ struct pri_party_connected_line connected;
-+};
-+
-+struct cmd_redirecting {
-+ struct pri_party_redirecting redirecting;
-+};
-+
-+struct cmd_cc_ccbs_rr {
-+ struct qsig_cc_request_res cc_request_res;
-+};
-+
-+struct cmd_cc_ccnr_rr {
-+ struct qsig_cc_request_res cc_request_res;
-+};
-+
-+struct cmd_cc_cancel_inv {
-+ struct qsig_cc_optional_arg cc_optional_arg;
-+};
-+
-+struct cmd_cc_execposible_inv {
-+ struct qsig_cc_optional_arg cc_optional_arg;
-+};
-+
-+struct cmd_cc_suspend_inv {
-+ struct qsig_cc_extension cc_extension;
-+};
-+
-+struct cmd_cc_ringout_inv {
-+ struct qsig_cc_extension cc_extension;
-+};
-+
-+struct cmd_cc_error {
-+ int error_value;
-+};
-+
-+struct subcommand {
-+ int cmd;
-+ union {
-+ struct cmd_connectedline connectedline;
-+ struct cmd_redirecting redirecting;
-+ struct cmd_cc_ccbs_rr cc_ccbs_rr;
-+ struct cmd_cc_ccnr_rr cc_ccnr_rr;
-+ struct cmd_cc_cancel_inv cc_cancel_inv;
-+ struct cmd_cc_execposible_inv cc_execposible_inv;
-+ struct cmd_cc_suspend_inv cc_suspend_inv;
-+ struct cmd_cc_ringout_inv cc_ringout_inv;
-+ struct cmd_cc_error cc_error;
-+ };
-+};
-+
-+/* Max number of subcommands per event message */
-+#define MAX_SUBCOMMANDS 4
-+
-+struct subcommands {
-+ int counter_subcmd;
-+ struct subcommand subcmd[MAX_SUBCOMMANDS];
-+};
-+
-+
- typedef struct pri_event_generic {
- /* Events with no additional information fall in this category */
- int e;
-@@ -328,6 +491,11 @@
- int progressmask;
- q931_call *call;
- char useruserinfo[260]; /* User->User info */
-+ char calledname[256];
-+ char callednum[256];
-+ int calledpres;
-+ int calledplan;
-+ struct subcommands subcmds;
- } pri_event_ringing;
-
- typedef struct pri_event_answer {
-@@ -338,6 +506,12 @@
- int progressmask;
- q931_call *call;
- char useruserinfo[260]; /* User->User info */
-+ char connectednum[256];
-+ char connectedname[256];
-+ int connectedpres;
-+ int connectedplan;
-+ int source;
-+ struct subcommands subcmds;
- } pri_event_answer;
-
- typedef struct pri_event_facname {
-@@ -351,6 +525,14 @@
- int callingplan; /* Dialing plan of Calling entity */
- } pri_event_facname;
-
-+struct pri_event_facility {
-+ int e;
-+ int channel;
-+ int cref;
-+ q931_call *call;
-+ struct subcommands subcmds;
-+};
-+
- #define PRI_CALLINGPLANANI
- #define PRI_CALLINGPLANRDNIS
- typedef struct pri_event_ring {
-@@ -383,6 +565,9 @@
- char origcallednum[256];
- int callingplanorigcalled; /* Dialing plan of Originally Called Number */
- int origredirectingreason;
-+ int redirectingpres;
-+ int redirectingcount;
-+ struct subcommands subcmds;
- } pri_event_ring;
-
- typedef struct pri_event_hangup {
-@@ -393,6 +578,7 @@
- q931_call *call; /* Opaque call pointer */
- long aoc_units; /* Advise of Charge number of charged units */
- char useruserinfo[260]; /* User->User info */
-+ struct subcommands subcmds;
- } pri_event_hangup;
-
- typedef struct pri_event_restart_ack {
-@@ -445,6 +631,7 @@
- pri_event_setup_ack setup_ack; /* SETUP_ACKNOWLEDGE structure */
- pri_event_notify notify; /* Notification */
- pri_event_keypad_digit digit; /* Digits that come during a call */
-+ struct pri_event_facility facility;
- } pri_event;
-
- struct pri;
-@@ -531,6 +718,12 @@
- Set non-isdn to non-zero if you are not connecting to ISDN equipment */
- int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
-
-+/* Give connected line information to a call */
-+int pri_connected_line_update(struct pri *pri, q931_call *call, struct pri_party_connected_line *connected);
-+
-+/* Give redirection information to a call */
-+int pri_redirecting_update(struct pri *pri, q931_call *call, struct pri_party_redirecting *redirecting);
-+
- /* Set CRV reference for GR-303 calls */
-
-
-@@ -558,7 +751,12 @@
-
- /* Create a new call */
- q931_call *pri_new_call(struct pri *pri);
-+q931_call *pri_new_nochannel_call(struct pri *pri, int *cr);
-
-+q931_call *pri_find_call(struct pri *pri, int cr);
-+
-+void pri_call_set_cc_operation(q931_call *call, int cc_operation);
-+
- /* Retrieve CRV reference for GR-303 calls. Returns >0 on success. */
- int pri_get_crv(struct pri *pri, q931_call *call, int *callmode);
-
-@@ -584,6 +782,11 @@
- int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int complete);
- int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres);
- int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason);
-+void pri_sr_set_redirecting_name(struct pri_sr *sr, char *name);
-+
-+int pri_sr_set_ccringout(struct pri_sr *sr, int ccringout);
-+int pri_sr_set_ccbsnr(struct pri_sr *sr, int ccbsnr);
-+
- #define PRI_USER_USER_TX
- /* Set the user user field. Warning! don't send binary data accross this field */
- void pri_sr_set_useruser(struct pri_sr *sr, const char *userchars);
-@@ -595,7 +798,10 @@
- /* Set a call has a call indpendent signalling connection (i.e. no bchan) */
- int pri_sr_set_connection_call_independent(struct pri_sr *req);
-
--/* Send an MWI indication to a remote location. If activate is non zero, activates, if zero, decativates */
-+/* Set a no channel call (i.e. QSIG-CCBS/CCNR) */
-+int pri_sr_set_no_channel_call(struct pri_sr *req);
-+
-+/* Send an MWI indication to a remote location. If activate is non zero, activates, if zero, deactivates */
- int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called, int calledplan);
-
- /* Send an MWI deactivate request to a remote location */
-@@ -698,6 +904,7 @@
- #define PRI_TIMER_TM20 28 /* maximum time avaiting XID response */
- #define PRI_TIMER_NM20 29 /* number of XID retransmits */
-
-+#define PRI_TIMER_CCBST2 30 /* maximum time on completion of CC Call */
- /* Get PRI version */
- const char *pri_get_version(void);
-
-Index: pri.c
-===================================================================
---- a/pri.c (.../tags/1.4.9) (revision 700)
-+++ b/pri.c (.../team/group/issue14292) (revision 700)
-@@ -166,6 +166,8 @@
- return PRI_TIMER_T321;
- else if (!strcasecmp(timer, "T322"))
- return PRI_TIMER_T322;
-+ else if (!strcasecmp(timer, "CCT2"))
-+ return PRI_TIMER_CCBST2;
- else
- return -1;
- }
-@@ -348,6 +350,8 @@
- return "Restart ACK";
- case PRI_EVENT_FACNAME:
- return "FacName";
-+ case PRI_EVENT_FACILITY:
-+ return "Facility";
- case PRI_EVENT_INFO_RECEIVED:
- return "Info Received";
- case PRI_EVENT_PROCEEDING:
-@@ -551,6 +555,131 @@
- return q931_connect(pri, call, channel, nonisdn);
- }
-
-+int pri_connected_line_update(struct pri *pri, q931_call *call, struct pri_party_connected_line *connected)
-+{
-+ if (!pri || !call)
-+ return -1;
-+
-+ libpri_copy_string(call->connectednum, connected->id.number, sizeof(call->connectednum));
-+ libpri_copy_string(call->connectedname, connected->id.name, sizeof(call->connectedname));
-+ call->connectedplan = connected->id.number_type;
-+ call->connectedpres = connected->id.number_presentation;
-+
-+ if (pri->switchtype == PRI_SWITCH_QSIG) {
-+ switch (call->ourcallstate) {
-+ case Q931_CALL_STATE_ACTIVE:
-+ /* immediately send callTransferComplete APDU, callStatus=answered(0) */
-+ qsig_initiate_call_transfer_complete(pri, call, 0);
-+ break;
-+ case Q931_CALL_STATE_OVERLAP_RECEIVING:
-+ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
-+ /* queue updates for next ALERTING */
-+ if (call->connectedname[0]) {
-+ /* queue connectedName to be send with next Q931_ALERTING */
-+ rose_called_name_encode(pri, call, Q931_ALERTING);
-+ }
-+
-+ if (call->divertedstate != DIVERTEDSTATE_NONE) {
-+ libpri_copy_string(call->divertedtonum, connected->id.number, sizeof(call->divertedtonum));
-+ libpri_copy_string(call->divertedtoname, connected->id.name, sizeof(call->divertedtoname));
-+ call->divertedtoplan = connected->id.number_type;
-+ call->divertedtopres = connected->id.number_presentation;
-+
-+ if ((call->divertedstate == DIVERTEDSTATE_DIVERTED) && call->divertedtonum[0]) {
-+ /* immediately send divertingLegInformation1 APDU */
-+ qsig_initiate_diverting_leg_information1(pri, call);
-+ call->divertedstate = DIVERTEDSTATE_DIVLEGINFO1SEND;
-+ }
-+ if ((call->divertedstate == DIVERTEDSTATE_DIVLEGINFO1SEND) && call->divertedtoname[0]) {
-+ /* queue divertingLegInformation3 to be send with next Q931_ALERTING */
-+ rose_diverting_leg_information3_encode(pri, call, Q931_ALERTING);
-+ call->divertedstate = DIVERTEDSTATE_DIVLEGINFO3SEND;
-+ }
-+ }
-+ break;
-+ case Q931_CALL_STATE_CALL_RECEIVED:
-+ /* queue updates for next CONNECT */
-+ if (call->connectedname[0] && ((call->divertedstate == DIVERTEDSTATE_NONE) || (call->divertedstate == DIVERTEDSTATE_DIVLEGINFO3SEND))) {
-+ /* queue connectedName to be send with next Q931_CONNECT */
-+ rose_connected_name_encode(pri, call, Q931_CONNECT);
-+ }
-+
-+ if (call->divertedstate != DIVERTEDSTATE_NONE) {
-+ libpri_copy_string(call->divertedtonum, connected->id.number, sizeof(call->divertedtonum));
-+ libpri_copy_string(call->divertedtoname, connected->id.name, sizeof(call->divertedtoname));
-+ call->divertedtoplan = connected->id.number_type;
-+ call->divertedtopres = connected->id.number_presentation;
-+
-+ if ((call->divertedstate == DIVERTEDSTATE_DIVERTED) && call->divertedtonum[0]) {
-+ /* queue divertingLegInformation1 to be send with next Q931_FACILITY */
-+ rose_diverting_leg_information1_encode(pri, call);
-+ call->divertedstate = DIVERTEDSTATE_DIVLEGINFO1SEND;
-+
-+ if (call->divertedtoname[0]) {
-+ /* queue divertingLegInformation3 to be send with next Q931_FACILITY */
-+ rose_diverting_leg_information3_encode(pri, call, Q931_FACILITY);
-+ call->divertedstate = DIVERTEDSTATE_DIVLEGINFO3SEND;
-+ }
-+
-+ /* immediately send Q931_FACILITY */
-+ if (q931_facility(pri, call)) {
-+ pri_message(pri, "Could not schedule facility message for divertingLegInfo1+3\n");
-+ }
-+ }
-+ if ((call->divertedstate == DIVERTEDSTATE_DIVLEGINFO1SEND) && call->divertedtoname[0]) {
-+ /* queue divertingLegInformation3 to be send with next Q931_CONNECT */
-+ rose_diverting_leg_information3_encode(pri, call, Q931_CONNECT);
-+ call->divertedstate = DIVERTEDSTATE_DIVLEGINFO3SEND;
-+ }
-+ }
-+ break;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+int pri_redirecting_update(struct pri *pri, q931_call *call, struct pri_party_redirecting *redirecting)
-+{
-+ if (!pri || !call)
-+ return -1;
-+
-+ libpri_copy_string(call->divertedtonum, redirecting->to.number, sizeof(call->divertedtonum));
-+ libpri_copy_string(call->divertedtoname, redirecting->to.name, sizeof(call->divertedtoname));
-+ call->divertedtoplan = redirecting->to.number_type;
-+ call->divertedtopres = redirecting->to.number_presentation;
-+ call->divertedtoreason = redirecting->reason;
-+
-+ if (pri->switchtype == PRI_SWITCH_QSIG) {
-+ switch (call->ourcallstate) {
-+ case Q931_CALL_STATE_ACTIVE:
-+ /* immediately send callTransferComplete APDU, callStatus=alerting(1) */
-+ qsig_initiate_call_transfer_complete(pri, call, 1);
-+ break;
-+ case Q931_CALL_STATE_OVERLAP_RECEIVING:
-+ case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
-+ call->divertedstate = DIVERTEDSTATE_DIVERTED;
-+
-+ if (call->divertedtonum[0]) {
-+ /* immediately send divertingLegInformation1 APDU */
-+ qsig_initiate_diverting_leg_information1(pri, call);
-+ call->divertedstate = DIVERTEDSTATE_DIVLEGINFO1SEND;
-+ }
-+ if ((call->divertedstate == DIVERTEDSTATE_DIVLEGINFO1SEND) && call->divertedtoname[0]) {
-+ /* queue divertingLegInformation3 to be send with next Q931_ALERTING */
-+ rose_diverting_leg_information3_encode(pri, call, Q931_ALERTING);
-+ call->divertedstate = DIVERTEDSTATE_DIVLEGINFO3SEND;
-+ }
-+ break;
-+ default:
-+ pri_message(pri, "Redirecting update in state %d\n", call->ourcallstate);
-+ break;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
- #if 0
- /* deprecated routines, use pri_hangup */
- int pri_release(struct pri *pri, q931_call *call, int cause)
-@@ -637,6 +766,17 @@
- return q931_new_call(pri);
- }
-
-+q931_call *pri_new_nochannel_call(struct pri *pri, int *cr)
-+{
-+ q931_call *call;
-+ if (!pri)
-+ return NULL;
-+ call = q931_new_call(pri);
-+ if (cr)
-+ *cr = call->cr;
-+ return call;
-+}
-+
- void pri_dump_event(struct pri *pri, pri_event *e)
- {
- if (!pri || !e)
-@@ -679,6 +819,15 @@
- return 0;
- }
-
-+int pri_sr_set_no_channel_call(struct pri_sr *req)
-+{
-+ if (!req)
-+ return -1;
-+
-+ req->nochannelsignalling = 1;
-+ return 0;
-+}
-+
- /* Don't call any other pri functions on this */
- int pri_mwi_activate(struct pri *pri, q931_call *c, char *caller, int callerplan, char *callername, int callerpres, char *called,
- int calledplan)
-@@ -829,6 +978,10 @@
- struct q921_frame *f;
- int q921outstanding = 0;
- #endif
-+ q931_call *cur, *prev;
-+ struct pri *master;
-+ int counter = 0;
-+
- if (!pri)
- return NULL;
-
-@@ -862,10 +1015,57 @@
- len += sprintf(buf + len, "T309 Timer: %d\n", pri->timers[PRI_TIMER_T309]);
- len += sprintf(buf + len, "T313 Timer: %d\n", pri->timers[PRI_TIMER_T313]);
- len += sprintf(buf + len, "N200 Counter: %d\n", pri->timers[PRI_TIMER_N200]);
-+ len += sprintf(buf + len, "CCT2 Timer: %d\n", pri->timers[PRI_TIMER_CCBST2]);
-+ /* Find the master - He has the call pool */
-+ if (pri->master)
-+ master = pri->master;
-+ else
-+ master = pri;
-
-+ cur = *master->callpool;
-+ prev = NULL;
-+ while(cur) {
-+ if (cur->cctimer2) {
-+ struct timeval tv;
-+ int time_ms_to_go, time_to_go_min, time_to_go_sec;
-+ gettimeofday(&tv, NULL);
-+ time_ms_to_go = (pri->pri_sched[cur->cctimer2].when.tv_sec - tv.tv_sec)*1000;
-+ time_to_go_min = time_ms_to_go/1000/60;
-+ time_to_go_sec = (time_ms_to_go-(time_to_go_min*60*1000))/1000;
-+
-+ len += sprintf(buf + len, "%d. Active Q.931 Call: %p cr=%d: (%dmin %dsec)\n",
-+ ++counter, cur, cur->cr,
-+ time_to_go_min, time_to_go_sec);
-+ } else {
-+ len += sprintf(buf + len, "%d. Active Q.931 Call: %p cr=%d\n", ++counter, cur, cur->cr);
-+ }
-+ cur = cur->next;
-+ }
-+
- return strdup(buf);
- }
-
-+q931_call *pri_find_call(struct pri *pri, int cr)
-+{
-+ q931_call *cur;
-+ struct pri *master;
-+
-+ /* Find the master - He has the call pool */
-+ if (pri->master)
-+ master = pri->master;
-+ else
-+ master = pri;
-+
-+ cur = *master->callpool;
-+ while(cur) {
-+ if (cur->cr == cr)
-+ return cur;
-+ cur = cur->next;
-+ }
-+
-+ return NULL;
-+}
-+
- int pri_get_crv(struct pri *pri, q931_call *call, int *callmode)
- {
- return q931_call_getcrv(pri, call, callmode);
-@@ -936,3 +1136,25 @@
- sr->redirectingreason = reason;
- return 0;
- }
-+
-+void pri_sr_set_redirecting_name(struct pri_sr *sr, char *name)
-+{
-+ sr->redirectingname = name;
-+}
-+
-+int pri_sr_set_ccringout(struct pri_sr *sr, int ccringout)
-+{
-+ sr->ccringout = ccringout;
-+ return 0;
-+}
-+
-+int pri_sr_set_ccbsnr(struct pri_sr *sr, int ccbsnr)
-+{
-+ sr->ccbsnr = ccbsnr;
-+ return 0;
-+}
-+
-+void pri_call_set_cc_operation(q931_call *call, int cc_operation)
-+{
-+ call->ccoperation = cc_operation;
-+}
-Index: pri_internal.h
-===================================================================
---- a/pri_internal.h (.../tags/1.4.9) (revision 700)
-+++ b/pri_internal.h (.../team/group/issue14292) (revision 700)
-@@ -36,6 +36,12 @@
- #define DBGHEAD __FILE__ ":%d %s: "
- #define DBGINFO __LINE__,__PRETTY_FUNCTION__
-
-+/* divertedstate */
-+#define DIVERTEDSTATE_NONE 0
-+#define DIVERTEDSTATE_DIVERTED 1
-+#define DIVERTEDSTATE_DIVLEGINFO1SEND 2
-+#define DIVERTEDSTATE_DIVLEGINFO3SEND 3
-+
- struct pri_sched {
- struct timeval when;
- void (*callback)(void *data);
-@@ -47,7 +53,7 @@
- enum q931_mode;
-
- /* No more than 128 scheduled events */
--#define MAX_SCHED 128
-+#define MAX_SCHED 128+256 /* 256 ccT2 timer events*/
-
- #define MAX_TIMERS 32
-
-@@ -142,13 +148,17 @@
- int calledplan;
- int userl1;
- int numcomplete;
-+ char *redirectingname;
- char *redirectingnum;
- int redirectingplan;
- int redirectingpres;
- int redirectingreason;
- int justsignalling;
-+ int nochannelsignalling;
-+ int ccbsnr;
- const char *useruserinfo;
- int transferable;
-+ int ccringout;
- };
-
- /* Internal switch types */
-@@ -202,6 +212,7 @@
-
- int sentchannel;
- int justsignalling; /* for a signalling-only connection */
-+ int nochannelsignalling;
-
- int progcode; /* Progress coding */
- int progloc; /* Progress Location */
-@@ -225,12 +236,19 @@
- char callernum[256];
- char callername[256];
-
-+ int ccoperation; /* QSIG_CCBSREQUEST/QSIG_CCNRREQUEST */
-+ int ccrequestresult;
-+ int cctimer2; /* Timer for QSIG-timer2 */
-+ /* QSIG cc infos (receive) */
-+ struct subcommands subcmds;
-+
- char keypad_digits[64]; /* Buffer for digits that come in KEYPAD_FACILITY */
-
- int ani2; /* ANI II */
-
- int calledplan;
- int nonisdn;
-+ char calledname[256];
- char callednum[256]; /* Called Number */
- int complete; /* no more digits coming */
- int newcall; /* if the received message has a new call reference value */
-@@ -241,6 +259,7 @@
- int redirectingplan;
- int redirectingpres;
- int redirectingreason;
-+ int redirectingcount;
- char redirectingnum[256]; /* Number of redirecting party */
- char redirectingname[256]; /* Name of redirecting party */
-
-@@ -251,6 +270,39 @@
- char origcalledname[256]; /* Original name of person being called */
- char origcallednum[256]; /* Orignal number of person being called */
-
-+ int connectedplan;
-+ int connectedpres;
-+ char connectednum[256];
-+ char connectedname[256];
-+
-+ /* divertingLegInformation1 */
-+ int divleginfo1activeflag;
-+ int divertedtoplan;
-+ int divertedtopres;
-+ int divertedtoreason;
-+ char divertedtonum[256];
-+ int divertedtocount;
-+
-+ /* divertingLegInformation3 */
-+ int divleginfo3activeflag;
-+ char divertedtoname[256];
-+ int divertedstate;
-+
-+ /* callTransferComplete */
-+ int ctcompleteflag;
-+ int ctcompletepres;
-+ int ctcompleteplan;
-+ char ctcompletenum[256];
-+ char ctcompletename[256];
-+ int ctcompletecallstatus;
-+
-+ /* callTransferActive */
-+ int ctactiveflag;
-+ int ctactivepres;
-+ int ctactiveplan;
-+ char ctactivenum[256];
-+ char ctactivename[256];
-+
- int useruserprotocoldisc;
- char useruserinfo[256];
- char callingsubaddr[256]; /* Calling parties sub address */
-Index: q921.c
-===================================================================
---- a/q921.c (.../tags/1.4.9) (revision 700)
-+++ b/q921.c (.../team/group/issue14292) (revision 700)
-@@ -268,12 +268,31 @@
- pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
- }
-
-+static void q921_send_queued_iframes(struct pri *pri)
-+{
-+ struct q921_frame *f;
-+
-+ f = pri->txqueue;
-+ while(f && (pri->windowlen < pri->window)) {
-+ if (!f->transmitted) {
-+ /* Send it now... */
-+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
-+ pri_message(pri, "-- Finally transmitting %d, since window opened up (%d)\n", f->h.n_s, pri->windowlen);
-+ f->transmitted++;
-+ pri->windowlen++;
-+ f->h.n_r = pri->v_r;
-+ f->h.p_f = 0;
-+ q921_transmit(pri, (q921_h *)(&f->h), f->len);
-+ }
-+ f = f->next;
-+ }
-+}
-+
- static pri_event *q921_ack_rx(struct pri *pri, int ack, int send_untransmitted_frames)
- {
- int x;
- int cnt=0;
- pri_event *ev;
-- struct q921_frame *f;
- /* Make sure the ACK was within our window */
- for (x=pri->v_a; (x != pri->v_s) && (x != ack); Q921_INC(x));
- if (x != ack) {
-@@ -309,20 +328,7 @@
- if (!pri->busy && send_untransmitted_frames) {
- pri->retrans = 0;
- /* Search for something to send */
-- f = pri->txqueue;
-- while(f && (pri->windowlen < pri->window)) {
-- if (!f->transmitted) {
-- /* Send it now... */
-- if (pri->debug & PRI_DEBUG_Q921_DUMP)
-- pri_message(pri, "-- Finally transmitting %d, since window opened up (%d)\n", f->h.n_s, pri->windowlen);
-- f->transmitted++;
-- pri->windowlen++;
-- f->h.n_r = pri->v_r;
-- f->h.p_f = 0;
-- q921_transmit(pri, (q921_h *)(&f->h), f->len);
-- }
-- f = f->next;
-- }
-+ q921_send_queued_iframes(pri);
- }
- if (pri->debug & PRI_DEBUG_Q921_DUMP)
- pri_message(pri, "-- Waiting for acknowledge, restarting T200 counter\n");
-@@ -515,7 +521,7 @@
- pri->txqueue = f;
- /* Immediately transmit unless we're in a recovery state, or the window
- size is too big */
-- if (!pri->retrans && !pri->busy) {
-+ if ((pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) && (!pri->retrans && !pri->busy)) {
- if (pri->windowlen < pri->window) {
- pri->windowlen++;
- q921_transmit(pri, (q921_h *)(&f->h), f->len);
-@@ -532,9 +538,14 @@
- pri_schedule_del(pri, pri->t203_timer);
- pri->t203_timer = 0;
- }
-- if (pri->debug & PRI_DEBUG_Q921_DUMP)
-- pri_message(pri, "Starting T_200 timer\n");
-- reschedule_t200(pri);
-+
-+ /* Check this so that we don't try to send frames while multi frame mode is down */
-+ if (pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) {
-+ if (pri->debug & PRI_DEBUG_Q921_DUMP)
-+ pri_message(pri, "Starting T_200 timer\n");
-+
-+ reschedule_t200(pri);
-+ }
- } else {
- pri_error(pri, "!! Out of memory for Q.921 transmit\n");
- return -1;
-@@ -776,9 +787,6 @@
-
- static pri_event *q921_dchannel_up(struct pri *pri)
- {
-- /* Reset counters, etc */
-- q921_reset(pri);
--
- /* Stop any SABME retransmissions */
- if (pri->sabme_timer) {
- pri_schedule_del(pri, pri->sabme_timer);
-@@ -799,6 +807,8 @@
- /* Notify Layer 3 */
- q931_dl_indication(pri, PRI_EVENT_DCHAN_UP);
-
-+ q921_send_queued_iframes(pri);
-+
- /* Report event that D-Channel is now up */
- pri->ev.gen.e = PRI_EVENT_DCHAN_UP;
- return &pri->ev;
-Index: q931.c
-===================================================================
---- a/q931.c (.../tags/1.4.9) (revision 700)
-+++ b/q931.c (.../team/group/issue14292) (revision 700)
-@@ -362,6 +362,11 @@
- /* We are ready to transmit single IE only */
- if (order > 1)
- return 0;
-+
-+ if (call->nochannelsignalling) {
-+ ie->data[pos++] = 0xac;
-+ return pos + 2;
-+ }
-
- if (call->justsignalling) {
- ie->data[pos++] = 0xac; /* Read the standards docs to figure this out
-@@ -804,7 +809,13 @@
- ie->data[1] = 0x90;
- return 4;
- }
--
-+
-+ if (call->nochannelsignalling) {
-+ ie->data[0] = 0xa8;
-+ ie->data[1] = 0x80;
-+ return 4;
-+ }
-+
- if (call->justsignalling) {
- ie->data[0] = 0xa8;
- ie->data[1] = 0x80;
-@@ -992,12 +1003,45 @@
- prefix, ie->data[2] >> 7, redirection_reason2str(ie->data[2] & 0x7f), ie->data[2] & 0x7f);
- break;
- }
-- }
-- while(!(ie->data[i++]& 0x80));
-+ } while(!(ie->data[i++]& 0x80));
- q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
- pri_message(pri, " '%s' ]\n", cnum);
- }
-
-+static FUNC_RECV(receive_connected_number)
-+{
-+ int i = 0;
-+
-+ /* 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 {
-+ switch(i) {
-+ case 0:
-+ call->connectedplan = ie->data[i] & 0x7f;
-+ break;
-+ case 1:
-+ call->connectedpres = ie->data[i] & 0x7f;
-+ break;
-+ }
-+ } while(!(ie->data[i++] & 0x80));
-+ q931_get_number((unsigned char *) call->connectednum, sizeof(call->connectednum), ie->data + i, ie->len - i);
-+
-+ return 0;
-+}
-+
-+static FUNC_SEND(transmit_connected_number)
-+{
-+ int datalen = strlen(call->connectednum);
-+ if (datalen > 0) {
-+ ie->data[0] = call->connectedplan;
-+ ie->data[1] = 0x80 | call->connectedpres;
-+ memcpy(ie->data + 2, call->connectednum, strlen(call->connectednum));
-+ return datalen + 4;
-+ }
-+
-+ return 0;
-+}
-+
- static FUNC_DUMP(dump_connected_number)
- {
- unsigned char cnum[256];
-@@ -1015,8 +1059,7 @@
- prefix, ie->data[1] >> 7, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
- break;
- }
-- }
-- while(!(ie->data[i++]& 0x80));
-+ } while(!(ie->data[i++]& 0x80));
- q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
- pri_message(pri, " '%s' ]\n", cnum);
- }
-@@ -1040,8 +1083,7 @@
- call->redirectingreason = ie->data[i] & 0x0f;
- break;
- }
-- }
-- while(!(ie->data[i++] & 0x80));
-+ } while(!(ie->data[i++] & 0x80));
- q931_get_number((unsigned char *) call->redirectingnum, sizeof(call->redirectingnum), ie->data + i, ie->len - i);
- return 0;
- }
-@@ -2183,7 +2225,7 @@
- { 1, Q931_IE_CALL_STATUS, "Call Status" },
- { 1, Q931_IE_CHANGE_STATUS, "Change Status" },
- { 1, Q931_IE_CONNECTED_ADDR, "Connected Number", dump_connected_number },
-- { 1, Q931_IE_CONNECTED_NUM, "Connected Number", dump_connected_number },
-+ { 1, Q931_IE_CONNECTED_NUM, "Connected Number", dump_connected_number, receive_connected_number, transmit_connected_number },
- { 1, Q931_IE_ORIGINAL_CALLED_NUMBER, "Original Called Number", dump_redirecting_number, receive_redirecting_number, transmit_redirecting_number },
- { 1, Q931_IE_USER_USER_FACILITY, "User-User Facility" },
- { 1, Q931_IE_UPDATE, "Update" },
-@@ -2478,8 +2520,7 @@
- maxlen -= res;
- iet = (q931_ie *)((char *)iet + res);
- }
-- }
-- while (res > 0 && order < ies_count);
-+ } while (res > 0 && order < ies_count);
- if (have_shift && total_res) {
- if (Q931_IE_CODESET(ies[x].ie))
- *codeset = Q931_IE_CODESET(ies[x].ie);
-@@ -2820,9 +2861,9 @@
- return send_message(pri, c, Q931_CALL_PROCEEDING, call_proceeding_ies);
- }
- #ifndef ALERTING_NO_PROGRESS
--static int alerting_ies[] = { Q931_PROGRESS_INDICATOR, Q931_IE_USER_USER, -1 };
-+static int alerting_ies[] = { Q931_PROGRESS_INDICATOR, Q931_IE_USER_USER, Q931_IE_FACILITY, -1 };
- #else
--static int alerting_ies[] = { -1 };
-+static int alerting_ies[] = { Q931_IE_FACILITY, -1 };
- #endif
-
- int q931_alerting(struct pri *pri, q931_call *c, int channel, int info)
-@@ -2841,7 +2882,7 @@
- return send_message(pri, c, Q931_ALERTING, alerting_ies);
- }
-
--static int connect_ies[] = { Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, -1 };
-+static int connect_ies[] = { Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, Q931_IE_CONNECTED_NUM, Q931_IE_FACILITY, -1 };
-
- int q931_setup_ack(struct pri *pri, q931_call *c, int channel, int nonisdn)
- {
-@@ -2923,6 +2964,18 @@
- q931_release(pri, c, PRI_CAUSE_NORMAL_CLEARING);
- }
-
-+static void pri_cctimer2_timeout(void *data)
-+{
-+ int cause = 16;
-+ struct q931_call *c = data;
-+ struct pri *pri = c->pri;
-+ if (pri->debug & PRI_DEBUG_Q931_STATE)
-+ pri_message(pri, "Timed out no-channel call\n");
-+ c->ccoperation = QSIG_CC_CANCEL;
-+ /* normal clear cause */
-+ q931_hangup(pri, c, cause);
-+}
-+
- int q931_connect(struct pri *pri, q931_call *c, int channel, int nonisdn)
- {
- if (channel) {
-@@ -2954,7 +3007,7 @@
- return send_message(pri, c, Q931_CONNECT, connect_ies);
- }
-
--static int release_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, -1 };
-+static int release_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, Q931_IE_FACILITY, -1 };
-
- int q931_release(struct pri *pri, q931_call *c, int cause)
- {
-@@ -3002,7 +3055,7 @@
- return send_message(pri, c, Q931_RESTART, restart_ies);
- }
-
--static int disconnect_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, -1 };
-+static int disconnect_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, Q931_IE_FACILITY, -1 };
-
- int q931_disconnect(struct pri *pri, q931_call *c, int cause)
- {
-@@ -3030,6 +3083,8 @@
-
- static int cis_setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_CALLED_PARTY_NUMBER, -1 };
-
-+static int nochannel_setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_SENDING_COMPLETE, -1 };
-+
- int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
- {
- int res;
-@@ -3055,6 +3110,7 @@
- c->nonisdn = req->nonisdn;
- c->newcall = 0;
- c->justsignalling = req->justsignalling;
-+ c->nochannelsignalling = req->nochannelsignalling;
- c->complete = req->numcomplete;
- if (req->exclusive)
- c->chanflags = FLAG_EXCLUSIVE;
-@@ -3082,6 +3138,10 @@
- }
- if (req->redirectingnum) {
- libpri_copy_string(c->redirectingnum, req->redirectingnum, sizeof(c->redirectingnum));
-+ if (req->redirectingname)
-+ libpri_copy_string(c->redirectingname, req->redirectingname, sizeof(c->redirectingname));
-+ else
-+ c->redirectingname[0] = '\0';
- c->redirectingplan = req->redirectingplan;
- if ((pri->switchtype == PRI_SWITCH_DMS100) ||
- (pri->switchtype == PRI_SWITCH_ATT4ESS)) {
-@@ -3092,6 +3152,7 @@
- c->redirectingpres = req->redirectingpres;
- c->redirectingreason = req->redirectingreason;
- } else {
-+ c->redirectingname[0] = '\0';
- c->redirectingnum[0] = '\0';
- c->redirectingplan = PRI_UNKNOWN;
- c->redirectingpres = PRES_NUMBER_NOT_AVAILABLE;
-@@ -3113,12 +3174,19 @@
- else
- c->progressmask = 0;
-
-+ if (req->ccringout)
-+ c->ccoperation = QSIG_CC_RINGOUT;
-+ if (req->ccbsnr)
-+ c->ccoperation = req->ccbsnr;
-+
- pri_call_add_standard_apdus(pri, c);
-
- if (pri->subchannel && !pri->bri)
- res = send_message(pri, c, Q931_SETUP, gr303_setup_ies);
- else if (c->justsignalling)
- res = send_message(pri, c, Q931_SETUP, cis_setup_ies);
-+ else if (c->nochannelsignalling)
-+ res = send_message(pri, c, Q931_SETUP, nochannel_setup_ies);
- else
- res = send_message(pri, c, Q931_SETUP, setup_ies);
- if (!res) {
-@@ -3132,7 +3200,7 @@
-
- }
-
--static int release_complete_ies[] = { Q931_IE_USER_USER, -1 };
-+static int release_complete_ies[] = { Q931_IE_USER_USER, Q931_IE_FACILITY, -1 };
-
- static int q931_release_complete(struct pri *pri, q931_call *c, int cause)
- {
-@@ -3187,6 +3255,18 @@
- /* We'll send RELEASE with these causes */
- disconnect = 0;
- }
-+ if (c->nochannelsignalling) {
-+ if (c->ccoperation == QSIG_CC_CANCEL) {
-+ add_qsigCcInv_facility_ie(pri, c, Q931_RELEASE);
-+ }
-+ if (c->cctimer2) {
-+ pri_schedule_del(pri, c->cctimer2);
-+ c->cctimer2 = 0;
-+ pri_message(pri, "NEW_HANGUP DEBUG: stop CC-Timer2\n");
-+ }
-+ disconnect = 0;
-+ }
-+
- /* All other causes we send with DISCONNECT */
- switch(c->ourcallstate) {
- case Q931_CALL_STATE_NULL:
-@@ -3227,6 +3307,10 @@
- break;
- case Q931_CALL_STATE_ACTIVE:
- /* received CONNECT */
-+ if (c->nochannelsignalling) {
-+ q931_release(pri,c,cause);
-+ break;
-+ }
- q931_disconnect(pri,c,cause);
- break;
- case Q931_CALL_STATE_DISCONNECT_REQUEST:
-@@ -3260,6 +3344,132 @@
- return 0;
- }
-
-+static void clr_subcommands(struct subcommands *sub)
-+{
-+ sub->counter_subcmd = 0;
-+}
-+
-+static struct subcommand *get_ptr_subcommand(struct subcommands *sub)
-+{
-+ if (sub->counter_subcmd < MAX_SUBCOMMANDS) {
-+ int count = sub->counter_subcmd;
-+ sub->counter_subcmd++;
-+ return &sub->subcmd[count];
-+ }
-+
-+ return NULL;
-+}
-+
-+static struct subcommand *get_ptr_q931_subcommand_by_index(struct subcommands *sub, int index)
-+{
-+ if (index < MAX_SUBCOMMANDS) {
-+ sub->counter_subcmd--;
-+ return &sub->subcmd[index];
-+ }
-+
-+ return NULL;
-+}
-+
-+static int q931_facilities2eventfacilities(struct pri *pri, q931_call *c, struct subcommands *subcmds)
-+{
-+ int facilitypos;
-+ int facility_number;
-+ struct subcommand *c_subcmd;
-+ struct subcommand *e_subcmd;
-+
-+ if (c->subcmds.counter_subcmd) {
-+ facility_number = c->subcmds.counter_subcmd;
-+
-+ for (facilitypos = 0; facilitypos < facility_number; facilitypos++) {
-+ c->subcmds.counter_subcmd--;
-+ c_subcmd = get_ptr_q931_subcommand_by_index(&c->subcmds, facilitypos);
-+ e_subcmd = get_ptr_subcommand(subcmds);
-+ if (c_subcmd && e_subcmd) {
-+ switch (c_subcmd->cmd) {
-+ case CMD_CC_CCBSREQUEST_RR:
-+ e_subcmd->cmd = c_subcmd->cmd;
-+ memcpy(&c_subcmd->cc_ccbs_rr, &e_subcmd->cc_ccbs_rr, sizeof(c_subcmd->cc_ccbs_rr));
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "facility(QSIG_CC_CCBSREQUEST) (%d/%d)\n",
-+ e_subcmd->cc_ccbs_rr.cc_request_res.no_path_reservation,
-+ e_subcmd->cc_ccbs_rr.cc_request_res.retain_service);
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "counter_subcmd(%d)\n", subcmds->counter_subcmd);
-+ c->ccrequestresult = 1;
-+ break;
-+ case CMD_CC_CCNRREQUEST_RR:
-+ e_subcmd->cmd = c_subcmd->cmd;
-+ memcpy(&c_subcmd->cc_ccnr_rr, &e_subcmd->cc_ccnr_rr, sizeof(c_subcmd->cc_ccnr_rr));
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "facility(QSIG_CC_CCNRREQUEST) (%d/%d)\n",
-+ e_subcmd->cc_ccnr_rr.cc_request_res.no_path_reservation,
-+ e_subcmd->cc_ccnr_rr.cc_request_res.retain_service);
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "counter_subcmd(%d)\n", subcmds->counter_subcmd);
-+ c->ccrequestresult = 1;
-+ break;
-+ case CMD_CC_CANCEL_INV:
-+ e_subcmd->cmd = c_subcmd->cmd;
-+ memcpy(&c_subcmd->cc_cancel_inv, &e_subcmd->cc_cancel_inv, sizeof(c_subcmd->cc_cancel_inv));
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "facility(QSIG_CC_CANCEL) (%s/%s)\n",
-+ e_subcmd->cc_cancel_inv.cc_optional_arg.number_A,
-+ e_subcmd->cc_cancel_inv.cc_optional_arg.number_B);
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "counter_subcmd(%d)\n", subcmds->counter_subcmd);
-+ break;
-+ case CMD_CC_EXECPOSIBLE_INV:
-+ e_subcmd->cmd = c_subcmd->cmd;
-+ memcpy(&c_subcmd->cc_execposible_inv, &e_subcmd->cc_execposible_inv, sizeof(c_subcmd->cc_execposible_inv));
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "facility(QSIG_CC_EXECPOSIBLE) (%s/%s)\n",
-+ e_subcmd->cc_execposible_inv.cc_optional_arg.number_A,
-+ e_subcmd->cc_execposible_inv.cc_optional_arg.number_B);
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "counter_subcmd(%d)\n", subcmds->counter_subcmd);
-+ break;
-+ case CMD_CC_RINGOUT_INV:
-+ e_subcmd->cmd = c_subcmd->cmd;
-+ memcpy(&c_subcmd->cc_ringout_inv, &e_subcmd->cc_ringout_inv, sizeof(c_subcmd->cc_ringout_inv));
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "facility(QSIG_CC_RINGOUT) (%d)\n",
-+ e_subcmd->cc_ringout_inv.cc_extension.cc_extension_tag);
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "counter_subcmd(%d)\n", subcmds->counter_subcmd);
-+ break;
-+ case CMD_CC_SUSPEND_INV:
-+ e_subcmd->cmd = c_subcmd->cmd;
-+ memcpy(&c_subcmd->cc_suspend_inv, &e_subcmd->cc_suspend_inv, sizeof(c_subcmd->cc_suspend_inv));
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "facility(QSIG_CC_SUSPEND) (%d)\n",
-+ e_subcmd->cc_suspend_inv.cc_extension.cc_extension_tag);
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "counter_subcmd(%d)\n", subcmds->counter_subcmd);
-+ break;
-+ case CMD_CC_ERROR:
-+ e_subcmd->cmd = c_subcmd->cmd;
-+ memcpy(&c_subcmd->cc_error, &e_subcmd->cc_error, sizeof(c_subcmd->cc_error));
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "facility(QSIG_CC_ERROR) (%d)\n",
-+ e_subcmd->cc_error.error_value);
-+ if (pri->debug & PRI_DEBUG_APDU)
-+ pri_message(pri, "counter_subcmd(%d)\n", subcmds->counter_subcmd);
-+ break;
-+ default:
-+ pri_error(pri, "Don't know how to handle Facility subcmd %d\n", c_subcmd->cmd);
-+ break;
-+ }
-+ }
-+ }
-+#if 0
-+ } else {
-+ pri_message(pri, "No facilities specified\n");
-+#endif
-+ }
-+ return 0;
-+}
-+
-+
- int q931_receive(struct pri *pri, q931_h *h, int len)
- {
- q931_mh *mh;
-@@ -3312,6 +3522,7 @@
- break;
- case Q931_FACILITY:
- c->callername[0] = '\0';
-+ c->subcmds.counter_subcmd = 0;
- break;
- case Q931_SETUP:
- if (pri->debug & PRI_DEBUG_Q931_STATE)
-@@ -3339,6 +3550,7 @@
- c->redirectingplan = -1;
- c->redirectingpres = -1;
- c->redirectingreason = -1;
-+ c->redirectingcount = 0;
- c->origcalledplan = -1;
- c->origcalledpres = -1;
- c->origredirectingreason = -1;
-@@ -3346,6 +3558,29 @@
- c->origcallednum[0] = '\0';
- c->redirectingname[0] = '\0';
- c->origcalledname[0] = '\0';
-+ c->connectedplan = -1;
-+ c->connectedpres = -1;
-+ c->connectednum[0] = '\0';
-+ c->connectedname[0] = '\0';
-+ c->divleginfo1activeflag = 0;
-+ c->divertedtocount = 0;
-+ c->divertedtoplan = -1;
-+ c->divertedtopres = -1;
-+ c->divertedtoreason = -1;
-+ c->divertedtonum[0] = '\0';
-+ c->divleginfo3activeflag = 0;
-+ c->divertedtoname[0] = '\0';
-+ c->divertedstate = DIVERTEDSTATE_NONE;
-+ c->ctcompleteflag = 0;
-+ c->ctcompleteplan = -1;
-+ c->ctcompletepres = -1;
-+ c->ctcompletenum[0] = '\0';
-+ c->ctcompletename[0] = '\0';
-+ c->ctactiveflag = 0;
-+ c->ctactiveplan = -1;
-+ c->ctactivepres = -1;
-+ c->ctactivenum[0] = '\0';
-+ c->ctactivename[0] = '\0';
- c->useruserprotocoldisc = -1;
- c->useruserinfo[0] = '\0';
- c->complete = 0;
-@@ -3353,7 +3588,9 @@
- c->aoc_units = -1;
- /* Fall through */
- case Q931_CONNECT:
-+ c->ccrequestresult = 0;
- case Q931_ALERTING:
-+ c->subcmds.counter_subcmd = 0;
- case Q931_PROGRESS:
- c->useruserinfo[0] = '\0';
- c->cause = -1;
-@@ -3369,6 +3606,7 @@
- break;
- case Q931_RELEASE:
- case Q931_DISCONNECT:
-+ c->subcmds.counter_subcmd = 0;
- c->cause = -1;
- c->causecode = -1;
- c->causeloc = -1;
-@@ -3383,6 +3621,7 @@
- pri_schedule_del(pri, c->retranstimer);
- c->retranstimer = 0;
- c->useruserinfo[0] = '\0';
-+ c->subcmds.counter_subcmd = 0;
- /* Fall through */
- case Q931_STATUS:
- c->cause = -1;
-@@ -3539,6 +3778,9 @@
- if (!c->newcall) {
- break;
- }
-+
-+ clr_subcommands(&pri->ev.ring.subcmds);
-+
- if (c->progressmask & PRI_PROG_CALLER_NOT_ISDN)
- c->nonisdn = 1;
- c->newcall = 0;
-@@ -3570,7 +3812,9 @@
- libpri_copy_string(pri->ev.ring.redirectingname, c->redirectingname, sizeof(pri->ev.ring.redirectingname));
- libpri_copy_string(pri->ev.ring.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo));
- c->useruserinfo[0] = '\0';
-+ pri->ev.ring.redirectingpres = c->redirectingpres;
- pri->ev.ring.redirectingreason = c->redirectingreason;
-+ pri->ev.ring.redirectingcount = c->redirectingcount;
- pri->ev.ring.origredirectingreason = c->origredirectingreason;
- pri->ev.ring.flexible = ! (c->chanflags & FLAG_EXCLUSIVE);
- pri->ev.ring.cref = c->cr;
-@@ -3578,15 +3822,21 @@
- pri->ev.ring.layer1 = c->userl1;
- pri->ev.ring.complete = c->complete;
- pri->ev.ring.ctype = c->transcapability;
-- pri->ev.ring.redirectingreason = c->redirectingreason;
- pri->ev.ring.progress = c->progress;
- pri->ev.ring.progressmask = c->progressmask;
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "Sending ring event (%d) nochannelsignalling (%d) facility_number (%d)\n",
-+ pri->ev.ring.cref, c->nochannelsignalling, pri->ev.ring.subcmds.counter_subcmd);
-+ }
-+ q931_facilities2eventfacilities(pri, c, &pri->ev.ring.subcmds);
- return Q931_RES_HAVEEVENT;
- case Q931_ALERTING:
- if (c->newcall) {
- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
- break;
- }
-+ clr_subcommands(&pri->ev.ringing.subcmds);
-+
- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_CALL_DELIVERED);
- c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED;
- pri->ev.e = PRI_EVENT_RINGING;
-@@ -3595,8 +3845,26 @@
- pri->ev.ringing.call = c;
- pri->ev.ringing.progress = c->progress;
- pri->ev.ringing.progressmask = c->progressmask;
-+
-+ if (c->divleginfo3activeflag) {
-+ c->divleginfo3activeflag = 0;
-+ libpri_copy_string(pri->ev.ringing.calledname, c->divertedtoname, sizeof(pri->ev.ringing.calledname));
-+ libpri_copy_string(pri->ev.ringing.callednum, (c->divertedtonum[0]) ? c->divertedtonum : c->callednum, sizeof(pri->ev.ringing.callednum));
-+ pri->ev.ringing.calledpres = c->divertedtopres;
-+ pri->ev.ringing.calledplan = c->divertedtoplan;
-+ } else {
-+ libpri_copy_string(pri->ev.ringing.calledname, c->calledname, sizeof(pri->ev.ringing.calledname));
-+ libpri_copy_string(pri->ev.ringing.callednum, (c->divertedtonum[0]) ? c->divertedtonum : c->callednum, sizeof(pri->ev.ringing.callednum));
-+ pri->ev.ringing.calledpres = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
-+ pri->ev.ringing.calledplan = c->calledplan;
-+ }
- libpri_copy_string(pri->ev.ringing.useruserinfo, c->useruserinfo, sizeof(pri->ev.ringing.useruserinfo));
- c->useruserinfo[0] = '\0';
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "Sending ringing event (%d) nochannelsignalling (%d) facility_number (%d)\n",
-+ pri->ev.ringing.cref, c->nochannelsignalling, pri->ev.ringing.subcmds.counter_subcmd);
-+ }
-+ q931_facilities2eventfacilities(pri, c, &pri->ev.ringing.subcmds);
-
- cur = c->apdus;
- while (cur) {
-@@ -3617,6 +3885,8 @@
- q931_status(pri, c, PRI_CAUSE_WRONG_MESSAGE);
- break;
- }
-+ clr_subcommands(&pri->ev.answer.subcmds);
-+
- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_ACTIVE);
- c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST;
- pri->ev.e = PRI_EVENT_ANSWER;
-@@ -3625,31 +3895,166 @@
- pri->ev.answer.call = c;
- pri->ev.answer.progress = c->progress;
- pri->ev.answer.progressmask = c->progressmask;
-+ libpri_copy_string(pri->ev.answer.connectednum, c->connectednum, sizeof(pri->ev.answer.connectednum));
-+ libpri_copy_string(pri->ev.answer.connectedname, c->connectedname, sizeof(pri->ev.answer.connectedname));
-+ pri->ev.answer.connectedpres = c->connectedpres;
-+ pri->ev.answer.connectedplan = c->connectedplan;
-+ pri->ev.answer.source = PRI_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
- libpri_copy_string(pri->ev.answer.useruserinfo, c->useruserinfo, sizeof(pri->ev.answer.useruserinfo));
- c->useruserinfo[0] = '\0';
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "Sending answer event (%d) nochannelsignalling (%d) facility_number (%d)\n",
-+ pri->ev.answer.cref, c->nochannelsignalling, pri->ev.answer.subcmds.counter_subcmd);
-+ }
-+ q931_facilities2eventfacilities(pri, c, &pri->ev.answer.subcmds);
- q931_connect_acknowledge(pri, c);
-+ if (c->nochannelsignalling) {
-+ if (c->ccrequestresult) {
-+ pri_message(pri, "Q931_CONNECT: start CC-Timer2\n");
-+ c->cctimer2 = pri_schedule_event(pri, pri->timers[PRI_TIMER_CCBST2], pri_cctimer2_timeout, c);
-+ }
-+ return Q931_RES_HAVEEVENT;
-+ }
- if (c->justsignalling) { /* Make sure WE release when we initiatie a signalling only connection */
- q931_release(pri, c, PRI_CAUSE_NORMAL_CLEARING);
- break;
- } else
- return Q931_RES_HAVEEVENT;
- case Q931_FACILITY:
-- if (c->newcall) {
-- q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-- break;
-+ {
-+ int haveevent = 0;
-+ clr_subcommands(&pri->ev.facility.subcmds);
-+
-+ if (c->newcall) {
-+ q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-+ break;
-+ }
-+ if (c->subcmds.counter_subcmd) {
-+ pri->ev.e = PRI_EVENT_FACILITY;
-+ pri->ev.facility.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-+ pri->ev.facility.cref = c->cr;
-+ pri->ev.facility.call = c;
-+
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "Sending facility event (%d) nochannelsignalling (%d) facility_number (%d)\n",
-+ pri->ev.facility.cref, c->nochannelsignalling, pri->ev.facility.subcmds.counter_subcmd);
-+ }
-+ q931_facilities2eventfacilities(pri, c, &pri->ev.facility.subcmds);
-+ haveevent = 1;
-+ }
-+ if (c->ctcompleteflag) {
-+ c->ctcompleteflag = 0;
-+
-+ if (c->ctcompletecallstatus == 0) {
-+ /* answered(0) */
-+ struct subcommand *subcmd;
-+
-+ pri_message(pri, "Got CT-Complete, callStatus = answered(0)\n");
-+ pri->ev.e = PRI_EVENT_FACILITY;
-+ pri->ev.facility.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-+ pri->ev.facility.call = c;
-+
-+ subcmd = get_ptr_subcommand(&pri->ev.facility.subcmds);
-+ if (subcmd) {
-+ struct cmd_connectedline *cmdcl = &subcmd->connectedline;
-+
-+ subcmd->cmd = CMD_CONNECTEDLINE;
-+ libpri_copy_string(cmdcl->connected.id.number, c->ctcompletenum, sizeof(cmdcl->connected.id.number));
-+ libpri_copy_string(cmdcl->connected.id.name, c->ctcompletename, sizeof(cmdcl->connected.id.name));
-+ cmdcl->connected.id.number_type = c->ctcompleteplan;
-+ cmdcl->connected.id.number_presentation = c->ctcompletepres;
-+ cmdcl->connected.source = PRI_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
-+ haveevent = 1;
-+ pri_message(pri, "CT-Complete, sending facility/CMD_CONNECTEDLINE (%s/%s)\n", cmdcl->connected.id.name, cmdcl->connected.id.number);
-+ }
-+ } else if (c->ctcompletecallstatus == 1) {
-+ /* alerting(1) */
-+ struct subcommand *subcmd;
-+
-+ pri_message(pri, "Got CT-Complete, callStatus = alerting(1)\n");
-+ pri->ev.e = PRI_EVENT_FACILITY;
-+ pri->ev.facility.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-+ pri->ev.facility.call = c;
-+
-+ subcmd = get_ptr_subcommand(&pri->ev.facility.subcmds);
-+ if (subcmd) {
-+ struct cmd_redirecting *cmdr = &subcmd->redirecting;
-+
-+ subcmd->cmd = CMD_REDIRECTING;
-+ libpri_copy_string(cmdr->redirecting.from.number, c->connectednum, sizeof(cmdr->redirecting.from.number));
-+ libpri_copy_string(cmdr->redirecting.from.name, c->connectedname, sizeof(cmdr->redirecting.from.name));
-+ cmdr->redirecting.from.number_type = c->connectedplan;
-+ cmdr->redirecting.from.number_presentation = c->connectedpres;
-+ libpri_copy_string(cmdr->redirecting.to.number, c->ctcompletenum, sizeof(cmdr->redirecting.to.number));
-+ libpri_copy_string(cmdr->redirecting.to.name, c->ctcompletename, sizeof(cmdr->redirecting.to.name));
-+ cmdr->redirecting.to.number_type = c->ctcompleteplan;
-+ cmdr->redirecting.to.number_presentation = c->ctcompletepres;
-+ cmdr->redirecting.count = 0;
-+ cmdr->redirecting.reason = PRI_REDIR_UNKNOWN;
-+ haveevent = 1;
-+ pri_message(pri, "CT-Complete, sending facility/CMD_REDIRECTING (%s/%s)\n", cmdr->redirecting.to.name, cmdr->redirecting.to.number);
-+ }
-+ } else {
-+ pri_message(pri, "illegal value for callStatus=%d\n", c->ctcompletecallstatus);
-+ }
-+ } else if (c->ctactiveflag) {
-+ struct subcommand *subcmd;
-+
-+ c->ctactiveflag = 0;
-+
-+ pri_message(pri, "Got CT-Active\n");
-+ pri->ev.e = PRI_EVENT_FACILITY;
-+ pri->ev.facility.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-+ pri->ev.facility.call = c;
-+
-+ subcmd = get_ptr_subcommand(&pri->ev.facility.subcmds);
-+ if (subcmd) {
-+ struct cmd_connectedline *cmdcl = &subcmd->connectedline;
-+
-+ subcmd->cmd = CMD_CONNECTEDLINE;
-+ libpri_copy_string(cmdcl->connected.id.number, c->ctcompletenum, sizeof(cmdcl->connected.id.number));
-+ libpri_copy_string(cmdcl->connected.id.name, c->ctcompletename, sizeof(cmdcl->connected.id.name));
-+ cmdcl->connected.id.number_type = c->ctcompleteplan;
-+ cmdcl->connected.id.number_presentation = c->ctcompletepres;
-+ cmdcl->connected.source = PRI_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
-+ haveevent = 1;
-+ pri_message(pri, "CT-Active, sending facility CMD_CONNECTEDLINE (%s/%s)\n", cmdcl->connected.id.name, cmdcl->connected.id.number);
-+ }
-+ }
-+ else if (c->divleginfo1activeflag) {
-+ struct subcommand *subcmd;
-+
-+ c->divleginfo1activeflag = 0;
-+
-+ pri_message(pri, "Got DivertingLegInformation1\n");
-+ pri->ev.e = PRI_EVENT_FACILITY;
-+ pri->ev.facility.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-+ pri->ev.facility.call = c;
-+
-+ subcmd = get_ptr_subcommand(&pri->ev.facility.subcmds);
-+ if (subcmd) {
-+ struct cmd_redirecting *cmdr = &subcmd->redirecting;
-+
-+ subcmd->cmd = CMD_REDIRECTING;
-+ libpri_copy_string(cmdr->redirecting.from.number, c->callednum, sizeof(cmdr->redirecting.from.number));
-+ cmdr->redirecting.from.name[0] = '\0';
-+ cmdr->redirecting.from.number_type = c->calledplan;
-+ cmdr->redirecting.from.number_presentation = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
-+ libpri_copy_string(cmdr->redirecting.to.number, c->divertedtonum, sizeof(cmdr->redirecting.to.number));
-+ cmdr->redirecting.to.name[0] = '\0';
-+ cmdr->redirecting.to.number_type = c->divertedtoplan;
-+ cmdr->redirecting.to.number_presentation = c->divertedtopres;
-+ cmdr->redirecting.count = c->divertedtocount;
-+ cmdr->redirecting.reason = c->divertedtoreason;
-+ haveevent = 1;
-+ pri_message(pri, "DivertingLegInformation1, sending facility/CMD_REDIRECTING (%s/%s)\n", cmdr->redirecting.to.name, cmdr->redirecting.to.number);
-+ }
-+ }
-+
-+ if (haveevent)
-+ return Q931_RES_HAVEEVENT;
- }
-- pri->ev.e = PRI_EVENT_FACNAME;
-- libpri_copy_string(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname));
-- libpri_copy_string(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingnum));
-- pri->ev.facname.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-- pri->ev.facname.callingpres = c->callerpres;
-- pri->ev.facname.callingplan = c->callerplan;
-- pri->ev.facname.cref = c->cr;
-- pri->ev.facname.call = c;
--#if 0
-- pri_message(pri, "Sending facility event (%s/%s)\n", pri->ev.facname.callingname, pri->ev.facname.callingnum);
--#endif
-- return Q931_RES_HAVEEVENT;
-+ break;
- case Q931_PROGRESS:
- if (missingmand) {
- q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
-@@ -3757,6 +4162,8 @@
- }
- break;
- case Q931_RELEASE_COMPLETE:
-+ clr_subcommands(&pri->ev.hangup.subcmds);
-+
- UPDATE_OURCALLSTATE(pri, c, Q931_CALL_STATE_NULL);
- c->peercallstate = Q931_CALL_STATE_NULL;
- pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
-@@ -3766,6 +4173,11 @@
- pri->ev.hangup.aoc_units = c->aoc_units;
- libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
- c->useruserinfo[0] = '\0';
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "Sending hangup event (%d) nochannelsignalling (%d) facility_number (%d)\n",
-+ pri->ev.hangup.cref, c->nochannelsignalling, pri->ev.hangup.subcmds.counter_subcmd);
-+ }
-+ q931_facilities2eventfacilities(pri, c, &pri->ev.hangup.subcmds);
- /* Free resources */
- if (c->alive) {
- pri->ev.e = PRI_EVENT_HANGUP;
-@@ -3783,6 +4195,8 @@
- q931_hangup(pri,c,c->cause);
- break;
- case Q931_RELEASE:
-+ clr_subcommands(&pri->ev.hangup.subcmds);
-+
- if (missingmand) {
- /* Force cause to be mandatory IE missing */
- c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
-@@ -3801,6 +4215,11 @@
- pri->ev.hangup.aoc_units = c->aoc_units;
- libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
- c->useruserinfo[0] = '\0';
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "Sending hangup event (%d) nochannelsignalling (%d) facility_number (%d)\n",
-+ pri->ev.hangup.cref, c->nochannelsignalling, pri->ev.hangup.subcmds.counter_subcmd);
-+ }
-+ q931_facilities2eventfacilities(pri, c, &pri->ev.hangup.subcmds);
- /* Don't send release complete if they send us release
- while we sent it, assume a NULL state */
- if (c->newcall)
-@@ -3809,6 +4228,8 @@
- return Q931_RES_HAVEEVENT;
- break;
- case Q931_DISCONNECT:
-+ clr_subcommands(&pri->ev.hangup.subcmds);
-+
- if (missingmand) {
- /* Still let user call release */
- c->cause = PRI_CAUSE_MANDATORY_IE_MISSING;
-@@ -3835,6 +4256,11 @@
- pri->ev.hangup.aoc_units = c->aoc_units;
- libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.hangup.useruserinfo));
- c->useruserinfo[0] = '\0';
-+ if (pri->debug & PRI_DEBUG_APDU) {
-+ pri_message(pri, "Sending hangup event (%d) nochannelsignalling (%d) facility_number (%d)\n",
-+ pri->ev.hangup.cref, c->nochannelsignalling, pri->ev.hangup.subcmds.counter_subcmd);
-+ }
-+ q931_facilities2eventfacilities(pri, c, &pri->ev.hangup.subcmds);
- if (c->alive)
- return Q931_RES_HAVEEVENT;
- else
-
-Property changes on: .
-___________________________________________________________________
-Added: automerge
- + *
-Added: automerge-propname
- + issue14292-integrated
-Added: svnmerge-integrated
- + /branches/1.4:1-688
-Added: automerge-email
- + rmudgett@digium.com
-Added: issue14292-integrated
- + /team/group/issue14068:1-699
-