Commit ba45095c authored by Richard Mudgett's avatar Richard Mudgett

ROSE ASN.1 facility encode and decode rewrite of existing messages.

Several components are now parsed correctly.  Most notably:
PartyNumber and Q.SIG Name.


git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@766 2fbb986a-6c06-0410-b554-c9c1f0a7f128
parent 18fa4716
...@@ -41,8 +41,42 @@ SONAME:=1.4 ...@@ -41,8 +41,42 @@ SONAME:=1.4
STATIC_LIBRARY=libpri.a STATIC_LIBRARY=libpri.a
DYNAMIC_LIBRARY:=libpri.so.$(SONAME) DYNAMIC_LIBRARY:=libpri.so.$(SONAME)
STATIC_OBJS=copy_string.o pri.o q921.o prisched.o q931.o pri_facility.o version.o STATIC_OBJS= \
DYNAMIC_OBJS=copy_string.lo pri.lo q921.lo prisched.lo q931.lo pri_facility.lo version.lo copy_string.o \
pri.o \
q921.o \
prisched.o \
q931.o \
pri_facility.o \
asn1_primitive.o \
rose.o \
rose_address.o \
rose_etsi_aoc.o \
rose_other.o \
rose_q931.o \
rose_qsig_ct.o \
rose_qsig_diversion.o \
rose_qsig_mwi.o \
rose_qsig_name.o \
version.o
DYNAMIC_OBJS= \
copy_string.lo \
pri.lo \
q921.lo \
prisched.lo \
q931.lo \
pri_facility.lo \
asn1_primitive.lo \
rose.lo \
rose_address.lo \
rose_etsi_aoc.lo \
rose_other.lo \
rose_q931.lo \
rose_qsig_ct.lo \
rose_qsig_diversion.lo \
rose_qsig_mwi.lo \
rose_qsig_name.lo \
version.lo
CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g -fPIC $(ALERTING) $(LIBPRI_COUNTERS) CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g -fPIC $(ALERTING) $(LIBPRI_COUNTERS)
INSTALL_PREFIX=$(DESTDIR) INSTALL_PREFIX=$(DESTDIR)
INSTALL_BASE=/usr INSTALL_BASE=/usr
...@@ -132,6 +166,9 @@ testprilib: testprilib.o ...@@ -132,6 +166,9 @@ testprilib: testprilib.o
pridump: pridump.o pridump: pridump.o
$(CC) -o pridump pridump.o -L. -lpri $(CFLAGS) $(CC) -o pridump pridump.o -L. -lpri $(CFLAGS)
rosetest: rosetest.o
$(CC) -o rosetest rosetest.o -L. -lpri $(CFLAGS)
MAKE_DEPS= -MD -MT $@ -MF .$(subst /,_,$@).d -MP MAKE_DEPS= -MD -MT $@ -MF .$(subst /,_,$@).d -MP
%.o: %.c %.o: %.c
......
This diff is collapsed.
This diff is collapsed.
...@@ -26,7 +26,14 @@ ...@@ -26,7 +26,14 @@
* provided with that copy of Asterisk, instead of the license * provided with that copy of Asterisk, instead of the license
* terms granted here. * terms granted here.
*/ */
/*
* NOTE:
* All new global identifiers that are added to this file MUST be
* prefixed with PRI_ or pri_ to indicate that they are part of this
* library and to reduce potential naming conflicts.
*/
#ifndef _LIBPRI_H #ifndef _LIBPRI_H
#define _LIBPRI_H #define _LIBPRI_H
...@@ -103,13 +110,13 @@ ...@@ -103,13 +110,13 @@
#define PRI_PROG_CALLER_RETURNED_TO_ISDN (1 << 9) #define PRI_PROG_CALLER_RETURNED_TO_ISDN (1 << 9)
/* Numbering plan identifier */ /* Numbering plan identifier */
#define PRI_NPI_UNKNOWN 0x0 #define PRI_NPI_UNKNOWN 0x0 /*!< Unknown numbering plan */
#define PRI_NPI_E163_E164 0x1 #define PRI_NPI_E163_E164 0x1 /*!< ISDN/telephony numbering plan (public) */
#define PRI_NPI_X121 0x3 #define PRI_NPI_X121 0x3 /*!< Data numbering plan */
#define PRI_NPI_F69 0x4 #define PRI_NPI_F69 0x4 /*!< Telex numbering plan */
#define PRI_NPI_NATIONAL 0x8 #define PRI_NPI_NATIONAL 0x8 /*!< National standard numbering plan */
#define PRI_NPI_PRIVATE 0x9 #define PRI_NPI_PRIVATE 0x9 /*!< Private numbering plan */
#define PRI_NPI_RESERVED 0xF #define PRI_NPI_RESERVED 0xF /*!< Reserved for extension */
/* Type of number */ /* Type of number */
#define PRI_TON_UNKNOWN 0x0 #define PRI_TON_UNKNOWN 0x0
...@@ -137,15 +144,44 @@ ...@@ -137,15 +144,44 @@
#define PRI_UNKNOWN 0x0 #define PRI_UNKNOWN 0x0
/* Presentation */ /* Presentation */
#define PRES_ALLOWED_USER_NUMBER_NOT_SCREENED 0x00 #define PRI_PRES_NUMBER_TYPE 0x03
#define PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN 0x01 #define PRI_PRES_USER_NUMBER_UNSCREENED 0x00
#define PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN 0x02 #define PRI_PRES_USER_NUMBER_PASSED_SCREEN 0x01
#define PRES_ALLOWED_NETWORK_NUMBER 0x03 #define PRI_PRES_USER_NUMBER_FAILED_SCREEN 0x02
#define PRES_PROHIB_USER_NUMBER_NOT_SCREENED 0x20 #define PRI_PRES_NETWORK_NUMBER 0x03
#define PRES_PROHIB_USER_NUMBER_PASSED_SCREEN 0x21
#define PRES_PROHIB_USER_NUMBER_FAILED_SCREEN 0x22 #define PRI_PRES_RESTRICTION 0x60
#define PRES_PROHIB_NETWORK_NUMBER 0x23 #define PRI_PRES_ALLOWED 0x00
#define PRES_NUMBER_NOT_AVAILABLE 0x43 #define PRI_PRES_RESTRICTED 0x20
#define PRI_PRES_UNAVAILABLE 0x40
#define PRI_PRES_RESERVED 0x60
#define PRES_ALLOWED_USER_NUMBER_NOT_SCREENED \
(PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_UNSCREENED)
#define PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN \
(PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_PASSED_SCREEN)
#define PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN \
(PRI_PRES_ALLOWED | PRI_PRES_USER_NUMBER_FAILED_SCREEN)
#define PRES_ALLOWED_NETWORK_NUMBER \
(PRI_PRES_ALLOWED | PRI_PRES_NETWORK_NUMBER)
#define PRES_PROHIB_USER_NUMBER_NOT_SCREENED \
(PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_UNSCREENED)
#define PRES_PROHIB_USER_NUMBER_PASSED_SCREEN \
(PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_PASSED_SCREEN)
#define PRES_PROHIB_USER_NUMBER_FAILED_SCREEN \
(PRI_PRES_RESTRICTED | PRI_PRES_USER_NUMBER_FAILED_SCREEN)
#define PRES_PROHIB_NETWORK_NUMBER \
(PRI_PRES_RESTRICTED | PRI_PRES_NETWORK_NUMBER)
#define PRES_NUMBER_NOT_AVAILABLE \
(PRI_PRES_UNAVAILABLE | PRI_PRES_NETWORK_NUMBER)
/* Causes for disconnection */ /* Causes for disconnection */
#define PRI_CAUSE_UNALLOCATED 1 #define PRI_CAUSE_UNALLOCATED 1
......
This diff is collapsed.
...@@ -32,122 +32,13 @@ ...@@ -32,122 +32,13 @@
#include "pri_q931.h" #include "pri_q931.h"
/* Protocol Profile field */ /* Protocol Profile field */
#define Q932_PROTOCOL_MASK 0x1F
#define Q932_PROTOCOL_ROSE 0x11 /* X.219 & X.229 */ #define Q932_PROTOCOL_ROSE 0x11 /* X.219 & X.229 */
#define Q932_PROTOCOL_CMIP 0x12 /* Q.941 */ #define Q932_PROTOCOL_CMIP 0x12 /* Q.941 */
#define Q932_PROTOCOL_ACSE 0x13 /* X.217 & X.227 */ #define Q932_PROTOCOL_ACSE 0x13 /* X.217 & X.227 */
#define Q932_PROTOCOL_GAT 0x16 #define Q932_PROTOCOL_GAT 0x16
#define Q932_PROTOCOL_EXTENSIONS 0x1F #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
#define COMP_TYPE_INVOKE 0xA1
#define COMP_TYPE_RETURN_RESULT 0xA2
#define COMP_TYPE_RETURN_ERROR 0xA3
#define COMP_TYPE_REJECT 0xA4
#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
#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_ANFPR_PATHREPLACEMENT 4
#define SS_DIVERTING_LEG_INFORMATION2 21
#define SS_MWI_ACTIVATE 80
#define SS_MWI_DEACTIVATE 81
#define SS_MWI_INTERROGATE 82
/* ROSE definitions and data structures */
#define INVOKE_IDENTIFIER 0x02
#define INVOKE_LINKED_IDENTIFIER 0x80
#define INVOKE_NULL_IDENTIFIER __USE_ASN1_NULL
/* 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_OBJECTDESCRIPTOR 0x07
#define ASN1_EXTERN 0x08
#define ASN1_REAL 0x09
#define ASN1_ENUMERATED 0x0a
#define ASN1_EMBEDDEDPDV 0x0b
#define ASN1_UTF8STRING 0x0c
#define ASN1_RELATIVEOBJECTID 0x0d
/* 0x0e & 0x0f are reserved for future ASN.1 editions */
#define ASN1_SEQUENCE 0x10
#define ASN1_SET 0x11
#define ASN1_NUMERICSTRING 0x12
#define ASN1_PRINTABLESTRING 0x13
#define ASN1_TELETEXSTRING 0x14
#define ASN1_IA5STRING 0x16
#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
/* ASN.1 Length masks */
#define ASN1_LEN_INDEF 0x80
#define INVOKE_OPERATION_INT __USE_ASN1_INTEGER
#define INVOKE_OBJECT_ID __USE_ASN1_OBJECTIDENTIFIER
/* Q.952 Divert cause */ /* Q.952 Divert cause */
#define Q952_DIVERT_REASON_UNKNOWN 0x00 #define Q952_DIVERT_REASON_UNKNOWN 0x00
#define Q952_DIVERT_REASON_CFU 0x01 #define Q952_DIVERT_REASON_CFU 0x01
...@@ -169,138 +60,6 @@ ...@@ -169,138 +60,6 @@
#define Q932_TON_SUBSCRIBER 0x04 #define Q932_TON_SUBSCRIBER 0x04
#define Q932_TON_ABBREVIATED 0x06 #define Q932_TON_ABBREVIATED 0x06
/* RLT related Operations */
#define RLT_SERVICE_ID 0x3e
#define RLT_OPERATION_IND 0x01
#define RLT_THIRD_PARTY 0x02
struct rose_component {
u_int8_t type;
u_int8_t len;
u_int8_t data[0];
};
#if 1
#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 != ASN1_LEN_INDEF) \
pri_message(pri, "Length (%d) of 0x%X component is too long\n", (component)->len, (component)->type); \
}
#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(pri, "XX Data:"); \
for (zzz = 0; zzz < (component)->len; ++zzz) \
pri_message(pri, " %02X", (component)->data[zzz]); \
pri_message(pri, "\n"); \
}
#endif
#define NEXT_COMPONENT(component, idx) \
(idx) += (component)->len + 2
#define SUB_COMPONENT(component, idx) \
(idx) += 2
#define CHECK_COMPONENT(component, comptype, message) \
if ((component)->type && ((component)->type & ASN1_TYPE_MASK) != (comptype)) { \
pri_message(pri, (message), (component)->type); \
asn1_dump(pri, (component), (component)->len+2); \
break; \
}
#define ASN1_GET_INTEGER(component, variable) \
do { \
int comp_idx; \
(variable) = 0; \
for (comp_idx = 0; comp_idx < (component)->len; ++comp_idx) \
(variable) = ((variable) << 8) | (component)->data[comp_idx]; \
} while (0)
#define ASN1_FIXUP_LEN(component, size) \
do { \
if ((component)->len == ASN1_LEN_INDEF) \
size += 2; \
} while (0)
#define ASN1_ADD_SIMPLE(component, comptype, ptr, idx) \
do { \
(component) = (struct rose_component *)&((ptr)[(idx)]); \
(component)->type = (comptype); \
(component)->len = 0; \
(idx) += 2; \
} while (0)
#define ASN1_ADD_BYTECOMP(component, comptype, ptr, idx, value) \
do { \
(component) = (struct rose_component *)&((ptr)[(idx)]); \
(component)->type = (comptype); \
(component)->len = 1; \
(component)->data[0] = (value); \
(idx) += 3; \
} while (0)
#define ASN1_ADD_WORDCOMP(component, comptype, ptr, idx, value) \
do { \
int __val = (value); \
int __i = 0; \
(component) = (struct rose_component *)&((ptr)[(idx)]); \
(component)->type = (comptype); \
if ((__val >> 24)) \
(component)->data[__i++] = (__val >> 24) & 0xff; \
if ((__val >> 16)) \
(component)->data[__i++] = (__val >> 16) & 0xff; \
if ((__val >> 8)) \
(component)->data[__i++] = (__val >> 8) & 0xff; \
(component)->data[__i++] = __val & 0xff; \
(component)->len = __i; \
(idx) += 2 + __i; \
} while (0)
#define ASN1_PUSH(stack, stackpointer, component) \
(stack)[(stackpointer)++] = (component)
#define ASN1_FIXUP(stack, stackpointer, data, idx) \
do { \
--(stackpointer); \
(stack)[(stackpointer)]->len = (unsigned char *)&((data)[(idx)]) - (unsigned char *)(stack)[(stackpointer)] - 2; \
} while (0)
/* Decoder for the invoke ROSE component */
int rose_invoke_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
/* Decoder for the return result ROSE component */
int rose_return_result_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
/* Decoder for the return error ROSE component */
int rose_return_error_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
/* Decoder for the reject ROSE component */
int rose_reject_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
int asn1_copy_string(char * buf, int buflen, struct rose_component *comp);
int asn1_string_encode(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len);
/* Get Name types from ASN.1 */
int asn1_name_decode(void * data, int len, char *namebuf, int buflen);
int typeofnumber_from_q931(struct pri *pri, int ton);
int redirectingreason_from_q931(struct pri *pri, int redirectingreason);
/* Queues an MWI apdu on a the given call */ /* Queues an MWI apdu on a the given call */
int mwi_message_send(struct pri *pri, q931_call *call, struct pri_sr *req, int activate); int mwi_message_send(struct pri *pri, q931_call *call, struct pri_sr *req, int activate);
...@@ -325,6 +84,18 @@ int pri_call_apdu_queue_cleanup(q931_call *call); ...@@ -325,6 +84,18 @@ int pri_call_apdu_queue_cleanup(q931_call *call);
/* Adds the "standard" APDUs to a call */ /* Adds the "standard" APDUs to a call */
int pri_call_add_standard_apdus(struct pri *pri, q931_call *call); int pri_call_add_standard_apdus(struct pri *pri, q931_call *call);
int asn1_dump(struct pri *pri, void *comp, int len); void asn1_dump(struct pri *ctrl, const unsigned char *start_asn1, const unsigned char *end);
/* Forward declare some ROSE structures for the following prototypes */
struct fac_extension_header;
struct rose_msg_invoke;
struct rose_msg_result;
struct rose_msg_error;
struct rose_msg_reject;
void rose_handle_invoke(struct pri *ctrl, q931_call *call, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_invoke *invoke);
void rose_handle_result(struct pri *ctrl, q931_call *call, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_result *result);
void rose_handle_error(struct pri *ctrl, q931_call *call, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_error *error);
void rose_handle_reject(struct pri *ctrl, q931_call *call, q931_ie *ie, const struct fac_extension_header *header, const struct rose_msg_reject *reject);
#endif /* _PRI_FACILITY_H */ #endif /* _PRI_FACILITY_H */
...@@ -33,6 +33,8 @@ ...@@ -33,6 +33,8 @@
#include <stddef.h> #include <stddef.h>
#include <sys/time.h> #include <sys/time.h>
#define ARRAY_LEN(arr) (sizeof(arr) / sizeof((arr)[0]))
#define DBGHEAD __FILE__ ":%d %s: " #define DBGHEAD __FILE__ ":%d %s: "
#define DBGINFO __LINE__,__PRETTY_FUNCTION__ #define DBGINFO __LINE__,__PRETTY_FUNCTION__
...@@ -51,6 +53,7 @@ enum q931_mode; ...@@ -51,6 +53,7 @@ enum q931_mode;
#define MAX_TIMERS 32 #define MAX_TIMERS 32
/*! \brief D channel controller structure */
struct pri { struct pri {
int fd; /* File descriptor for D-Channel */ int fd; /* File descriptor for D-Channel */
pri_io_cb read_func; /* Read data callback */ pri_io_cb read_func; /* Read data callback */
...@@ -128,10 +131,11 @@ struct pri { ...@@ -128,10 +131,11 @@ struct pri {
unsigned int q931_rxcount; unsigned int q931_rxcount;
#endif #endif
unsigned char last_invoke; /* Last ROSE invoke ID */ short last_invoke; /* Last ROSE invoke ID */
unsigned char sendfacility; unsigned char sendfacility;
}; };
/*! \brief New call setup parameter structure */
struct pri_sr { struct pri_sr {
int transmode; int transmode;
int channel; int channel;
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "pri_q921.h" #include "pri_q921.h"
#include "pri_q931.h" #include "pri_q931.h"
#include "pri_facility.h" #include "pri_facility.h"
#include "rose.h"
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -1015,8 +1016,7 @@ static FUNC_DUMP(dump_redirecting_number) ...@@ -1015,8 +1016,7 @@ static FUNC_DUMP(dump_redirecting_number)
prefix, ie->data[2] >> 7, redirection_reason2str(ie->data[2] & 0x7f), ie->data[2] & 0x7f); prefix, ie->data[2] >> 7, redirection_reason2str(ie->data[2] & 0x7f), ie->data[2] & 0x7f);
break; break;
} }
} } while(!(ie->data[i++]& 0x80));
while(!(ie->data[i++]& 0x80));
q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i); q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
pri_message(pri, " '%s' ]\n", cnum); pri_message(pri, " '%s' ]\n", cnum);
} }
...@@ -1038,8 +1038,7 @@ static FUNC_DUMP(dump_connected_number) ...@@ -1038,8 +1038,7 @@ static FUNC_DUMP(dump_connected_number)
prefix, ie->data[1] >> 7, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f); prefix, ie->data[1] >> 7, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
break; break;
} }
} } while(!(ie->data[i++]& 0x80));
while(!(ie->data[i++]& 0x80));
q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i); q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
pri_message(pri, " '%s' ]\n", cnum); pri_message(pri, " '%s' ]\n", cnum);
} }
...@@ -1063,8 +1062,7 @@ static FUNC_RECV(receive_redirecting_number) ...@@ -1063,8 +1062,7 @@ static FUNC_RECV(receive_redirecting_number)
call->redirectingreason = ie->data[i] & 0x0f; call->redirectingreason = ie->data[i] & 0x0f;
break; 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); q931_get_number((unsigned char *) call->redirectingnum, sizeof(call->redirectingnum), ie->data + i, ie->len - i);
return 0; return 0;
} }
...@@ -1353,15 +1351,19 @@ static FUNC_SEND(transmit_facility) ...@@ -1353,15 +1351,19 @@ static FUNC_SEND(transmit_facility)
if ((tmp->message == msgtype) && !tmp->sent) if ((tmp->message == msgtype) && !tmp->sent)
break; break;
} }
if (!tmp) /* No APDU found */ if (!tmp) /* No APDU found */
return 0; return 0;
if (pri->debug & PRI_DEBUG_APDU) {
pri_message(pri, "Adding facility ie contents to send message:\n");
facility_decode_dump(pri, tmp->apdu, tmp->apdu_len);
}
if (tmp->apdu_len > 235) { /* TODO: find out how much space we can use */ if (tmp->apdu_len > 235) { /* TODO: find out how much space we can use */
pri_message(pri, "Requested APDU (%d bytes) is too long\n", tmp->apdu_len); pri_message(pri, "Requested APDU (%d bytes) is too long\n", tmp->apdu_len);
return 0; return 0;
} }
memcpy(&ie->data[i], tmp->apdu, tmp->apdu_len); memcpy(&ie->data[i], tmp->apdu, tmp->apdu_len);
i += tmp->apdu_len; i += tmp->apdu_len;
tmp->sent = 1; tmp->sent = 1;
...@@ -1369,114 +1371,77 @@ static FUNC_SEND(transmit_facility) ...@@ -1369,114 +1371,77 @@ static FUNC_SEND(transmit_facility)
return i + 2; return i + 2;
} }
static FUNC_RECV(receive_facility) static int receive_facility(int full_ie, struct pri *ctrl, q931_call *call, int msgtype, q931_ie *ie, int len)
{ {
int i = 0; struct fac_extension_header header;
int protocol, next_protocol; struct rose_message rose;
struct rose_component *comp = NULL; const unsigned char *pos;
enum { const unsigned char *end;
Q932_STATE_NFE, /* Network facility extension */
Q932_STATE_NPP, /* Network protocol profile */
Q932_STATE_INTERPRETATION, /* Interpretation component */
Q932_STATE_SERVICE /* Service component(s) */
} state = Q932_STATE_SERVICE;
#define Q932_HANDLE_PROC(component, my_state, name, handler) \
case component: \
if(state > my_state) { \
pri_error(pri, "!! %s component received in wrong place\n"); \
break; \
} \
state = my_state; \
if (pri->debug) \
pri_message(pri, "Handle Q.932 %s component\n", name); \
(handler)(pri, call, ie, comp->data, comp->len); \
break;
#define Q932_HANDLE_NULL(component, my_state, name, handle) \
case component: \
if(state > my_state) { \
pri_error(pri, "!! %s component received in wrong place\n"); \
break; \
} \
state = my_state; \
if (pri->debug & PRI_DEBUG_APDU) \
pri_message(pri, "Q.932 %s component is not handled\n", name); \
break;
if (ie->len < 1) pos = ie->data;
return -1; end = ie->data + ie->len;
switch(next_protocol = protocol = (ie->data[i] & 0x1f)) { /* Make sure we have enough room for the protocol profile ie octet(s) */
case Q932_PROTOCOL_CMIP: if (end < pos + 2) {
case Q932_PROTOCOL_ACSE:
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, "!! Don't know how to handle Q.932 Protocol Profile of type 0x%X\n", protocol);
return -1; return -1;
case Q932_PROTOCOL_EXTENSIONS: }
state = Q932_STATE_NFE; switch (*pos & Q932_PROTOCOL_MASK) {
next_protocol = Q932_PROTOCOL_ROSE;
break;
case Q932_PROTOCOL_ROSE: case Q932_PROTOCOL_ROSE:
case Q932_PROTOCOL_EXTENSIONS:
break; break;
default: default:
pri_error(pri, "!! Invalid Q.932 Protocol Profile of type 0x%X received\n", protocol); case Q932_PROTOCOL_CMIP:
case Q932_PROTOCOL_ACSE:
if (ctrl->debug & PRI_DEBUG_APDU) {
pri_message(ctrl,
"!! Don't know how to handle Q.932 Protocol Profile type 0x%X\n",
*pos & Q932_PROTOCOL_MASK);
}
return -1; return -1;
} }
/* Service indicator octet - Just ignore for now */ if (!(*pos & 0x80)) {
if (!(ie->data[i] & 0x80)) /* DMS-100 Service indicator octet - Just ignore for now */
i++; ++pos;
i++; }
++pos;
if (ie->len < 3) if (ctrl->debug & PRI_DEBUG_APDU) {
asn1_dump(ctrl, pos, end);
}
pos = fac_dec_extension_header(ctrl, pos, end, &header);
if (!pos) {
return -1; return -1;
}
while ((i+1 < ie->len) && (&ie->data[i])) { if (header.npp_present) {
comp = (struct rose_component*)&ie->data[i]; if (ctrl->debug & PRI_DEBUG_APDU) {
if (comp->type) { pri_message(ctrl,
if (protocol == Q932_PROTOCOL_EXTENSIONS) { "!! Don't know how to handle Network Protocol Profile type 0x%X\n",
switch (comp->type) { header.npp);
Q932_HANDLE_NULL(COMP_TYPE_INTERPRETATION, Q932_STATE_INTERPRETATION, "Interpretation", NULL);
Q932_HANDLE_NULL(COMP_TYPE_NFE, Q932_STATE_NFE, "Network facility extensions", NULL);
Q932_HANDLE_NULL(COMP_TYPE_NETWORK_PROTOCOL_PROFILE, Q932_STATE_NPP, "Network protocol profile", NULL);
default:
protocol = next_protocol;
break;
}
}
switch (protocol) {
case Q932_PROTOCOL_ROSE:
switch (comp->type) {
Q932_HANDLE_PROC(COMP_TYPE_INVOKE, Q932_STATE_SERVICE, "ROSE Invoke", rose_invoke_decode);
Q932_HANDLE_PROC(COMP_TYPE_RETURN_RESULT, Q932_STATE_SERVICE, "ROSE return result", rose_return_result_decode);
Q932_HANDLE_PROC(COMP_TYPE_RETURN_ERROR, Q932_STATE_SERVICE, "ROSE return error", rose_return_error_decode);
Q932_HANDLE_PROC(COMP_TYPE_REJECT, Q932_STATE_SERVICE, "ROSE reject", rose_reject_decode);
default:
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, "Don't know how to handle ROSE component of type 0x%X\n", comp->type);
break;
}
break;
case Q932_PROTOCOL_CMIP:
switch (comp->type) {
default:
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, "Don't know how to handle CMIP component of type 0x%X\n", comp->type);
break;
}
break;
case Q932_PROTOCOL_ACSE:
switch (comp->type) {
default:
if (pri->debug & PRI_DEBUG_APDU)
pri_message(pri, "Don't know how to handle ACSE component of type 0x%X\n", comp->type);
break;
}
break;
}
} }
i += (comp->len + 2); return -1;
} }
#undef Q932_HANDLE
pos = rose_decode(ctrl, pos, end, &rose);
if (!pos) {
return -1;
}
switch (rose.type) {
case ROSE_COMP_TYPE_INVOKE:
rose_handle_invoke(ctrl, call, ie, &header, &rose.component.invoke);