[Asterisk-cvs] libpri libpri.h, 1.45, 1.46 pri.c, 1.33,
1.34 pri_facility.c, 1.7, 1.8 pri_facility.h, 1.3,
1.4 pri_internal.h, 1.18, 1.19 q931.c, 1.121, 1.122
mattf at lists.digium.com
mattf at lists.digium.com
Mon Apr 4 23:03:09 CDT 2005
Update of /usr/cvsroot/libpri
In directory mongoose.digium.com:/tmp/cvs-serv4245
Modified Files:
libpri.h pri.c pri_facility.c pri_facility.h pri_internal.h
q931.c
Log Message:
Merging Advice of Charge code into libpri (bug #3843)
Index: libpri.h
===================================================================
RCS file: /usr/cvsroot/libpri/libpri.h,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -d -r1.45 -r1.46
--- libpri.h 3 Apr 2005 23:07:55 -0000 1.45
+++ libpri.h 5 Apr 2005 03:55:58 -0000 1.46
@@ -37,7 +37,8 @@
#define PRI_DEBUG_Q931_DUMP (1 << 5) /* Show interpreted Q.931 frames */
#define PRI_DEBUG_Q931_STATE (1 << 6) /* Debug Q.931 state machine changes */
#define PRI_DEBUG_Q931_ANOMALY (1 << 7) /* Show unexpected events */
-#define PRI_DEBUG_APDU (1 << 8) /* Debug of APDU components such as ROSE */
+#define PRI_DEBUG_APDU (1 << 8) /* Debug of APDU components such as ROSE */
+#define PRI_DEBUG_AOC (1 << 9) /* Debug of Advice of Charge ROSE Messages */
#define PRI_DEBUG_ALL (0xffff) /* Everything */
@@ -53,7 +54,7 @@
#define PRI_SWITCH_GR303_EOC 8 /* GR-303 Embedded Operations Channel */
#define PRI_SWITCH_GR303_TMC 9 /* GR-303 Timeslot Management Channel */
#define PRI_SWITCH_QSIG 10 /* QSIG Switch */
-/* Switchtypes 10 - 20 are reserved for internal use */
+/* Switchtypes 11 - 20 are reserved for internal use */
/* PRI D-Channel Events */
@@ -322,6 +323,7 @@
int cause;
int cref;
q931_call *call; /* Opaque call pointer */
+ long aoc_units; /* Advise of Charge number of charged units */
} pri_event_hangup;
typedef struct pri_event_restart_ack {
Index: pri.c
===================================================================
RCS file: /usr/cvsroot/libpri/pri.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- pri.c 17 Mar 2005 15:46:23 -0000 1.33
+++ pri.c 5 Apr 2005 03:55:58 -0000 1.34
@@ -474,6 +474,9 @@
call2->pri->switchtype != PRI_SWITCH_LUCENT5E)
return -1;
+ /* Check for bearer capability */
+ if (call1->transcapability != call2->transcapability)
+ return -1;
/* Check to see if calls are on the same PRI dchannel
* Currently only support calls on the same dchannel
*/
Index: pri_facility.c
===================================================================
RCS file: /usr/cvsroot/libpri/pri_facility.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- pri_facility.c 16 Mar 2005 15:10:41 -0000 1.7
+++ pri_facility.c 5 Apr 2005 03:55:58 -0000 1.8
@@ -16,6 +16,7 @@
#include "pri_q931.h"
#include "pri_facility.h"
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -32,128 +33,151 @@
int pres;
};
+static void dump_apdu(unsigned char *c, int len)
+{
+ #define MAX_APDU_LENGTH 255
+ int i;
+ char message[(2 + MAX_APDU_LENGTH * 3 + 6 + MAX_APDU_LENGTH + 3)] = ""; /* please adjust here, if you make changes below! */
+
+ if (len > MAX_APDU_LENGTH)
+ return;
+
+ snprintf(message, sizeof(message)-1, " [");
+ for (i=0; i<len; i++)
+ snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, " %02x", c[i]);
+ snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, " ] - [");
+ for (i=0; i<len; i++) {
+ if (c[i] < 20 || c[i] >= 128)
+ snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, "°");
+ else
+ snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, "%c", c[i]);
+ }
+ snprintf((char *)(message+strlen(message)), sizeof(message)-strlen(message)-1, "]\n");
+ pri_message(message);
+}
+
int redirectingreason_from_q931(struct pri *pri, int redirectingreason)
{
switch(pri->switchtype) {
- case PRI_SWITCH_QSIG:
- switch(redirectingreason) {
- case PRI_REDIR_UNKNOWN:
- return QSIG_DIVERT_REASON_UNKNOWN;
- case PRI_REDIR_FORWARD_ON_BUSY:
- return QSIG_DIVERT_REASON_CFB;
- case PRI_REDIR_FORWARD_ON_NO_REPLY:
- return QSIG_DIVERT_REASON_CFNR;
- case PRI_REDIR_UNCONDITIONAL:
- return QSIG_DIVERT_REASON_CFU;
- case PRI_REDIR_DEFLECTION:
- case PRI_REDIR_DTE_OUT_OF_ORDER:
- case PRI_REDIR_FORWARDED_BY_DTE:
- pri_message("!! Don't know how to convert Q.931 redirection reason %d to Q.SIG\n", redirectingreason);
- /* Fall through */
- default:
- return QSIG_DIVERT_REASON_UNKNOWN;
- }
- default:
- switch(redirectingreason) {
- case PRI_REDIR_UNKNOWN:
- return Q952_DIVERT_REASON_UNKNOWN;
- case PRI_REDIR_FORWARD_ON_BUSY:
- return Q952_DIVERT_REASON_CFB;
- case PRI_REDIR_FORWARD_ON_NO_REPLY:
- return Q952_DIVERT_REASON_CFNR;
- case PRI_REDIR_DEFLECTION:
- return Q952_DIVERT_REASON_CD;
- case PRI_REDIR_UNCONDITIONAL:
- return Q952_DIVERT_REASON_CFU;
- case PRI_REDIR_DTE_OUT_OF_ORDER:
- case PRI_REDIR_FORWARDED_BY_DTE:
- pri_message("!! Don't know how to convert Q.931 redirection reason %d to Q.952\n", redirectingreason);
- /* Fall through */
+ case PRI_SWITCH_QSIG:
+ switch(redirectingreason) {
+ case PRI_REDIR_UNKNOWN:
+ return QSIG_DIVERT_REASON_UNKNOWN;
+ case PRI_REDIR_FORWARD_ON_BUSY:
+ return QSIG_DIVERT_REASON_CFB;
+ case PRI_REDIR_FORWARD_ON_NO_REPLY:
+ return QSIG_DIVERT_REASON_CFNR;
+ case PRI_REDIR_UNCONDITIONAL:
+ return QSIG_DIVERT_REASON_CFU;
+ case PRI_REDIR_DEFLECTION:
+ case PRI_REDIR_DTE_OUT_OF_ORDER:
+ case PRI_REDIR_FORWARDED_BY_DTE:
+ pri_message("!! Don't know how to convert Q.931 redirection reason %d to Q.SIG\n", redirectingreason);
+ /* Fall through */
+ default:
+ return QSIG_DIVERT_REASON_UNKNOWN;
+ }
default:
- return Q952_DIVERT_REASON_UNKNOWN;
- }
+ switch(redirectingreason) {
+ case PRI_REDIR_UNKNOWN:
+ return Q952_DIVERT_REASON_UNKNOWN;
+ case PRI_REDIR_FORWARD_ON_BUSY:
+ return Q952_DIVERT_REASON_CFB;
+ case PRI_REDIR_FORWARD_ON_NO_REPLY:
+ return Q952_DIVERT_REASON_CFNR;
+ case PRI_REDIR_DEFLECTION:
+ return Q952_DIVERT_REASON_CD;
+ case PRI_REDIR_UNCONDITIONAL:
+ return Q952_DIVERT_REASON_CFU;
+ case PRI_REDIR_DTE_OUT_OF_ORDER:
+ case PRI_REDIR_FORWARDED_BY_DTE:
+ pri_message("!! Don't know how to convert Q.931 redirection reason %d to Q.952\n", redirectingreason);
+ /* Fall through */
+ default:
+ return Q952_DIVERT_REASON_UNKNOWN;
+ }
}
}
static int redirectingreason_for_q931(struct pri *pri, int redirectingreason)
{
switch(pri->switchtype) {
- case PRI_SWITCH_QSIG:
- switch(redirectingreason) {
- case QSIG_DIVERT_REASON_UNKNOWN:
- return PRI_REDIR_UNKNOWN;
- case QSIG_DIVERT_REASON_CFU:
- return PRI_REDIR_UNCONDITIONAL;
- case QSIG_DIVERT_REASON_CFB:
- return PRI_REDIR_FORWARD_ON_BUSY;
- case QSIG_DIVERT_REASON_CFNR:
- return PRI_REDIR_FORWARD_ON_NO_REPLY;
- default:
- pri_message("!! Unknown Q.SIG diversion reason %d\n", redirectingreason);
- return PRI_REDIR_UNKNOWN;
- }
- default:
- switch(redirectingreason) {
- case Q952_DIVERT_REASON_UNKNOWN:
- return PRI_REDIR_UNKNOWN;
- case Q952_DIVERT_REASON_CFU:
- return PRI_REDIR_UNCONDITIONAL;
- case Q952_DIVERT_REASON_CFB:
- return PRI_REDIR_FORWARD_ON_BUSY;
- case Q952_DIVERT_REASON_CFNR:
- return PRI_REDIR_FORWARD_ON_NO_REPLY;
- case Q952_DIVERT_REASON_CD:
- return PRI_REDIR_DEFLECTION;
- case Q952_DIVERT_REASON_IMMEDIATE:
- pri_message("!! Dont' know how to convert Q.952 diversion reason IMMEDIATE to PRI analog\n");
- return PRI_REDIR_UNKNOWN; /* ??? */
+ case PRI_SWITCH_QSIG:
+ switch(redirectingreason) {
+ case QSIG_DIVERT_REASON_UNKNOWN:
+ return PRI_REDIR_UNKNOWN;
+ case QSIG_DIVERT_REASON_CFU:
+ return PRI_REDIR_UNCONDITIONAL;
+ case QSIG_DIVERT_REASON_CFB:
+ return PRI_REDIR_FORWARD_ON_BUSY;
+ case QSIG_DIVERT_REASON_CFNR:
+ return PRI_REDIR_FORWARD_ON_NO_REPLY;
+ default:
+ pri_message("!! Unknown Q.SIG diversion reason %d\n", redirectingreason);
+ return PRI_REDIR_UNKNOWN;
+ }
default:
- pri_message("!! Unknown Q.952 diversion reason %d\n", redirectingreason);
- return PRI_REDIR_UNKNOWN;
- }
+ switch(redirectingreason) {
+ case Q952_DIVERT_REASON_UNKNOWN:
+ return PRI_REDIR_UNKNOWN;
+ case Q952_DIVERT_REASON_CFU:
+ return PRI_REDIR_UNCONDITIONAL;
+ case Q952_DIVERT_REASON_CFB:
+ return PRI_REDIR_FORWARD_ON_BUSY;
+ case Q952_DIVERT_REASON_CFNR:
+ return PRI_REDIR_FORWARD_ON_NO_REPLY;
+ case Q952_DIVERT_REASON_CD:
+ return PRI_REDIR_DEFLECTION;
+ case Q952_DIVERT_REASON_IMMEDIATE:
+ pri_message("!! Dont' know how to convert Q.952 diversion reason IMMEDIATE to PRI analog\n");
+ return PRI_REDIR_UNKNOWN; /* ??? */
+ default:
+ pri_message("!! Unknown Q.952 diversion reason %d\n", redirectingreason);
+ return PRI_REDIR_UNKNOWN;
+ }
}
}
int typeofnumber_from_q931(struct pri *pri, int ton)
{
switch(ton) {
- case PRI_TON_INTERNATIONAL:
- return Q932_TON_INTERNATIONAL;
- case PRI_TON_NATIONAL:
- return Q932_TON_NATIONAL;
- case PRI_TON_NET_SPECIFIC:
- return Q932_TON_NET_SPECIFIC;
- case PRI_TON_SUBSCRIBER:
- return Q932_TON_SUBSCRIBER;
- case PRI_TON_ABBREVIATED:
- return Q932_TON_ABBREVIATED;
- case PRI_TON_RESERVED:
- default:
- pri_message("!! Unsupported Q.931 TypeOfNumber value (%d)\n", ton);
- /* fall through */
- case PRI_TON_UNKNOWN:
- return Q932_TON_UNKNOWN;
+ case PRI_TON_INTERNATIONAL:
+ return Q932_TON_INTERNATIONAL;
+ case PRI_TON_NATIONAL:
+ return Q932_TON_NATIONAL;
+ case PRI_TON_NET_SPECIFIC:
+ return Q932_TON_NET_SPECIFIC;
+ case PRI_TON_SUBSCRIBER:
+ return Q932_TON_SUBSCRIBER;
+ case PRI_TON_ABBREVIATED:
+ return Q932_TON_ABBREVIATED;
+ case PRI_TON_RESERVED:
+ default:
+ pri_message("!! Unsupported Q.931 TypeOfNumber value (%d)\n", ton);
+ /* fall through */
+ case PRI_TON_UNKNOWN:
+ return Q932_TON_UNKNOWN;
}
}
static int typeofnumber_for_q931(struct pri *pri, int ton)
{
switch (ton) {
- case Q932_TON_UNKNOWN:
- return PRI_TON_UNKNOWN;
- case Q932_TON_INTERNATIONAL:
- return PRI_TON_INTERNATIONAL;
- case Q932_TON_NATIONAL:
- return PRI_TON_NATIONAL;
- case Q932_TON_NET_SPECIFIC:
- return PRI_TON_NET_SPECIFIC;
- case Q932_TON_SUBSCRIBER:
- return PRI_TON_SUBSCRIBER;
- case Q932_TON_ABBREVIATED:
- return PRI_TON_ABBREVIATED;
- default:
- pri_message("!! Invalid Q.932 TypeOfNumber %d\n", ton);
- return PRI_TON_UNKNOWN;
+ case Q932_TON_UNKNOWN:
+ return PRI_TON_UNKNOWN;
+ case Q932_TON_INTERNATIONAL:
+ return PRI_TON_INTERNATIONAL;
+ case Q932_TON_NATIONAL:
+ return PRI_TON_NATIONAL;
+ case Q932_TON_NET_SPECIFIC:
+ return PRI_TON_NET_SPECIFIC;
+ case Q932_TON_SUBSCRIBER:
+ return PRI_TON_SUBSCRIBER;
+ case Q932_TON_ABBREVIATED:
+ return PRI_TON_ABBREVIATED;
+ default:
+ pri_message("!! Invalid Q.932 TypeOfNumber %d\n", ton);
+ return PRI_TON_UNKNOWN;
}
}
@@ -235,39 +259,39 @@
GET_COMPONENT(comp, i, vdata, len);
switch(comp->type) {
- case 0xA0: /* unknownPartyNumber */
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] unknownPartyNumber */
if(rose_number_digits_decode(pri, call, comp->data, comp->len, value))
return -1;
value->npi = PRI_NPI_UNKNOWN;
value->ton = PRI_TON_UNKNOWN;
break;
- case 0xA1: /* publicPartyNumber */
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] publicPartyNumber */
if(rose_public_party_number_decode(pri, call, comp->data, comp->len, value) != 0)
return -1;
value->npi = PRI_NPI_E163_E164;
break;
- case 0xA2: /* nsapEncodedNumber */
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2): /* [2] nsapEncodedNumber */
pri_message("!! NsapEncodedNumber isn't handled\n");
return -1;
- case 0xA3: /* dataPartyNumber */
+ 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("!! dataPartyNumber isn't handled\n");
return -1;
- case 0xA4: /* telexPartyNumber */
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4): /* [4] telexPartyNumber */
if (rose_number_digits_decode(pri, call, comp->data, comp->len, value))
return -1;
value->npi = PRI_NPI_F69 /* ??? */;
value->ton = PRI_TON_UNKNOWN /* ??? */;
pri_message("!! telexPartyNumber isn't handled\n");
return -1;
- case 0xA5: /* priavePartyNumber */
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] priavePartyNumber */
pri_message("!! privatePartyNumber isn't handled\n");
value->npi = PRI_NPI_PRIVATE;
return -1;
- case 0xA8: /* nationalStandardPartyNumber */
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_8): /* [8] nationalStandardPartyNumber */
if (rose_number_digits_decode(pri, call, comp->data, comp->len, value))
return -1;
value->npi = PRI_NPI_NATIONAL;
@@ -302,24 +326,24 @@
GET_COMPONENT(comp, i, vdata, len);
switch(comp->type) {
- case 0xA0: /* [0] presentationAllowedNumber */
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] presentationAllowedNumber */
value->pres = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
return rose_address_decode(pri, call, comp->data, comp->len, value);
- case 0x81: /* [1] IMPLICIT presentationRestricted */
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* [1] IMPLICIT presentationRestricted */
if (comp->len != 0) { /* must be NULL */
pri_error("!! Invalid PresentationRestricted component received (len != 0)\n");
return -1;
}
value->pres = PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
return 0;
- case 0x82: /* [2] IMPLICIT numberNotAvailableDueToInterworking */
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2): /* [2] IMPLICIT numberNotAvailableDueToInterworking */
if (comp->len != 0) { /* must be NULL */
pri_error("!! Invalid NumberNotAvailableDueToInterworking component received (len != 0)\n");
return -1;
}
value->pres = PRES_NUMBER_NOT_AVAILABLE;
return 0;
- case 0xA3: /* [3] presentationRestrictedNumber */
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] presentationRestrictedNumber */
value->pres = PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
return rose_address_decode(pri, call, comp->data, comp->len, value);
default:
@@ -419,7 +443,7 @@
return -1;
}
- buffer[i] = 0x80 | Q932_PROTOCOL_EXTENSIONS;
+ buffer[i] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
i++;
/* Interpretation component */
ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0x00 /* Discard unrecognized invokes */);
@@ -436,7 +460,7 @@
ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, ROSE_DIVERTING_LEG_INFORMATION2);
/* ROSE ARGUMENT component */
- ASN1_ADD_SIMPLE(comp, 0x30, buffer, i);
+ 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 */
@@ -446,7 +470,7 @@
ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, redirectingreason_from_q931(pri, call->redirectingreason));
/* ROSE DivertingLegInformation2.divertingNr component */
- ASN1_ADD_SIMPLE(comp, 0xA1, buffer, i);
+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
ASN1_PUSH(compstk, compsp, comp);
/* Redirecting information always not screened */
@@ -455,10 +479,10 @@
case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
if (call->redirectingnum && strlen(call->redirectingnum)) {
- ASN1_ADD_SIMPLE(comp, 0xA0, buffer, i);
+ 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, 0xA1, buffer, i);
+ 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));
@@ -473,35 +497,35 @@
/* fall through */
case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
- ASN1_ADD_SIMPLE(comp, 0x81, buffer, i);
+ 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, 0x81, buffer, i);
+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
break;
default:
pri_message("!! Undefined presentation value for redirecting number: %d\n", call->redirectingpres);
case PRES_NUMBER_NOT_AVAILABLE:
- ASN1_ADD_SIMPLE(comp, 0x82, buffer, i);
+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i);
break;
}
ASN1_FIXUP(compstk, compsp, buffer, i);
/* ROSE DivertingLegInformation2.originalCalledNr component */
/* This information isn't supported by current design - duplicate divertingNr */
- ASN1_ADD_SIMPLE(comp, 0xA2, buffer, i);
+ 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, 0xA0, buffer, i);
+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
ASN1_PUSH(compstk, compsp, comp);
- ASN1_ADD_SIMPLE(comp, 0xA1, buffer, i);
+ 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));
@@ -517,19 +541,19 @@
/* fall through */
case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
- ASN1_ADD_SIMPLE(comp, 0x81, buffer, i);
+ 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, 0x81, buffer, i);
+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
break;
default:
pri_message("!! Undefined presentation value for redirecting number: %d\n", call->redirectingpres);
case PRES_NUMBER_NOT_AVAILABLE:
- ASN1_ADD_SIMPLE(comp, 0x82, buffer, i);
+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i);
break;
}
ASN1_FIXUP(compstk, compsp, buffer, i);
@@ -568,13 +592,13 @@
return -1;
}
- buffer[i++] = 0x80 | Q932_PROTOCOL_EXTENSIONS;
+ buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
/* Interpretation component */
ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
ASN1_PUSH(compstk, compsp, comp);
- ASN1_ADD_BYTECOMP(comp, 0x80, buffer, i, 0);
- ASN1_ADD_BYTECOMP(comp, 0x82, buffer, i, 0);
+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
ASN1_FIXUP(compstk, compsp, buffer, i);
ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
@@ -607,13 +631,13 @@
namelen = 50; /* truncate the name */
}
- buffer[i++] = 0x80 | Q932_PROTOCOL_EXTENSIONS;
+ buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
/* Interpretation component */
ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
ASN1_PUSH(compstk, compsp, comp);
- ASN1_ADD_BYTECOMP(comp, 0x80, buffer, i, 0);
- ASN1_ADD_BYTECOMP(comp, 0x82, buffer, i, 0);
+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
ASN1_FIXUP(compstk, compsp, buffer, i);
ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
@@ -627,7 +651,7 @@
/* Operation ID: Calling name */
ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, SS_CNID_CALLINGNAME);
- res = asn1_string_encode(0x80, &buffer[i], sizeof(buffer)-i, 50, c->callername, namelen);
+ res = asn1_string_encode((ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), &buffer[i], sizeof(buffer)-i, 50, c->callername, namelen);
if (res < 0)
return -1;
i += res;
@@ -638,7 +662,6 @@
return 0;
}
-
/* End Callername */
/* MWI related encode and decode functions */
@@ -661,13 +684,13 @@
} else if (destlen > 20)
destlen = 20; /* Destination number cannot be greater then 20 digits */
- buffer[i++] = 0x80 | Q932_PROTOCOL_EXTENSIONS;
+ buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
/* Interpretation component */
ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
ASN1_PUSH(compstk, compsp, comp);
- ASN1_ADD_BYTECOMP(comp, 0x80, buffer, i, 0);
- ASN1_ADD_BYTECOMP(comp, 0x82, buffer, i, 0);
+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
ASN1_FIXUP(compstk, compsp, buffer, i);
ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
@@ -678,10 +701,10 @@
ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, (activate) ? SS_MWI_ACTIVATE : SS_MWI_DEACTIVATE);
- ASN1_ADD_SIMPLE(comp, 0x30 /* Sequence */, buffer, i);
+ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
ASN1_PUSH(compstk, compsp, comp);
/* PartyNumber */
- res = asn1_string_encode(0x80, &buffer[i], sizeof(buffer)-i, destlen, req->called, destlen);
+ res = asn1_string_encode((ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), &buffer[i], sizeof(buffer)-i, destlen, req->called, destlen);
if (res < 0)
return -1;
@@ -718,13 +741,13 @@
0x08,
};
- buffer[i++] = 0x80 | Q932_PROTOCOL_EXTENSIONS;
+ buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
/* Interpretation component */
ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i);
ASN1_PUSH(compstk, compsp, comp);
- ASN1_ADD_BYTECOMP(comp, 0x80, buffer, i, 0);
- ASN1_ADD_BYTECOMP(comp, 0x82, buffer, i, 0);
+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0);
+ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0);
ASN1_FIXUP(compstk, compsp, buffer, i);
ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0);
@@ -739,9 +762,9 @@
return -1;
i += res;
- ASN1_ADD_SIMPLE(comp, ASN1_SEQUENCE | 0x20, buffer, i);
+ ASN1_ADD_SIMPLE(comp, (ASN1_SEQUENCE | ASN1_CONSTRUCTOR), buffer, i);
ASN1_PUSH(compstk, compsp, comp);
- ASN1_ADD_WORDCOMP(comp, 0x02, buffer, i, call_reference);
+ ASN1_ADD_WORDCOMP(comp, ASN1_INTEGER, buffer, i, call_reference);
ASN1_FIXUP(compstk, compsp, buffer, i);
ASN1_FIXUP(compstk, compsp, buffer, i);
@@ -764,6 +787,211 @@
}
/* End EECT */
+/* AOC */
+static int aoc_aoce_charging_request_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
+{
+ int chargingcase = -1;
+ unsigned char *vdata = data;
+ struct rose_component *comp = NULL;
+ int pos1 = 0;
+
+ if (pri->debug & PRI_DEBUG_AOC)
+ dump_apdu (data, len);
+
+ do {
+ GET_COMPONENT(comp, pos1, vdata, len);
+ CHECK_COMPONENT(comp, ASN1_ENUMERATED, "!! Invalid AOC Charging Request argument. Expected Enumerated (0x0A) but Received 0x%02X\n");
+ ASN1_GET_INTEGER(comp, chargingcase);
+ if (chargingcase >= 0 && chargingcase <= 2) {
+ if (pri->debug & PRI_DEBUG_APDU)
+ pri_message("Channel %d/%d, Call %d - received AOC charging request - charging case: %i\n",
+ call->ds1no, call->channelno, call->cr, chargingcase);
+ } else {
+ pri_message("!! unkown AOC ChargingCase: 0x%02X", chargingcase);
+ chargingcase = -1;
+ }
+ NEXT_COMPONENT(comp, pos1);
+ } while (pos1 < len);
+ if (pos1 < len) {
+ pri_message("!! Only reached position %i in %i bytes long AOC-E structure:", pos1, len );
+ dump_apdu (data, len);
+ return -1; /* Aborted before */
+ }
+ return 0;
+}
+
+
+static int aoc_aoce_charging_unit_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
+{
+ long chargingunits = 0, chargetype = -1, temp, chargeIdentifier = -1;
+ unsigned char *vdata = data;
+ struct rose_component *comp1 = NULL, *comp2 = NULL, *comp3 = NULL;
+ int pos1 = 0, pos2, pos3, sublen2, sublen3;
+ struct addressingdataelements_presentednumberunscreened chargednr;
+
+ if (pri->debug & PRI_DEBUG_AOC)
+ dump_apdu (data, len);
+
+ do {
+ GET_COMPONENT(comp1, pos1, vdata, len); /* AOCEChargingUnitInfo */
+ CHECK_COMPONENT(comp1, ASN1_SEQUENCE, "!! Invalid AOC-E Charging Unit argument. Expected Sequence (0x30) but Received 0x%02X\n");
+ SUB_COMPONENT(comp1, pos1);
+ GET_COMPONENT(comp1, pos1, vdata, len);
+ switch (comp1->type) {
+ case (ASN1_SEQUENCE | ASN1_CONSTRUCTOR): /* specificChargingUnits */
+ sublen2 = comp1->len;
+ pos2 = pos1;
+ comp2 = comp1;
+ SUB_COMPONENT(comp2, pos2);
+ do {
+ GET_COMPONENT(comp2, pos2, vdata, len);
+ switch (comp2->type) {
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* RecordedUnitsList (0xA1) */
+ SUB_COMPONENT(comp2, pos2);
+ GET_COMPONENT(comp2, pos2, vdata, len);
+ CHECK_COMPONENT(comp2, ASN1_SEQUENCE, "!! Invalid AOC-E Charging Unit argument. Expected Sequence (0x30) but received 0x02%X\n"); /* RecordedUnits */
+ sublen3 = pos2 + comp2->len;
+ pos3 = pos2;
+ comp3 = comp2;
+ SUB_COMPONENT(comp3, pos3);
+ do {
+ GET_COMPONENT(comp3, pos3, vdata, len);
+ switch (comp3->type) {
+ case ASN1_INTEGER: /* numberOfUnits */
+ ASN1_GET_INTEGER(comp3, temp);
+ chargingunits += temp;
+ case ASN1_NULL: /* notAvailable */
+ break;
+ default:
+ pri_message("!! Don't know how to handle 0x%02X in AOC-E RecordedUnits\n", comp3->type);
+ }
+ NEXT_COMPONENT(comp3, pos3);
+ } while (pos3 < sublen3);
+ if (pri->debug & PRI_DEBUG_AOC)
+ pri_message("Channel %d/%d, Call %d - received AOC-E charging: %i unit%s\n",
+ call->ds1no, call->channelno, call->cr, chargingunits, (chargingunits == 1) ? "" : "s");
+ break;
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2): /* AOCEBillingID (0xA2) */
+ SUB_COMPONENT(comp2, pos2);
+ GET_COMPONENT(comp2, pos2, vdata, len);
+ ASN1_GET_INTEGER(comp2, chargetype);
+ pri_message("!! not handled: Channel %d/%d, Call %d - received AOC-E billing ID: %i\n",
+ call->ds1no, call->channelno, call->cr, chargetype);
+ break;
+ default:
+ pri_message("!! Don't know how to handle 0x%02X in AOC-E RecordedUnitsList\n", comp2->type);
+ }
+ NEXT_COMPONENT(comp2, pos2);
+ } while (pos2 < sublen2);
+ break;
+ case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* freeOfCharge (0x81) */
+ if (pri->debug & PRI_DEBUG_AOC)
+ pri_message("Channel %d/%d, Call %d - received AOC-E free of charge\n", call->ds1no, call->channelno, call->cr);
+ chargingunits = 0;
+ break;
+ default:
+ pri_message("!! Invalid AOC-E specificChargingUnits. Expected Sequence (0x30) or Object Identifier (0x81/0x01) but received 0x%02X\n", comp1->type);
+ }
+ NEXT_COMPONENT(comp1, pos1);
+ GET_COMPONENT(comp1, pos1, vdata, len); /* get optional chargingAssociation. will 'break' when reached end of structure */
+ 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)
+ return -1;
+ pri_message("!! not handled: Received ChargedNr '%s' \n", chargednr.partyaddress);
+ pri_message(" ton = %d, pres = %d, npi = %d\n", chargednr.ton, chargednr.pres, chargednr.npi);
+ break;
+ case ASN1_INTEGER:
+ ASN1_GET_INTEGER(comp1, chargeIdentifier);
+ break;
+ default:
+ pri_message("!! Invalid AOC-E chargingAssociation. Expected Object Identifier (0xA0) or Integer (0x02) but received 0x%02X\n", comp1->type);
+ }
+ NEXT_COMPONENT(comp1, pos1);
+ } while (pos1 < len);
+
+ if (pos1 < len) {
+ pri_message("!! Only reached position %i in %i bytes long AOC-E structure:", pos1, len );
+ dump_apdu (data, len);
+ return -1; /* oops - aborted before */
+ }
+ call->aoc_units = chargingunits;
+
+ return 0;
+}
+
+static int aoc_aoce_charging_unit_encode(struct pri *pri, q931_call *c, long chargedunits)
+{
+ /* sample data: [ 91 a1 12 02 02 3a 78 02 01 24 30 09 30 07 a1 05 30 03 02 01 01 ] */
+ int i = 0, res = 0, compsp = 0;
+ unsigned char buffer[255] = "";
+ struct rose_component *comp = NULL, *compstk[10];
+
+ /* ROSE protocol (0x91)*/
+ buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_ROSE);
+
+ /* ROSE Component (0xA1,len)*/
+ ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
+ ASN1_PUSH(compstk, compsp, comp);
+
+ /* ROSE invokeId component (0x02,len,id)*/
+ ASN1_ADD_WORDCOMP(comp, INVOKE_IDENTIFIER, buffer, i, ++pri->last_invoke);
+
+ /* ROSE operationId component (0x02,0x01,0x24)*/
+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, ROSE_AOC_AOCE_CHARGING_UNIT);
+
+ /* AOCEChargingUnitInfo (0x30,len) */
+ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
+ ASN1_PUSH(compstk, compsp, comp);
+
+ if (chargedunits > 0) {
+ /* SpecificChargingUnits (0x30,len) */
+ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
+ ASN1_PUSH(compstk, compsp, comp);
+
+ /* RecordedUnitsList (0xA1,len) */
+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
+ ASN1_PUSH(compstk, compsp, comp);
+
+ /* RecordedUnits (0x30,len) */
+ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
+ ASN1_PUSH(compstk, compsp, comp);
+
+ /* NumberOfUnits (0x02,len,charge) */
+ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, chargedunits);
+
+ ASN1_FIXUP(compstk, compsp, buffer, i);
+ ASN1_FIXUP(compstk, compsp, buffer, i);
+ ASN1_FIXUP(compstk, compsp, buffer, i);
+ } else {
+ /* freeOfCharge (0x81,0) */
+ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i);
+ }
+ ASN1_FIXUP(compstk, compsp, buffer, i);
+ ASN1_FIXUP(compstk, compsp, buffer, i);
+
+ if (pri->debug & PRI_DEBUG_AOC)
+ dump_apdu (buffer, i);
+
+ /* code below is untested */
+ res = pri_call_apdu_queue(c, Q931_FACILITY, buffer, i, NULL, NULL);
+ if (res) {
+ pri_message("Could not queue ADPU in facility message\n");
+ return -1;
+ }
+
+ /* Remember that if we queue a facility IE for a facility message we
+ * have to explicitly send the facility message ourselves */
+ res = q931_facility(c->pri, c);
+ if (res) {
+ pri_message("Could not schedule facility message for call %d\n", c->cr);
+ return -1;
+ }
+
+ return 0;
+}
+/* End AOC */
extern int rose_invoke_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
{
@@ -771,11 +999,11 @@
int operation_tag;
unsigned char *vdata = data;
struct rose_component *comp = NULL, *invokeid = NULL, *operationid = NULL;
-
+
do {
/* Invoke ID stuff */
GET_COMPONENT(comp, i, vdata, len);
- CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if first ROSE component is of type 0x%x\n");
+ CHECK_COMPONENT(comp, INVOKE_IDENTIFIER, "Don't know what to do if first ROSE component is of type 0x%x\n");
invokeid = comp;
NEXT_COMPONENT(comp, i);
@@ -806,23 +1034,77 @@
memcpy(call->callername, comp->data, comp->len);
call->callername[comp->len] = 0;
if (pri->debug & PRI_DEBUG_APDU)
- pri_message(" Received caller name '%s'\n", call->callername);
+ pri_message(" Received caller name '%s'\n", call->callername);
return 0;
default:
- pri_message("Do not handle argument of type 0x%X\n", comp->type);
+ if (pri->debug & PRI_DEBUG_APDU)
+ pri_message("Do not handle argument of type 0x%X\n", comp->type);
return -1;
}
break;
case ROSE_DIVERTING_LEG_INFORMATION2:
if (pri->debug & PRI_DEBUG_APDU)
pri_message(" Handle DivertingLegInformation2\n");
- if (comp->type != 0x30) { /* Sequence */
+ if (comp->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
pri_message("Invalid DivertingLegInformation2Type argument\n");
return -1;
}
return rose_diverting_leg_information2_decode(pri, call, comp->data, comp->len);
+ case ROSE_AOC_NO_CHARGING_INFO_AVAILABLE:
+ if (pri->debug & PRI_DEBUG_APDU) {
+ pri_message("ROSE %i: AOC No Charging Info Available - not handled!", operation_tag);
+ dump_apdu (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("ROSE %i: AOC-S Currency - not handled!", operation_tag);
+ dump_apdu ((u_int8_t *)comp, comp->len + 2);
+ }
+ return -1;
+ case ROSE_AOC_AOCS_SPECIAL_ARR:
+ if (pri->debug & PRI_DEBUG_APDU) {
+ pri_message("ROSE %i: AOC-S Special Array - not handled!", operation_tag);
+ dump_apdu ((u_int8_t *)comp, comp->len + 2);
+ }
+ return -1;
+ case ROSE_AOC_AOCD_CURRENCY:
+ if (pri->debug & PRI_DEBUG_APDU) {
+ pri_message("ROSE %i: AOC-D Currency - not handled!", operation_tag);
+ dump_apdu ((u_int8_t *)comp, comp->len + 2);
+ }
+ return -1;
+ case ROSE_AOC_AOCD_CHARGING_UNIT:
+ if (pri->debug & PRI_DEBUG_APDU) {
+ pri_message("ROSE %i: AOC-D Charging Unit - not handled!", operation_tag);
+ dump_apdu ((u_int8_t *)comp, comp->len + 2);
+ }
+ return -1;
+ case ROSE_AOC_AOCE_CURRENCY:
+ if (pri->debug & PRI_DEBUG_APDU) {
+ pri_message("ROSE %i: AOC-E Currency - not handled!", operation_tag);
+ dump_apdu ((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("ROSE %i: AOC Identification Of Charge - not handled!", operation_tag);
+ dump_apdu ((u_int8_t *)comp, comp->len + 2);
+ }
+ return -1;
default:
- pri_message("!! Unable to handle ROSE operation %d\n", operation_tag);
+ if (pri->debug & PRI_DEBUG_APDU) {
+ pri_message("!! Unable to handle ROSE operation %d", operation_tag);
+ dump_apdu ((u_int8_t *)comp, comp->len + 2);
+ }
return -1;
}
} while(0);
@@ -848,7 +1130,7 @@
memcpy(new_event->apdu, apdu, apdu_len);
new_event->apdu_len = apdu_len;
} else {
- pri_error("malloc failed\n");
+ pri_error("!! Malloc failed!\n");
return -1;
}
Index: pri_facility.h
===================================================================
RCS file: /usr/cvsroot/libpri/pri_facility.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- pri_facility.h 2 Mar 2005 15:56:11 -0000 1.3
+++ pri_facility.h 5 Apr 2005 03:55:58 -0000 1.4
@@ -32,10 +32,20 @@
#define COMP_TYPE_NFE 0xAA
/* Operation ID values */
-/* Q.952 ROSE operations */
+/* Q.952 ROSE operations (Diverting) */
#define ROSE_DIVERTING_LEG_INFORMATION1 18
#define ROSE_DIVERTING_LEG_INFORMATION2 15
#define ROSE_DIVERTING_LEG_INFORMATION3 19
+/* Q.956 ROSE operations (Advice Of Charge) */
+#define ROSE_AOC_NO_CHARGING_INFO_AVAILABLE 26
+#define ROSE_AOC_CHARGING_REQUEST 30
+#define ROSE_AOC_AOCS_CURRENCY 31
+#define ROSE_AOC_AOCS_SPECIAL_ARR 32
+#define ROSE_AOC_AOCD_CURRENCY 33
+#define ROSE_AOC_AOCD_CHARGING_UNIT 34
+#define ROSE_AOC_AOCE_CURRENCY 35
+#define ROSE_AOC_AOCE_CHARGING_UNIT 36
+#define ROSE_AOC_IDENTIFICATION_OF_CHARGE 37
/* Q.SIG operations */
#define SS_CNID_CALLINGNAME 0
#define SS_DIVERTING_LEG_INFORMATION2 22
@@ -48,14 +58,15 @@
#define INVOKE_LINKED_IDENTIFIER 0x80
#define INVOKE_NULL_IDENTIFIER __USE_ASN1_NULL
-/* ASN.1 Data types */
+/* ASN.1 Identifier Octet - Data types */
+#define ASN1_TYPE_MASK 0x1f
#define ASN1_BOOLEAN 0x01
#define ASN1_INTEGER 0x02
#define ASN1_BITSTRING 0x03
#define ASN1_OCTETSTRING 0x04
#define ASN1_NULL 0x05
#define ASN1_OBJECTIDENTIFIER 0x06
-#define ASN1_OBJECTDESCRIPTER 0x07
+#define ASN1_OBJECTDESCRIPTOR 0x07
#define ASN1_EXTERN 0x08
#define ASN1_REAL 0x09
#define ASN1_ENUMERATED 0x0a
@@ -72,6 +83,31 @@
#define ASN1_UTCTIME 0x17
#define ASN1_GENERALIZEDTIME 0x18
+/* ASN.1 Identifier Octet - Tags */
+#define ASN1_TAG_0 0x00
+#define ASN1_TAG_1 0x01
+#define ASN1_TAG_2 0x02
+#define ASN1_TAG_3 0x03
+#define ASN1_TAG_4 0x04
+#define ASN1_TAG_5 0x05
+#define ASN1_TAG_6 0x06
+#define ASN1_TAG_7 0x07
+#define ASN1_TAG_8 0x08
+#define ASN1_TAG_9 0x09
+
+/* ASN.1 Identifier Octet - Primitive/Constructor Bit */
+#define ASN1_PC_MASK 0x20
+#define ASN1_PRIMITIVE 0x00
+#define ASN1_CONSTRUCTOR 0x20
+
+/* ASN.1 Identifier Octet - Clan Bits */
+#define ASN1_CLAN_MASK 0xc0
+#define ASN1_UNIVERSAL 0x00
+#define ASN1_APPLICATION 0x40
+#define ASN1_CONTEXT_SPECIFIC 0x80
+#define ASN1_PRIVATE 0xc0
+
+
#define INVOKE_OPERATION_INT __USE_ASN1_INTEGER
#define INVOKE_OBJECT_ID __USE_ASN1_OBJECTIDENTIFIER
@@ -103,7 +139,7 @@
};
#define GET_COMPONENT(component, idx, ptr, length) \
- if ((idx)+2 >= (length)) \
+ if ((idx)+2 > (length)) \
break; \
(component) = (struct rose_component*)&((ptr)[idx]); \
if ((idx)+(component)->len+2 > (length)) { \
@@ -128,7 +164,7 @@
(idx) += 2
#define CHECK_COMPONENT(component, comptype, message) \
- if ((component)->type && ((component)->type&0x1f) != (comptype)) { \
+ if ((component)->type && ((component)->type & ASN1_TYPE_MASK) != (comptype)) { \
pri_message((message), (component)->type); \
break; \
}
Index: pri_internal.h
===================================================================
RCS file: /usr/cvsroot/libpri/pri_internal.h,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- pri_internal.h 17 Mar 2005 15:46:23 -0000 1.18
+++ pri_internal.h 5 Apr 2005 03:55:58 -0000 1.19
@@ -219,6 +219,8 @@
int useruserprotocoldisc;
char useruserinfo[256];
char callingsubaddr[256]; /* Calling parties sub address */
+
+ long aoc_units; /* Advice of Charge Units */
struct apdu_event *apdus; /* APDU queue for call */
};
Index: q931.c
===================================================================
RCS file: /usr/cvsroot/libpri/q931.c,v
retrieving revision 1.121
retrieving revision 1.122
diff -u -d -r1.121 -r1.122
--- q931.c 3 Apr 2005 23:07:55 -0000 1.121
+++ q931.c 5 Apr 2005 03:55:58 -0000 1.122
@@ -3170,6 +3170,7 @@
c->cause = -1;
c->causecode = -1;
c->causeloc = -1;
+ c->aoc_units = -1;
if (c->retranstimer)
pri_schedule_del(pri, c->retranstimer);
c->retranstimer = 0;
@@ -3183,6 +3184,7 @@
c->causecode = -1;
c->causeloc = -1;
c->sugcallstate = -1;
+ c->aoc_units = -1;
break;
case Q931_RESTART_ACKNOWLEDGE:
c->channelno = -1;
@@ -3538,6 +3540,7 @@
pri->ev.hangup.cref = c->cr;
pri->ev.hangup.cause = c->cause;
pri->ev.hangup.call = c;
+ pri->ev.hangup.aoc_units = c->aoc_units;
/* Don't send release complete if they send us release
while we sent it, assume a NULL state */
if (c->newcall)
@@ -3563,6 +3566,7 @@
pri->ev.hangup.cref = c->cr;
pri->ev.hangup.cause = c->cause;
pri->ev.hangup.call = c;
+ pri->ev.hangup.aoc_units = c->aoc_units;
if (c->alive)
return Q931_RES_HAVEEVENT;
else
More information about the svn-commits
mailing list