[libpri-commits] rmudgett: branch 1.4 r766 - /branches/1.4/

SVN commits to the libpri project libpri-commits at lists.digium.com
Tue Apr 21 17:08:49 CDT 2009


Author: rmudgett
Date: Tue Apr 21 17:08:45 2009
New Revision: 766

URL: http://svn.digium.com/svn-view/libpri?view=rev&rev=766
Log:
ROSE ASN.1 facility encode and decode rewrite of existing messages.

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

Added:
    branches/1.4/asn1.h
      - copied unchanged from r765, team/rmudgett/facility/asn1.h
    branches/1.4/asn1_primitive.c
      - copied unchanged from r765, team/rmudgett/facility/asn1_primitive.c
    branches/1.4/rose.c
      - copied unchanged from r765, team/rmudgett/facility/rose.c
    branches/1.4/rose.h
      - copied unchanged from r765, team/rmudgett/facility/rose.h
    branches/1.4/rose_address.c
      - copied unchanged from r765, team/rmudgett/facility/rose_address.c
    branches/1.4/rose_etsi_aoc.c
      - copied unchanged from r765, team/rmudgett/facility/rose_etsi_aoc.c
    branches/1.4/rose_internal.h
      - copied unchanged from r765, team/rmudgett/facility/rose_internal.h
    branches/1.4/rose_other.c
      - copied unchanged from r765, team/rmudgett/facility/rose_other.c
    branches/1.4/rose_q931.c
      - copied unchanged from r765, team/rmudgett/facility/rose_q931.c
    branches/1.4/rose_qsig_ct.c
      - copied unchanged from r765, team/rmudgett/facility/rose_qsig_ct.c
    branches/1.4/rose_qsig_diversion.c
      - copied unchanged from r765, team/rmudgett/facility/rose_qsig_diversion.c
    branches/1.4/rose_qsig_mwi.c
      - copied unchanged from r765, team/rmudgett/facility/rose_qsig_mwi.c
    branches/1.4/rose_qsig_name.c
      - copied unchanged from r765, team/rmudgett/facility/rose_qsig_name.c
    branches/1.4/rosetest.c
      - copied unchanged from r765, team/rmudgett/facility/rosetest.c
Modified:
    branches/1.4/Makefile
    branches/1.4/libpri.h
    branches/1.4/pri_facility.c
    branches/1.4/pri_facility.h
    branches/1.4/pri_internal.h
    branches/1.4/q931.c

Modified: branches/1.4/Makefile
URL: http://svn.digium.com/svn-view/libpri/branches/1.4/Makefile?view=diff&rev=766&r1=765&r2=766
==============================================================================
--- branches/1.4/Makefile (original)
+++ branches/1.4/Makefile Tue Apr 21 17:08:45 2009
@@ -41,8 +41,42 @@
 
 STATIC_LIBRARY=libpri.a
 DYNAMIC_LIBRARY:=libpri.so.$(SONAME)
-STATIC_OBJS=copy_string.o pri.o q921.o prisched.o q931.o pri_facility.o version.o
-DYNAMIC_OBJS=copy_string.lo pri.lo q921.lo prisched.lo q931.lo pri_facility.lo version.lo
+STATIC_OBJS= \
+	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)
 INSTALL_PREFIX=$(DESTDIR)
 INSTALL_BASE=/usr
@@ -132,6 +166,9 @@
 pridump: pridump.o
 	$(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
 
 %.o: %.c

Modified: branches/1.4/libpri.h
URL: http://svn.digium.com/svn-view/libpri/branches/1.4/libpri.h?view=diff&rev=766&r1=765&r2=766
==============================================================================
--- branches/1.4/libpri.h (original)
+++ branches/1.4/libpri.h Tue Apr 21 17:08:45 2009
@@ -26,7 +26,14 @@
  * provided with that copy of Asterisk, instead of the license
  * 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
 #define _LIBPRI_H
 
@@ -103,13 +110,13 @@
 #define PRI_PROG_CALLER_RETURNED_TO_ISDN					(1 << 9)
 
 /* Numbering plan identifier */
-#define PRI_NPI_UNKNOWN					0x0
-#define PRI_NPI_E163_E164				0x1
-#define PRI_NPI_X121					0x3
-#define PRI_NPI_F69						0x4
-#define PRI_NPI_NATIONAL				0x8
-#define PRI_NPI_PRIVATE					0x9
-#define PRI_NPI_RESERVED				0xF
+#define PRI_NPI_UNKNOWN					0x0 /*!< Unknown numbering plan */
+#define PRI_NPI_E163_E164				0x1 /*!< ISDN/telephony numbering plan (public) */
+#define PRI_NPI_X121					0x3 /*!< Data numbering plan */
+#define PRI_NPI_F69						0x4 /*!< Telex numbering plan */
+#define PRI_NPI_NATIONAL				0x8 /*!< National standard numbering plan */
+#define PRI_NPI_PRIVATE					0x9 /*!< Private numbering plan */
+#define PRI_NPI_RESERVED				0xF /*!< Reserved for extension */
 
 /* Type of number */
 #define PRI_TON_UNKNOWN					0x0
@@ -137,15 +144,44 @@
 #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 PRI_PRES_NUMBER_TYPE				0x03
+#define PRI_PRES_USER_NUMBER_UNSCREENED		0x00
+#define PRI_PRES_USER_NUMBER_PASSED_SCREEN	0x01
+#define PRI_PRES_USER_NUMBER_FAILED_SCREEN	0x02
+#define PRI_PRES_NETWORK_NUMBER				0x03
+
+#define PRI_PRES_RESTRICTION				0x60
+#define PRI_PRES_ALLOWED					0x00
+#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 */
 #define PRI_CAUSE_UNALLOCATED					1

Modified: branches/1.4/pri_facility.c
URL: http://svn.digium.com/svn-view/libpri/branches/1.4/pri_facility.c?view=diff&rev=766&r1=765&r2=766
==============================================================================
--- branches/1.4/pri_facility.c (original)
+++ branches/1.4/pri_facility.c Tue Apr 21 17:08:45 2009
@@ -33,872 +33,511 @@
 #include "pri_q921.h"
 #include "pri_q931.h"
 #include "pri_facility.h"
+#include "rose.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <limits.h>
 
-static char *asn1id2text(int id)
-{
-	static char data[32];
-	static char *strings[] = {
-		"none",
-		"Boolean",
-		"Integer",
-		"Bit String",
-		"Octet String",
-		"NULL",
-		"Object Identifier",
-		"Object Descriptor",
-		"External Reference",
-		"Real Number",
-		"Enumerated",
-		"Embedded PDV",
-		"UTF-8 String",
-		"Relative Object ID",
-		"Reserved (0e)",
-		"Reserved (0f)",
-		"Sequence",
-		"Set",
-		"Numeric String",
-		"Printable String",
-		"Tele-Text String",
-		"IA-5 String",
-		"UTC Time",
-		"Generalized Time",
-	};
-	if (id > 0 && id <= 0x18) {
-		return strings[id];
-	} else {
-		sprintf(data, "Unknown (%02x)", id);
-		return data;
-	}
-}
-
-static int asn1_dumprecursive(struct pri *pri, void *comp_ptr, int len, int level)
-{
-	unsigned char *vdata = (unsigned char *)comp_ptr;
-	struct rose_component *comp;
-	int i = 0;
-	int j, k, l;
-	int clen = 0;
-
-	while (len > 0) {
-		GET_COMPONENT(comp, i, vdata, len);
-		pri_message(pri, "%*s%02X %04X", 2 * level, "", comp->type, comp->len);
-		if ((comp->type == 0) && (comp->len == 0))
-			return clen + 2;
-		if ((comp->type & ASN1_PC_MASK) == ASN1_PRIMITIVE) {
-			for (j = 0; j < comp->len; ++j)
-				pri_message(pri, " %02X", comp->data[j]);
-		}
-		if ((comp->type & ASN1_CLAN_MASK) == ASN1_UNIVERSAL) {
-			switch (comp->type & ASN1_TYPE_MASK) {
-			case 0:
-				pri_message(pri, " (none)");
-				break;
-			case ASN1_BOOLEAN:
-				pri_message(pri, " (BOOLEAN: %d)", comp->data[0]);
-				break;
-			case ASN1_INTEGER:
-				for (k = l = 0; k < comp->len; ++k)
-					l = (l << 8) | comp->data[k];
-				pri_message(pri, " (INTEGER: %d)", l);
-				break;
-			case ASN1_BITSTRING:
-				pri_message(pri, " (BITSTRING:");
-				for (k = 0; k < comp->len; ++k)
-				pri_message(pri, " %02x", comp->data[k]);
-				pri_message(pri, ")");
-				break;
-			case ASN1_OCTETSTRING:
-				pri_message(pri, " (OCTETSTRING:");
-				for (k = 0; k < comp->len; ++k)
-					pri_message(pri, " %02x", comp->data[k]);
-				pri_message(pri, ")");
-				break;
-			case ASN1_NULL:
-				pri_message(pri, " (NULL)");
-				break;
-			case ASN1_OBJECTIDENTIFIER:
-				pri_message(pri, " (OBJECTIDENTIFIER:");
-				for (k = 0; k < comp->len; ++k)
-					pri_message(pri, " %02x", comp->data[k]);
-				pri_message(pri, ")");
-				break;
-			case ASN1_ENUMERATED:
-				for (k = l = 0; k < comp->len; ++k)
-					l = (l << 8) | comp->data[k];
-				pri_message(pri, " (ENUMERATED: %d)", l);
-				break;
-			case ASN1_SEQUENCE:
-				pri_message(pri, " (SEQUENCE)");
-				break;
-			default:
-				pri_message(pri, " (component %02x - %s)", comp->type, asn1id2text(comp->type & ASN1_TYPE_MASK));
-				break;
-			}
-		}
-		else if ((comp->type & ASN1_CLAN_MASK) == ASN1_CONTEXT_SPECIFIC) {
-			pri_message(pri, " (CONTEXT SPECIFIC [%d])", comp->type & ASN1_TYPE_MASK);
-		}
-		else {
-			pri_message(pri, " (component %02x)", comp->type);
-		}
-		pri_message(pri, "\n");
-		if ((comp->type & ASN1_PC_MASK) == ASN1_CONSTRUCTOR)
-			j = asn1_dumprecursive(pri, comp->data, (comp->len ? comp->len : INT_MAX), level+1);
-		else
-			j = comp->len;
-		j += 2;
-		len -= j;
-		vdata += j;
-		clen += j;
-	}
-	return clen;
-}
-
-int asn1_dump(struct pri *pri, void *comp, int len)
-{
-	return asn1_dumprecursive(pri, comp, len, 0);
-}
-
-static unsigned char get_invokeid(struct pri *pri)
-{
-	return ++pri->last_invoke;
-}
-
-struct addressingdataelements_presentednumberunscreened {
-	char partyaddress[21];
-	char partysubaddress[21];
-	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'; \
-			pri_message(pri, "%s", message); \
-			msgptr = message; \
-		}
-
-static void dump_apdu(struct pri *pri, unsigned char *c, int len) 
-{
-	#define MAX_APDU_LENGTH	255
-	static char hexs[16] = "0123456789ABCDEF";
-	int i;
-	char message[(2 + MAX_APDU_LENGTH * 3 + 6 + MAX_APDU_LENGTH + 3)] = "";	/* please adjust here, if you make changes below! */
-	char *msgptr;
-	
-	msgptr = message;
-	*msgptr++ = ' ';
-	*msgptr++ = '[';
-	for (i=0; i<len; i++) {
-		PRI_CHECKOVERFLOW(3);
-		*msgptr++ = ' ';
-		*msgptr++ = hexs[(c[i] >> 4) & 0x0f];
-		*msgptr++ = hexs[(c[i]) & 0x0f];
-	}
-	PRI_CHECKOVERFLOW(6);
-	strcpy(msgptr, " ] - [");
-	msgptr += strlen(msgptr);
-	for (i=0; i<len; i++) {
-		PRI_CHECKOVERFLOW(1);
-		*msgptr++ = ((c[i] < ' ') || (c[i] > '~')) ? '.' : c[i];
-	}
-	PRI_CHECKOVERFLOW(2);
-	*msgptr++ = ']';
-	*msgptr++ = '\n';
-	*msgptr = '\0';
-	pri_message(pri, "%s", message);
-}
-#undef PRI_CHECKOVERFLOW
-
-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(pri, "!! Don't know how to convert Q.931 redirection reason %d to Q.SIG\n", redirectingreason);
-					/* Fall through */
-				default:
-					return QSIG_DIVERT_REASON_UNKNOWN;
-			}
+static short get_invokeid(struct pri *ctrl)
+{
+	return ++ctrl->last_invoke;
+}
+
+static int redirectingreason_from_q931(struct pri *ctrl, int redirectingreason)
+{
+	int value;
+
+	switch (ctrl->switchtype) {
+	case PRI_SWITCH_QSIG:
+		switch (redirectingreason) {
+		case PRI_REDIR_UNKNOWN:
+			value = QSIG_DIVERT_REASON_UNKNOWN;
+			break;
+		case PRI_REDIR_FORWARD_ON_BUSY:
+			value = QSIG_DIVERT_REASON_CFB;
+			break;
+		case PRI_REDIR_FORWARD_ON_NO_REPLY:
+			value = QSIG_DIVERT_REASON_CFNR;
+			break;
+		case PRI_REDIR_UNCONDITIONAL:
+			value = QSIG_DIVERT_REASON_CFU;
+			break;
+		case PRI_REDIR_DEFLECTION:
+		case PRI_REDIR_DTE_OUT_OF_ORDER:
+		case PRI_REDIR_FORWARDED_BY_DTE:
+			pri_message(ctrl,
+				"!! Don't know how to convert Q.931 redirection reason %d to Q.SIG\n",
+				redirectingreason);
+			/* Fall through */
 		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(pri, "!! 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(pri, "!! Unknown Q.SIG diversion reason %d\n", redirectingreason);
-					return PRI_REDIR_UNKNOWN;
-			}
+			value = QSIG_DIVERT_REASON_UNKNOWN;
+			break;
+		}
+		break;
+	default:
+		switch (redirectingreason) {
+		case PRI_REDIR_UNKNOWN:
+			value = Q952_DIVERT_REASON_UNKNOWN;
+			break;
+		case PRI_REDIR_FORWARD_ON_BUSY:
+			value = Q952_DIVERT_REASON_CFB;
+			break;
+		case PRI_REDIR_FORWARD_ON_NO_REPLY:
+			value = Q952_DIVERT_REASON_CFNR;
+			break;
+		case PRI_REDIR_DEFLECTION:
+			value = Q952_DIVERT_REASON_CD;
+			break;
+		case PRI_REDIR_UNCONDITIONAL:
+			value = Q952_DIVERT_REASON_CFU;
+			break;
+		case PRI_REDIR_DTE_OUT_OF_ORDER:
+		case PRI_REDIR_FORWARDED_BY_DTE:
+			pri_message(ctrl,
+				"!! Don't know how to convert Q.931 redirection reason %d to Q.952\n",
+				redirectingreason);
+			/* Fall through */
 		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(pri, "!! Dont' know how to convert Q.952 diversion reason IMMEDIATE to PRI analog\n");
-					return PRI_REDIR_UNKNOWN;	/* ??? */
-				default:
-					pri_message(pri, "!! 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:
+			value = Q952_DIVERT_REASON_UNKNOWN;
+			break;
+		}
+		break;
+	}
+
+	return value;
+}
+
+static int redirectingreason_for_q931(struct pri *ctrl, int redirectingreason)
+{
+	int value;
+
+	switch (ctrl->switchtype) {
+	case PRI_SWITCH_QSIG:
+		switch (redirectingreason) {
+		case QSIG_DIVERT_REASON_UNKNOWN:
+			value = PRI_REDIR_UNKNOWN;
+			break;
+		case QSIG_DIVERT_REASON_CFU:
+			value = PRI_REDIR_UNCONDITIONAL;
+			break;
+		case QSIG_DIVERT_REASON_CFB:
+			value = PRI_REDIR_FORWARD_ON_BUSY;
+			break;
+		case QSIG_DIVERT_REASON_CFNR:
+			value = PRI_REDIR_FORWARD_ON_NO_REPLY;
+			break;
 		default:
-			pri_message(pri, "!! 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)
-{
+			pri_message(ctrl, "!! Unknown Q.SIG diversion reason %d\n",
+				redirectingreason);
+			value = PRI_REDIR_UNKNOWN;
+			break;
+		}
+		break;
+	default:
+		switch (redirectingreason) {
+		case Q952_DIVERT_REASON_UNKNOWN:
+			value = PRI_REDIR_UNKNOWN;
+			break;
+		case Q952_DIVERT_REASON_CFU:
+			value = PRI_REDIR_UNCONDITIONAL;
+			break;
+		case Q952_DIVERT_REASON_CFB:
+			value = PRI_REDIR_FORWARD_ON_BUSY;
+			break;
+		case Q952_DIVERT_REASON_CFNR:
+			value = PRI_REDIR_FORWARD_ON_NO_REPLY;
+			break;
+		case Q952_DIVERT_REASON_CD:
+			value = PRI_REDIR_DEFLECTION;
+			break;
+		case Q952_DIVERT_REASON_IMMEDIATE:
+			pri_message(ctrl,
+				"!! Dont' know how to convert Q.952 diversion reason IMMEDIATE to PRI analog\n");
+			value = PRI_REDIR_UNKNOWN;	/* ??? */
+			break;
+		default:
+			pri_message(ctrl, "!! Unknown Q.952 diversion reason %d\n",
+				redirectingreason);
+			value = PRI_REDIR_UNKNOWN;
+			break;
+		}
+		break;
+	}
+
+	return value;
+}
+
+/*!
+ * \brief Convert the Q.931 type-of-number field to facility.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param ton Q.931 ton/plan octet.
+ *
+ * \return PartyNumber enumeration value.
+ */
+static int typeofnumber_from_q931(struct pri *ctrl, int ton)
+{
+	int value;
+
+	switch ((ton >> 4) & 0x03) {
+	default:
+		pri_message(ctrl, "!! Unsupported Q.931 TypeOfNumber value (%d)\n", ton);
+		/* fall through */
+	case PRI_TON_UNKNOWN:
+		value = Q932_TON_UNKNOWN;
+		break;
+	case PRI_TON_INTERNATIONAL:
+		value = Q932_TON_INTERNATIONAL;
+		break;
+	case PRI_TON_NATIONAL:
+		value = Q932_TON_NATIONAL;
+		break;
+	case PRI_TON_NET_SPECIFIC:
+		value = Q932_TON_NET_SPECIFIC;
+		break;
+	case PRI_TON_SUBSCRIBER:
+		value = Q932_TON_SUBSCRIBER;
+		break;
+	case PRI_TON_ABBREVIATED:
+		value = Q932_TON_ABBREVIATED;
+		break;
+	}
+
+	return value;
+}
+
+static int typeofnumber_for_q931(struct pri *ctrl, int ton)
+{
+	int value;
+
 	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(pri, "!! Invalid Q.932 TypeOfNumber %d\n", ton);
-			return PRI_TON_UNKNOWN;
-	}
-}
-
-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;
-
-	if (comp->len == ASN1_LEN_INDEF) {
-		datalen = strlen((char *)comp->data);
-		res = datalen + 2;
-	} else
-		datalen = res = comp->len;
-
-	if (datalen > buflen) {
-		/* Truncate */
-		datalen = buflen;
-	}
-	memcpy(namebuf, comp->data, datalen);
-	return res + 2;
-}
-
-int asn1_string_encode(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len)
-{
-	struct rose_component *comp = NULL;
-	
-	if (len < 2 + src_len)
-		return -1;
-
-	if (max_len && (src_len > max_len))
-		src_len = max_len;
-
-	comp = (struct rose_component *)data;
-	comp->type = asn1_type;
-	comp->len = src_len;
-	memcpy(comp->data, src, src_len);
-	
-	return 2 + src_len;
-}
-
-int asn1_copy_string(char * buf, int buflen, struct rose_component *comp)
-{
-	int res;
-	int datalen;
-
-	if ((comp->len > buflen) && (comp->len != ASN1_LEN_INDEF))
-		return -1;
-
-	if (comp->len == ASN1_LEN_INDEF) {
-		datalen = strlen((char*)comp->data);
-		res = datalen + 2;
-	} else
-		res = datalen = comp->len;
-
-	memcpy(buf, comp->data, datalen);
-	buf[datalen] = 0;
-
-	return res;
-}
-
-static int rose_number_digits_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 datalen = 0;
-	int res = 0;
-
-	do {
-		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);
-			return -1;
-		}
-		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;
-	}
-	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)
-{
-	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 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);
-		if (res < 0)
-			return -1;
-		value->ton = ton;
-
-		return res + 3;
-
-	} while(0);
-	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;
-	struct rose_component *comp = NULL;
-	unsigned char *vdata = data;
-	int res = 0;
-
-	do {
-		GET_COMPONENT(comp, i, vdata, len);
-
-		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);
-			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);
-			if (res < 0)
-				return -1;
-			value->npi = PRI_NPI_UNKNOWN;
-			value->ton = PRI_TON_UNKNOWN;
-			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);
-			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);
-			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);
-			if (res < 0)
-			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);
-			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);
-			return -1;
-		}
-		ASN1_FIXUP_LEN(comp, res);
-		NEXT_COMPONENT(comp, i);
-		if(i < len)
-			pri_message(pri, "!! not all information is handled from Address component\n");
-		return res + 2;
-	}
-	while (0);
-
-	return -1;
-}
-
-static int rose_presented_number_unscreened_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;
-
-	/* Fill in default values */
-	value->ton = PRI_TON_UNKNOWN;
-	value->npi = PRI_NPI_E163_E164;
-	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] presentationAllowedNumber */
-			value->pres = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
-			size = rose_address_decode(pri, call, comp->data, comp->len, value);
-			ASN1_FIXUP_LEN(comp, size);
-			return size + 2;
-		case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1):		/* [1] IMPLICIT presentationRestricted */
-			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_NOT_SCREENED;
-			return 2;
-		case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2):		/* [2] IMPLICIT numberNotAvailableDueToInterworking */
-			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;
-			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;
-			ASN1_FIXUP_LEN(comp, size);
-			return size + 2;
-		default:
-			pri_message(pri, "Invalid PresentedNumberUnscreened component 0x%X\n", comp->type);
-		}
-		return -1;
-	}
-	while (0);
-
-	return -1;
-}
-
-static int rose_diverting_leg_information2_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
-{
-	int i = 0;
-	int diversion_counter;
-	int diversion_reason;
-	char origcalledname[50] = "", redirectingname[50] = "";
-	struct addressingdataelements_presentednumberunscreened divertingnr;
- 	struct addressingdataelements_presentednumberunscreened originalcallednr;
-	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 */
-		pri_message(pri, "Invalid DivertingLegInformation2Type 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 {
-		/* diversionCounter stuff */
-		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");
-		ASN1_GET_INTEGER(comp, diversion_counter);
-		NEXT_COMPONENT(comp, i);
-
-		/* diversionReason stuff */
-		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);
-
-		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)) {
-			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]);
-				if (pri->debug & PRI_DEBUG_APDU)
-					pri_message(pri, "    Received reason for original redirection %d\n", call->origredirectingreason);
-				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)
-					return -1;
-				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)
-					return -1;
-				ASN1_FIXUP_LEN(comp, res);
-				comp->len = res;
-				if (pri->debug & PRI_DEBUG_APDU) {
-					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)
-					return -1;
-				ASN1_FIXUP_LEN(comp, res);
-				comp->len = res;
-				if (pri->debug & PRI_DEBUG_APDU)
-					pri_message(pri, "    Received RedirectingName '%s'\n", redirectingname);
-				break;
-			case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4):
-				res = asn1_name_decode(comp->data, comp->len, origcalledname, sizeof(origcalledname));
-				if (res < 0)
-					return -1;
-				ASN1_FIXUP_LEN(comp, res);
-				comp->len = res;
-				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 */
-				}
-				pri_message(pri, "!! Invalid DivertingLegInformation2 component received 0x%X\n", comp->type);
-				return -1;
-			}
-		}
-
-		if (divertingnr.pres >= 0) {
-			call->redirectingplan = divertingnr.npi;
-			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));
-		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;
-	struct rose_component *comp, *compstk[10];
+	default:
+		pri_message(ctrl, "!! Invalid TypeOfNumber %d\n", ton);
+		/* fall through */
+	case Q932_TON_UNKNOWN:
+		value = PRI_TON_UNKNOWN;
+		break;
+	case Q932_TON_INTERNATIONAL:
+		value = PRI_TON_INTERNATIONAL;
+		break;
+	case Q932_TON_NATIONAL:
+		value = PRI_TON_NATIONAL;
+		break;
+	case Q932_TON_NET_SPECIFIC:
+		value = PRI_TON_NET_SPECIFIC;
+		break;
+	case Q932_TON_SUBSCRIBER:
+		value = PRI_TON_SUBSCRIBER;
+		break;
+	case Q932_TON_ABBREVIATED:
+		value = PRI_TON_ABBREVIATED;
+		break;
+	}
+
+	return value << 4;
+}
+
+/*!
+ * \internal
+ * \brief Convert the Q.931 numbering plan field to facility.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param plan Q.931 ton/plan octet.
+ *
+ * \return PartyNumber enumeration value.
+ */
+static int numbering_plan_from_q931(struct pri *ctrl, int plan)
+{
+	int value;
+
+	switch (plan & 0x0F) {
+	default:
+		pri_message(ctrl, "!! Unsupported Q.931 numbering plan value (%d)\n", plan);
+		/* fall through */
+	case PRI_NPI_UNKNOWN:
+		value = 0;	/* unknown */
+		break;
+	case PRI_NPI_E163_E164:
+		value = 1;	/* public */
+		break;
+	case PRI_NPI_X121:
+		value = 3;	/* data */
+		break;
+	case PRI_NPI_F69:
+		value = 4;	/* telex */
+		break;
+	case PRI_NPI_NATIONAL:
+		value = 8;	/* nationalStandard */
+		break;
+	case PRI_NPI_PRIVATE:
+		value = 5;	/* private */
+		break;
+	}
+
+	return value;
+}
+
+/*!
+ * \internal
+ * \brief Convert the PartyNumber numbering plan to Q.931 plan field value.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param plan PartyNumber enumeration value.
+ *
+ * \return Q.931 plan field value.
+ */
+static int numbering_plan_for_q931(struct pri *ctrl, int plan)
+{
+	int value;
+
+	switch (plan) {
+	default:
+		pri_message(ctrl,
+			"!! Unsupported PartyNumber to Q.931 numbering plan value (%d)\n", plan);
+		/* fall through */
+	case 0:	/* unknown */
+		value = PRI_NPI_UNKNOWN;
+		break;
+	case 1:	/* public */
+		value = PRI_NPI_E163_E164;
+		break;
+	case 3:	/* data */
+		value = PRI_NPI_X121;
+		break;
+	case 4:	/* telex */
+		value = PRI_NPI_F69;
+		break;
+	case 5:	/* private */
+		value = PRI_NPI_PRIVATE;
+		break;
+	case 8:	/* nationalStandard */
+		value = PRI_NPI_NATIONAL;
+		break;
+	}
+
+	return value;
+}
+
+/*!
+ * \internal
+ * \brief Convert the Q.931 number presentation field to facility.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param presentation Q.931 presentation/screening octet.
+ * \param number_present Non-zero if the number is available.
+ *
+ * \return Presented<Number/Address><Screened/Unscreened> enumeration value.
+ */
+static int presentation_from_q931(struct pri *ctrl, int presentation, int number_present)
+{
+	int value;
+
+	switch (presentation & PRI_PRES_RESTRICTION) {
+	case PRI_PRES_ALLOWED:
+		value = 0;	/* presentationAllowed<Number/Address> */
+		break;
+	default:
+		pri_message(ctrl, "!! Unsupported Q.931 number presentation value (%d)\n",
+			presentation);
+		/* fall through */
+	case PRI_PRES_RESTRICTED:
+		if (number_present) {
+			value = 3;	/* presentationRestricted<Number/Address> */
+		} else {
+			value = 1;	/* presentationRestricted */
+		}
+		break;
+	case PRI_PRES_UNAVAILABLE:
+		value = 2;	/* numberNotAvailableDueToInterworking */
+		break;
+	}
+
+	return value;
+}
+
+/*!
+ * \internal
+ * \brief Convert the Presented<Number/Address><Screened/Unscreened> presentation
+ * to Q.931 presentation field value.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param presentation Presented<Number/Address><Screened/Unscreened> value.
+ *
+ * \return Q.931 presentation field value.
+ */
+static int presentation_for_q931(struct pri *ctrl, int presentation)
+{
+	int value;
+
+	switch (presentation) {
+	case 0:	/* presentationAllowed<Number/Address> */
+		value = PRI_PRES_ALLOWED;
+		break;
+	default:
+		pri_message(ctrl,
+			"!! Unsupported Presented<Number/Address><Screened/Unscreened> to Q.931 value (%d)\n",
+			presentation);
+		/* fall through */
+	case 1:	/* presentationRestricted */
+	case 3:	/* presentationRestricted<Number/Address> */
+		value = PRI_PRES_RESTRICTED;
+		break;
+	case 2:	/* numberNotAvailableDueToInterworking */
+		value = PRI_PRES_UNAVAILABLE;
+		break;
+	}
+
+	return value;
+}
+
+/*!
+ * \internal
+ * \brief Encode the Q.SIG DivertingLegInformation2 invoke message.
+ *
+ * \param ctrl D channel controller for diagnostic messages or global options.
+ * \param pos Starting position to encode the facility ie contents.
+ * \param end End of facility ie contents encoding data buffer.
+ * \param call Call leg from which to encode diversion leg 2.
+ *
+ * \retval Start of the next ASN.1 component to encode on success.
+ * \retval NULL on error.
+ */
+static unsigned char *enc_qsig_diverting_leg_information2(struct pri *ctrl,
+	unsigned char *pos, unsigned char *end, q931_call *call)
+{
+	struct fac_extension_header header;
+	struct rose_msg_invoke msg;
+
+	memset(&header, 0, sizeof(header));
+	header.nfe_present = 1;
+	header.nfe.source_entity = 0;	/* endPINX */
+	header.nfe.destination_entity = 0;	/* endPINX */
+	header.interpretation_present = 1;
+	header.interpretation = 0;	/* discardAnyUnrecognisedInvokePdu */
+	pos = facility_encode_header(ctrl, pos, end, &header);
+	if (!pos) {
+		return NULL;
+	}
+
+	memset(&msg, 0, sizeof(msg));

[... 3787 lines stripped ...]



More information about the libpri-commits mailing list