diff options
author | Timo Teras <timo.teras@iki.fi> | 2009-11-28 02:49:14 +0200 |
---|---|---|
committer | Timo Teras <timo.teras@iki.fi> | 2009-11-28 02:50:34 +0200 |
commit | bf4a081b091fc26e782bb24c786ae5ceb0577fb3 (patch) | |
tree | 872c7b04573804463a6fe5dfa00dc58d6a68a899 /main/libpri/libpri-1.4.9-i14292.patch | |
parent | 25668b00edf92d80fc2f15691948b659a4ac3b59 (diff) | |
download | aports-bf4a081b091fc26e782bb24c786ae5ceb0577fb3.tar.bz2 aports-bf4a081b091fc26e782bb24c786ae5ceb0577fb3.tar.xz |
main/libpri: upgrade to latest svn snapshot
Diffstat (limited to 'main/libpri/libpri-1.4.9-i14292.patch')
-rw-r--r-- | main/libpri/libpri-1.4.9-i14292.patch | 5668 |
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 27ed1b8d4..000000000 --- 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 - |