Index: pri_facility.c =================================================================== --- pri_facility.c (revision 400) +++ pri_facility.c (working copy) @@ -167,11 +167,20 @@ struct addressingdataelements_presentednumberunscreened { char partyaddress[21]; char partysubaddress[21]; - int npi; - int ton; - int pres; + int npi; /* Numbering Plan Indicator */ + int ton; /* Type Of Number */ + int pres; /* Presentation */ }; +struct addressingdataelements_presentednumberscreened { + char partyaddress[21]; + char partysubaddress[21]; + int npi; /* Numbering Plan Indicator */ + int ton; /* Type Of Number */ + int pres; /* Presentation */ + int scrind; /* Screening Indicator */ +}; + #define PRI_CHECKOVERFLOW(size) \ if (msgptr - message + (size) >= sizeof(message)) { \ *msgptr = '\0'; \ @@ -453,6 +462,35 @@ return -1; } +static int rose_private_party_number_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value) +{ + int i = 0; + struct rose_component *comp = NULL; + unsigned char *vdata = data; + int ton; + int res = 0; + + if (len < 2) + return -1; + + do { + 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); + if (res < 0) + return -1; + value->ton = ton; + + return res + 3; + + } while(0); + return -1; +} + static int rose_address_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value) { int i = 0; @@ -503,9 +541,11 @@ pri_message(pri, "!! telexPartyNumber isn't handled\n"); return -1; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] priavePartyNumber */ - pri_message(pri, "!! privatePartyNumber isn't handled\n"); + res = rose_private_party_number_decode(pri, call, comp->data, comp->len, value); + if (res < 0) + return -1; value->npi = PRI_NPI_PRIVATE; - return -1; + break; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_8): /* [8] nationalStandardPartyNumber */ res = rose_number_digits_decode(pri, call, comp->data, comp->len, value); if (res < 0) @@ -589,6 +629,8 @@ struct rose_component *comp = NULL; unsigned char *vdata = sequence->data; int res = 0; + memset(&divertingnr, 0, sizeof(divertingnr)); + memset(&originalcallednr, 0, sizeof(originalcallednr)); /* Data checks */ if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */ @@ -670,6 +712,9 @@ if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, " Received Originally Called Name '%s'\n", origcalledname); break; + case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): + pri_message(pri, "!! Ignoring DivertingLegInformation2 component 0x%X\n", comp->type); + break; default: if (comp->type == 0 && comp->len == 0) { break; /* Found termination characters */ @@ -684,11 +729,13 @@ 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->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)); @@ -1348,6 +1395,434 @@ } /* End AOC */ +/* ===== 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; + + + do { + GET_COMPONENT(comp, i, vdata, len); + + 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; + + 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; + + 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); + if (size < 0) + return -1; + value->npi = PRI_NPI_X121 /* ??? */; + value->ton = PRI_TON_UNKNOWN /* ??? */; + 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); + 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, call, comp->data, comp->len, value); + if (size < 0) + return -1; + value->npi = PRI_NPI_PRIVATE; + 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; + 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_number_screened_decode(struct pri *pri, q931_call *call, 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, call, (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, q931_call *call, 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->ton = PRI_TON_UNKNOWN; + value->npi = PRI_NPI_UNKNOWN; + value->pres = -1; /* Data is not available */ + + 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, call, 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, call, 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_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 = 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; + 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"); + 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-Complete: 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); + 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); + + +#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)); + 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); + + + /* Call Status */ + 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); + + + /* 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); + 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); + + return 0; + } + while (0); + + return -1; +} + + +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; + + 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; + + + /* Data checks */ + if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */ + pri_message(pri, "Invalid callTransferComplete 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-Complete: 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); + + /* 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); + + +#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 + + + /* 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); + 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); + + return 0; + } + while (0); + + return -1; +} + + +/* ===== End Call Transfer Supplementary Service (ECMA-178) ===== */ + + + int rose_reject_decode(struct pri *pri, q931_call *call, unsigned char *data, int len) { int i = 0; @@ -1595,6 +2070,50 @@ return -1; } break; + 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); + 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); + 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, " Handle DivertingLegInformation2\n"); Index: pri_facility.h =================================================================== --- pri_facility.h (revision 400) +++ pri_facility.h (working copy) @@ -32,6 +32,15 @@ #define COMP_TYPE_NFE 0xAA /* Operation ID values */ +/* Q.952.7 (ECMA-178) ROSE operations (Transfer) */ +#define ROSE_CALL_TRANSFER_IDENTIFY 7 +#define ROSE_CALL_TRANSFER_ABANDON 8 +#define ROSE_CALL_TRANSFER_INITIATE 9 +#define ROSE_CALL_TRANSFER_SETUP 10 +#define ROSE_CALL_TRANSFER_ACTIVE 11 +#define ROSE_CALL_TRANSFER_COMPLETE 12 +#define ROSE_CALL_TRANSFER_UPDATE 13 +#define ROSE_SUBADDRESS_TRANSFER 14 /* Q.952 ROSE operations (Diverting) */ #define ROSE_DIVERTING_LEG_INFORMATION1 18 #define ROSE_DIVERTING_LEG_INFORMATION2 0x15 @@ -146,7 +155,8 @@ u_int8_t data[0]; }; -#define GET_COMPONENT(component, idx, ptr, length) \ +#if 1 + #define GET_COMPONENT(component, idx, ptr, length) \ if ((idx)+2 > (length)) \ break; \ (component) = (struct rose_component*)&((ptr)[idx]); \ @@ -154,16 +164,24 @@ if ((component)->len != ASN1_LEN_INDEF) \ pri_message(pri, "Length (%d) of 0x%X component is too long\n", (component)->len, (component)->type); \ } -/* - pri_message("XX Got component %d (0x%02X), length %d\n", (component)->type, (component)->type, (component)->len); \ +#else /* Debugging */ + #define GET_COMPONENT(component, idx, ptr, length) \ + if ((idx)+2 > (length)) \ + break; \ + (component) = (struct rose_component*)&((ptr)[idx]); \ + if ((idx)+(component)->len+2 > (length)) { \ + if ((component)->len != 128) \ + pri_message(pri, "Length (%d) of 0x%X component is too long\n", (component)->len, (component)->type); \ + } \ + pri_message(pri, "XX %s:%d Got component %d (0x%02X), length %d\n", __FUNCTION__, __LINE__, (component)->type, (component)->type, (component)->len); \ if ((component)->len > 0) { \ int zzz; \ - pri_message("XX Data:"); \ + pri_message(pri, "XX Data:"); \ for (zzz = 0; zzz < (component)->len; ++zzz) \ - pri_message(" %02X", (component)->data[zzz]); \ - pri_message("\n"); \ + pri_message(pri, " %02X", (component)->data[zzz]); \ + pri_message(pri, "\n"); \ } -*/ +#endif #define NEXT_COMPONENT(component, idx) \ (idx) += (component)->len + 2 Index: libpri.h =================================================================== --- libpri.h (revision 400) +++ libpri.h (working copy) @@ -291,6 +291,8 @@ typedef struct pri_event_facname { int e; + int callingpres; /* Presentation of Calling CallerID */ + int callingplan; /* Dialing plan of Calling entity */ char callingname[256]; char callingnum[256]; int channel; Index: q931.c =================================================================== --- q931.c (revision 400) +++ q931.c (working copy) @@ -3335,6 +3335,7 @@ return Q931_RES_HAVEEVENT; case Q931_ALERTING: if (c->newcall) { + pri_error(pri, "XXX Q931_ALERTING newcall:%d\n", c->newcall); q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); break; } @@ -3351,6 +3352,7 @@ return Q931_RES_HAVEEVENT; case Q931_CONNECT: if (c->newcall) { + pri_error(pri, "XXX Q931_CONNECT newcall:%d\n", c->newcall); q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); break; } @@ -3376,6 +3378,7 @@ return Q931_RES_HAVEEVENT; case Q931_FACILITY: if (c->newcall) { + pri_error(pri, "XXX Q931_FACILITY newcall:%d\n", c->newcall); q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); break; } @@ -3383,6 +3386,8 @@ 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 @@ -3400,6 +3405,7 @@ /* Fall through */ case Q931_CALL_PROCEEDING: if (c->newcall) { + pri_error(pri, "XXX Q931_CALL_PROCEEDING newcall:%d\n", c->newcall); q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); break; } @@ -3432,6 +3438,7 @@ return Q931_RES_HAVEEVENT; case Q931_CONNECT_ACKNOWLEDGE: if (c->newcall) { + pri_error(pri, "XXX Q931_CONNECT_ACKNOWLEDGE newcall:%d\n", c->newcall); q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); break; } @@ -3534,8 +3541,10 @@ c->useruserinfo[0] = '\0'; /* Don't send release complete if they send us release while we sent it, assume a NULL state */ - if (c->newcall) + if (c->newcall) { + pri_error(pri, "XXX Q931_RELEASE newcall:%d\n", c->newcall); q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); + } else return Q931_RES_HAVEEVENT; break; @@ -3545,6 +3554,7 @@ c->cause = PRI_CAUSE_MANDATORY_IE_MISSING; } if (c->newcall) { + pri_error(pri, "XXX Q931_DISCONNECT newcall:%d\n", c->newcall); q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); break; } @@ -3577,6 +3587,7 @@ + the "Complete" msg which is basically an EOF on further digits XXX */ if (c->newcall) { + pri_error(pri, "XXX Q931_INFORMATION newcall:%d\n", c->newcall); q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); break; } @@ -3598,12 +3609,14 @@ return Q931_RES_HAVEEVENT; case Q931_STATUS_ENQUIRY: if (c->newcall) { + pri_error(pri, "XXX Q931_STATUS_ENQUIRY newcall:%d\n", c->newcall); q931_release_complete(pri, c, PRI_CAUSE_INVALID_CALL_REFERENCE); } else q931_status(pri,c, 0); break; case Q931_SETUP_ACKNOWLEDGE: if (c->newcall) { + pri_error(pri, "XXX Q931_SETUP_ACKNOWLEDGE newcall:%d\n", c->newcall); q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); break; }