[Pkg-voip-commits] r931 - libpri/trunk/debian/patches

Mark Purcell msp at costa.debian.org
Tue Nov 1 21:34:17 UTC 2005


Author: msp
Date: 2005-11-01 21:34:16 +0000 (Tue, 01 Nov 2005)
New Revision: 931

Removed:
   libpri/trunk/debian/patches/bristuff-0.2.0-RC8l.dpatch
   libpri/trunk/debian/patches/bristuff_2.0.0-RC8h.dpatch
   libpri/trunk/debian/patches/bristuff_2.0.0-RC8j.dpatch
Log:
Bristuff requires update for beta

Deleted: libpri/trunk/debian/patches/bristuff-0.2.0-RC8l.dpatch
===================================================================
--- libpri/trunk/debian/patches/bristuff-0.2.0-RC8l.dpatch	2005-11-01 21:30:40 UTC (rev 930)
+++ libpri/trunk/debian/patches/bristuff-0.2.0-RC8l.dpatch	2005-11-01 21:34:16 UTC (rev 931)
@@ -1,4562 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## bristuff-0.2.0-RC8l.dpatch by  <santiago at unicauca.edu.co>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: No description.
-
- at DPATCH@
-diff -urNad libpri-1.0.9/libpri.h /tmp/dpep.9zBkJK/libpri-1.0.9/libpri.h
---- libpri-1.0.9/libpri.h	2005-04-04 02:19:59.000000000 -0500
-+++ /tmp/dpep.9zBkJK/libpri-1.0.9/libpri.h	2005-07-30 01:24:09.000000000 -0500
-@@ -26,8 +26,12 @@
- #define _LIBPRI_H
- 
- /* Node types */
--#define PRI_NETWORK		1
-+#define PRI_NETWORK		1	/* PTP modes, default for PRI */
- #define PRI_CPE			2
-+#define BRI_NETWORK_PTMP	3	/* PTMP modes, default for BRI */
-+#define BRI_CPE_PTMP		4	
-+#define BRI_NETWORK		5	/* PTP modes */
-+#define BRI_CPE			6	
- 
- /* Debugging */
- #define PRI_DEBUG_Q921_RAW		(1 << 0)	/* Show raw HDLC frames */
-@@ -72,6 +76,12 @@
- #define PRI_EVENT_HANGUP_REQ	15	/* Requesting the higher layer to hangup */
- #define PRI_EVENT_NOTIFY	16	/* Notification received */
- #define PRI_EVENT_PROGRESS	17	/* When we get CALL_PROCEEDING or PROGRESS */
-+#define PRI_EVENT_HOLD_REQ	18	/* R */
-+#define PRI_EVENT_RETRIEVE_REQ  19
-+#define PRI_EVENT_SUSPEND_REQ   20	/* park */
-+#define PRI_EVENT_RESUME_REQ    21	/* unpark */
-+#define PRI_EVENT_DISPLAY_RECEIVED    22
-+#define PRI_EVENT_FACILITY	23	/* Facility */
- 
- /* Simple states */
- #define PRI_STATE_DOWN		0
-@@ -95,6 +105,18 @@
- #define PRI_TON_ABBREVIATED				0x6
- #define PRI_TON_RESERVED				0x7
- 
-+/* Progress indicator values */
-+#define PRI_PROG_CALL_NOT_E2E_ISDN						(1 << 0)
-+#define PRI_PROG_CALLED_NOT_ISDN						(1 << 1)
-+#define PRI_PROG_CALLER_NOT_ISDN						(1 << 2)
-+#define PRI_PROG_INBAND_AVAILABLE						(1 << 3)
-+#define PRI_PROG_DELAY_AT_INTERF						(1 << 4)
-+#define PRI_PROG_INTERWORKING_WITH_PUBLIC				(1 << 5)
-+#define PRI_PROG_INTERWORKING_NO_RELEASE				(1 << 6)
-+#define PRI_PROG_INTERWORKING_NO_RELEASE_PRE_ANSWER		(1 << 7)
-+#define PRI_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER	(1 << 8)
-+#define PRI_PROG_CALLER_RETURNED_TO_ISDN					(1 << 9)
-+
- /* Redirection reasons */
- #define PRI_REDIR_UNKNOWN				0x0
- #define PRI_REDIR_FORWARD_ON_BUSY		0x1
-@@ -151,6 +173,7 @@
- #define PRI_CAUSE_INCOMING_CALL_BARRED     		54
- #define PRI_CAUSE_BEARERCAPABILITY_NOTAUTH		57
- #define PRI_CAUSE_BEARERCAPABILITY_NOTAVAIL     58
-+#define PRI_CAUSE_UNKNOWN				63
- #define PRI_CAUSE_BEARERCAPABILITY_NOTIMPL		65
- #define PRI_CAUSE_CHAN_NOT_IMPLEMENTED     		66
- #define PRI_CAUSE_FACILITY_NOT_IMPLEMENTED      69
-@@ -231,11 +254,13 @@
- #define PRI_NSF_ATT_MULTIQUEST         0xF0
- #define PRI_NSF_CALL_REDIRECTION_SERVICE       0xF7
- 
-+typedef struct q921_call q921_call;
- typedef struct q931_call q931_call;
- 
- typedef struct pri_event_generic {
- 	/* Events with no additional information fall in this category */
- 	int e;
-+	int tei;
- } pri_event_generic;
- 
- typedef struct pri_event_error {
-@@ -252,12 +277,14 @@
- 	int e;
- 	int channel;
- 	int cref;
-+	int progressmask;
- 	q931_call *call;
- } pri_event_ringing;
- 
- typedef struct pri_event_answer {
- 	int e;
- 	int channel;
-+	int tei;				/* belongs to this tei */
- 	int cref;
- 	q931_call *call;
- } pri_event_answer;
-@@ -275,8 +302,11 @@
- 	int e;
- 	int channel;				/* Channel requested */
- 	int callingpres;			/* Presentation of Calling CallerID */
-+	int callingpresuser;			/* Presentation of Calling CallerID */
- 	int callingplan;			/* Dialing plan of Calling entity */
--	char callingnum[256];		/* Calling number */
-+	int callingplanuser;			/* Dialing plan of Calling entity */
-+	char callingnum[256];		/* Calling number, network provided */
-+	char callingnumuser[256];		/* Calling number, user provided */
- 	char callingname[256];		/* Calling name (if provided) */
- 	int calledplan;				/* Dialing plan of Called number */
- 	int ani2;                   /* ANI II */
-@@ -289,6 +319,7 @@
- 	int layer1;				/* User layer 1 */
- 	int complete;				/* Have we seen "Complete" i.e. no more number? */
- 	q931_call *call;			/* Opaque call pointer */
-+	int tei;				/* belongs to this tei */
- 	char callingsubaddr[256];		/* Calling parties subaddress */
- } pri_event_ring;
- 
-@@ -297,6 +328,8 @@
- 	int channel;				/* Channel requested */
- 	int cause;
- 	int cref;
-+	int tei;
-+	int inband_progress;
- 	q931_call *call;			/* Opaque call pointer */
- } pri_event_hangup;	
- 
-@@ -308,11 +341,14 @@
- typedef struct pri_event_proceeding {
- 	int e;
- 	int channel;
-+	int cause;
-+	q931_call *call;			/* Opaque call pointer */
- } pri_event_proceeding;
-  
- typedef struct pri_event_setup_ack {
- 	int e;
- 	int channel;
-+	q931_call *call;			/* Opaque call pointer */
- } pri_event_setup_ack;
- 
- typedef struct pri_event_notify {
-@@ -321,20 +357,80 @@
- 	int info;
- } pri_event_notify;
- 
-+typedef struct pri_event_hold_req {
-+	int e;
-+	int channel;
-+	int cref;
-+	int tei;
-+	q931_call *call;
-+} pri_event_hold_req;
-+
-+/* euroisdn faciltiy fun */
-+typedef struct pri_event_facility_req {
-+	int e;
-+	int channel;
-+	int cref;
-+	int tei;
-+	int operation;
-+	char forwardnum[256];		/* Redirection destination */
-+	q931_call *call;
-+} pri_event_facility_req;
-+
-+typedef struct pri_event_retrieve_req {
-+	int e;
-+	int channel;
-+	int cref;
-+	int tei;
-+	q931_call *call;
-+} pri_event_retrieve_req;
-+
-+typedef struct pri_event_suspend_req {
-+	int e;
-+	int channel;
-+	int cref;
-+	int tei;
-+	q931_call *call;
-+	char callid[10];
-+} pri_event_suspend_req;
-+
-+typedef struct pri_event_resume_req {
-+	int e;
-+	int channel;
-+	int cref;
-+	int tei;
-+	q931_call *call;
-+	char callid[10];
-+} pri_event_resume_req;
-+
-+typedef struct pri_event_display {
-+	int e;
-+	int channel;		
-+	int cref;			
-+	q931_call *call;
-+	char text[256];
-+} pri_event_display;
-+
-+
- typedef union {
- 	int e;
- 	pri_event_generic gen;		/* Generic view */
- 	pri_event_restart restart;	/* Restart view */
- 	pri_event_error	  err;		/* Error view */
- 	pri_event_facname facname;	/* Caller*ID Name on Facility */
-+	pri_event_facility_req facility;	/* sservices */
- 	pri_event_ring	  ring;		/* Ring */
- 	pri_event_hangup  hangup;	/* Hang up */
- 	pri_event_ringing ringing;	/* Ringing */
--	pri_event_ringing answer;	/* Answer */
-+	pri_event_answer  answer;	/* Answer */
- 	pri_event_restart_ack restartack;	/* Restart Acknowledge */
- 	pri_event_proceeding  proceeding;	/* Call proceeding & Progress */
- 	pri_event_setup_ack   setup_ack;	/* SETUP_ACKNOWLEDGE structure */
- 	pri_event_notify notify;		/* Notification */
-+	pri_event_hold_req hold_req;
-+	pri_event_retrieve_req retrieve_req;
-+	pri_event_suspend_req suspend_req;
-+	pri_event_resume_req resume_req;
-+	pri_event_display display;
- } pri_event;
- 
- struct pri;
-@@ -389,6 +485,12 @@
- /* Send a digit in overlap mode */
- extern int pri_information(struct pri *pri, q931_call *call, char digit);
- 
-+/* Send a INFO msg with display ie  */
-+extern int pri_information_display(struct pri *pri, q931_call *call, char *display);
-+
-+/* add a display ie to a call, so it can be sent with the next message */
-+extern int pri_add_display(struct pri *pri, q931_call *call, char *display);
-+
- /* Answer the incomplete(call without called number) call on the given channel.
-    Set non-isdn to non-zero if you are not connecting to ISDN equipment */
- extern int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn);
-@@ -397,6 +499,33 @@
-    Set non-isdn to non-zero if you are not connecting to ISDN equipment */
- extern int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
- 
-+/* Ack a HOLD_REQ */
-+extern int pri_hold_acknowledge(struct pri *pri, q931_call *call);
-+
-+/* Reject a HOLD_REQ */
-+extern int pri_hold_reject(struct pri *pri, q931_call *call);
-+
-+/* Ack a RETRIEVE_REQ */
-+extern int pri_retrieve_acknowledge(struct pri *pri, q931_call *call, int channel);
-+
-+/* Reject a RETRIEVE_REQ */
-+extern int pri_retrieve_reject(struct pri *pri, q931_call *call);
-+
-+/* Ack a SUSPEND_REQ */
-+extern int pri_suspend_acknowledge(struct pri *pri, q931_call *call, char *display);
-+
-+/* Reject a SUSPEND_REQ */
-+extern int pri_suspend_reject(struct pri *pri, q931_call *call, char *display);
-+
-+/* Reject a RESUME_REQ */
-+extern int pri_resume_reject(struct pri *pri, q931_call *call, char *display);
-+
-+/* Ack a RESUME_REQ */
-+extern int pri_resume_acknowledge(struct pri *pri, q931_call *call, int channel, char *display);
-+
-+/* Send a Facility Message */
-+extern int pri_facility(struct pri *pri, q931_call *call, int operation, char *arguments);
-+
- /* Set CRV reference for GR-303 calls */
- 
- 
-diff -urNad libpri-1.0.9/Makefile /tmp/dpep.9zBkJK/libpri-1.0.9/Makefile
---- libpri-1.0.9/Makefile	2005-05-10 22:37:29.000000000 -0500
-+++ /tmp/dpep.9zBkJK/libpri-1.0.9/Makefile	2005-07-30 01:24:09.000000000 -0500
-@@ -36,7 +36,7 @@
- DYNAMIC_LIBRARY=libpri.so.1.0
- STATIC_OBJS=pri.o q921.o prisched.o q931.o
- DYNAMIC_OBJS=pri.lo q921.lo prisched.lo q931.lo
--CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g $(ALERTING) $(LIBPRI_COUNTERS)
-+CFLAGS=-Wall -Wstrict-prototypes -Wmissing-prototypes -g $(ALERTING) $(LIBPRI_COUNTERS)
- INSTALL_PREFIX=
- ifeq (${OSARCH},Linux)
- LDCONFIG_FLAGS=-n
-diff -urNad libpri-1.0.9/pri.c /tmp/dpep.9zBkJK/libpri-1.0.9/pri.c
---- libpri-1.0.9/pri.c	2004-12-15 13:06:38.000000000 -0500
-+++ /tmp/dpep.9zBkJK/libpri-1.0.9/pri.c	2005-07-30 01:24:09.000000000 -0500
-@@ -33,6 +33,14 @@
- 		return "Network";
- 	case PRI_CPE:
- 		return "CPE";
-+	case BRI_NETWORK:
-+		return "Network";
-+	case BRI_CPE:
-+		return "CPE";
-+	case BRI_NETWORK_PTMP:
-+		return "Network (PtMP)";
-+	case BRI_CPE_PTMP:
-+		return "CPE (PtMP)";
- 	default:
- 		return "Invalid value";
- 	}
-@@ -113,7 +121,7 @@
- 		}
- 		/* Start Q.921 layer, Wait if we're the network */
- 		if (p)
--			q921_start(p, p->localtype == PRI_CPE);
-+			q921_start(p, p->localtype == PRI_CPE, 0);
- 	}
- 	return p;
- }
-@@ -270,6 +278,21 @@
- 	return q931_notify(pri, call, channel, info);
- }
- 
-+int pri_information_display(struct pri *pri, q931_call *call, char *display)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_information_display(pri, call, display);
-+}
-+
-+int pri_add_display(struct pri *pri, q931_call *call, char *display)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_add_display(pri, call, display);
-+}
-+
-+
- void pri_destroycall(struct pri *pri, q931_call *call)
- {
- 	if (pri && call)
-@@ -291,6 +314,69 @@
- 	return q931_connect(pri, call, channel, nonisdn);
- }
- 
-+int pri_hold_acknowledge(struct pri *pri, q931_call *call)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_hold_acknowledge(pri, call);
-+}
-+
-+int pri_hold_reject(struct pri *pri, q931_call *call)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_hold_reject(pri, call);
-+}
-+
-+int pri_retrieve_acknowledge(struct pri *pri, q931_call *call, int channel)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_retrieve_acknowledge(pri, call, channel);
-+}
-+
-+int pri_retrieve_reject(struct pri *pri, q931_call *call)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_retrieve_reject(pri, call);
-+}
-+
-+int pri_suspend_acknowledge(struct pri *pri, q931_call *call, char *display)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_suspend_acknowledge(pri, call, display);
-+}
-+
-+int pri_suspend_reject(struct pri *pri, q931_call *call, char *display)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_suspend_reject(pri, call, display);
-+}
-+
-+int pri_resume_reject(struct pri *pri, q931_call *call, char *display)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_resume_reject(pri, call, display);
-+}
-+
-+int pri_resume_acknowledge(struct pri *pri, q931_call *call, int channel, char *display)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_resume_acknowledge(pri, call, channel, display);
-+}
-+
-+int pri_facility(struct pri *pri, q931_call *call, int operation, char *arguments)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_facility(pri, call, operation, arguments);
-+}
-+
- #if 0
- /* deprecated routines, use pri_hangup */
- int pri_release(struct pri *pri, q931_call *call, int cause)
-@@ -310,12 +396,24 @@
- 
- int pri_hangup(struct pri *pri, q931_call *call, int cause)
- {
-+	int res=0;
- 	if (!pri || !call)
- 		return -1;
- 	if (cause == -1)
- 		/* normal clear cause */
- 		cause = 16;
--	return q931_hangup(pri, call, cause);
-+	if (pri->localtype == BRI_NETWORK_PTMP) {
-+	    res = q921_hangup(pri, call, 127);
-+	    if (res) {
-+		// q921_setup might give a HANGUP_ACK, if nobody got the call
-+		q931_hangup(pri, call, cause);
-+		return res;
-+	    } else {
-+		return q931_hangup(pri, call, cause);
-+	    }
-+	} else {
-+	    return q931_hangup(pri, call, cause);
-+	}
- }
- 
- int pri_reset(struct pri *pri, int channel)
-@@ -471,13 +569,14 @@
- 	}
- 	len += sprintf(buf + len, "Q921 Outstanding: %d\n", q921outstanding);
- #endif
--	len += sprintf(buf + len, "Window Length: %d/%d\n", pri->windowlen, pri->window);
--	len += sprintf(buf + len, "Sentrej: %d\n", pri->sentrej);
--	len += sprintf(buf + len, "SolicitFbit: %d\n", pri->solicitfbit);
--	len += sprintf(buf + len, "Retrans: %d\n", pri->retrans);
--	len += sprintf(buf + len, "Busy: %d\n", pri->busy);
-+	if (pri->localtype != BRI_NETWORK_PTMP) {
-+	    len += sprintf(buf + len, "Window Length: %d/%d\n", pri->windowlen[0], pri->window[0]);
-+	    len += sprintf(buf + len, "Sentrej: %d\n", pri->sentrej[0]);
-+	    len += sprintf(buf + len, "SolicitFbit: %d\n", pri->solicitfbit[0]);
-+	    len += sprintf(buf + len, "Retrans: %d\n", pri->retrans[0]);
-+	    len += sprintf(buf + len, "Busy: %d\n", pri->busy[0]);
-+	}
- 	len += sprintf(buf + len, "Overlap Dial: %d\n", pri->overlapdial);
--
- 	return strdup(buf);
- }
- 
-diff -urNad libpri-1.0.9/pri_internal.h /tmp/dpep.9zBkJK/libpri-1.0.9/pri_internal.h
---- libpri-1.0.9/pri_internal.h	2004-06-25 23:37:09.000000000 -0500
-+++ /tmp/dpep.9zBkJK/libpri-1.0.9/pri_internal.h	2005-07-30 01:24:09.000000000 -0500
-@@ -30,7 +30,10 @@
- struct pri_sched {
- 	struct timeval when;
- 	void (*callback)(void *data);
-+	void (*callback2)(void *data, int);
- 	void *data;
-+	char hasdata2;
-+	int data2;
- };
- 
- struct q921_frame;
-@@ -38,8 +41,15 @@
- enum q931_mode;
- 
- /* No more than 128 scheduled events */
-+/* XXX is this sufficient for nfs ??? */
- #define MAX_SCHED 128
- 
-+/* this can be freely configured to support more devices .... ok, 63 would be max! */
-+#define Q921_MAX_TEIS 16
-+
-+/* dynamically allocated TEIs start here */
-+#define Q921_TEI_BASE 64
-+
- struct pri {
- 	int fd;				/* File descriptor for D-Channel */
- 	struct pri *subchannel;	/* Sub-channel if appropriate */
-@@ -57,33 +67,43 @@
- 	int protodisc;
- 	
- 	/* Q.921 State */
--	int q921_state;	
--	int window;			/* Max window size */
--	int windowlen;		/* Fullness of window */
--	int v_s;			/* Next N(S) for transmission */
--	int v_a;			/* Last acknowledged frame */
--	int v_r;			/* Next frame expected to be received */
--	int v_na;			/* What we've told our peer we've acknowledged */
--	int solicitfbit;	/* Have we sent an I or S frame with the F-bit set? */
--	int retrans;		/* Retransmissions */
--	int sentrej;		/* Are we in reject state */
--	
--	int cref;			/* Next call reference value */
--	
--	int busy;			/* Peer is busy */
-+ 	int q921_state[Q921_MAX_TEIS];	
-+ 	char dchanup;
-+ 	
-+ 	/* TEI registry */
-+     	char q921_teis[Q921_MAX_TEIS];
-+  	
-+ 	unsigned int ri; 
-+ 
-+ 	int cref;			/* Next call reference value */  // let's think about this for a while...
-+  	
-+ 	int busy[Q921_MAX_TEIS];			/* Peer is busy */
-+  
-+ 	int window[Q921_MAX_TEIS];			/* Max window size */
-+	int windowlen[Q921_MAX_TEIS];		/* Fullness of window */
-+ 	int v_s[Q921_MAX_TEIS];			/* Next N(S) for transmission */
-+ 	int v_a[Q921_MAX_TEIS];			/* Last acknowledged frame */
-+ 	int v_r[Q921_MAX_TEIS];			/* Next frame expected to be received */
-+ 	int v_na[Q921_MAX_TEIS];			/* What we've told our peer we've acknowledged */
-+ 	int solicitfbit[Q921_MAX_TEIS];	/* Have we sent an I or S frame with the F-bit set? */
-+ 	int retrans[Q921_MAX_TEIS];		/* Retransmissions */
- 
--	/* Various timers */
--	int sabme_timer;	/* SABME retransmit */
--	int t203_timer;		/* Max idle time */
--	int t200_timer;		/* T-200 retransmission timer */
-+	int sentrej[Q921_MAX_TEIS];		/* Are we in reject state */
- 	
-+	/* Various timers */
-+ 	int sabme_timer[Q921_MAX_TEIS];
-+ 	int t203_timer[Q921_MAX_TEIS];
-+ 	int t202_timer[Q921_MAX_TEIS];
-+ 	int t201_timer[Q921_MAX_TEIS];
-+ 	int t200_timer[Q921_MAX_TEIS];
-+
- 	/* Used by scheduler */
- 	struct timeval tv;
- 	int schedev;
- 	pri_event ev;		/* Static event thingy */
- 	
- 	/* Q.921 Re-transmission queue */
--	struct q921_frame *txqueue;
-+	struct q921_frame *txqueue[Q921_MAX_TEIS];
- 	
- 	/* Q.931 calls */
- 	q931_call **callpool;
-@@ -121,6 +141,7 @@
- #define PRI_SWITCH_GR303_TMC_SWITCHING	11
- 
- extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);
-+extern int pri_schedule_event2(struct pri *pri, int ms, void (*function)(void *data, int data2), void *data, int data2);
- 
- extern pri_event *pri_schedule_run(struct pri *pri);
- 
-diff -urNad libpri-1.0.9/pri_q921.h /tmp/dpep.9zBkJK/libpri-1.0.9/pri_q921.h
---- libpri-1.0.9/pri_q921.h	2004-10-29 09:12:45.000000000 -0500
-+++ /tmp/dpep.9zBkJK/libpri-1.0.9/pri_q921.h	2005-07-30 01:24:09.000000000 -0500
-@@ -39,9 +39,14 @@
- 
- #define T_WAIT_MIN	2000
- #define T_WAIT_MAX	10000
--#define T_200		1000		/* 1 second between SABME's */
-+#define T_200		3000		/* 3 second between SABME's */
-+#define T_201		2000
-+#define T_202		5000		/* 5 seconds between TEI requests */
- #define T_203		10000		/* 10 seconds with no packets max */
- #define N_200		3		/* 3 retries */
-+#define N_202		3
-+
-+#define T_303		4000
- 
- #define Q921_FRAMETYPE_MASK	0x3
- 
-@@ -50,6 +55,13 @@
- #define Q921_FRAMETYPE_S	0x1
- 
- #define Q921_TEI_GROUP				127
-+#define Q921_TEI_ID_REQUEST	0x1
-+#define Q921_TEI_ID_ASSIGNED	0x2
-+#define Q921_TEI_ID_DENIED	0x3
-+#define Q921_TEI_ID_CHK_REQ	0x4
-+#define Q921_TEI_ID_CHK_RES	0x5
-+#define Q921_TEI_ID_REMOVE	0x6
-+#define Q921_TEI_ID_VERIFY	0x7
- #define Q921_TEI_GR303_EOC_PATH			0
- #define Q921_TEI_GR303_EOC_OPS			4
- #define Q921_TEI_GR303_TMC_SWITCHING		0
-@@ -167,12 +179,14 @@
- extern void q921_dump(q921_h *h, int len, int showraw, int txrx);
- 
- /* Bring up the D-channel */
--extern void q921_start(struct pri *pri, int now);
-+extern void q921_start(struct pri *pri, int now, int tei);
- 
--extern void q921_reset(struct pri *pri);
-+extern void q921_reset(struct pri *pri, int tei);
- 
- extern pri_event *q921_receive(struct pri *pri, q921_h *h, int len);
- 
--extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr);
-+extern int q921_transmit_uframe(struct pri *pri, void *buf, int len, int cr, int tei);
-+
-+extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr, int tei);
- 
- #endif
-diff -urNad libpri-1.0.9/pri_q931.h /tmp/dpep.9zBkJK/libpri-1.0.9/pri_q931.h
---- libpri-1.0.9/pri_q931.h	2004-06-16 10:33:58.000000000 -0500
-+++ /tmp/dpep.9zBkJK/libpri-1.0.9/pri_q931.h	2005-07-30 01:24:09.000000000 -0500
-@@ -190,6 +190,10 @@
- #define Q931_IE_CODESET(x)		((x) >> 8)
- #define Q931_IE_IE(x)			((x) & 0xff)
- #define Q931_FULL_IE(codeset, ie)	(((codeset) << 8) | ((ie) & 0xff))
-+#define Q931_IE_MAX_LEN			257
-+
-+// BRI+
-+#define Q931_COLP	0x4c
- 
- #define Q931_DISPLAY					0x28
- #define Q931_IE_SEGMENTED_MSG			0x00
-@@ -217,6 +221,8 @@
- #define Q931_IE_USER_USER				0x7E
- #define Q931_IE_ESCAPE_FOR_EXT			0x7F
- 
-+#define Q931_IE_SPECIAL		0x02
-+
- 
- /* Call state stuff */
- #define Q931_CALL_STATE_NULL				0
-@@ -242,7 +248,7 @@
- /* EuroISDN  */
- #define Q931_SENDING_COMPLETE		0xa1
- 
--extern int q931_receive(struct pri *pri, q931_h *h, int len);
-+extern int q931_receive(struct pri *pri, q931_h *h, int len, int tei);
- 
- extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info);
- 
-@@ -256,6 +262,10 @@
- 
- extern int q931_information(struct pri *pri, q931_call *call, char digit);
- 
-+extern int q931_information_display(struct pri *pri, q931_call *call, char *display);
-+
-+extern int q931_add_display(struct pri *pri, q931_call *call, char *display);
-+
- extern int q931_connect(struct pri *pri, q931_call *call, int channel, int nonisdn);
- 
- extern int q931_release(struct pri *pri, q931_call *call, int cause);
-@@ -264,6 +274,10 @@
- 
- extern int q931_hangup(struct pri *pri, q931_call *call, int cause);
- 
-+extern int q921_hangup(struct pri *pri, q931_call *c, int tei);
-+
-+extern int q921_handle_hangup(struct pri *pri, q931_call *c, int tei);
-+
- extern int q931_restart(struct pri *pri, int channel);
- 
- extern int q931_call_getcrv(struct pri *pri, q931_call *call, int *callmode);
-@@ -276,5 +290,23 @@
- extern void q931_dump(q931_h *h, int len, int txrx);
- 
- extern void __q931_destroycall(struct pri *pri, q931_call *c);
-+
-+extern int q931_hold_acknowledge(struct pri *pri, q931_call *c);
-+
-+extern int q931_hold_reject(struct pri *pri, q931_call *c);
-+
-+extern int q931_retrieve_acknowledge(struct pri *pri, q931_call *c, int channel);
-+	
-+extern int q931_retrieve_reject(struct pri *pri, q931_call *c);
-+
-+extern int q931_suspend_acknowledge(struct pri *pri, q931_call *c, char *display);
- 	
-+extern int q931_suspend_reject(struct pri *pri, q931_call *c, char *display);
-+
-+extern int q931_resume_reject(struct pri *pri, q931_call *c, char *display);
-+
-+extern int q931_resume_acknowledge(struct pri *pri, q931_call *c, int channel, char *display);
-+
-+extern int q931_facility(struct pri *pri, q931_call *c, int operation, char *arguments);
-+
- #endif
-diff -urNad libpri-1.0.9/prisched.c /tmp/dpep.9zBkJK/libpri-1.0.9/prisched.c
---- libpri-1.0.9/prisched.c	2004-06-05 01:50:55.000000000 -0500
-+++ /tmp/dpep.9zBkJK/libpri-1.0.9/prisched.c	2005-07-30 01:24:09.000000000 -0500
-@@ -35,7 +35,7 @@
- 	int x;
- 	struct timeval tv;
- 	for (x=1;x<MAX_SCHED;x++)
--		if (!pri->pri_sched[x].callback)
-+		if ((!pri->pri_sched[x].callback2) && (!pri->pri_sched[x].callback))
- 			break;
- 	if (x == MAX_SCHED) {
- 		pri_error("No more room in scheduler\n");
-@@ -52,7 +52,39 @@
- 	}
- 	pri->pri_sched[x].when = tv;
- 	pri->pri_sched[x].callback = function;
-+	pri->pri_sched[x].callback2 = NULL;
- 	pri->pri_sched[x].data = data;
-+	pri->pri_sched[x].hasdata2 = 0;
-+	pri->pri_sched[x].data2 = 0;
-+	return x;
-+}
-+
-+int pri_schedule_event2(struct pri *pri, int ms, void (*function)(void *data, int data2), void *data, int data2)
-+{
-+	int x;
-+	struct timeval tv;
-+	for (x=1;x<MAX_SCHED;x++)
-+		if ((!pri->pri_sched[x].callback2) && (!pri->pri_sched[x].callback))
-+			break;
-+	if (x == MAX_SCHED) {
-+		pri_error("No more room in scheduler\n");
-+		return -1;
-+	}
-+	if (x > maxsched)
-+		maxsched = x;
-+	gettimeofday(&tv, NULL);
-+	tv.tv_sec += ms / 1000;
-+	tv.tv_usec += (ms % 1000) * 1000;
-+	if (tv.tv_usec > 1000000) {
-+		tv.tv_usec -= 1000000;
-+		tv.tv_sec += 1;
-+	}
-+	pri->pri_sched[x].when = tv;
-+	pri->pri_sched[x].callback = NULL;
-+	pri->pri_sched[x].callback2 = function;
-+	pri->pri_sched[x].data = data;
-+	pri->pri_sched[x].hasdata2 = 1;
-+	pri->pri_sched[x].data2 = data2;
- 	return x;
- }
- 
-@@ -64,7 +96,7 @@
- 	if (pri->subchannel)
- 		closest = pri_schedule_next(pri->subchannel);
- 	for (x=1;x<MAX_SCHED;x++) {
--		if (pri->pri_sched[x].callback && 
-+		if ((pri->pri_sched[x].callback || pri->pri_sched[x].callback2) && 
- 			(!closest || (closest->tv_sec > pri->pri_sched[x].when.tv_sec) ||
- 				((closest->tv_sec == pri->pri_sched[x].when.tv_sec) && 
- 				 (closest->tv_usec > pri->pri_sched[x].when.tv_usec))))
-@@ -75,26 +107,38 @@
- 
- static pri_event *__pri_schedule_run(struct pri *pri, struct timeval *tv)
- {
--	int x;
--	void (*callback)(void *);
--	void *data;
-+ 	int x;
-+ 	void (*callback)(void *);
-+	void (*callback2)(void *, int);
-+ 	void *data;
-+	int data2;
- 	pri_event *e;
-+
- 	if (pri->subchannel) {
- 		if ((e = __pri_schedule_run(pri->subchannel, tv))) {
- 			return e;
- 		}
- 	}
- 	for (x=1;x<MAX_SCHED;x++) {
--		if (pri->pri_sched[x].callback &&
-+		if ((pri->pri_sched[x].callback || pri->pri_sched[x].callback2) &&
- 			((pri->pri_sched[x].when.tv_sec < tv->tv_sec) ||
- 			 ((pri->pri_sched[x].when.tv_sec == tv->tv_sec) &&
- 			  (pri->pri_sched[x].when.tv_usec <= tv->tv_usec)))) {
- 			        pri->schedev = 0;
- 			  	callback = pri->pri_sched[x].callback;
-+			  	callback2 = pri->pri_sched[x].callback2;
- 				data = pri->pri_sched[x].data;
-+				data2 = pri->pri_sched[x].data2;
- 				pri->pri_sched[x].callback = NULL;
-+				pri->pri_sched[x].callback2 = NULL;
- 				pri->pri_sched[x].data = NULL;
--				callback(data);
-+				pri->pri_sched[x].data2 = 0;
-+				if (pri->pri_sched[x].hasdata2 == 1) {
-+				    pri->pri_sched[x].hasdata2 = 0;
-+				    callback2(data, data2);
-+				} else {
-+				    callback(data);
-+				}
-             if (pri->schedev)
-                   return &pri->ev;
- 	    }
-@@ -115,4 +159,5 @@
- 	if ((id >= MAX_SCHED) || (id < 0)) 
- 		pri_error("Asked to delete sched id %d???\n", id);
- 	pri->pri_sched[id].callback = NULL;
-+	pri->pri_sched[id].callback2 = NULL;
- }
-diff -urNad libpri-1.0.9/pritest.c /tmp/dpep.9zBkJK/libpri-1.0.9/pritest.c
---- libpri-1.0.9/pritest.c	2004-06-05 01:50:55.000000000 -0500
-+++ /tmp/dpep.9zBkJK/libpri-1.0.9/pritest.c	2005-07-30 01:24:09.000000000 -0500
-@@ -51,8 +51,8 @@
- #define PRI_DEF_NODETYPE	PRI_CPE
- #define PRI_DEF_SWITCHTYPE	PRI_SWITCH_NI2
- 
--#define MAX_CHAN		32
--#define	DCHANNEL_TIMESLOT	16
-+#define MAX_CHAN		3
-+#define	DCHANNEL_TIMESLOT	3
- 
- 
- static int offset = 0;
-@@ -60,7 +60,7 @@
- static void do_channel(ZAP *z)
- {
- 	/* This is the part that runs on a given channel */
--	zap_playf(z, "raw.ulaw", 0);
-+	zap_playf(z, "raw.alaw", 0);
- }
- 
- struct pri_chan {
-@@ -76,6 +76,14 @@
- 		return PRI_CPE;
- 	if (!strcasecmp(node, "network"))
- 		return PRI_NETWORK;
-+	if (!strcasecmp(node, "bri_cpe_ptmp"))
-+		return BRI_CPE_PTMP;
-+	if (!strcasecmp(node, "bri_network_ptmp"))
-+		return BRI_NETWORK_PTMP;
-+	if (!strcasecmp(node, "bri_cpe"))
-+		return BRI_CPE;
-+	if (!strcasecmp(node, "bri_network"))
-+		return BRI_NETWORK;
- 	return -1;
- }
- 
-@@ -285,6 +293,10 @@
- 		}
- 		
- 		break;
-+	case PRI_EVENT_HANGUP_REQ:
-+		printf("-- Hanging up channel %d\n", e->hangup.channel);
-+		hangup_channel(e->hangup.channel);
-+		break;
- 	default:
- 		fprintf(stderr, "--!! Unknown PRI event %d\n", e->e);
- 	}
-diff -urNad libpri-1.0.9/q921.c /tmp/dpep.9zBkJK/libpri-1.0.9/q921.c
---- libpri-1.0.9/q921.c	2004-07-23 11:04:01.000000000 -0500
-+++ /tmp/dpep.9zBkJK/libpri-1.0.9/q921.c	2005-07-30 01:24:09.000000000 -0500
-@@ -5,6 +5,8 @@
-  *
-  * Copyright (C) 2001, Linux Support Services, Inc.
-  * All Rights Reserved.
-+ * Copyright (C) 2003,2004,2005 Junghanns.NET GmbH
-+ * Klaus-Peter Junghanns <kpj at junghanns.net>
-  *
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License as published by
-@@ -49,19 +51,22 @@
- 	(hf).h.tei = (pri)->tei; \
- } while(0)
- 
--static void reschedule_t203(struct pri *pri);
-+static void reschedule_t203(struct pri *pri, int tei);
- 
--static void q921_discard_retransmissions(struct pri *pri)
-+static void q921_discard_retransmissions(struct pri *pri, int tei)
- {
- 	struct q921_frame *f, *p;
--	f = pri->txqueue;
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+	
-+	f = pri->txqueue[teio];
- 	while(f) {
--		p = f;
--		f = f->next;
--		/* Free frame */
--		free(p);
-+	    p = f;
-+	    f = f->next;
-+	    /* Free frame */
-+	    free(p);
- 	}
--	pri->txqueue = NULL;
-+        pri->txqueue[teio] = NULL;
- }
- 
- static int q921_transmit(struct pri *pri, q921_h *h, int len) 
-@@ -80,18 +85,22 @@
- #endif
- 	/* Just send it raw */
- 	if (pri->debug & PRI_DEBUG_Q921_DUMP)
--		q921_dump(h, len, pri->debug & PRI_DEBUG_Q921_RAW, 1);
-+		q921_dump(h, len, 1, 1);
- 	/* Write an extra two bytes for the FCS */
- 	res = write(pri->fd, h, len + 2);
- 	if (res != (len + 2)) {
- 		pri_error("Short write: %d/%d (%s)\n", res, len + 2, strerror(errno));
- 		return -1;
- 	}
--	reschedule_t203(pri);
-+	if (pri->localtype == BRI_CPE_PTMP) {
-+	    reschedule_t203(pri, pri->tei);
-+	} else if (h->h.tei != Q921_TEI_GROUP) {
-+	    reschedule_t203(pri, h->h.tei);
-+	}
- 	return 0;
- }
- 
--static void q921_send_ua(struct pri *pri, int pfbit)
-+static void q921_send_ua(struct pri *pri, int pfbit, int tei)
- {
- 	q921_h h;
- 	Q921_INIT(pri, h);
-@@ -99,6 +108,7 @@
- 	h.u.m2 = 0;		/* M2 = 0 */
- 	h.u.p_f = pfbit;	/* Final bit on */
- 	h.u.ft = Q921_FRAMETYPE_U;
-+	h.h.tei = tei;
- 	switch(pri->localtype) {
- 	case PRI_NETWORK:
- 		h.h.c_r = 0;
-@@ -106,6 +116,19 @@
- 	case PRI_CPE:
- 		h.h.c_r = 1;
- 		break;
-+	case BRI_NETWORK_PTMP:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE_PTMP:
-+		h.h.tei = pri->tei;
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_NETWORK:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE:
-+		h.h.c_r = 1;
-+		break;
- 	default:
- 		pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
- 		return;
-@@ -114,19 +137,302 @@
- 		pri_message("Sending Unnumbered Acknowledgement\n");
- 	q921_transmit(pri, &h, 3);
- }
-+/*
-+static void q921_send_disconnect(struct pri *pri, int pfbit, int tei)
-+{
-+	q921_h h;
-+	Q921_INIT(pri, h);
-+	h.u.m3 = 2;
-+	h.u.m2 = 0;
-+	h.u.p_f = pfbit;
-+	h.u.ft = Q921_FRAMETYPE_U;
-+	h.h.tei = tei;
-+	switch(pri->localtype) {
-+	case PRI_NETWORK:
-+		h.h.c_r = 0;
-+		break;
-+	case PRI_CPE:
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_NETWORK_PTMP:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE_PTMP:
-+		h.h.tei = pri->tei;
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_NETWORK:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE:
-+		h.h.c_r = 1;
-+		break;
-+	default:
-+		pri_error("Don't know how to disconnect on a type %d node\n", pri->localtype);
-+		return;
-+	}
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+		pri_message("Sending Disconnect\n");
-+	q921_transmit(pri, &h, 3);
-+}
-+*/
-+static void q921_send_dm(struct pri *pri, int pfbit, int tei)
-+{
-+	q921_h h;
-+	Q921_INIT(pri, h);
-+	h.u.m3 = 0;		/* M3 = 0 */
-+	h.u.m2 = 3;		/* M2 = 3 */
-+	h.u.p_f = pfbit;	/* Final bit on */
-+	h.u.ft = Q921_FRAMETYPE_U;
-+	h.h.tei = tei;
-+	switch(pri->localtype) {
-+	case PRI_NETWORK:
-+		h.h.c_r = 0;
-+		break;
-+	case PRI_CPE:
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_NETWORK_PTMP:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE_PTMP:
-+		h.h.tei = pri->tei;
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_NETWORK:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE:
-+		h.h.c_r = 1;
-+		break;
-+	default:
-+		pri_error("Don't know how to DM on a type %d node\n", pri->localtype);
-+		return;
-+	}
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+		pri_message("Sending DM\n");
-+	q921_transmit(pri, &h, 3);
-+}
- 
--static void q921_send_sabme_now(void *vpri);
-+static void q921_send_teireq(void *vpri) {
-+    struct pri *pri = vpri;
-+    unsigned short ri=0x6464;
-+    q921_u *f;
-+    ri = rand();
- 
--static void q921_send_sabme(void *vpri, int now)
-+    if (pri->localtype != BRI_CPE_PTMP) {
-+	pri_error("TEI req for non-ptmp???\n"); 
-+	return;
-+    }
-+    if (pri->t202_timer[0]) { 
-+	pri_schedule_del(pri, pri->t202_timer[0]);
-+	pri->t202_timer[0] = 0;
-+    }
-+
-+    pri->t202_timer[0] = pri_schedule_event(pri, T_202, q921_send_teireq, pri);
-+
-+    pri->ri = ri;
-+    f = malloc(sizeof(q921_u) + 5 + 2);
-+    memset(f,0x0,sizeof(q921_u) + 5 + 2);
-+    if (f) {
-+	f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
-+	f->h.tei = Q921_TEI_GROUP;
-+	f->h.c_r = 0;	
-+	f->h.ea1 = 0;	
-+	f->h.ea2 = 1;	
-+	f->m2 = 0;
-+	f->m3 = 0;
-+	f->ft = Q921_FRAMETYPE_U;
-+	f->data[0] = 0xf;
-+	f->data[1] = ri >> 8;
-+	f->data[2] = ri & 0xff;
-+	f->data[3] = Q921_TEI_ID_REQUEST;
-+	f->data[4] = 0xff;
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+    	    pri_message("Sending TEI Request ri=%d\n",ri);
-+	q921_transmit(pri,(q921_h *)&(f->h),8);
-+	free(f);
-+    }
-+}
-+
-+static void q921_send_teiassign(struct pri *pri,int ri,int tei) {
-+    q921_u *f;
-+
-+    if (pri->localtype != BRI_NETWORK_PTMP) {
-+	pri_error("TEI assign for non-ptmp???\n"); 
-+	return;
-+    }
-+
-+    f = malloc(sizeof(q921_u) + 5 + 2);
-+    memset(f,0x0,sizeof(q921_u) + 5 + 2);
-+    if (f) {
-+	f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
-+	f->h.tei = Q921_TEI_GROUP;
-+	f->h.c_r = 1;	
-+	f->h.ea1 = 0;	
-+	f->h.ea2 = 1;	
-+	f->m2 = 0;
-+	f->m3 = 0;
-+	f->ft = Q921_FRAMETYPE_U;
-+	f->data[0] = 0xf;
-+	f->data[1] = ri >> 8;
-+	f->data[2] = ri & 0xff;
-+	f->data[3] = Q921_TEI_ID_ASSIGNED;
-+	f->data[4] = (tei << 1) | 0x1;
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+    	    pri_message("Sending TEI assign ri=%d tei=%d\n",ri,tei);
-+	q921_transmit(pri,(q921_h *)&(f->h),8);
-+	free(f);
-+    }
-+}
-+
-+static void q921_send_teichkresp(struct pri *pri,int tei) {
-+    q921_u *f;
-+    unsigned short ri=0x6464;
-+    ri = rand();
-+
-+    if (pri->localtype != BRI_CPE_PTMP) {
-+	pri_error("TEI check response for non-ptmp???\n"); 
-+	return;
-+    }
-+
-+    f = malloc(sizeof(q921_u) + 5 + 2);
-+    memset(f,0x0,sizeof(q921_u) + 5 + 2);
-+    if (f) {
-+	f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
-+	f->h.tei = Q921_TEI_GROUP;
-+	f->h.c_r = 0; // command u->n	
-+	f->h.ea1 = 0;	
-+	f->h.ea2 = 1;	
-+	f->m2 = 0;
-+	f->m3 = 0;
-+	f->ft = Q921_FRAMETYPE_U;
-+	f->data[0] = 0xf;
-+	f->data[1] = ri >> 8;
-+	f->data[2] = ri & 0xff;
-+	f->data[3] = Q921_TEI_ID_CHK_RES;
-+	f->data[4] = (tei << 1) | 0x1;
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+    	    pri_message("Sending TEI check resp ri=%d tei=%d\n",ri,tei);
-+	q921_transmit(pri,(q921_h *)&(f->h),8);
-+	free(f);
-+    }
-+}
-+/* 
-+static void q921_send_teiverify(struct pri *pri,int tei) {
-+    q921_u *f;
-+
-+    if (pri->localtype != BRI_CPE_PTMP) {
-+	pri_error("TEI verify for non-ptmp???\n"); 
-+	return;
-+    }
-+
-+    f = malloc(sizeof(q921_u) + 5 + 2);
-+    memset(f,0x0,sizeof(q921_u) + 5 + 2);
-+    if (f) {
-+	f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
-+	f->h.tei = Q921_TEI_GROUP;
-+	f->h.c_r = 0; // command u->n	
-+	f->h.ea1 = 0;	
-+	f->h.ea2 = 1;	
-+	f->m2 = 0;
-+	f->m3 = 0;
-+	f->ft = Q921_FRAMETYPE_U;
-+	f->data[0] = 0xf;
-+	f->data[1] = 0;
-+	f->data[2] = 0;
-+	f->data[3] = Q921_TEI_ID_VERIFY;
-+	f->data[4] = (tei << 1) | 0x1;
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+    	    pri_message("Sending TEI verify tei=%d\n", tei);
-+	q921_transmit(pri,(q921_h *)&(f->h),8);
-+	free(f);
-+    }
-+}
-+*/
-+static void q921_send_teiremove(struct pri *pri, int tei) {
-+    q921_u *f;
-+    unsigned short ri=0x6464;
-+    ri = rand();
-+
-+    if (pri->localtype != BRI_NETWORK_PTMP) {
-+	pri_error("TEI remove for non-ptmp???\n"); 
-+	return;
-+    }
-+
-+    f = malloc(sizeof(q921_u) + 5 + 2);
-+    memset(f,0x0,sizeof(q921_u) + 5 + 2);
-+    if (f) {
-+	f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
-+	f->h.tei = Q921_TEI_GROUP;
-+	f->h.c_r = 1;	
-+	f->h.ea1 = 0;	
-+	f->h.ea2 = 1;	
-+	f->m2 = 0;
-+	f->m3 = 0;
-+	f->ft = Q921_FRAMETYPE_U;
-+	f->data[0] = 0xf;
-+	f->data[1] = ri >> 8;
-+	f->data[2] = ri & 0xff;
-+	f->data[3] = Q921_TEI_ID_REMOVE;
-+	f->data[4] = (tei << 1) | 0x1;
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+    	    pri_message("Sending TEI remove tei=%d\n",tei);
-+	q921_transmit(pri,(q921_h *)&(f->h),8);
-+	free(f);
-+    }
-+}
-+
-+static void q921_send_teidenied(struct pri *pri, int ri, int tei) {
-+    q921_u *f;
-+
-+    if (pri->localtype != BRI_NETWORK_PTMP) {
-+	pri_error("TEI ID denied for non-ptmp???\n"); 
-+	return;
-+    }
-+
-+    f = malloc(sizeof(q921_u) + 5 + 2);
-+    memset(f,0x0,sizeof(q921_u) + 5 + 2);
-+    if (f) {
-+	f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
-+	f->h.tei = Q921_TEI_GROUP;
-+	f->h.c_r = 1;	
-+	f->h.ea1 = 0;	
-+	f->h.ea2 = 1;	
-+	f->m2 = 0;
-+	f->m3 = 0;
-+	f->ft = Q921_FRAMETYPE_U;
-+	f->data[0] = 0xf;
-+	f->data[1] = ri >> 8;
-+	f->data[2] = ri & 0xff;
-+	f->data[3] = Q921_TEI_ID_DENIED;
-+	f->data[4] = (tei << 1) | 0x1;
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+    	    pri_message("Sending TEI ID denied tei=%d\n",tei);
-+	q921_transmit(pri,(q921_h *)&(f->h),8);
-+	free(f);
-+    }
-+}
-+
-+static void q921_send_sabme_now(void *vpri, int tei);
-+
-+static void q921_send_sabme(void *vpri, int now, int tei)
- {
- 	struct pri *pri = vpri;
- 	q921_h h;
--	pri_schedule_del(pri, pri->sabme_timer);
--	pri->sabme_timer = 0;
--	pri->sabme_timer = pri_schedule_event(pri, T_200, q921_send_sabme_now, pri);
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+
-+	if (pri->sabme_timer[teio]) {
-+	    pri_schedule_del(pri, pri->sabme_timer[teio]);
-+	    pri->sabme_timer[teio] = 0;
-+	}
-+	pri->sabme_timer[teio] = pri_schedule_event2(pri, T_200, q921_send_sabme_now, pri, tei);
- 	if (!now)
- 		return;
- 	Q921_INIT(pri, h);
-+	// XXX
-+	h.h.tei = tei;
- 	h.u.m3 = 3;	/* M3 = 3 */
- 	h.u.m2 = 3;	/* M2 = 3 */
- 	h.u.p_f = 1;	/* Poll bit set */
-@@ -138,6 +444,19 @@
- 	case PRI_CPE:
- 		h.h.c_r = 0;
- 		break;
-+	case BRI_NETWORK_PTMP:
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_CPE_PTMP:
-+		h.h.c_r = 0;
-+		h.h.tei = pri->tei;
-+		break;
-+	case BRI_NETWORK:
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_CPE:
-+		h.h.c_r = 0;
-+		break;
- 	default:
- 		pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
- 		return;
-@@ -145,18 +464,20 @@
- 	if (pri->debug & PRI_DEBUG_Q921_STATE)
- 		pri_message("Sending Set Asynchronous Balanced Mode Extended\n");
- 	q921_transmit(pri, &h, 3);
--	pri->q921_state = Q921_AWAITING_ESTABLISH;
-+	pri->q921_state[teio] = Q921_AWAITING_ESTABLISH;
- }
- 
--static void q921_send_sabme_now(void *vpri)
-+static void q921_send_sabme_now(void *vpri, int tei)
- {
--	q921_send_sabme(vpri, 1);
-+	q921_send_sabme(vpri, 1, tei);
- }
- 
--static int q921_ack_packet(struct pri *pri, int num)
-+static int q921_ack_packet(struct pri *pri, int num, int tei)
- {
- 	struct q921_frame *f, *prev = NULL;
--	f = pri->txqueue;
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+	f = pri->txqueue[teio];
- 	while(f) {
- 		if (f->h.n_s == num) {
- 			/* Cancel each packet as necessary */
-@@ -164,26 +485,26 @@
- 			if (prev)
- 				prev->next = f->next;
- 			else
--				pri->txqueue = f->next;
-+				pri->txqueue[teio] = f->next;
- 			if (pri->debug & PRI_DEBUG_Q921_STATE)
--				pri_message("-- ACKing packet %d, new txqueue is %d (-1 means empty)\n", f->h.n_s, pri->txqueue ? pri->txqueue->h.n_s : -1);
-+				pri_message("-- ACKing packet %d, new txqueue is %d (-1 means empty)\n", f->h.n_s, pri->txqueue[teio] ? pri->txqueue[teio]->h.n_s : -1);
- 			/* Update v_a */
--			pri->v_a = num;
-+			pri->v_a[teio] = num;
- 			free(f);
- 			/* Reset retransmission counter if we actually acked something */
--			pri->retrans = 0;
-+			pri->retrans[teio] = 0;
- 			/* Decrement window size */
--			pri->windowlen--;
-+			pri->windowlen[teio]--;
- 			/* Search for something to send */
--			f = pri->txqueue;
-+			f = pri->txqueue[teio];
- 			while(f) {
- 				if (!f->transmitted) {
- 					/* Send it now... */
- 					if (pri->debug & PRI_DEBUG_Q921_STATE)
- 						pri_message("-- Finally transmitting %d, since window opened up\n", f->h.n_s);
- 					f->transmitted++;
--					pri->windowlen++;
--					f->h.n_r = pri->v_r;
-+					pri->windowlen[teio]++;
-+					f->h.n_r = pri->v_r[teio];
- 					q921_transmit(pri, (q921_h *)(&f->h), f->len);
- 					break;
- 				}
-@@ -197,77 +518,85 @@
- 	return 0;
- }
- 
--static void t203_expire(void *);
--static void t200_expire(void *);
--static pri_event *q921_dchannel_down(struct pri *pri);
-+static void t203_expire(void *, int tei);
-+static void t200_expire(void *, int tei);
-+static pri_event *q921_dchannel_down(struct pri *pri, int tei);
- 
--static void reschedule_t203(struct pri *pri)
-+static void reschedule_t203(struct pri *pri, int tei)
- {
--	if (pri->t203_timer) {
--		pri_schedule_del(pri, pri->t203_timer);
--		if (pri->debug &  PRI_DEBUG_Q921_STATE)
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+	if (pri->t203_timer[teio]) {
-+		pri_schedule_del(pri, pri->t203_timer[teio]);
-+ 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
- 			pri_message("-- Restarting T203 counter\n");
- 		/* Nothing to transmit, start the T203 counter instead */
--		pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri);
-+		pri->t203_timer[teio] = pri_schedule_event2(pri, T_203, t203_expire, pri, tei);
- 	}
- }
- 
--static pri_event *q921_ack_rx(struct pri *pri, int ack)
-+static pri_event *q921_ack_rx(struct pri *pri, int ack, int tei)
- {
- 	int x;
- 	int cnt=0;
- 	pri_event *ev;
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
- 	/* Make sure the ACK was within our window */
--	for (x=pri->v_a; (x != pri->v_s) && (x != ack); Q921_INC(x));
-+	for (x=pri->v_a[teio]; (x != pri->v_s[teio]) && (x != ack); Q921_INC(x));
- 	if (x != ack) {
- 		/* ACK was outside of our window --- ignore */
--		pri_error("ACK received for '%d' outside of window of '%d' to '%d', restarting\n", ack, pri->v_a, pri->v_s);
--		ev = q921_dchannel_down(pri);
--		q921_start(pri, 1);
-+		pri_error("ACK received for '%d' outside of window of '%d' to '%d', restarting\n", ack, pri->v_a[teio], pri->v_s[teio]);
-+		ev = q921_dchannel_down(pri, tei);
-+		q921_start(pri, 1, tei);
- 		pri->schedev = 1;
- 		return ev;
- 	}
- 	/* Cancel each packet as necessary */
- 	if (pri->debug & PRI_DEBUG_Q921_STATE)
--		pri_message("-- ACKing all packets from %d to (but not including) %d\n", pri->v_a, ack);
--	for (x=pri->v_a; x != ack; Q921_INC(x)) 
--		cnt += q921_ack_packet(pri, x);	
--	if (!pri->txqueue) {
-+		pri_message("-- ACKing all packets from %d to (but not including) %d\n", pri->v_a[teio], ack);
-+	for (x=pri->v_a[teio]; x != ack; Q921_INC(x)) 
-+		cnt += q921_ack_packet(pri, x,tei);	
-+	if (!pri->txqueue[teio]) {
- 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
- 			pri_message("-- Since there was nothing left, stopping T200 counter\n");
- 		/* Something was ACK'd.  Stop T200 counter */
--		pri_schedule_del(pri, pri->t200_timer);
--		pri->t200_timer = 0;
-+		if (pri->t200_timer[teio]) {
-+		    pri_schedule_del(pri, pri->t200_timer[teio]);
-+		    pri->t200_timer[teio] = 0;
-+		}
- 	}
--	if (pri->t203_timer) {
-+	if (pri->t203_timer[teio]) {
- 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
- 			pri_message("-- Stopping T203 counter since we got an ACK\n");
--		pri_schedule_del(pri, pri->t203_timer);
--		pri->t203_timer = 0;
-+		pri_schedule_del(pri, pri->t203_timer[teio]);
-+		pri->t203_timer[teio] = 0;
- 	}
--	if (pri->txqueue) {
-+	if (pri->txqueue[teio]) {
- 		/* Something left to transmit, Start the T200 counter again if we stopped it */
- 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
--			pri_message("-- Something left to transmit (%d), restarting T200 counter\n", pri->txqueue->h.n_s);
--		if (!pri->t200_timer)
--			pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
-+			pri_message("-- Something left to transmit (%d), restarting T200 counter\n", pri->txqueue[teio]->h.n_s);
-+		if (!pri->t200_timer[teio])
-+			pri->t200_timer[teio] = pri_schedule_event2(pri, T_200, t200_expire, pri, tei);
- 	} else {
- 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
- 			pri_message("-- Nothing left, starting T203 counter\n");
- 		/* Nothing to transmit, start the T203 counter instead */
--		pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri);
-+		pri->t203_timer[teio] = pri_schedule_event2(pri, T_203, t203_expire, pri, tei);
- 	}
- 	return NULL;
- }
- 
--static void q921_reject(struct pri *pri, int pf)
-+static void q921_reject(struct pri *pri, int pf, int tei)
- {
- 	q921_h h;
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
- 	Q921_INIT(pri, h);
- 	h.s.x0 = 0;	/* Always 0 */
- 	h.s.ss = 2;	/* Reject */
- 	h.s.ft = 1;	/* Frametype (01) */
--	h.s.n_r = pri->v_r;	/* Where to start retransmission */
-+	h.s.n_r = pri->v_r[teio];	/* Where to start retransmission */
- 	h.s.p_f = pf;	
- 	switch(pri->localtype) {
- 	case PRI_NETWORK:
-@@ -276,23 +605,38 @@
- 	case PRI_CPE:
- 		h.h.c_r = 1;
- 		break;
-+	case BRI_NETWORK_PTMP:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE_PTMP:
-+		h.h.c_r = 1;
-+		h.h.tei = tei;
-+		break;
-+	case BRI_NETWORK:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE:
-+		h.h.c_r = 1;
-+		break;
- 	default:
- 		pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
- 		return;
- 	}
- 	if (pri->debug & PRI_DEBUG_Q921_STATE)
--		pri_message("Sending Reject (%d)\n", pri->v_r);
--	pri->sentrej = 1;
-+		pri_message("Sending Reject (%d)\n", pri->v_r[teio]);
-+	pri->sentrej[teio] = 1;
- 	q921_transmit(pri, &h, 4);
- }
- 
--static void q921_rr(struct pri *pri, int pbit, int cmd) {
-+static void q921_rr(struct pri *pri, int pbit, int cmd, int tei) {
- 	q921_h h;
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
- 	Q921_INIT(pri, h);
- 	h.s.x0 = 0;	/* Always 0 */
- 	h.s.ss = 0; /* Receive Ready */
- 	h.s.ft = 1;	/* Frametype (01) */
--	h.s.n_r = pri->v_r;	/* N/R */
-+	h.s.n_r = pri->v_r[teio];	/* N/R */
- 	h.s.p_f = pbit;		/* Poll/Final set appropriately */
- 	switch(pri->localtype) {
- 	case PRI_NETWORK:
-@@ -307,81 +651,153 @@
- 		else
- 			h.h.c_r = 1;
- 		break;
-+	case BRI_NETWORK_PTMP:
-+		h.h.tei = tei;
-+		if (cmd)
-+			h.h.c_r = 1;
-+		else
-+			h.h.c_r = 0;
-+		break;
-+	case BRI_CPE_PTMP:
-+		h.h.tei = tei;
-+		if (cmd)
-+			h.h.c_r = 0;
-+		else
-+			h.h.c_r = 1;
-+		break;
-+	case BRI_NETWORK:
-+		if (cmd)
-+			h.h.c_r = 1;
-+		else
-+			h.h.c_r = 0;
-+		break;
-+	case BRI_CPE:
-+		if (cmd)
-+			h.h.c_r = 0;
-+		else
-+			h.h.c_r = 1;
-+		break;
- 	default:
- 		pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
- 		return;
- 	}
--	pri->v_na = pri->v_r;	/* Make a note that we've already acked this */
-+	pri->v_na[teio] = pri->v_r[teio];	/* Make a note that we've already acked this */
- 	if (pri->debug & PRI_DEBUG_Q921_STATE)
--		pri_message("Sending Receiver Ready (%d)\n", pri->v_r);
-+		pri_message("Sending Receiver Ready (%d)\n", pri->v_r[teio]);
- 	q921_transmit(pri, &h, 4);
- }
- 
--static void t200_expire(void *vpri)
-+static void t200_expire(void *vpri, int tei)
- {
- 	struct pri *pri = vpri;
--	if (pri->txqueue) {
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+	if (pri->txqueue[teio]) {
- 		/* Retransmit first packet in the queue, setting the poll bit */
- 		if (pri->debug & PRI_DEBUG_Q921_STATE)
- 			pri_message("-- T200 counter expired, What to do...\n");
- 		/* Force Poll bit */
--		pri->txqueue->h.p_f = 1;	
-+		pri->txqueue[teio]->h.p_f = 1;	
- 		/* Update nr */
--		pri->txqueue->h.n_r = pri->v_r;
--		pri->v_na = pri->v_r;
--		pri->solicitfbit = 1;
--		pri->retrans++;
-+		pri->txqueue[teio]->h.n_r = pri->v_r[teio];
-+		pri->v_na[teio] = pri->v_r[teio];
-+		pri->solicitfbit[teio] = 1;
-+		pri->retrans[teio]++;
-       /* Up to three retransmissions */
--      if (pri->retrans < N_200) {
-+      if (pri->retrans[teio] < N_200) {
-          /* Reschedule t200_timer */
-          if (pri->debug & PRI_DEBUG_Q921_STATE)
--            pri_message("-- Retransmitting %d bytes\n", pri->txqueue->len);
--		if (pri->busy) 
--			q921_rr(pri, 1, 0);
-+            pri_message("-- Retransmitting %d bytes\n", pri->txqueue[teio]->len);
-+		if (pri->busy[teio]) 
-+			q921_rr(pri, 1, 0, tei);
- 		else {
--			if (!pri->txqueue->transmitted) 
-+			if (!pri->txqueue[teio]->transmitted) 
- 				pri_error("!! Not good - head of queue has not been transmitted yet\n");
--			q921_transmit(pri, (q921_h *)&pri->txqueue->h, pri->txqueue->len);
-+			q921_transmit(pri, (q921_h *)&pri->txqueue[teio]->h, pri->txqueue[teio]->len);
- 		}
-          if (pri->debug & PRI_DEBUG_Q921_STATE) 
--               pri_message("-- Rescheduling retransmission (%d)\n", pri->retrans);
--         pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
-+               pri_message("-- Rescheduling retransmission (%d)\n", pri->retrans[teio]);
-+         pri->t200_timer[teio] = pri_schedule_event2(pri, T_200, t200_expire, pri, tei);
-       } else {
-          if (pri->debug & PRI_DEBUG_Q921_STATE) 
-                pri_message("-- Timeout occured, restarting PRI\n");
--         pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
--      	pri->t200_timer = 0;
--         q921_dchannel_down(pri);
--         q921_start(pri, 1);
-+    	pri->q921_state[teio] = Q921_LINK_CONNECTION_RELEASED;
-+    	pri->t200_timer[teio] = 0;
-+         q921_dchannel_down(pri, tei);
-+         q921_start(pri, 1, tei);
-          pri->schedev = 1;
-       }
--	} else if (pri->solicitfbit) {
-+	} else if (pri->solicitfbit[teio]) {
-          if (pri->debug & PRI_DEBUG_Q921_STATE)
-             pri_message("-- Retrying poll with f-bit\n");
--		pri->retrans++;
--		if (pri->retrans < N_200) {
--			pri->solicitfbit = 1;
--			q921_rr(pri, 1, 1);
--			pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
-+		pri->retrans[teio]++;
-+		if (pri->retrans[teio] < N_200) {
-+			pri->solicitfbit[teio] = 1;
-+			q921_rr(pri, 1, 1, tei);
-+			pri->t200_timer[teio] = pri_schedule_event2(pri, T_200, t200_expire, pri, tei);
- 		} else {
- 			if (pri->debug & PRI_DEBUG_Q921_STATE) 
- 				pri_message("-- Timeout occured, restarting PRI\n");
--			pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
--			pri->t200_timer = 0;
--			q921_dchannel_down(pri);
--			q921_start(pri, 1);
--			pri->schedev = 1;
-+        		pri->q921_state[teio] = Q921_LINK_CONNECTION_RELEASED;
-+      			pri->t200_timer[teio] = 0;
-+			q921_dchannel_down(pri, tei);
-+        		q921_start(pri, 1, tei); 
-+        		pri->schedev = 1; 
- 		}
- 	} else {
- 		pri_error("T200 counter expired, nothing to send...\n");
--	   	pri->t200_timer = 0;
-+	   	pri->t200_timer[teio] = 0;
- 	}
- }
- 
--int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr)
-+int q921_transmit_uframe(struct pri *pri, void *buf, int len, int cr, int tei)
-+{
-+	q921_u *uf;
-+	uf = malloc(sizeof(q921_u) + len + 2);
-+	memset(uf,0,sizeof(q921_u) + len + 2);
-+
-+	uf->h.sapi = 0;
-+	uf->h.ea1 = 0;
-+	uf->h.ea2 = 1;
-+	uf->h.tei = tei;
-+	uf->m3 = 0;
-+	uf->m2 = 0;
-+	uf->ft = Q921_FRAMETYPE_U;
-+	switch(pri->localtype) {
-+	case PRI_NETWORK:
-+		uf->h.c_r = 1;
-+		break;
-+	case PRI_CPE:
-+		uf->h.c_r = 0;
-+		break;
-+	case BRI_NETWORK_PTMP:
-+		uf->h.c_r = 1;
-+		break;
-+	case BRI_CPE_PTMP:
-+		uf->h.c_r = 0;
-+		break;
-+	case BRI_NETWORK:
-+		uf->h.c_r = 1;
-+		break;
-+	case BRI_CPE:
-+		uf->h.c_r = 0;
-+		break;
-+	default:
-+		pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
-+		return -1;
-+ 	}
-+	memcpy(uf->data,buf,len);
-+	q921_transmit(pri, (q921_h*)&(uf->h), 3+len);
-+	free(uf);
-+	return 0;
-+}
-+
-+int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr, int tei)
- {
- 	q921_frame *f, *prev=NULL;
--	for (f=pri->txqueue; f; f = f->next) prev = f;
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+	for (f=pri->txqueue[teio]; f; f = f->next) prev = f;
- 	f = malloc(sizeof(q921_frame) + len + 2);
- 	if (f) {
- 		memset(f,0,sizeof(q921_frame) + len + 2);
-@@ -399,47 +815,75 @@
- 			else
- 				f->h.h.c_r = 1;
- 		break;
-+		case BRI_NETWORK_PTMP:
-+			f->h.h.tei = tei;
-+			if (cr)
-+				f->h.h.c_r = 1;
-+			else
-+				f->h.h.c_r = 0;
-+		break;
-+		case BRI_CPE_PTMP:
-+			f->h.h.tei = pri->tei;
-+			if (cr)
-+				f->h.h.c_r = 0;
-+			else
-+				f->h.h.c_r = 1;
-+		break;
-+		case BRI_NETWORK:
-+			if (cr)
-+				f->h.h.c_r = 1;
-+			else
-+				f->h.h.c_r = 0;
-+		break;
-+		case BRI_CPE:
-+			if (cr)
-+				f->h.h.c_r = 0;
-+			else
-+				f->h.h.c_r = 1;
-+		break;
- 		}
- 		f->next = NULL;
- 		f->transmitted = 0;
- 		f->len = len + 4;
- 		memcpy(f->h.data, buf, len);
--		f->h.n_s = pri->v_s;
--		f->h.n_r = pri->v_r;
--		pri->v_s++;
--		pri->v_na = pri->v_r;
-+		f->h.n_s = pri->v_s[teio];
-+		f->h.n_r = pri->v_r[teio];
-+		pri->v_s[teio]++;
-+		pri->v_na[teio] = pri->v_r[teio];
- 		f->h.p_f = 0;
- 		f->h.ft = 0;
- 		if (prev)
- 			prev->next = f;
- 		else
--			pri->txqueue = f;
-+			pri->txqueue[teio] = f;
- 		/* Immediately transmit unless we're in a recovery state, or the window
- 		   size is too big */
--		if (!pri->retrans && !pri->busy) {
--			if (pri->windowlen < pri->window) {
--				pri->windowlen++;
-+// XXXXXX think about this...
-+//		if (!pri->retrans[teio] && !pri->busy[teio]) {
-+		if (!pri->retrans[teio] && !pri->busy[teio]) {
-+			if (pri->windowlen[teio] < pri->window[teio]) {
-+				pri->windowlen[teio]++;
- 				q921_transmit(pri, (q921_h *)(&f->h), f->len);
- 				f->transmitted++;
- 			} else {
- 				if (pri->debug & PRI_DEBUG_Q921_STATE)
- 					pri_message("Delaying transmission of %d, window is %d/%d long\n", 
--						f->h.n_s, pri->windowlen, pri->window);
-+						f->h.n_s, pri->windowlen[teio], pri->window[teio]);
- 			}
- 		}
--		if (pri->t203_timer) {
-+		if (pri->t203_timer[teio]) {
- 			if (pri->debug & PRI_DEBUG_Q921_STATE)
- 				pri_message("Stopping T_203 timer\n");
--			pri_schedule_del(pri, pri->t203_timer);
--			pri->t203_timer = 0;
-+			pri_schedule_del(pri, pri->t203_timer[teio]);
-+			pri->t203_timer[teio] = 0;
- 		}
--		if (!pri->t200_timer) {
-+		if (!pri->t200_timer[teio]) {
- 			if (pri->debug & PRI_DEBUG_Q921_STATE)
- 				pri_message("Starting T_200 timer\n");
--			pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
-+			pri->t200_timer[teio] = pri_schedule_event2(pri, T_200, t200_expire, pri, tei);
- 		} else
- 			if (pri->debug & PRI_DEBUG_Q921_STATE)
--				pri_message("T_200 timer already going (%d)\n", pri->t200_timer);
-+				pri_message("T_200 timer already going (%d)\n", pri->t200_timer[teio]);
- 		
- 	} else {
- 		pri_error("!! Out of memory for Q.921 transmit\n");
-@@ -448,22 +892,25 @@
- 	return 0;
- }
- 
--static void t203_expire(void *vpri)
-+static void t203_expire(void *vpri, int tei)
- {
- 	struct pri *pri = vpri;
--	if (pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) {
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+
-+	if (pri->q921_state[teio] == Q921_LINK_CONNECTION_ESTABLISHED) {
- 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
- 			pri_message("T203 counter expired, sending RR and scheduling T203 again\n");
- 		/* Solicit an F-bit in the other's RR */
--		pri->solicitfbit = 1;
--		pri->retrans = 0;
--		q921_rr(pri, 1, 1);
-+		pri->retrans[teio] = 0;
-+		pri->solicitfbit[teio] = 1;
-+		q921_rr(pri, 1, 1, tei);
- 		/* Start timer T200 to resend our RR if we don't get it */
--		pri->t203_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
-+		pri->t203_timer[teio] = pri_schedule_event2(pri, T_200, t200_expire, pri, tei);
- 	} else {
- 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
--			pri_message("T203 counter expired in weird state %d\n", pri->q921_state);
--		pri->t203_timer = 0;
-+			pri_message("T203 counter expired in weird state %d\n", pri->q921_state[teio]);
-+		pri->t203_timer[teio] = 0;
- 	}
- }
- 
-@@ -471,26 +918,28 @@
- {
- 	int res;
- 	pri_event *ev;
-+	int teio= i->h.tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
- 	/* Make sure this is a valid packet */
--	if (i->n_s == pri->v_r) {
-+	if (i->n_s == pri->v_r[teio]) {
- 		/* Increment next expected I-frame */
--		Q921_INC(pri->v_r);
-+		Q921_INC(pri->v_r[teio]);
- 		/* Handle their ACK */
--		pri->sentrej = 0;
--		ev = q921_ack_rx(pri, i->n_r);
-+		pri->sentrej[teio] = 0;
-+		ev = q921_ack_rx(pri, i->n_r, i->h.tei);
- 		if (ev)
- 			return ev;
- 		if (i->p_f) {
- 			/* If the Poll/Final bit is set, immediate send the RR */
--			q921_rr(pri, 1, 0);
--		} else if (pri->busy) {
--			q921_rr(pri, 0, 0);
-+			q921_rr(pri, 1, 0, i->h.tei);
-+		} else if (pri->busy[teio]) {
-+			q921_rr(pri, 0, 0, i->h.tei);
- 		}
- 		/* Receive Q.931 data */
--		res = q931_receive(pri, (q931_h *)i->data, len - 4);
-+		res = q931_receive(pri, (q931_h *)i->data, len - 4, i->h.tei);
- 		/* Send an RR if one wasn't sent already */
--		if (pri->v_na != pri->v_r) 
--			q921_rr(pri, 0, 0);
-+		if (pri->v_na[teio] != pri->v_r[teio]) 
-+			q921_rr(pri, 0, 0,  i->h.tei);
- 		if (res == -1) {
- 			return NULL;
- 		}
-@@ -499,10 +948,10 @@
- 	} else {
- 		/* If we haven't already sent a reject, send it now, otherwise
- 		   we are obliged to RR */
--		if (!pri->sentrej)
--			q921_reject(pri, i->p_f);
-+		if (!pri->sentrej[teio])
-+			q921_reject(pri, i->p_f, i->h.tei);
- 		else if (i->p_f)
--			q921_rr(pri, 1, 0);
-+			q921_rr(pri, 1, 0,  i->h.tei);
- 	}
- 	return NULL;
- }
-@@ -640,62 +1089,94 @@
- 	};
- }
- 
--static pri_event *q921_dchannel_up(struct pri *pri)
-+static pri_event *q921_dchannel_up(struct pri *pri, int tei)
- {
-+	// we treat this as MFE
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+
- 	/* Reset counters, etc */
--	q921_reset(pri);
-+	q921_reset(pri, tei);
- 	
- 	/* Stop any SABME retransmissions */
--	pri_schedule_del(pri, pri->sabme_timer);
--	pri->sabme_timer = 0;
-+	if (pri->sabme_timer[teio]) {
-+	    pri_schedule_del(pri, pri->sabme_timer[teio]);
-+	    pri->sabme_timer[teio] = 0;
-+	}
-+	
-+	if (pri->t202_timer[teio]) {
-+	    pri_schedule_del(pri, pri->t202_timer[teio]);
-+	    pri->t202_timer[teio] = 0;
-+	}
- 	
- 	/* Reset any rejects */
--	pri->sentrej = 0;
-+	pri->sentrej[teio] = 0;
- 	
- 	/* Go into connection established state */
--	pri->q921_state = Q921_LINK_CONNECTION_ESTABLISHED;
-+	pri->q921_state[teio] = Q921_LINK_CONNECTION_ESTABLISHED;
- 
- 	/* Start the T203 timer */
--	pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri);
-+	pri->t203_timer[teio] = pri_schedule_event2(pri, T_203, t203_expire, pri, tei);
- 	
- 	/* Report event that D-Channel is now up */
--	pri->ev.gen.e = PRI_EVENT_DCHAN_UP;
--	return &pri->ev;
-+        pri->ev.gen.e = PRI_EVENT_DCHAN_UP;
-+        pri->ev.gen.tei = tei;
-+        return &pri->ev;
- }
- 
--static pri_event *q921_dchannel_down(struct pri *pri)
-+static pri_event *q921_dchannel_down(struct pri *pri, int tei)
- {
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+	// we treat this as MF disc
- 	/* Reset counters, reset sabme timer etc */
--	q921_reset(pri);
-+	q921_reset(pri, tei);
- 	
--	/* Report event that D-Channel is now up */
-+	/* Report event that D-Channel is now down */
-+	if (pri->localtype == BRI_NETWORK_PTMP) {
-+	    if (pri->t203_timer[teio]) {
-+		if (pri->debug & PRI_DEBUG_Q921_STATE) {
-+			pri_message("Stopping T_203 timer for TEI %d\n", tei);
-+		}
-+		pri_schedule_del(pri, pri->t203_timer[teio]);
-+		pri->t203_timer[teio] = 0;
-+	    }
-+	}
- 	pri->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
--	return &pri->ev;
-+	pri->ev.gen.tei = tei;
-+	return &pri->ev;	
- }
- 
--void q921_reset(struct pri *pri)
-+void q921_reset(struct pri *pri, int tei)
- {
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
- 	/* Having gotten a SABME we MUST reset our entire state */
--	pri->v_s = 0;
--	pri->v_a = 0;
--	pri->v_r = 0;
--	pri->v_na = 0;
--	pri->window = 7;
--	pri->windowlen = 0;
--	pri_schedule_del(pri, pri->sabme_timer);
--	pri_schedule_del(pri, pri->t203_timer);
--	pri_schedule_del(pri, pri->t200_timer);
--	pri->sabme_timer = 0;
--	pri->t203_timer = 0;
--	pri->t200_timer = 0;
--	pri->busy = 0;
--	pri->solicitfbit = 0;
--	pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
--	pri->retrans = 0;
--	pri->sentrej = 0;
--	
-+	pri->v_s[teio] = 0;
-+	pri->v_a[teio] = 0;
-+	pri->v_r[teio] = 0;
-+	pri->v_na[teio] = 0;
-+	pri->window[teio] = 7;
-+	pri->windowlen[teio] = 0;
-+	pri_schedule_del(pri, pri->sabme_timer[teio]);
-+	pri_schedule_del(pri, pri->t203_timer[teio]);
-+	pri_schedule_del(pri, pri->t200_timer[teio]);
-+	pri->sabme_timer[teio] = 0;
-+	pri->t203_timer[teio] = 0;
-+	pri->t200_timer[teio] = 0;
-+	pri_schedule_del(pri, pri->t202_timer[teio]);
-+	pri->t202_timer[teio] = 0;
-+	pri_schedule_del(pri, pri->t201_timer[teio]);
-+	pri->t201_timer[teio] = 0;
-+	// xxx HMMM?
-+	pri->busy[teio] = 0;
-+	pri->solicitfbit[teio] = 0;
-+	pri->q921_state[teio] = Q921_LINK_CONNECTION_RELEASED;
-+	pri->retrans[teio] = 0;
-+	pri->sentrej[teio] = 0;
-+
- 	/* Discard anything waiting to go out */
--	q921_discard_retransmissions(pri);
-+	q921_discard_retransmissions(pri, tei);
- }
- 
- static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
-@@ -703,12 +1184,16 @@
- 	q921_frame *f;
- 	pri_event *ev;
- 	int sendnow;
-+	int tei;
-+	int res=-1;
-+	int teio=h->h.tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
- 
- 	switch(h->h.data[0] & Q921_FRAMETYPE_MASK) {
- 	case 0:
- 	case 2:
--		if (pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED) {
--			pri_error("!! Got I-frame while link state %d\n", pri->q921_state);
-+		if (pri->q921_state[teio] != Q921_LINK_CONNECTION_ESTABLISHED) {
-+			pri_error("!! Got I-frame while link state %d\n", pri->q921_state[teio]);
- 			return NULL;
- 		}
- 		/* Informational frame */
-@@ -719,7 +1204,7 @@
- 		return q921_handle_iframe(pri, &h->i, len);	
- 		break;
- 	case 1:
--		if (pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED) {
-+		if (pri->q921_state[teio] != Q921_LINK_CONNECTION_ESTABLISHED) {
- 			pri_error("!! Got S-frame while link down\n");
- 			return NULL;
- 		}
-@@ -730,22 +1215,22 @@
- 		switch(h->s.ss) {
- 		case 0:
- 			/* Receiver Ready */
--			pri->busy = 0;
-+			pri->busy[teio] = 0;
- 			/* Acknowledge frames as necessary */
--			ev = q921_ack_rx(pri, h->s.n_r);
-+			ev = q921_ack_rx(pri, h->s.n_r, h->h.tei);
- 			if (ev)
- 				return ev;
- 			if (h->s.p_f) {
- 				/* If it's a p/f one then send back a RR in return with the p/f bit set */
--				if (pri->solicitfbit) {
-+				if (pri->solicitfbit[teio]) {
- 					if (pri->debug & PRI_DEBUG_Q921_STATE) 
- 						pri_message("-- Got RR response to our frame\n");
- 				} else {
- 					if (pri->debug & PRI_DEBUG_Q921_STATE) 
- 						pri_message("-- Unsolicited RR with P/F bit, responding\n");
--						q921_rr(pri, 1, 0);
-+						q921_rr(pri, 1, 0, h->h.tei);
- 				}
--				pri->solicitfbit = 0;
-+				pri->solicitfbit[teio] = 0;
- 			}
- 			break;
-       case 1:
-@@ -754,9 +1239,9 @@
-             pri_message("-- Got receiver not ready\n");
- 	 if(h->s.p_f) {
- 		/* Send RR if poll bit set */
--		q921_rr(pri, h->s.p_f, 0);
-+		q921_rr(pri, h->s.p_f, 0, h->h.tei);
- 	 }
--         pri->busy = 1;
-+         pri->busy[teio] = 1;
-          break;   
-       case 2:
-          /* Just retransmit */
-@@ -764,22 +1249,22 @@
-             pri_message("-- Got reject requesting packet %d...  Retransmitting.\n", h->s.n_r);
-          if (h->s.p_f) {
-             /* If it has the poll bit set, send an appropriate supervisory response */
--            q921_rr(pri, 1, 0);
-+            q921_rr(pri, 1, 0, h->h.tei);
-          }
- 		 sendnow = 0;
-          /* Resend the proper I-frame */
--         for(f=pri->txqueue;f;f=f->next) {
-+         for(f=pri->txqueue[teio];f;f=f->next) {
-                if ((sendnow || (f->h.n_s == h->s.n_r)) && f->transmitted) {
-                      /* Matches the request, or follows in our window, and has
- 					    already been transmitted. */
- 					 sendnow = 1;
- 					 pri_error("!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n", h->s.n_r, f->h.n_s);
--				     f->h.n_r = pri->v_r;
-+				     f->h.n_r = pri->v_r[teio];
-                      q921_transmit(pri, (q921_h *)(&f->h), f->len);
-                }
-          }
-          if (!sendnow) {
--               if (pri->txqueue) {
-+               if (pri->txqueue[teio]) {
-                      /* This should never happen */
- 		     if (!h->s.p_f || h->s.n_r) {
- 			pri_error("!! Got reject for frame %d, but we only have others!\n", h->s.n_r);
-@@ -787,23 +1272,23 @@
-                } else {
-                      /* Hrm, we have nothing to send, but have been REJ'd.  Reset v_a, v_s, etc */
- 				pri_error("!! Got reject for frame %d, but we have nothing -- resetting!\n", h->s.n_r);
--                     pri->v_a = h->s.n_r;
--                     pri->v_s = h->s.n_r;
-+                     pri->v_a[teio] = h->s.n_r;
-+                     pri->v_s[teio] = h->s.n_r;
-                      /* Reset t200 timer if it was somehow going */
--                     if (pri->t200_timer) {
--                           pri_schedule_del(pri, pri->t200_timer);
--                           pri->t200_timer = 0;
-+                     if (pri->t200_timer[teio]) {
-+                           pri_schedule_del(pri, pri->t200_timer[teio]);
-+                           pri->t200_timer[teio] = 0;
-                      }
-                      /* Reset and restart t203 timer */
--                     if (pri->t203_timer)
--                           pri_schedule_del(pri, pri->t203_timer);
--                     pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri);
-+                     if (pri->t203_timer[teio])
-+                           pri_schedule_del(pri, pri->t203_timer[teio]);
-+                     pri->t203_timer[teio] = pri_schedule_event2(pri, T_203, t203_expire, pri, h->h.tei);
-                }
-          }
-          break;
- 		default:
- 			pri_error("!! XXX Unknown Supervisory frame ss=0x%02x,pf=%02xnr=%02x vs=%02x, va=%02x XXX\n", h->s.ss, h->s.p_f, h->s.n_r,
--					pri->v_s, pri->v_a);
-+					pri->v_s[teio], pri->v_a[teio]);
- 		}
- 		break;
- 	case 3:
-@@ -816,12 +1301,13 @@
- 			if (h->u.m2 == 3) {
- 				if (h->u.p_f) {
- 					/* Section 5.7.1 says we should restart on receiving a DM response with the f-bit set to
-+
- 					   one, but we wait T200 first */
- 					if (pri->debug & PRI_DEBUG_Q921_STATE)
- 						pri_message("-- Got DM Mode from peer.\n");
- 					/* Disconnected mode, try again after T200 */
--					ev = q921_dchannel_down(pri);
--					q921_start(pri, 0);
-+					ev = q921_dchannel_down(pri, h->h.tei);
-+					q921_start(pri, 0, h->h.tei);
- 					return ev;
- 						
- 				} else {
-@@ -829,21 +1315,136 @@
- 						pri_message("-- Ignoring unsolicited DM with p/f set to 0\n");
- #if 0
- 					/* Requesting that we start */
--					q921_start(pri, 0);
-+					q921_start(pri, 0, h->h.tei);
- #endif					
- 				}
- 				break;
--			} else if (!h->u.m2) {
--				pri_message("XXX Unnumbered Information not implemented XXX\n");
-+			} else if (h->u.m2 == 0) {
-+				if (h->u.ft == 3) {
-+				    switch (h->u.data[0]) { /* Management Entity Identifier  */
-+					case 0x0f:
-+					/* TEI Procedure */
-+					switch (h->u.data[3]) {
-+					    case Q921_TEI_ID_VERIFY:
-+						if (pri->localtype != BRI_NETWORK_PTMP)
-+						    break;
-+						    if (pri->debug & PRI_DEBUG_Q921_STATE)
-+							pri_message("got TEI verify for TEI = %d\n",h->u.data[4] >> 1);
-+					    break;
-+					    case Q921_TEI_ID_ASSIGNED:
-+						if (pri->localtype != BRI_CPE_PTMP)
-+						    break;
-+						if (pri->tei == (h->u.data[4] >> 1)) {
-+						    // TEI already assgined, CHECK_TEI or REMOVE_TEI
-+						    pri_error("Double assgined TEI!\n");
-+						}
-+						if (pri->ri == ((unsigned short) (h->u.data[1] << 8) + h->u.data[2])) {
-+						    if (pri->t202_timer[0]) {
-+							pri_schedule_del(pri, pri->t202_timer[0]);
-+							pri->t202_timer[0] = 0;
-+						    }
-+						    pri->tei = h->u.data[4] >> 1; 
-+						    pri->ri = 0;
-+						    if (pri->debug & PRI_DEBUG_Q921_STATE)
-+							pri_message("received TEI assign TEI = %d ri=%d\n",pri->tei,(unsigned short) (h->u.data[1] << 8) + h->u.data[2]);
-+						    q921_send_sabme_now(pri, pri->tei);
-+						}
-+					    break;
-+					    case Q921_TEI_ID_REMOVE:
-+					    	if (pri->localtype != BRI_CPE_PTMP)
-+						    break;
-+						if (pri->tei == (h->u.data[4] >> 1)){ 
-+						    if (pri->debug & PRI_DEBUG_Q921_STATE)
-+							pri_message("received TEI remove TEI = %d\n",pri->tei);
-+						    pri->tei = 0;
-+						    pri->ri = 0;
-+						    // get a new TEI
-+						    q921_reset(pri,0);
-+						    q921_send_teireq(pri);
-+						}
-+					    break;
-+					    case Q921_TEI_ID_REQUEST:
-+						if (pri->localtype != BRI_NETWORK_PTMP)
-+						    break;
-+						
-+						tei = h->u.data[4] >> 1;
-+						if (tei != Q921_TEI_GROUP) {
-+						    pri_message("got TEI request for unavailable TEI..\n");
-+						    q921_send_teidenied(pri,((unsigned int)(h->u.data[1] << 8) + h->u.data[2]),h->u.data[4] >> 1);
-+						    break;
-+						}
-+						
-+						for (tei=0;tei<Q921_MAX_TEIS;tei++) {
-+						    if (pri->q921_teis[tei] == 0) {
-+						        pri->q921_teis[tei] = 1;
-+						        break;
-+						    }
-+						}
-+						if (tei < Q921_MAX_TEIS) {
-+						    q921_send_teiassign(pri,((unsigned int)(h->u.data[1] << 8) + h->u.data[2]),tei + Q921_TEI_BASE);
-+						} else {
-+						    // if you plug too many TEs into my bus it's your fault!!!
-+
-+						    pri_error("Whooopsie...general protection fault in module TEI manager.\n");
-+
-+						    // XXX IMPLEMENT TEI RECOVERY!!!
-+						    for (tei=0;tei<Q921_MAX_TEIS;tei++) {
-+							    // XXX ri should be 0?
-+						//	    q921_reset(pri, tei + Q921_TEI_BASE);
-+						//	    q921_send_teiremove(pri,((unsigned int)(h->u.data[1] << 8) + h->u.data[2]),tei + Q921_TEI_BASE);
-+						//    	    pri->q921_teis[tei] = 0;
-+							    // XXX dont forget schedulers, etc...
-+						    }
-+						    q921_send_teidenied(pri,((unsigned int)(h->u.data[1] << 8) + h->u.data[2]),h->u.data[4] >> 1);
-+						}
-+					    break;
-+					    case Q921_TEI_ID_CHK_REQ:
-+						if (pri->localtype != BRI_CPE_PTMP)
-+						    break;
-+						    if ((((h->u.data[4] >> 1) == Q921_TEI_GROUP) || ((h->u.data[4] >> 1) == 0) || ((h->u.data[4] >> 1) == pri->tei)) && (pri->tei > 0)) {
-+							pri_message("received TEI check request for TEI = %d\n",h->u.data[4] >> 1);
-+							q921_send_teichkresp(pri, pri->tei);
-+						    }
-+					    break;
-+					    default:
-+						pri_message("Ri = %d TEI msg = %x TEI = %x\n", (h->u.data[1] << 8) + h->u.data[2], h->u.data[3], h->u.data[4] >> 1);
-+					} 
-+					break;
-+					case Q931_PROTOCOL_DISCRIMINATOR:
-+					    if (pri->localtype == BRI_CPE_PTMP) {
-+					    res = q931_receive(pri, (q931_h *)h->u.data, len-3, h->h.tei);
-+					    /* Send an RR if one wasn't sent already */
-+					    if (pri->v_na[teio] != pri->v_r[teio]) 
-+						q921_rr(pri, 0, 0, pri->tei);
-+					    if (res == -1) {
-+						return NULL;
-+					    }
-+					    if (res & Q931_RES_HAVEEVENT)
-+						return &pri->ev;
-+					    }
-+					break;
-+				    }
-+				} else {
-+				    pri_message("XXX Unnumbered Information not implemented XXX\n");
-+				}
- 			}
- 			break;
- 		case 2:
- 			if (pri->debug &  PRI_DEBUG_Q921_STATE)
- 				pri_message("-- Got Disconnect from peer.\n");
- 			/* Acknowledge */
--			q921_send_ua(pri, h->u.p_f);
--			ev = q921_dchannel_down(pri);
--			q921_start(pri, 0);
-+			q921_send_ua(pri, h->u.p_f, h->h.tei);
-+			ev = q921_dchannel_down(pri, h->h.tei);
-+			if ((pri->localtype == BRI_CPE_PTMP) || (pri->localtype == BRI_CPE)) {
-+			    // keep layer 2 up
-+			    q921_send_sabme(pri, 1, pri->tei);
-+			    if (pri->t203_timer[teio])
-+				pri_schedule_del(pri, pri->t203_timer[teio]);
-+			    pri->t203_timer[teio] = 0;
-+			}
-+			if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)){
-+    			    q921_start(pri, 0, 0);
-+			}
- 			return ev;
- 		case 3:
- 			if (h->u.m2 == 3) {
-@@ -865,17 +1466,17 @@
- 					}
- 				}
- 				/* Send Unnumbered Acknowledgement */
--				q921_send_ua(pri, h->u.p_f);
--				return q921_dchannel_up(pri);
-+				q921_send_ua(pri, h->u.p_f,h->h.tei);
-+				return q921_dchannel_up(pri, h->h.tei);
- 			} else if (h->u.m2 == 0) {
- 					/* It's a UA */
--				if (pri->q921_state == Q921_AWAITING_ESTABLISH) {
-+				if (pri->q921_state[teio] == Q921_AWAITING_ESTABLISH) {
- 					if (pri->debug & PRI_DEBUG_Q921_STATE) {
- 						pri_message("-- Got UA from %s peer  Link up.\n", h->h.c_r ? "cpe" : "network");
- 					}
--					return q921_dchannel_up(pri);
-+					return q921_dchannel_up(pri, h->h.tei);
- 				} else 
--					pri_error("!! Got a UA, but i'm in state %d\n", pri->q921_state);
-+					pri_error("!! Got a UA, but i'm in state %d\n", pri->q921_state[teio]);
- 			} else 
- 				pri_error("!! Weird frame received (m3=3, m2 = %d)\n", h->u.m2);
- 			break;
-@@ -900,19 +1501,43 @@
- 	/* Discard FCS */
- 	len -= 2;
- 	
--	if (!pri->master && pri->debug & PRI_DEBUG_Q921_DUMP)
--		q921_dump(h, len, pri->debug & PRI_DEBUG_Q921_RAW, 0);
--
- 	/* Check some reject conditions -- Start by rejecting improper ea's */
- 	if (h->h.ea1 || !(h->h.ea2))
- 		return NULL;
- 
--	/* Check for broadcasts - not yet handled */
--	if (h->h.tei == Q921_TEI_GROUP)
--		return NULL;
-+	if ((pri->localtype == PRI_CPE) || (pri->localtype == PRI_NETWORK)) {
-+	    /* Check for broadcasts - not yet handled (for PRI) */
-+	    if (h->h.tei == Q921_TEI_GROUP) {
-+ 		return NULL;
-+	    }
-+	} else if ((pri->localtype == BRI_CPE) || (pri->localtype == BRI_CPE_PTMP)) {
-+    	    if ((h->h.tei != pri->tei) && (h->h.tei != Q921_TEI_GROUP)) {
-+	    	return NULL;
-+	    }
-+	} else if (pri->localtype == BRI_NETWORK_PTMP) {
-+	    /* discard anything from a strange TEI (strange == not assigned by us or the broadcast tei) */
-+    	    if (((h->h.tei < Q921_TEI_BASE) || (h->h.tei > Q921_TEI_BASE + Q921_MAX_TEIS)) && (h->h.tei != Q921_TEI_GROUP)) {
-+		if (pri->debug & PRI_DEBUG_Q921_DUMP)
-+		    pri_message("Received a Q.921 message from strange/unassigned TEI %d.\n");
-+	    	return NULL;
-+	    } else {
-+		if ((pri->q921_teis[h->h.tei - Q921_TEI_BASE] != 1) && (h->h.tei != Q921_TEI_GROUP)) {
-+		    if (pri->debug & PRI_DEBUG_Q921_DUMP)
-+			pri_message("Received a Q.921 message from unassigned TEI %d.. Sending DM and assigning.\n", h->h.tei);
-+		    // send DM 
-+		    q921_send_dm(pri, 1, h->h.tei);
-+		    pri->q921_teis[h->h.tei - Q921_TEI_BASE] = 1; 
-+		}
-+	    }
-+	}    
-+
-+	if (!pri->master && pri->debug & PRI_DEBUG_Q921_DUMP)
-+		q921_dump(h, len, pri->debug & PRI_DEBUG_Q921_RAW, 0);
- 
-+	if (pri->localtype != BRI_NETWORK_PTMP) {
- 	/* Check for SAPIs we don't yet handle */
--	if ((h->h.sapi != pri->sapi) || (h->h.tei != pri->tei)) {
-+	    if (((h->h.sapi != pri->sapi) && (h->h.sapi != Q921_SAPI_LAYER2_MANAGEMENT)) || ((h->h.tei != pri->tei) && (h->h.tei != Q921_TEI_GROUP) )) {
-+
- #ifdef PROCESS_SUBCHANNELS
- 		/* If it's not us, try any subchannels we have */
- 		if (pri->subchannel)
-@@ -920,10 +1545,16 @@
- 		else 
- #endif
- 			return NULL;
--
-+    	    }
- 	}
- 	ev = __q921_receive_qualified(pri, h, len);
--	reschedule_t203(pri);
-+
-+// Q921_GROUP_TEI
-+	if (pri->localtype == BRI_CPE_PTMP) {
-+	    reschedule_t203(pri, pri->tei);
-+	} else {
-+	    reschedule_t203(pri, h->h.tei);
-+	}
- 	return ev;
- }
- 
-@@ -937,14 +1568,51 @@
- 	return e;
- }
- 
--void q921_start(struct pri *pri, int now)
-+static void q921_start_tei(struct pri *pri, int tei)
- {
--	if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED) {
--		pri_error("!! q921_start: Not in 'Link Connection Released' state\n");
--		return;
-+    int teio=tei - Q921_TEI_BASE;
-+    if (pri->localtype != BRI_NETWORK_PTMP) { return; }
-+    if (((teio < 0) || (teio > Q921_MAX_TEIS))) { teio=0; }
-+    pri->q921_teis[teio] = 0;
-+    q921_send_teiremove(pri, tei);
-+    q921_reset(pri,tei);
-+}
-+
-+void q921_start(struct pri *pri, int now, int tei)
-+{
-+	int i=0;
-+/*	if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED) {
-+ 		pri_error("!! q921_start: Not in 'Link Connection Released' state\n");
-+ 		return;
-+	} */
-+ 	/* Reset our interface */
-+	if (pri->localtype != BRI_NETWORK_PTMP) {
-+	    q921_reset(pri,0);
-+	}
-+ 	/* Do the SABME XXX Maybe we should implement T_WAIT? XXX */
-+	if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE) || (pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_CPE)) { 
-+	    q921_send_sabme(pri, now, 0);
-+	}
-+	
-+	if (pri->localtype == BRI_NETWORK_PTMP) { 
-+	    if (tei == 0) {
-+		// initial start or complete restart
-+		q921_send_teiremove(pri, 127);
-+		pri->dchanup = 0;
-+		for (i=0;i<Q921_MAX_TEIS;i++) {
-+		    q921_start_tei(pri,Q921_TEI_BASE+i);
-+		}
-+	    } else if ((tei >= Q921_TEI_BASE) && (tei < Q921_TEI_BASE + Q921_MAX_TEIS)){
-+		// restart of a single p2p datalink
-+		q921_start_tei(pri,tei);
-+	    }
-+	} 
-+	if (pri->localtype == BRI_CPE_PTMP) { 
-+	    if (tei == 0) {
-+		/* let's get a TEI */
-+		q921_send_teireq(pri);
-+	    } else {
-+		q921_send_sabme(pri, now, tei);
-+	    }
- 	}
--	/* Reset our interface */
--	q921_reset(pri);
--	/* Do the SABME XXX Maybe we should implement T_WAIT? XXX */
--	q921_send_sabme(pri, now);
- }
-diff -urNad libpri-1.0.9/q931.c /tmp/dpep.9zBkJK/libpri-1.0.9/q931.c
---- libpri-1.0.9/q931.c	2005-05-29 10:10:34.000000000 -0500
-+++ /tmp/dpep.9zBkJK/libpri-1.0.9/q931.c	2005-07-30 01:24:09.000000000 -0500
-@@ -5,6 +5,8 @@
-  *
-  * Copyright (C) 2001, Linux Support Services, Inc.
-  * All Rights Reserved.
-+ * Copyright (C) 2003,2004,2005 Junghanns.NET GmbH
-+ * Klaus-Peter Junghanns <kpj at junghanns.net>
-  *
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License as published by
-@@ -31,6 +33,7 @@
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
-+#include <time.h>
- 
- #define MAX_MAND_IES 10
- 
-@@ -177,9 +180,11 @@
- #define PRI_TRANS_CAP_AUDIO_4ESS	0x08
- 
- 
-+/* Don't forget to update PRI_PROG_xxx at libpri.h */
- #define Q931_PROG_CALL_NOT_E2E_ISDN						0x01
- #define Q931_PROG_CALLED_NOT_ISDN						0x02
- #define Q931_PROG_CALLER_NOT_ISDN						0x03
-+#define Q931_PROG_CALLER_RETURNED_TO_ISDN					0x04
- #define Q931_PROG_INBAND_AVAILABLE						0x08
- #define Q931_PROG_DELAY_AT_INTERF						0x0a
- #define Q931_PROG_INTERWORKING_WITH_PUBLIC				0x10
-@@ -187,6 +192,8 @@
- #define Q931_PROG_INTERWORKING_NO_RELEASE_PRE_ANSWER	0x12
- #define Q931_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER	0x13
- 
-+
-+
- #define CODE_CCITT					0x0
- #define CODE_INTERNATIONAL 			0x1
- #define CODE_NATIONAL 				0x2
-@@ -205,6 +212,13 @@
- #define T_305			30000
- #define T_313			4000
- 
-+struct q921_call {
-+    int tei;	
-+    int proc;		
-+    int channel;	
-+    q921_call *next;
-+};
-+
- struct q931_call {
- 	struct pri *pri;	/* PRI */
- 	int cr;		/* Call Reference */
-@@ -222,7 +236,11 @@
- 	int alive;			/* Whether or not the call is alive */
- 	int acked;			/* Whether setup has been acked or not */
- 	int sendhangupack;		/* Whether or not to send a hangup ack */
--	int proc;			/* Whether we've sent a call proceeding / alerting */
-+	int proc;			/* Whether we've sent a call proceeding */
-+	int alert;			/* Whether we've sent an alerting */
-+
-+	int tei;
-+	q921_call *phones;
- 	
- 	int ri;			/* Restart Indicator (Restart Indicator IE) */
- 
-@@ -240,6 +258,7 @@
- 	int progcode;			/* Progress coding */
- 	int progloc;			/* Progress Location */	
- 	int progress;			/* Progress indicator */
-+	int progressmask;	
- 	
- 	int notify;			/* Notification */
- 	
-@@ -253,7 +272,10 @@
- 	
- 	int callerplan;
- 	int callerpres;			/* Caller presentation */
--	char callernum[256];	/* Caller */
-+	int callerplanuser;
-+	int callerpresuser;			/* Caller presentation */
-+	char callernum[256];	/* Calling Number (network provided) */
-+	char callernumuser[256];	/* Calling Number, (user provided) */
- 	char callername[256];
- 
- 	int ani2;               /* ANI II */
-@@ -271,9 +293,19 @@
- 	int redirectingreason;	      
- 	char redirectingnum[256];
- 
-+	int t303timer;		
-+	int t303running;		
-+
-         int useruserprotocoldisc;
- 	char useruserinfo[256];
- 	char callingsubaddr[256];	/* Calling parties sub address */
-+	char callid[10];	/* call identity for SUSPEND/RESUME */
-+	char digits[256];	/* additional digits received via info msgs (cpn or keypad) */
-+	char display[256];	/* display ie received in info msgs or for sending */
-+
-+	/* euroisdn facility fun */
-+	int facility; /* FACILTIY received */
-+	int aoc;
- };
- 
- #define FUNC_DUMP(name) void ((name))(int full_ie, q931_ie *ie, int len, char prefix)
-@@ -315,6 +347,11 @@
- 	c->next = NULL;
- 	c->sentchannel = 0;
- 	c->newcall = 1;
-+	c->t303timer = 0;
-+	c->t303running = 0;
-+	c->aoc = 0;
-+	c->phones = NULL;
-+	c->progressmask = 0;
- 	c->ourcallstate = Q931_CALL_STATE_NULL;
- 	c->peercallstate = Q931_CALL_STATE_NULL;
- }
-@@ -334,16 +371,20 @@
- {	
- 	int x;
- 	int pos=0;
--#ifdef NO_BRI_SUPPORT
-- 	if (!ie->data[0] & 0x20) {
--		pri_error("!! Not PRI type!?\n");
-- 		return -1;
-+	if ((pri->localtype != PRI_CPE) && (pri->localtype != PRI_NETWORK)) {
-+//		pri_error("!! BRI type %d!?\n",ie->data[0] & 0x03);
-+		call->channelno = ie->data[0] & 0x03;
-+		if (call->channelno == 3) {
-+		    call->channelno = -1; // any channel
-+		}
-+ 		return 0;
-  	}
--#endif
- #ifndef NOAUTO_CHANNEL_SELECTION_SUPPORT
--	if ((ie->data[0] & 3) != 1) {
-+	if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
-+	    if ((ie->data[0] & 3) != 1) {
- 		pri_error("!! Unexpected Channel selection %d\n", ie->data[0] & 3);
- 		return -1;
-+	    }
- 	}
- #endif
- 	if (ie->data[0] & 0x08)
-@@ -390,10 +431,16 @@
- {
- 	int pos=0;
- 	/* Start with standard stuff */
--	if (pri->switchtype == PRI_SWITCH_GR303_TMC)
-+	if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
- 		ie->data[pos] = 0x69;
--	else
-+	} else {
-+	    if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
- 		ie->data[pos] = 0xa1;
-+	    } else {
-+		// BRI
-+		ie->data[pos] = 0x80;
-+	    }
-+	}
- 	/* Add exclusive flag if necessary */
- 	if (call->chanflags & FLAG_EXCLUSIVE)
- 		ie->data[pos] |= 0x08;
-@@ -410,6 +457,7 @@
- 	} else
- 		pos++;
- 	if ((call->channelno > -1) || (call->slotmap != -1)) {
-+	    if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
- 		/* We'll have the octet 8.2 and 8.3's present */
- 		ie->data[pos++] = 0x83;
- 		if (call->channelno > -1) {
-@@ -425,11 +473,41 @@
- 			ie->data[pos++] = (call->slotmap & 0xff);
- 			return pos + 2;
- 		}
--	}
-+	    } else {
-+		// BRI
-+		// pri_error("channelno %d, ds1no %d data %d\n",call->channelno,call->ds1no,ie->data[pos-1]);
-+		if (pri->localtype == BRI_CPE_PTMP) {
-+		    if (msgtype == Q931_SETUP) {
-+			// network, you decide!
-+			if (call->channelno > -1) {
-+//		    	    ie->data[pos-1] = 0x83;
-+		    	    ie->data[pos-1] = 0x80 | call->channelno;
-+			}
-+		    } else {
-+			if (call->channelno > -1) {
-+		    	    ie->data[pos-1] |= call->channelno;
-+			}
-+		    }
-+		} else {
-+		    if (call->channelno > -1) {
-+		        ie->data[pos-1] |= call->channelno;
-+		    }
-+		}
-+		return pos + 2;
-+	    }	
-+        } else {
-+	    if (pri->localtype == BRI_CPE) {
-+	        ie->data[pos++] = 0x80 | 3;
-+	        return pos + 2;
-+	    }
-+	}	
- 	if (call->ds1no > 0) {
- 		/* We're done */
- 		return pos + 2;
- 	}
-+	if (msgtype == Q931_RESTART_ACKNOWLEDGE) {
-+	    return 0;
-+	}	
- 	pri_error("!! No channel map, no channel, and no ds1?  What am I supposed to identify?\n");
- 	return -1;
- }
-@@ -765,6 +843,10 @@
- 
- static void q931_get_number(unsigned char *num, int maxlen, unsigned char *src, int len)
- {
-+	if (len < 0) {
-+	    pri_error("q931_get_number received invalid len = %d\n", len);
-+	    return;
-+	}
- 	if (len > maxlen - 1) {
- 		num[0] = 0;
- 		return;
-@@ -776,44 +858,70 @@
- static FUNC_DUMP(dump_called_party_number)
- {
- 	unsigned char cnum[256];
--
--	q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
--	pri_message("%c Called Number (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d) '%s' ]\n",
--		prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f, cnum);
-+  
-+	if (len >= 3) {
-+	    q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
-+ 	    pri_message("%c Called Number (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d) '%s' ]\n",
-+ 		    prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f, cnum);
-+ 	} else {
-+ 	    pri_error("Called Number (len=%2d) too short.\n", len);
-+ 	}
- }
- 
- static FUNC_DUMP(dump_called_party_subaddr)
- {
- 	unsigned char cnum[256];
--	q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
--	pri_message("%c Called Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d) O: %d '%s' ]\n",
-+	if (len >= 3) {
-+	    q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
-+	    pri_message("%c Called Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d) O: %d '%s' ]\n",
- 		prefix, len, ie->data[0] >> 7,
- 		subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
- 		(ie->data[0] & 0x08) >> 3, cnum);
-+	} else {
-+	    pri_error("Called Party Subaddress (len=%2d) too short.\n", len);
-+	}
- }
- 
- static FUNC_DUMP(dump_calling_party_number)
- {
- 	unsigned char cnum[256];
--	if (ie->data[0] & 0x80)
-+	if ((ie->data[0] & 0x80) && (len >= 3)) {
- 		q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
--	else
--		q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
--	pri_message("%c Calling Number (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
--	if (ie->data[0] & 0x80)
-+		pri_message("%c Calling Number (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
- 		pri_message("%c                           Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(0), 0, cnum);
--	else
-+	} else if (len >= 4) {
-+		q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
-+		pri_message("%c Calling Number (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
- 		pri_message("%c                           Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum);
-+	} else {
-+	    pri_error("Calling Party Number (len=%2d) too short.\n", len);
-+	}
- }
- 
- static FUNC_DUMP(dump_calling_party_subaddr)
- {
- 	unsigned char cnum[256];
--	q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
--	pri_message("%c Calling Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d) O: %d '%s' ]\n",
-+	if (len >= 4) {
-+	    q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
-+	    pri_message("%c Calling Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d) O: %d '%s' ]\n",
- 		prefix, len, ie->data[0] >> 7,
- 		subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
- 		(ie->data[0] & 0x08) >> 3, cnum);
-+	} else {
-+	    pri_error("Calling Party Subaddress (len=%2d) too short.\n", len);
-+	}
-+}
-+
-+static FUNC_DUMP(dump_colp)
-+{
-+	unsigned char cnum[256];
-+	if (len >= 4) {
-+	    q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
-+	    pri_message("%c COLP (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
-+	    pri_message("%c                           Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum);
-+	} else {
-+	    pri_error("COLP (len=%2d) too short.\n", len);
-+	}
- }
- 
- static FUNC_DUMP(dump_redirecting_number)
-@@ -862,8 +970,12 @@
- 		}
- 	}
- 	while(!(ie->data[i++]& 0x80));
--	q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
--	pri_message(" '%s' ]\n", cnum);
-+	if ((ie->len - i) >= 0) {
-+	    q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
-+	    pri_message(" '%s' ]\n", cnum);
-+	} else {
-+	    pri_error("Connected Number (len=%2d) too short.\n", len);
-+	}
- }
- 
- 
-@@ -887,7 +999,11 @@
- 		}
- 	}
- 	while(!(ie->data[i++] & 0x80));
--	q931_get_number((unsigned char *) call->redirectingnum, sizeof(call->redirectingnum), ie->data + i, ie->len - i);
-+	if ((ie->len - i) >= 0) {
-+	    q931_get_number((unsigned char *) call->redirectingnum, sizeof(call->redirectingnum), ie->data + i, ie->len - i);
-+	} else {
-+	    pri_error("Redirecting Number (len=%2d) too short.\n", len);
-+	}
- 	return 0;
- }
- 
-@@ -895,25 +1011,41 @@
- static FUNC_DUMP(dump_redirecting_subaddr)
- {
- 	unsigned char cnum[256];
--	q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
--	pri_message("%c Redirecting Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d) O: %d '%s' ]\n",
-+	if (len >= 4) {
-+	    q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
-+	    pri_message("%c Redirecting Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d) O: %d '%s' ]\n",
- 		prefix, len, ie->data[0] >> 7,
- 		subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
- 		(ie->data[0] & 0x08) >> 3, cnum);
-+	} else {
-+	    pri_error("Redirecting Subaddress (len=%2d) too short.\n", len);
-+	}
- }
- 
- static FUNC_RECV(receive_calling_party_subaddr)
- {
- 	/* copy digits to call->callingsubaddr */
-- 	q931_get_number((unsigned char *) call->callingsubaddr, sizeof(call->callingsubaddr), ie->data + 2, len - 4);
-+ 	if (len >= 4) {
-+ 	    q931_get_number((unsigned char *) call->callingsubaddr, sizeof(call->callingsubaddr), ie->data + 2, len - 4);
-+	} else {
-+	    pri_error("Calling Party Subaddress (len=%2d) too short.\n", len);
-+	}
- 	return 0;
- }
- 
- static FUNC_RECV(receive_called_party_number)
- {
--	/* copy digits to call->callednum */
-- 	q931_get_number((unsigned char *) call->callednum, sizeof(call->callednum), ie->data + 1, len - 3);
--	call->calledplan = ie->data[0] & 0x7f;
-+	/* copy digits to call->callednum or call->digits */
-+	if (len >= 3) {
-+	    if (msgtype == Q931_INFORMATION) {
-+ 		q931_get_number((unsigned char *) call->digits, sizeof(call->digits), ie->data + 1, len - 3);
-+	    } else {
-+ 		q931_get_number((unsigned char *) call->callednum, sizeof(call->callednum), ie->data + 1, len - 3);
-+	    }
-+	    call->calledplan = ie->data[0] & 0x7f;
-+	} else {
-+	    pri_error("Called Party Number (len=%2d) too short.\n", len);
-+	}
- 	return 0;
- }
- 
-@@ -929,16 +1061,37 @@
- {
-         int extbit;
-         
--        call->callerplan = ie->data[0] & 0x7f;
--        extbit = (ie->data[0] >> 7) & 0x01;
--
-+	if (strlen(call->callernum)) {
-+ 	    call->callerplanuser = ie->data[0] & 0x7f;
-+	} else {
-+ 	    call->callerplan = ie->data[0] & 0x7f;
-+	}
-+	extbit = (ie->data[0] >> 7) & 0x01;
-         if (extbit) {
--	  q931_get_number((unsigned char *) call->callernum, sizeof(call->callernum), ie->data + 1, len - 3);
--	  call->callerpres = 0; /* PI presentation allowed
--				   SI user-provided, not screened */        
--        } else {
--	  q931_get_number((unsigned char *) call->callernum, sizeof(call->callernum), ie->data + 2, len - 4);
--	  call->callerpres = ie->data[1] & 0x7f;
-+	    if (len >= 3) {
-+		if (strlen(call->callernum)) {
-+		    /* got A NUM already (this is not 100% correct, but the network should do it this way to protect bad implementations */
-+		    q931_get_number(call->callernumuser, sizeof(call->callernumuser), ie->data + 1, len - 3);
-+	    	    call->callerpresuser = 0; /* PI presentation allowed  SI user-provided, not screened */        
-+		} else {
-+ 		     q931_get_number(call->callernum, sizeof(call->callernum), ie->data + 1, len - 3);
-+		    call->callerpres = 0; /* PI presentation allowed  SI user-provided, not screened */        
-+		}
-+	  } else {
-+		pri_error("Calling Party Number (len=%2d) too short.\n", len);
-+	  }
-+	} else {
-+	    if (len >= 4) {
-+		if (strlen(call->callernum)) {
-+	    	    q931_get_number(call->callernumuser, sizeof(call->callernumuser), ie->data + 2, len - 4);
-+		    call->callerpresuser = ie->data[1] & 0x7f;
-+		} else {
-+		    q931_get_number(call->callernum, sizeof(call->callernum), ie->data + 2, len - 4);
-+	    	    call->callerpres = ie->data[1] & 0x7f;
-+		}
-+	    } else {
-+		pri_error("Calling Party Number (len=%2d) too short.\n", len);
-+	     }
-         }
- 	return 0;
- }
-@@ -965,11 +1118,33 @@
- static FUNC_RECV(receive_user_user)
- {        
-         call->useruserprotocoldisc = ie->data[0] & 0xff;
--        if (call->useruserprotocoldisc == 4) /* IA5 */
--          q931_get_number((unsigned char *) call->useruserinfo, sizeof(call->useruserinfo), ie->data + 1, len - 3);
-+	if (call->useruserprotocoldisc == 4) { /* IA5 */
-+	    if (len >= 3) {
-+     		q931_get_number((unsigned char *) call->useruserinfo, sizeof(call->useruserinfo), ie->data + 1, len - 3);
-+	    } else {
-+		pri_error("User-User Information (len=%2d) too short.\n", len);
-+	    }
-+	}
-+	return 0;
-+}
-+
-+static FUNC_RECV(receive_call_identity)
-+{
-+	if (len >= 2) {
-+ 	    q931_get_number(call->callid, sizeof(call->callid), ie->data, len - 2);
-+	} else {
-+	    pri_error("Call Identity (len=%2d) too short.\n", len);
-+	}
- 	return 0;
- }
- 
-+static FUNC_SEND(transmit_call_identity)
-+{
-+	if (strlen(call->callid)) 
-+		memcpy(ie->data , call->callid, strlen(call->callid));
-+	return strlen(call->callednum) + 3;
-+}
-+
- static char *prog2str(int prog)
- {
- 	static struct msgtype progs[] = {
-@@ -1030,21 +1205,40 @@
- 		data++;
- 		len--;
- 	}
--	q931_get_number((unsigned char *) call->callername, sizeof(call->callername), data, len - 2);
-+	if (msgtype == Q931_SETUP) {
-+	    /* we treat display IEs in the SETUP msg as callername */
-+	    if (len >= 2) {
-+		q931_get_number((unsigned char *) call->callername, sizeof(call->callername), data, len - 2);
-+	    } else {
-+		pri_error("Display (len=%2d) too short.\n", len);
-+	    }
-+	} else {
-+	    /* in other msgs we will pass it as text to chan_zap */
-+	    if (len >= 2) {
-+		q931_get_number((unsigned char *) call->display, sizeof(call->display), data, len - 2);
-+	    } else {
-+		pri_error("Display (len=%2d) too short.\n", len);
-+	    }
-+	}
- 	return 0;
- }
- 
- static FUNC_SEND(transmit_display)
- {
- 	int i;
--	if ((pri->switchtype != PRI_SWITCH_NI1) && strlen(call->callername)) {
-+	if ((pri->switchtype != PRI_SWITCH_NI1) && strlen(call->callername) && (pri->localtype != BRI_CPE) && (pri->localtype != BRI_CPE_PTMP) && (pri->localtype != PRI_CPE)) {
- 		i = 0;
- 		if(pri->switchtype != PRI_SWITCH_EUROISDN_E1) {
- 			ie->data[0] = 0xb1;
- 			++i;
- 		}
--		memcpy(ie->data + i, call->callername, strlen(call->callername));
--		return 2 + i + strlen(call->callername);
-+	    	if (msgtype == Q931_SETUP_ACKNOWLEDGE) {
-+		    memcpy(ie->data + i, call->display, strlen(call->display));
-+		    return 2 + i + strlen(call->display);
-+	 	} else {
-+		    memcpy(ie->data + i, call->callername, strlen(call->callername));
-+		    return 2 + i + strlen(call->callername);
-+	    	}
- 	}
- 	return 0;
- }
-@@ -1054,19 +1248,149 @@
- 	call->progloc = ie->data[0] & 0xf;
- 	call->progcode = (ie->data[0] & 0x60) >> 5;
- 	call->progress = (ie->data[1] & 0x7f);
-+
-+	call->progloc = ie->data[0] & 0xf;
-+	call->progcode = (ie->data[0] & 0x60) >> 5;
-+	switch (call->progress = (ie->data[1] & 0x7f)) {
-+	case Q931_PROG_CALL_NOT_E2E_ISDN:
-+		call->progressmask |= PRI_PROG_CALL_NOT_E2E_ISDN;
-+		break;
-+	case Q931_PROG_CALLED_NOT_ISDN:
-+		call->progressmask |= PRI_PROG_CALLED_NOT_ISDN;
-+		break;
-+	case Q931_PROG_CALLER_NOT_ISDN:
-+		call->progressmask |= PRI_PROG_CALLER_NOT_ISDN;
-+		break;
-+	case Q931_PROG_CALLER_RETURNED_TO_ISDN:
-+		call->progressmask |= PRI_PROG_CALLER_RETURNED_TO_ISDN;
-+		break;
-+	case Q931_PROG_INBAND_AVAILABLE:
-+		call->progressmask |= PRI_PROG_INBAND_AVAILABLE;
-+		break;
-+	case Q931_PROG_DELAY_AT_INTERF:
-+		call->progressmask |= PRI_PROG_DELAY_AT_INTERF;
-+		break;
-+	case Q931_PROG_INTERWORKING_WITH_PUBLIC:
-+		call->progressmask |= PRI_PROG_INTERWORKING_WITH_PUBLIC;
-+		break;
-+	case Q931_PROG_INTERWORKING_NO_RELEASE:
-+		call->progressmask |= PRI_PROG_INTERWORKING_NO_RELEASE;
-+		break;
-+	case Q931_PROG_INTERWORKING_NO_RELEASE_PRE_ANSWER:
-+		call->progressmask |= PRI_PROG_INTERWORKING_NO_RELEASE_PRE_ANSWER;
-+		break;
-+	case Q931_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER:
-+		call->progressmask |= PRI_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER;
-+		break;
-+	default:
-+		pri_error("XXX Invalid Progress indicator value received: %02x\n",(ie->data[1] & 0x7f));
-+		break;
-+	}
-+	
- 	return 0;
- }
- 
- static FUNC_RECV(receive_facility)
- {
--	if (ie->len < 14) {
--		pri_error("!! Facility message shorter than 14 bytes\n");
-+	unsigned char cpt_tag, cp_len, invoke_id_tag, invoke_id_len, operation_value_len, operation_value_tag;
-+	unsigned char arg_len = 0;
-+	unsigned char pos = 0;
-+	short invoke_id = 0, operation_value = 0;
-+	if ((ie->data[pos++] & 0x1F) == 0x11) {
-+	    /* service discriminator == supplementary services */
-+	    cpt_tag = ie->data[pos++] & 0x1F;
-+	    cp_len = ie->data[pos++];
-+	    switch (cpt_tag) {
-+		case 1: /* invoke */
-+		        invoke_id_tag = ie->data[pos++];
-+			if (invoke_id_tag != 0x02) {
-+			//    pri_error("invoke id tag != 0x02\n");
-+			    break;
-+			}
-+			invoke_id_len = ie->data[pos++]; // 4
-+		        while (invoke_id_len > 0) {
-+		    	    invoke_id = (invoke_id << 8) | (ie->data[pos++] & 0xFF);
-+			    invoke_id_len--;
-+			}
-+			operation_value_tag = ie->data[pos++];
-+			if (operation_value_tag != 0x02) {
-+			//    pri_error("operation value tag != 0x02\n");
-+			    break;
-+			}
-+			operation_value_len = ie->data[pos++];
-+		        while (operation_value_len > 0) {
-+		    	    operation_value = (operation_value << 8) | (ie->data[pos++] & 0xFF);
-+			    operation_value_len--;
-+			}
-+			arg_len = ie->len - pos;
-+			switch (operation_value) {
-+			    case 0x06:	/* ECT execute */
-+					call->facility = operation_value;
-+					break;
-+			    case 0x0D:	/* call deflection */
-+			    		call->facility = operation_value;
-+					/* dirty hack! */
-+					arg_len -= 6;
-+					if (arg_len > 0) {
-+					    pos += 6;
-+ 					    q931_get_number(call->redirectingnum, sizeof(call->redirectingnum), ie->data + pos, arg_len);
-+					}
-+					/* now retrieve the number */
-+					break;
-+			    case 0x22:  /* AOC-D */
-+					break;
-+			    case 0x24:  /* AOC-E */
-+					break;
-+			}
-+		        break;
-+		case 2: /* return result */
-+			break;
-+	        case 3: /* return error */
-+ 			break;
-+		case 4: /* reject */
-+			break;
-+	    }
-+	} else {
-+	    /* OLD DIRTY ULAW HACK */
-+	    if (ie->len < 14) {
-+  		pri_error("!! Facility message shorter than 14 bytes\n");
- 		return 0;
-+	    }
-+	    if (ie->data[13] + 14 == ie->len) {
-+		q931_get_number(call->callername, sizeof(call->callername) - 1, ie->data + 14, ie->len - 14);
-+	    } 
-+	    call->facility = 0x0;
- 	}
--	if (ie->data[13] + 14 == ie->len) {
--		q931_get_number((unsigned char *) call->callername, sizeof(call->callername) - 1, ie->data + 14, ie->len - 14);
--	} 
--	return 0;
-+  	return 0;
-+}
-+
-+static FUNC_SEND(transmit_facility)
-+{
-+	int i = 0;
-+	return i;
-+	if (call->aoc && (pri->switchtype == PRI_SWITCH_EUROISDN_E1) && ((pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_NETWORK_PTMP) || (pri->localtype == PRI_NETWORK))) {
-+	    ie->data[0] = 0x90;  /* PP remote operations */
-+	    ie->data[i++] = 0x00; /* component tag */
-+	    ie->data[i++] = 0x02; /* invoke id tag */
-+	    ie->data[i++] = 0x02; /* invoke id len */
-+	    ie->data[i++] = 0x34; /* invoke id */
-+	    ie->data[i++] = 0x56; /* invoke id */
-+	    ie->data[i++] = 0x02; /* operation value tag */
-+	    ie->data[i++] = 0x01; /* operation value len */
-+	    switch (msgtype) {
-+		case Q931_SETUP:
-+		    ie->data[i++] = 0x26; /* operation value AOC-S */
-+		    break;
-+		case Q931_DISCONNECT:
-+		    ie->data[i++] = 0x24; /* operation value AOC-E */
-+		    break;
-+		default:
-+		    ie->data[i++] = 0x22; /* operation value AOC-D */
-+		    break;
-+	    }
-+	    // ARGUMENTS!	
-+	}
-+//	return 2 + i;
- }
- 
- static FUNC_SEND(transmit_progress_indicator)
-@@ -1075,6 +1399,7 @@
- 	if (!pri->subchannel && (call->progress > 0)) {
- 		ie->data[0] = 0x80 | (call->progcode << 5)  | (call->progloc);
- 		ie->data[1] = 0x80 | (call->progress);
-+//		ie->data[1] = 0x88;
- 		return 4;
- 	} else {
- 		/* Leave off */
-@@ -1156,6 +1481,26 @@
- 	pri_message(" ]\n");
- }
- 
-+static FUNC_RECV(receive_time_date)
-+{
-+    return 0;
-+}
-+
-+static FUNC_SEND(transmit_time_date) {
-+    time_t now;
-+    struct tm *timedate;
-+    time(&now);
-+    timedate = localtime(&now);
-+    ie->data[0] = timedate->tm_year - 100; // 1900+
-+    ie->data[1] = timedate->tm_mon + 1;
-+    ie->data[2] = timedate->tm_mday;
-+    ie->data[3] = timedate->tm_hour;
-+    ie->data[4] = timedate->tm_min;
-+    return 7;
-+}
-+
-+
-+
- static FUNC_DUMP(dump_display)
- {
- 	int x, y;
-@@ -1175,6 +1520,32 @@
- 	}
- }
- 
-+static FUNC_RECV(receive_keypad_facility)
-+{
-+	/* copy digits to call->callednum or call->digits */
-+	if (msgtype == Q931_SETUP) {
-+	    if (len >= 2) {
-+ 		q931_get_number(call->digits, sizeof(call->digits), ie->data , len - 2);
-+	    } else {
-+		pri_error("Keypad facility (len=%2d) too short.\n", len);
-+	    }
-+	} else {
-+	    // XXX we assume 1 byte keypad
-+	    call->digits[0] = ie->data[0] & 0x7f;
-+	    call->digits[1] = '\0';
-+	}
-+	return 0;
-+}
-+
-+static FUNC_DUMP(dump_keypad_facility)
-+{
-+	int x;
-+	pri_message("%c Keypad Facility (len=%2d) [ ", prefix, len);
-+	for (x=0;x<ie->len;x++) 
-+		pri_message("%c", ie->data[x] & 0x7f);
-+	pri_message(" ]\n");
-+}
-+
- static void dump_ie_data(unsigned char *c, int len)
- {
- 	char tmp[1024] = "";
-@@ -1432,7 +1803,53 @@
- #endif
- 	return 0;
- }
-+/*
-+static int transmit_special(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
-+{
-+// 1C 02 95 81 97 02 02 32 39 04 01 80 05 02 01 5B
-+	ie->data[0] = 0x1c;
-+	ie->data[1] = 0x02;
-+	ie->data[2] = 0x95;
-+	ie->data[3] = 0x81;
-+	ie->data[4] = 0x97;
-+	ie->data[5] = 0x02;
-+	ie->data[6] = 0x02;
-+	ie->data[7] = 0x32;
- 
-+	ie->data[8] = 0x39;
-+	ie->data[9] = 0x04;
-+	ie->data[10] = 0x01;
-+	ie->data[11] = 0x80;
-+	ie->data[12] = 0x05;
-+	ie->data[13] = 0x02;
-+	ie->data[14] = 0x01;
-+	ie->data[15] = 0x5B;
-+
-+
-+	return 17;
-+}
-+
-+static int receive_special(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len) 
-+{
-+    return 0;
-+}
-+
-+static void dump_special(q931_ie *ie, int len, char prefix)
-+{
-+	int x=0;
-+	pri_message("%c SPECIAL (len=%2d) [ ", prefix, ie->len);
-+	for (x=0;x<ie->len;x++) 
-+		pri_message("%2x ", ie->data[x]);
-+	pri_message("]\n");
-+}
-+
-+static int transmit_my_paging_signal(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
-+{
-+	ie->data[0] = 0x47;
-+	return 3;
-+}
-+
-+*/
- struct ie ies[] = {
- 	/* Codeset 0 - Common */
- 	{ NATIONAL_CHANGE_STATUS, "Change Status" },
-@@ -1461,20 +1878,21 @@
- 	{ Q931_LOW_LAYER_COMPAT, "Low-layer Compatibility" },
- 	{ Q931_HIGH_LAYER_COMPAT, "High-layer Compatibility" },
- 	{ Q931_PACKET_SIZE, "Packet Size" },
--	{ Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility },
-+	{ Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility, transmit_facility },
- 	{ Q931_IE_REDIRECTION_NUMBER, "Redirection Number" },
- 	{ Q931_IE_REDIRECTION_SUBADDR, "Redirection Subaddress" },
- 	{ Q931_IE_FEATURE_ACTIVATE, "Feature Activation" },
- 	{ Q931_IE_INFO_REQUEST, "Feature Request" },
- 	{ Q931_IE_FEATURE_IND, "Feature Indication" },
- 	{ Q931_IE_SEGMENTED_MSG, "Segmented Message" },
--	{ Q931_IE_CALL_IDENTITY, "Call Identity", dump_call_identity },
-+	{ Q931_IE_CALL_IDENTITY, "Call Identity", dump_call_identity, receive_call_identity, transmit_call_identity },
- 	{ Q931_IE_ENDPOINT_ID, "Endpoint Identification" },
- 	{ Q931_IE_NOTIFY_IND, "Notification Indicator", dump_notify, receive_notify, transmit_notify },
- 	{ Q931_DISPLAY, "Display", dump_display, receive_display, transmit_display },
--	{ Q931_IE_TIME_DATE, "Date/Time", dump_time_date },
--	{ Q931_IE_KEYPAD_FACILITY, "Keypad Facility" },
--	{ Q931_IE_SIGNAL, "Signal" },
-+	{ Q931_IE_TIME_DATE, "Date/Time", dump_time_date, receive_time_date, transmit_time_date },
-+	{ Q931_IE_KEYPAD_FACILITY, "Keypad Facility" , dump_keypad_facility, receive_keypad_facility},
-+	{ Q931_IE_SIGNAL, "Signal"},
-+//	{ Q931_IE_SIGNAL, "Signal",dump_special, receive_special, transmit_my_paging_signal},
- 	{ Q931_IE_SWITCHHOOK, "Switch-hook" },
- 	{ Q931_IE_USER_USER, "User-User", dump_user_user, receive_user_user },
- 	{ Q931_IE_ESCAPE_FOR_EXT, "Escape for Extension" },
-@@ -1485,6 +1903,7 @@
- 	{ Q931_IE_ORIGINAL_CALLED_NUMBER, "Original Called Number" },
- 	{ Q931_IE_USER_USER_FACILITY, "User-User Facility" },
- 	{ Q931_IE_UPDATE, "Update" },
-+	{ Q931_COLP, "Connect Line ID Presentation", dump_colp},
- 	{ Q931_SENDING_COMPLETE, "Sending Complete", dump_sending_complete, receive_sending_complete, transmit_sending_complete },
- 	/* Codeset 6 - Network specific */
- 	{ Q931_IE_FACILITY | Q931_CODESET(6), "Facility", dump_facility, receive_facility },
-@@ -1548,7 +1967,7 @@
- {
- 	if ((ie->ie & 0x80) != 0)
- 		return 1;
--	else
-+	else 
- 		return 2 + ie->len;
- }
- 
-@@ -1578,13 +1997,13 @@
- 			break;
- 		case 1:
- 			cr = h->crv[0];
--			if (cr & 0x80) {
-+		/*	if (cr & 0x80) {
- 				cr &= ~0x80;
- 				cr |= 0x8000;
--			}
-+			} */
- 			break;
--		default:
--			pri_error("Call Reference Length not supported: %d\n", h->crlen);
-+		// default:
-+		//	pri_error("Call Reference Length not supported: %d\n", h->crlen);
- 	}
- 	return cr;
- }
-@@ -1595,6 +2014,11 @@
- 	int full_ie = Q931_FULL_IE(codeset, ie->ie);
- 	int base_ie;
- 
-+	if (ielen(ie) > Q931_IE_MAX_LEN) {
-+	    pri_error("!! %c Invalid IE length %d (len = %d)\n", prefix, base_ie, ielen(ie));
-+	    return;
-+	}
-+
- 	pri_message("%c [", prefix);
- 	pri_message("%02x", ie->ie);
- 	if (!(ie->ie & 0x80)) {
-@@ -1622,14 +2046,46 @@
- 	pri_error("!! %c Unknown IE %d (len = %d)\n", prefix, base_ie, ielen(ie));
- }
- 
--static q931_call *q931_getcall(struct pri *pri, int cr)
-+static q921_call *q921_getcall(struct pri *pri, struct q931_call *c, int tei)
-+{
-+	q921_call *cur;
-+	cur = c->phones;
-+	while(cur) {
-+	    if (cur->tei == tei) {
-+		    return cur;
-+	    } 
-+	    cur = cur->next;
-+	}
-+	/* No call exists, make a new one */
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+		pri_message("-- Making new q921 call for cref %d tei %d\n", c->cr, tei);
-+	cur = malloc(sizeof(struct q921_call));
-+	memset(cur, 0, sizeof(cur));
-+	cur->tei = tei;
-+	cur->proc = 0;
-+	cur->channel = -1;
-+	cur->next = c->phones;
-+	c->phones = cur;
-+	return cur;
-+}
-+
-+static q931_call *q931_getcall(struct pri *pri, int cr, int tei)
- {
- 	q931_call *cur, *prev;
- 	cur = *pri->callpool;
- 	prev = NULL;
- 	while(cur) {
--		if (cur->cr == cr)
--			return cur;
-+		if ((pri->localtype == BRI_NETWORK_PTMP) && (tei >= 0)) {
-+		    // hmm...ok, we might be the 1st responding to the setup
-+		    // or it is really our call
-+		    if ((cur->cr == cr) && ((cur->tei == tei) || (cur->tei == 127)))
-+			    return cur;
-+	    	    // or we might not be the 1st responding, then we need to clone
-+		    // the call struct to hangup properly
-+		} else {
-+		    if (cur->cr == cr)
-+			    return cur;
-+		}
- 		prev = cur;
- 		cur = cur->next;
- 	}
-@@ -1642,6 +2098,7 @@
- 		/* Call reference */
- 		cur->cr = cr;
- 		cur->pri = pri;
-+		cur->tei = tei;
- 		/* Append to end of list */
- 		if (prev)
- 			prev->next = cur;
-@@ -1657,24 +2114,42 @@
- 	do {
- 		cur = *pri->callpool;
- 		pri->cref++;
--		if (pri->cref > 32767)
--			pri->cref = 1;
-+		if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
-+		    if (pri->cref > 32767)
-+			    pri->cref = 1;
-+		} else {
-+		    // BRI
-+		    if (pri->cref > 255)
-+			    pri->cref = 1;
-+		}
- 		while(cur) {
--			if (cur->cr == (0x8000 | pri->cref))
--				break;
-+			if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
-+			    if (cur->cr == (0x8000 | pri->cref))
-+				    break;
-+			} else {
-+			    // BRIs have only 1 bye cref
-+			    if (cur->cr == (0x80 | pri->cref))
-+				    break;
-+			}
- 			cur = cur->next;
- 		}
- 	} while(cur);
--	return q931_getcall(pri, pri->cref | 0x8000);
-+	if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
-+	    return q931_getcall(pri, pri->cref | 0x8000, 0);
-+	} else {
-+	    // BRI
-+	    return q931_getcall(pri, pri->cref | 0x80, 0);
-+	}
- }
- 
--static void q931_destroy(struct pri *pri, int cr, q931_call *c)
-+static void q931_destroy(struct pri *pri, int cr, q931_call *c, int tei)
- {
- 	q931_call *cur, *prev;
- 	prev = NULL;
- 	cur = *pri->callpool;
- 	while(cur) {
--		if ((c && (cur == c)) || (!c && (cur->cr == cr))) {
-+//		if ((c && (cur == c)) || (!c && (cur->cr == cr))) {
-+		if ((c && (cur == c)) || (!c && ((cur->cr == cr) && ((pri->localtype != BRI_NETWORK_PTMP) || (cur->tei == tei))))) {
- 			if (prev)
- 				prev->next = cur->next;
- 			else
-@@ -1683,6 +2158,8 @@
- 				pri_message("NEW_HANGUP DEBUG: Destroying the call, ourstate %s, peerstate %s\n",callstate2str(cur->ourcallstate),callstate2str(cur->peercallstate));
- 			if (cur->retranstimer)
- 				pri_schedule_del(pri, cur->retranstimer);
-+			if (cur->t303timer)
-+				pri_schedule_del(pri, cur->t303timer);
- 			free(cur);
- 			return;
- 		}
-@@ -1692,16 +2169,17 @@
- 	pri_error("Can't destroy call %d!\n", cr);
- }
- 
--static void q931_destroycall(struct pri *pri, int cr)
-+
-+static void q931_destroycall(struct pri *pri, int cr, int tei)
- {
--	return q931_destroy(pri, cr, NULL);
-+	return q931_destroy(pri, cr, NULL, tei);
- }
- 
- 
- void __q931_destroycall(struct pri *pri, q931_call *c) 
- {
- 	if (pri && c)
--		q931_destroy(pri,0, c);
-+		q931_destroy(pri,0, c, c->tei);
- 	return;
- }
- 
-@@ -1799,6 +2277,10 @@
- {
- 	unsigned int x;
- 	int full_ie = Q931_FULL_IE(codeset, ie->ie);
-+	if (ielen(ie) > Q931_IE_MAX_LEN) {
-+	    pri_error("!! Invalid IE length %d (len = %d)\n", full_ie, ielen(ie));
-+	    return -1;
-+	}
- 	if (pri->debug & PRI_DEBUG_Q931_STATE)
- 		pri_message("-- Processing IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));
- 	for (x=0;x<sizeof(ies) / sizeof(ies[0]);x++) {
-@@ -1816,21 +2298,36 @@
- 	return -1;
- }
- 
--static void init_header(struct pri *pri, q931_call *call, unsigned char *buf, q931_h **hb, q931_mh **mhb, int *len)
-+static void init_header(struct pri *pri, q931_call *call, unsigned char *buf, q931_h **hb, q931_mh **mhb, int *len, int briflag)
- {
- 	/* Returns header and message header and modifies length in place */
-+	q931_mh *mh;
- 	q931_h *h = (q931_h *)buf;
--	q931_mh * mh = (q931_mh *)(h->contents + 2);
- 	h->pd = pri->protodisc;
- 	h->x0 = 0;		/* Reserved 0 */
--	h->crlen = 2;	/* Two bytes of Call Reference.  Invert the top bit to make it from our sense */
--	if (call->cr || call->forceinvert) {
-+
-+	if (briflag == 1) {
-+	    mh = (q931_mh *)(h->contents + 1);
-+ 	    h->crlen = 1;	/* One bytes of Call Reference.  Invert the top bit to make it from our sense */
-+	    if (call->cr || call->forceinvert) {
-+		h->crv[0] = (call->cr ^ 0x80);
-+	    } else {
-+		/* Unless of course this has no call reference */
-+		h->crv[0] = 0;
-+	    }
-+	    *len -= 4;
-+	} else {
-+	    mh = (q931_mh *)(h->contents + 2);
-+ 	    h->crlen = 2;	/* Two bytes of Call Reference.  Invert the top bit to make it from our sense */
-+	    if (call->cr || call->forceinvert) {
- 		h->crv[0] = ((call->cr ^ 0x8000) & 0xff00) >> 8;
- 		h->crv[1] = (call->cr & 0xff);
--	} else {
-+	    } else {
- 		/* Unless of course this has no call reference */
- 		h->crv[0] = 0;
- 		h->crv[1] = 0;
-+	    }
-+	    *len -= 5;
- 	}
- 	if (pri->subchannel) {
- 		/* On GR-303, top bit is always 0 */
-@@ -1839,13 +2336,37 @@
- 	mh->f = 0;
- 	*hb = h;
- 	*mhb = mh;
--	*len -= 5;
--	
- }
- 
--static int q931_xmit(struct pri *pri, q931_h *h, int len, int cr)
-+static int q931_xmit(struct pri *pri, q931_h *h, int len, int cr, int tei)
- {
--	q921_transmit_iframe(pri, h, len, cr);
-+	q931_mh *mh;
-+	if (pri->localtype == BRI_NETWORK_PTMP) {
-+	    mh = (q931_mh *)(h->contents + 1);
-+	    if (mh->msg == Q931_SETUP) {
-+		q921_transmit_uframe(pri, h, len, cr, tei);
-+	    } else {
-+		q921_transmit_iframe(pri, h, len, cr, tei);
-+	    }
-+	} else if (pri->localtype == BRI_CPE_PTMP) {
-+	    mh = (q931_mh *)(h->contents + 1);
-+	    if ((pri->state == Q921_LINK_CONNECTION_RELEASED) && (mh->msg == Q931_SETUP)) {
-+	        // no MFE
-+	/*        if (pri->tei == 0) {
-+		    pri_error("no tei\n");
-+		    q921_send_teireq(pri);
-+		} else {
-+		    q921_send_sabme(pri,1,pri->tei);
-+		    pri->q921_state[tei - Q921_TEI_BASE] = Q921_AWAITING_ESTABLISH;
-+		}
-+		q921_reset(pri, pri->tei); */
-+	    }
-+	    // XXX D    IRTY!, we rely on the fact that the L3 frames will be retransmitted
-+	    // if they dont get ACKed. however this is supposed to work.
-+	     q921_transmit_iframe(pri, h, len, cr, pri->tei);
-+	} else {
-+	    q921_transmit_iframe(pri, h, len, cr, tei);
-+	}
- 	/* The transmit operation might dump the q921 header, so logging the q931
- 	   message body after the transmit puts the sections of the message in the
- 	   right order in the log */
-@@ -1869,7 +2390,11 @@
- 	int codeset;
- 	memset(buf, 0, sizeof(buf));
- 	len = sizeof(buf);
--	init_header(pri, c, buf, &h, &mh, &len);
-+	if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
-+	    init_header(pri, c, buf, &h, &mh, &len, 0);
-+	} else {
-+	    init_header(pri, c, buf, &h, &mh, &len, 1);
-+	}
- 	mh->msg = msgtype;
- 	x=0;
- 	codeset = 0;
-@@ -1885,11 +2410,33 @@
- 	}
- 	/* Invert the logic */
- 	len = sizeof(buf) - len;
--	q931_xmit(pri, h, len, 1);
-+	if (pri->localtype == BRI_CPE_PTMP) {
-+	    q931_xmit(pri, h, len, 1, pri->tei);
-+	} else {
-+	    q931_xmit(pri, h, len, 1, c->tei);
-+	}
- 	c->acked = 1;
- 	return 0;
- }
- 
-+static int facility_ies[] = { Q931_IE_FACILITY, -1 };
-+
-+int q931_facility(struct pri *pri, q931_call *c, int operation, char *arguments)
-+{
-+	switch (operation) {
-+	    case 0x26:	c->aoc = 1;
-+			break;
-+	    case 0x24:	c->aoc = 1;
-+			break;
-+	    case 0x22:	c->aoc = 1;
-+			break;
-+	    default:
-+		return -1;
-+	}
-+	return send_message(pri, c, Q931_FACILITY, facility_ies);
-+}
-+
-+
- static int status_ies[] = { Q931_CAUSE, Q931_CALL_STATE, -1 };
- 
- static int q931_status(struct pri *pri, q931_call *c, int cause)
-@@ -1927,12 +2474,42 @@
- 	return send_message(pri, c, Q931_INFORMATION, information_ies);
- }
- 
-+static int information_display_ies[] = { Q931_DISPLAY, -1 };
-+
-+int q931_information_display(struct pri *pri, q931_call *c, char *display)
-+{
-+	int res=0;
-+	char temp[256];
-+	if (!display) return -1;
-+	strncpy(temp, c->callername, sizeof(temp));
-+	strncpy(c->callername, display, sizeof(c->callername));
-+	res = send_message(pri, c, Q931_INFORMATION, information_display_ies);
-+	strncpy(c->callername, temp, sizeof(c->callername));
-+	return res;
-+}
-+
-+int q931_add_display(struct pri *pri, q931_call *c, char *display)
-+{
-+	strncpy(c->display, display, sizeof(c->display));
-+	return 0;
-+}
-+
-+/* static int information_special_ies[] = { Q931_IE_SPECIAL, -1 };
-+static int q931_information_special(struct pri *pri, q931_call *c)
-+{
-+	return send_message(pri, c, Q931_FACILITY, information_special_ies);
-+}
-+*/
-+
-+
- static int restart_ack_ies[] = { Q931_CHANNEL_IDENT, Q931_RESTART_INDICATOR, -1 };
- 
- static int restart_ack(struct pri *pri, q931_call *c)
- {
- 	c->ourcallstate = Q931_CALL_STATE_NULL;
- 	c->peercallstate = Q931_CALL_STATE_NULL;
-+        c->chanflags &= ~FLAG_PREFERRED;
-+        c->chanflags |= FLAG_EXCLUSIVE;
- 	return send_message(pri, c, Q931_RESTART_ACKNOWLEDGE, restart_ack_ies);
- }
- 
-@@ -2003,8 +2580,14 @@
- static int alerting_ies[] = { -1 };
- #endif
- 
-+// static int alerting_BRI_ies[] = { -1 };
-+
- int q931_alerting(struct pri *pri, q931_call *c, int channel, int info)
- {
-+	// never send two ALERTINGs!
-+	if (c->alert > 0) return 0;		
-+	// XXX novo vox hack
-+//	if ((!c->proc) && (pri->localtype != BRI_CPE_PTMP))
- 	if (!c->proc) 
- 		q931_call_proceeding(pri, c, channel, 0);
- 	if (info) {
-@@ -2015,11 +2598,126 @@
- 		c->progress = -1;
- 	c->ourcallstate = Q931_CALL_STATE_CALL_RECEIVED;
- 	c->peercallstate = Q931_CALL_STATE_CALL_DELIVERED;
-+	c->alert = 1;
- 	c->alive = 1;
- 	return send_message(pri, c, Q931_ALERTING, alerting_ies);
-+/*	if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
-+	    return send_message(pri, c, Q931_ALERTING, alerting_ies);
-+	} else {
-+	    if ((pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_NETWORK_PTMP)) {
-+		return send_message(pri, c, Q931_ALERTING, alerting_ies);
-+    	    } else {
-+		// no PROGRESS_IND for BRI please
-+		return send_message(pri, c, Q931_ALERTING, alerting_BRI_ies);
-+	    }
-+	} */
- }
- 
--static int connect_ies[] = {  Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, -1 };
-+static int hold_acknowledge_ies[] = { -1 };
-+
-+int q931_hold_acknowledge(struct pri *pri, q931_call *c)
-+{
-+	return send_message(pri, c, Q931_HOLD_ACKNOWLEDGE, hold_acknowledge_ies);
-+}
-+
-+static int hold_reject_ies[] = { Q931_CAUSE, -1 };
-+
-+int q931_hold_reject(struct pri *pri, q931_call *c)
-+{
-+	c->cause = 12;
-+	c->causecode = CODE_CCITT;
-+	c->causeloc = LOC_PRIV_NET_LOCAL_USER;
-+	return send_message(pri, c, Q931_HOLD_REJECT, hold_reject_ies);
-+}
-+
-+static int retrieve_acknowledge_ies[] = { Q931_CHANNEL_IDENT, -1 };
-+
-+int q931_retrieve_acknowledge(struct pri *pri, q931_call *c, int channel)
-+{
-+	if (channel)
-+		c->channelno = channel;
-+	c->chanflags &= ~FLAG_PREFERRED;
-+	c->chanflags |= FLAG_EXCLUSIVE;
-+	return send_message(pri, c, Q931_RETRIEVE_ACKNOWLEDGE, retrieve_acknowledge_ies);
-+}
-+
-+static int retrieve_reject_ies[] = { -1 };
-+
-+int q931_retrieve_reject(struct pri *pri, q931_call *c)
-+{
-+	return send_message(pri, c, Q931_RETRIEVE_REJECT, retrieve_reject_ies);
-+}
-+
-+static int suspend_acknowledge_ies[] = { Q931_DISPLAY, -1 };
-+
-+int q931_suspend_acknowledge(struct pri *pri, q931_call *c, char *display)
-+{
-+	char tempcallername[256];
-+	int res;
-+	c->ourcallstate = Q931_CALL_STATE_NULL;
-+	c->peercallstate = Q931_CALL_STATE_NULL;
-+	strncpy(tempcallername,c->callername,sizeof(tempcallername));
-+	strncpy(c->callername,display,sizeof(c->callername));
-+	res = send_message(pri, c, Q931_SUSPEND_ACKNOWLEDGE, suspend_acknowledge_ies);
-+	strncpy(c->callername,tempcallername,sizeof(c->callername));
-+	return res;
-+}
-+
-+static int suspend_reject_ies[] = { Q931_DISPLAY, Q931_CAUSE, -1 };
-+
-+int q931_suspend_reject(struct pri *pri, q931_call *c, char *display)
-+{
-+	char tempcallername[256];
-+	int res;
-+	strncpy(tempcallername,c->callername,sizeof(tempcallername));
-+	strncpy(c->callername,display,sizeof(c->callername));
-+	c->cause = 12;
-+	c->causecode = CODE_CCITT;
-+	c->causeloc = LOC_PRIV_NET_LOCAL_USER;
-+	res = send_message(pri, c, Q931_SUSPEND_REJECT, suspend_reject_ies);
-+	strncpy(c->callername,tempcallername,sizeof(c->callername));
-+	return res;
-+}
-+
-+static int resume_reject_ies[] = { Q931_CAUSE, Q931_DISPLAY,  -1 };
-+
-+int q931_resume_reject(struct pri *pri, q931_call *c, char *display)
-+{
-+	char tempcallername[256];
-+	int res;
-+	c->cause = 12;
-+	c->causecode = CODE_CCITT;
-+	c->causeloc = LOC_PRIV_NET_LOCAL_USER;
-+	strncpy(tempcallername,c->callername,sizeof(tempcallername));
-+	strncpy(c->callername,display,sizeof(c->callername));
-+	res = send_message(pri, c, Q931_RESUME_REJECT, resume_reject_ies);
-+	strncpy(c->callername,tempcallername,sizeof(c->callername));
-+	return res;
-+}
-+
-+static int resume_acknowledge_ies[] = { Q931_CHANNEL_IDENT, Q931_DISPLAY,  -1 };
-+
-+int q931_resume_acknowledge(struct pri *pri, q931_call *c, int channel, char *display)
-+{
-+	char tempcallername[256];
-+	int res;
-+	if (channel)
-+		c->channelno = channel;
-+	c->chanflags &= ~FLAG_PREFERRED;
-+	c->chanflags |= FLAG_EXCLUSIVE;
-+	c->alive = 1;
-+	c->ourcallstate = Q931_CALL_STATE_ACTIVE;
-+	c->peercallstate = Q931_CALL_STATE_ACTIVE;
-+	strncpy(tempcallername,c->callername,sizeof(tempcallername));
-+	strncpy(c->callername,display,sizeof(c->callername));
-+	res = send_message(pri, c, Q931_RESUME_ACKNOWLEDGE, resume_acknowledge_ies);
-+	strncpy(c->callername,tempcallername,sizeof(c->callername));
-+	return res;
-+}
-+
-+
-+static int connect_ies[] = {  Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, Q931_DISPLAY, -1 };
-+static int connect_NET_ies[] = {  Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, Q931_IE_TIME_DATE, -1 };
-  
- int q931_setup_ack(struct pri *pri, q931_call *c, int channel, int nonisdn)
- {
-@@ -2039,9 +2737,35 @@
- 	c->ourcallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
- 	c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;
- 	c->alive = 1;
-+	if (pri->localtype == BRI_NETWORK_PTMP) {
-+		c->progloc = LOC_PRIV_NET_LOCAL_USER;
-+		c->progcode = CODE_CCITT;
-+		c->progress = Q931_PROG_INBAND_AVAILABLE;
-+	}
- 	return send_message(pri, c, Q931_SETUP_ACKNOWLEDGE, connect_ies);
- }
- 
-+static void pri_setup_response_timeout(void *data)
-+{
-+	struct q931_call *c = data;
-+	struct pri *pri = NULL;
-+	if (!c) return;
-+	pri = c->pri;
-+	if (!pri) return;
-+	c->alive = 1;
-+	c->cause = PRI_CAUSE_NO_USER_RESPONSE;
-+	if (pri->debug & PRI_DEBUG_Q931_STATE)
-+		pri_message("No response to SETUP message\n");
-+	pri->schedev = 1;
-+	pri->ev.e = PRI_EVENT_HANGUP;
-+	pri->ev.hangup.channel = c->channelno;
-+	pri->ev.hangup.cref = c->cr;
-+//	pri->ev.hangup.cause = c->cause;
-+	pri->ev.hangup.cause = PRI_CAUSE_SWITCH_CONGESTION;
-+	pri->ev.hangup.call = c;
-+	q931_hangup(pri, c, c->cause);
-+}
-+
- static void pri_connect_timeout(void *data)
- {
- 	struct q931_call *c = data;
-@@ -2116,7 +2840,12 @@
- 	c->retranstimer = 0;
- 	if ((pri->localtype == PRI_CPE) && (!pri->subchannel))
- 		c->retranstimer = pri_schedule_event(pri, T_313, pri_connect_timeout, c);
--	return send_message(pri, c, Q931_CONNECT, connect_ies);
-+	if ((pri->localtype != PRI_CPE) && (pri->localtype != BRI_CPE) && (pri->localtype != BRI_CPE_PTMP)) {
-+	    // networks may send datetime
-+	    return send_message(pri, c, Q931_CONNECT, connect_NET_ies);
-+	} else {
-+	    return send_message(pri, c, Q931_CONNECT, connect_ies);
-+	}
- }
- 
- static int release_ies[] = { Q931_CAUSE, -1 };
-@@ -2150,7 +2879,7 @@
- int q931_restart(struct pri *pri, int channel)
- {
- 	struct q931_call *c;
--	c = q931_getcall(pri, 0 | 0x8000);
-+	c = q931_getcall(pri, 0 | 0x8000, 0);
- 	if (!c)
- 		return -1;
- 	if (!channel)
-@@ -2186,15 +2915,24 @@
- 		return 0;
- }
- 
-+//static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_DISPLAY, Q931_PROGRESS_INDICATOR,
-+//	 Q931_IE_SIGNAL, Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_SENDING_COMPLETE, -1 };
-+
- static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, Q931_NETWORK_SPEC_FAC, Q931_DISPLAY,
- 	Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_SENDING_COMPLETE, Q931_IE_ORIGINATING_LINE_INFO, -1 };
- 
- static int gr303_setup_ies[] =  { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, -1 };
- 
-+
- int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
- {
- 	int res;
- 	
-+	if (pri->localtype == BRI_NETWORK_PTMP) {
-+	    c->tei = 127;
-+	} else {
-+	    c->tei = 0;
-+	}
- 	
- 	c->transcapability = req->transmode;
- 	c->transmoderate = TRANS_MODE_64_CIRCUIT;
-@@ -2251,12 +2989,17 @@
- 		res = send_message(pri, c, Q931_SETUP, gr303_setup_ies);
- 	else
- 		res = send_message(pri, c, Q931_SETUP, setup_ies);
-+
- 	if (!res) {
- 		c->alive = 1;
- 		/* make sure we call PRI_EVENT_HANGUP_ACK once we send/receive RELEASE_COMPLETE */
- 		c->sendhangupack = 1;
- 		c->ourcallstate = Q931_CALL_STATE_CALL_INITIATED;
- 		c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;	
-+//		if ((pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_NETWORK_PTMP) || (pri->localtype == PRI_NETWORK)) {
-+		    c->t303timer = pri_schedule_event(pri, T_303, pri_setup_response_timeout, c);
-+		    c->t303running = 1;
-+//		}
- 	}
- 	return res;
- 	
-@@ -2297,6 +3040,118 @@
- 	return 0;
- }
- 
-+
-+
-+/* here we cleanly hangup the phones that responded to our call but didnt get the call  */
-+int q921_hangup(struct pri *pri, q931_call *c, int tei)
-+{
-+    q921_call *cur,*prev;
-+    int tc;
-+    int ttei;
-+    int res=0;
-+
-+    if (!pri || !c)
-+	return -1;
-+    
-+    if (pri->localtype != BRI_NETWORK_PTMP){
-+	return 0;
-+    }
-+//	pri_error("q921_hangup(%d, %d)\n", c->cr, tei);
-+
-+    if (tei == 127) {
-+	tei = c->tei;
-+    }
-+//	pri_error("tei %d\n", tei);
-+
-+    cur = c->phones;
-+    
-+    tc = c->cause;
-+    ttei = c->tei;
-+    while (cur) {
-+	if (cur->tei != tei) {
-+	    c->cause = PRI_CAUSE_NORMAL_CLEARING;
-+	    c->tei = cur->tei;
-+	    if (pri->debug & PRI_DEBUG_Q921_STATE)
-+		pri_message("sending RELEASE for TEI %d\n", cur->tei);
-+	    send_message(pri, c, Q931_RELEASE, release_ies);
-+	}
-+	prev = cur;
-+	cur = cur->next;
-+	if (prev) {
-+	    free(prev);
-+	    prev = NULL;
-+	}
-+    }
-+    c->phones = NULL;
-+    c->tei = ttei;
-+    c->cause = tc;
-+
-+    if (c->tei == 127) {
-+	q931_destroycall(pri, c->cr, c->tei);
-+	// make sure * frees the channel
-+/*	pri_error("returning PRI_EVENT_HANGUP_ACK\n");
-+	res = Q931_RES_HAVEEVENT;
-+	pri->ev.hangup.channel = c->channelno;
-+	pri->ev.e = PRI_EVENT_HANGUP_ACK;  */
-+    } 
-+    return res; 
-+}
-+
-+/* here we handle release_completes from the phones 
-+   because some (elmeg) phones do not send a disconnect
-+   message when the phone is busy */
-+int q921_handle_hangup(struct pri *pri, q931_call *c, int tei)
-+{
-+    q921_call *cur,*match,*prev=NULL;
-+    int left=0;
-+    int res=0;
-+    
-+    if (!pri || !c)
-+	return -1;
-+
-+    if (pri->localtype != BRI_NETWORK_PTMP){
-+	return 0;
-+    }
-+
-+    cur = c->phones;
-+    
-+    while (cur) {
-+	if (cur->tei == tei) {
-+	    match = cur;
-+	    if (prev) {
-+		prev->next = cur->next;
-+		cur = prev;
-+	    } else {
-+		c->phones = cur->next;
-+	    }
-+	    free(match);
-+	}
-+	prev = cur;
-+	if (cur) cur = cur->next;
-+    }
-+
-+    cur = c->phones;
-+    
-+    while (cur) {
-+	left++;
-+	cur = cur->next;
-+    }
-+    
-+    // if all phones have signalled busy AND the timer is not running anymore!
-+    if ((left==0) && (c->cause == PRI_CAUSE_USER_BUSY) && (c->t303running == 0)) {
-+//	pri_error("q921_handle_hangup(%d, %d, %d)\n", c->cr, tei, c->tei);
-+	// make sure * frees the channel
-+	res = Q931_RES_HAVEEVENT;
-+	pri->ev.hangup.cause = PRI_CAUSE_USER_BUSY;
-+	pri->ev.hangup.channel = c->channelno | (c->ds1no << 8);
-+	pri->ev.hangup.cref = c->cr;          		
-+	pri->ev.hangup.call = c;
-+	pri->ev.e = PRI_EVENT_HANGUP; 
-+    } 
-+    return res; 
-+}
-+
-+
- int q931_hangup(struct pri *pri, q931_call *c, int cause)
- {
- 	int disconnect = 1;
-@@ -2322,7 +3177,7 @@
- 	case Q931_CALL_STATE_NULL:
- 		if (c->peercallstate == Q931_CALL_STATE_NULL)
- 			/* free the resources if we receive or send REL_COMPL */
--			q931_destroycall(pri, c->cr);
-+			q931_destroycall(pri, c->cr, c->tei);
- 		else if (c->peercallstate == Q931_CALL_STATE_RELEASE_REQUEST)
- 			q931_release_complete(pri,c,cause);
- 		break;
-@@ -2348,14 +3203,21 @@
- 		/* received SETUP_ACKNOWLEDGE */
- 		/* send DISCONNECT in general */
- 		if (c->peercallstate != Q931_CALL_STATE_NULL && c->peercallstate != Q931_CALL_STATE_DISCONNECT_REQUEST && c->peercallstate != Q931_CALL_STATE_DISCONNECT_INDICATION && c->peercallstate != Q931_CALL_STATE_RELEASE_REQUEST && c->peercallstate != Q931_CALL_STATE_RESTART_REQUEST && c->peercallstate != Q931_CALL_STATE_RESTART) {
--			if (disconnect)
-+			if (pri->localtype == BRI_NETWORK_PTMP) {
-+			    if (c->tei == 127) {
-+			        break;
-+			    }
-+			} 
-+			if (disconnect) {
- 				q931_disconnect(pri,c,cause);
--			else if (release_compl)
-+			} else if (release_compl) {
- 				q931_release_complete(pri,c,cause);
--			else
-+			} else {
- 				q931_release(pri,c,cause);
--		} else 
-+			}
-+		} else {
- 			pri_error("Wierd, doing nothing but this shouldn't happen, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate));
-+		}
- 		break;
- 	case Q931_CALL_STATE_DISCONNECT_REQUEST:
- 		/* sent DISCONNECT */
-@@ -2363,8 +3225,14 @@
- 		break;
- 	case Q931_CALL_STATE_DISCONNECT_INDICATION:
- 		/* received DISCONNECT */
-+		if (pri->localtype == BRI_NETWORK_PTMP) {
-+		    if (c->tei == 127) {
-+			break;
-+		    }
-+		} 
- 		if (c->peercallstate == Q931_CALL_STATE_DISCONNECT_REQUEST) {
- 			c->alive = 1;
-+//		    pri_error("sending release to %d\n", c->tei);
- 			q931_release(pri,c,cause);
- 		}
- 		break;
-@@ -2385,9 +3253,10 @@
- 	return 0;
- }
- 
--int q931_receive(struct pri *pri, q931_h *h, int len)
-+int q931_receive(struct pri *pri, q931_h *h, int len, int tei)
- {
- 	q931_mh *mh;
-+	q921_call *l2c;
- 	q931_call *c;
- 	q931_ie *ie;
- 	unsigned int x;
-@@ -2410,13 +3279,14 @@
- 		   KLUDGE this by changing byte 4 from a 0xf (SERVICE) 
- 		   to a 0x7 (SERVICE ACKNOWLEDGE) */
- 		h->raw[h->crlen + 2] -= 0x8;
--		q931_xmit(pri, h, len, 1);
-+		q931_xmit(pri, h, len, 1, tei);
- 		return 0;
- 	} else if (h->pd != pri->protodisc) {
- 		pri_error("Warning: unknown/inappropriate protocol discriminator received (%02x/%d)\n", h->pd, h->pd);
- 		return 0;
- 	}
--	c = q931_getcall(pri, q931_cr(h));
-+//	pri_error("searching for cref %d tei %d\n", q931_cr(h), tei);
-+	c = q931_getcall(pri, q931_cr(h), tei);
- 	if (!c) {
- 		pri_error("Unable to locate call %d\n", q931_cr(h));
- 		return -1;
-@@ -2439,6 +3309,7 @@
- 	case Q931_SETUP:
- 		if (pri->debug & PRI_DEBUG_Q931_STATE)
- 			pri_message("-- Processing Q.931 Call Setup\n");
-+		c->tei = tei;
- 		c->channelno = -1;
- 		c->slotmap = -1;
- 		c->chanflags = 0;
-@@ -2463,11 +3334,25 @@
- 		strcpy(c->redirectingnum, "");
-                 c->useruserprotocoldisc = -1; 
- 		strcpy(c->useruserinfo, "");
-+		strcpy(c->digits, "");
-+		strcpy(c->display, "");
- 		c->complete = 0;
- 		break;
- 	case Q931_CONNECT:
-+		if (c->t303timer) {
-+		    c->t303running = 0;
-+		    pri_schedule_del(pri, c->t303timer);
-+    		}
-+		c->t303timer = 0;
-+		c->progress = -1;
-+		break;
- 	case Q931_ALERTING:
- 	case Q931_PROGRESS:
-+		if (c->t303timer) {
-+		    c->t303running = 0;
-+		    pri_schedule_del(pri, c->t303timer);
-+		}
-+		c->t303timer = 0;
- 		c->progress = -1;
- 		break;
- 	case Q931_CONNECT_ACKNOWLEDGE:
-@@ -2476,6 +3361,11 @@
- 		c->retranstimer = 0;
- 		/* Fall through */
- 	case Q931_CALL_PROCEEDING:
-+		if (c->t303timer) {
-+		    c->t303running = 0;
-+		    pri_schedule_del(pri, c->t303timer);
-+    		}
-+		c->t303timer = 0;
- 		/* Do nothing */
- 		break;
- 	case Q931_RELEASE:
-@@ -2486,10 +3376,15 @@
- 		if (c->retranstimer)
- 			pri_schedule_del(pri, c->retranstimer);
- 		c->retranstimer = 0;
-+		if (c->t303timer) {
-+		    c->t303running = 0;
-+		    pri_schedule_del(pri, c->t303timer);
-+    		}
-+		c->t303timer = 0;
- 		break;
- 	case Q931_RELEASE_COMPLETE:
- 		if (c->retranstimer)
--			pri_schedule_del(pri, c->retranstimer);
-+		    pri_schedule_del(pri, c->retranstimer);
- 		c->retranstimer = 0;
- 	case Q931_STATUS:
- 		c->cause = -1;
-@@ -2505,22 +3400,32 @@
- 	case Q931_STATUS_ENQUIRY:
- 		break;
- 	case Q931_SETUP_ACKNOWLEDGE:
-+		if (c->t303timer) {
-+		    c->t303running = 0;
-+		    pri_schedule_del(pri, c->t303timer);
-+		}
-+		c->t303timer = 0;
- 		break;
- 	case Q931_NOTIFY:
- 		break;
-+	case Q931_HOLD:
-+		break;
-+	case Q931_RETRIEVE:
-+		break;
-+	case Q931_RESUME:
-+		c->tei = tei;
-+		break;
-+	case Q931_SUSPEND:
-+		break;
- 	case Q931_USER_INFORMATION:
- 	case Q931_SEGMENT:
- 	case Q931_CONGESTION_CONTROL:
--	case Q931_HOLD:
- 	case Q931_HOLD_ACKNOWLEDGE:
- 	case Q931_HOLD_REJECT:
--	case Q931_RETRIEVE:
- 	case Q931_RETRIEVE_ACKNOWLEDGE:
- 	case Q931_RETRIEVE_REJECT:
--	case Q931_RESUME:
- 	case Q931_RESUME_ACKNOWLEDGE:
- 	case Q931_RESUME_REJECT:
--	case Q931_SUSPEND:
- 	case Q931_SUSPEND_ACKNOWLEDGE:
- 	case Q931_SUSPEND_REJECT:
- 		pri_error("!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
-@@ -2529,7 +3434,7 @@
- 		pri_error("!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
- 		q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
- 		if (c->newcall) 
--			q931_destroycall(pri,c->cr);
-+			q931_destroycall(pri,c->cr, c->tei);
- 		return -1;
- 	}
- 	memset(mandies, 0, sizeof(mandies));
-@@ -2610,7 +3515,7 @@
- 	for (x=0;x<MAX_MAND_IES;x++) {
- 		if (mandies[x]) {
- 			/* check if there is no channel identification when we're configured as network -> that's not an error */
--			if ((pri->localtype != PRI_NETWORK) || (mh->msg != Q931_SETUP) || (mandies[x] != Q931_CHANNEL_IDENT)) {
-+			if (((pri->localtype != PRI_NETWORK) || (pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_NETWORK_PTMP)) && ((mh->msg != Q931_SETUP) || (mandies[x] != Q931_CHANNEL_IDENT))) {
- 				pri_error("XXX Missing handling for mandatory IE %d (cs%d, %s) XXX\n", Q931_IE_IE(mandies[x]), Q931_IE_CODESET(mandies[x]), ie2str(mandies[x]));
- 				missingmand++;
- 			}
-@@ -2622,7 +3527,7 @@
- 	case Q931_RESTART:
- 		if (missingmand) {
- 			q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
--			q931_destroycall(pri, c->cr);
-+			q931_destroycall(pri, c->cr, c->tei);
- 			break;
- 		}
- 		c->ourcallstate = Q931_CALL_STATE_RESTART;
-@@ -2640,7 +3545,8 @@
- 		}
- 		/* Must be new call */
- 		if (!c->newcall) {
--			break;
-+			pri_error("received SETUP message for call that is not a new call, wicked!!! going on ...\n");
-+//			break;
- 		}
- 		c->newcall = 0;
- 		c->ourcallstate = Q931_CALL_STATE_CALL_PRESENT;
-@@ -2660,8 +3566,9 @@
-                 strncpy(pri->ev.ring.redirectingnum, c->redirectingnum, sizeof(pri->ev.ring.redirectingnum) - 1);
-                 strncpy(pri->ev.ring.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo) - 1);
- 		pri->ev.ring.flexible = ! (c->chanflags & FLAG_EXCLUSIVE);
--		pri->ev.ring.cref = c->cr;
-+		pri->ev.ring.tei = c->tei;
- 		pri->ev.ring.call = c;
-+		pri->ev.ring.cref = c->cr;
- 		pri->ev.ring.layer1 = c->userl1;
- 		pri->ev.ring.complete = c->complete; 
- 		pri->ev.ring.ctype = c->transcapability;
-@@ -2675,12 +3582,16 @@
- 			q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
- 			break;
- 		}
-+		if (pri->localtype == BRI_NETWORK_PTMP) {
-+		    l2c = q921_getcall(pri, c, tei);
-+		}
- 		c->ourcallstate = Q931_CALL_STATE_CALL_DELIVERED;
- 		c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED;
- 		pri->ev.e = PRI_EVENT_RINGING;
- 		pri->ev.ringing.channel = c->channelno | (c->ds1no << 8);
- 		pri->ev.ringing.cref = c->cr;
- 		pri->ev.ringing.call = c;
-+		pri->ev.ringing.progressmask = c->progressmask;
- 		return Q931_RES_HAVEEVENT;
- 	case Q931_CONNECT:
- 		if (c->newcall) {
-@@ -2691,36 +3602,65 @@
- 			q931_status(pri, c, PRI_CAUSE_WRONG_MESSAGE);
- 			break;
- 		}
-+		// tei got the call
-+		c->tei = tei;
- 		c->ourcallstate = Q931_CALL_STATE_ACTIVE;
- 		c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST;
- 		pri->ev.e = PRI_EVENT_ANSWER;
- 		pri->ev.answer.channel = c->channelno | (c->ds1no << 8);
- 		pri->ev.answer.cref = c->cr;
-+		pri->ev.answer.tei = c->tei;
- 		pri->ev.answer.call = c;
- 		q931_connect_acknowledge(pri, c);
-+	
-+		if (pri->localtype == BRI_NETWORK_PTMP) {
-+		    q921_hangup(pri, c, tei);
-+		}
- 		return Q931_RES_HAVEEVENT;
- 	case Q931_FACILITY:
- 		if (c->newcall) {
--			q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-+			if ((pri->localtype == PRI_CPE) || (pri->localtype == PRI_NETWORK)) {
-+			    q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-+			} else {
-+			    // BRI uses the dummy cref for sservices like ccnr
-+			}
- 			break;
- 		}
--		pri->ev.e = PRI_EVENT_FACNAME;
--		strncpy(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname) - 1);
--		strncpy(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingname) - 1);
--		pri->ev.facname.channel = c->channelno | (c->ds1no << 8);
--		pri->ev.facname.cref = c->cr;
--		pri->ev.facname.call = c;
--#if 0
--		pri_message("Sending facility event (%s/%s)\n", pri->ev.facname.callingname, pri->ev.facname.callingnum);
--#endif
-+		if (c->facility > 0) {
-+		    pri->ev.e = PRI_EVENT_FACILITY;
-+		    pri->ev.facility.channel = c->channelno | (c->ds1no << 8);
-+		    pri->ev.facility.cref = c->cr;
-+		    pri->ev.facility.tei = c->tei;
-+		    pri->ev.facility.call = c; 
-+		    switch (c->facility) {
-+			case 0x06: /* ECT execute */
-+				pri->ev.facility.operation = 0x06; 
-+			    break;
-+			case 0x0D:
-+				pri->ev.facility.operation = 0x0D; 
-+				strncpy(pri->ev.facility.forwardnum, c->redirectingnum,  sizeof(pri->ev.facility.forwardnum) - 1);
-+			    break;
-+			default:
-+				pri->ev.facility.operation = c->facility; 
-+		    }
-+		} else {
-+		    pri->ev.e = PRI_EVENT_FACNAME;
-+		    strncpy(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname) - 1);
-+		    strncpy(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingname) - 1);
-+		    pri->ev.facname.channel = c->channelno | (c->ds1no << 8);
-+		    pri->ev.facname.cref = c->cr;
-+		    pri->ev.facname.call = c; 
-+		}
-+
- 		return Q931_RES_HAVEEVENT;
- 	case Q931_PROGRESS:
- 		if (missingmand) {
- 			q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
--			q931_destroycall(pri, c->cr);
-+			q931_destroycall(pri, c->cr, c->tei);
- 			break;
- 		}
- 		pri->ev.e = PRI_EVENT_PROGRESS;
-+		pri->ev.proceeding.cause = c->cause;
- 		/* Fall through */
- 	case Q931_CALL_PROCEEDING:
- 		if (c->newcall) {
-@@ -2734,7 +3674,13 @@
- 			q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE);
- 			break;
- 		}
-+		if (pri->localtype == BRI_NETWORK_PTMP) {
-+		    l2c = q921_getcall(pri, c, tei);
-+		    l2c->proc = 1;
-+		    l2c->channel = c->channelno;
-+		}
- 		pri->ev.proceeding.channel = c->channelno | (c->ds1no << 8);
-+		pri->ev.proceeding.call = c;
- 		if (mh->msg == Q931_CALL_PROCEEDING) {
- 			pri->ev.e = PRI_EVENT_PROCEEDING;
- 			c->ourcallstate = Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING;
-@@ -2756,7 +3702,7 @@
- 	case Q931_STATUS:
- 		if (missingmand) {
- 			q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
--			q931_destroycall(pri, c->cr);
-+			q931_destroycall(pri, c->cr, c->tei);
- 			break;
- 		}
- 		if (c->newcall) {
-@@ -2794,27 +3740,42 @@
- 		}
- 		break;
- 	case Q931_RELEASE_COMPLETE:
--		c->ourcallstate = Q931_CALL_STATE_NULL;
--		c->peercallstate = Q931_CALL_STATE_NULL;
--		pri->ev.hangup.channel = c->channelno | (c->ds1no << 8);
--		pri->ev.hangup.cref = c->cr;          		
--		pri->ev.hangup.cause = c->cause;      		
--		pri->ev.hangup.call = c;              		
--		/* Free resources */
--		if (c->alive) {
-+		if (c->cause != PRI_CAUSE_INCOMPATIBLE_DESTINATION) {
-+		    if (c->t303timer) {
-+			c->t303running = 0;
-+			pri_schedule_del(pri, c->t303timer);
-+    		    }
-+		    c->t303timer = 0;
-+		}
-+		if ((pri->localtype != BRI_NETWORK_PTMP) || (c->tei == tei)) {
-+		    c->ourcallstate = Q931_CALL_STATE_NULL;
-+		    c->peercallstate = Q931_CALL_STATE_NULL;
-+		    pri->ev.hangup.channel = c->channelno | (c->ds1no << 8);
-+		    pri->ev.hangup.cref = c->cr;          		
-+		    pri->ev.hangup.cause = c->cause;      		
-+		    pri->ev.hangup.call = c;              		
-+		    /* Free resources */
-+		    if (c->alive) {
- 			pri->ev.e = PRI_EVENT_HANGUP;
- 			res = Q931_RES_HAVEEVENT;
- 			c->alive = 0;
--		} else if (c->sendhangupack) {
-+		    } else if (c->sendhangupack) {
- 			res = Q931_RES_HAVEEVENT;
- 			pri->ev.e = PRI_EVENT_HANGUP_ACK;
- 			pri_hangup(pri, c, c->cause);
--		} else
-+		    } else
- 			res = 0;
--		if (res)
-+		    if (res)
- 			return res;
--		else
-+		    else
- 			q931_hangup(pri,c,c->cause);
-+		} else {
-+		    // BRI_NET_PTMP
-+		    // ignoring relase_complete
-+		    res = q921_handle_hangup(pri,c,tei);
-+		    if (res)
-+			return res;
-+		}
- 		break;
- 	case Q931_RELEASE:
- 		if (missingmand) {
-@@ -2830,6 +3791,7 @@
- 		pri->ev.e = PRI_EVENT_HANGUP;
- 		pri->ev.hangup.channel = c->channelno | (c->ds1no << 8);
- 		pri->ev.hangup.cref = c->cr;
-+		pri->ev.hangup.tei = c->tei;
- 		pri->ev.hangup.cause = c->cause;
- 		pri->ev.hangup.call = c;
- 		/* Don't send release complete if they send us release 
-@@ -2855,8 +3817,14 @@
- 		pri->ev.e = PRI_EVENT_HANGUP_REQ;
- 		pri->ev.hangup.channel = c->channelno | (c->ds1no << 8);
- 		pri->ev.hangup.cref = c->cr;
-+		pri->ev.hangup.tei = c->tei;
- 		pri->ev.hangup.cause = c->cause;
- 		pri->ev.hangup.call = c;
-+		if (c->progressmask & Q931_PROG_INBAND_AVAILABLE) {
-+		    pri->ev.hangup.inband_progress = 1;
-+		} else {
-+		    pri->ev.hangup.inband_progress = 0;
-+		}
- 		if (c->alive)
- 			return Q931_RES_HAVEEVENT;
- 		else
-@@ -2877,15 +3845,35 @@
- 			q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
- 			break;
- 		}
-+
- 		if (c->ourcallstate!=Q931_CALL_STATE_OVERLAP_RECEIVING)
- 			break;
--		pri->ev.e = PRI_EVENT_INFO_RECEIVED;
--		pri->ev.ring.call = c;
--		pri->ev.ring.channel = c->channelno | (c->ds1no << 8);
--		strncpy(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum) - 1);
--		strncpy(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr) - 1);
--		pri->ev.ring.complete = c->complete; 	/* this covers IE 33 (Sending Complete) */
--		return Q931_RES_HAVEEVENT;
-+		if ((pri->localtype != BRI_NETWORK_PTMP) && (pri->localtype != BRI_NETWORK)) {
-+		    if ((c->ourcallstate!=Q931_CALL_STATE_OVERLAP_RECEIVING) && (c->ourcallstate!=Q931_CALL_STATE_ACTIVE))
-+		    break;
-+		} else {
-+		    // we want to use keypad and information ies for out of band dtmf, also when not using overlapdial
-+		}
-+		if (strlen(c->digits)) {
-+		    pri->ev.e = PRI_EVENT_INFO_RECEIVED;
-+		    pri->ev.ring.call = c;
-+		    pri->ev.ring.channel = c->channelno | (c->ds1no << 8);
-+		    strncpy(pri->ev.ring.callednum, c->digits, sizeof(pri->ev.ring.callednum) - 1);
-+		    strncpy(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr) - 1);
-+		    pri->ev.ring.complete = c->complete; 	/* this covers IE 33 (Sending Complete) */
-+		    return Q931_RES_HAVEEVENT;
-+		} else if (strlen(c->display)) {
-+		    pri->ev.e = PRI_EVENT_DISPLAY_RECEIVED;
-+		    pri->ev.display.call = c;
-+		    pri->ev.display.channel = c->channelno | (c->ds1no << 8);
-+		    strncpy(pri->ev.display.text, c->display, sizeof(pri->ev.display.text) - 1);
-+		    return Q931_RES_HAVEEVENT;
-+		} else {
-+		    if (pri->debug & PRI_DEBUG_Q931_STATE)
-+			pri_message("ignoring INFORMATION msg without Called Party Number, Keypad Facility or Display\n");
-+		}
-+		strcpy(c->digits, "");
-+		strcpy(c->display, "");
- 		break;
- 	case Q931_STATUS_ENQUIRY:
- 		if (c->newcall) {
-@@ -2902,25 +3890,61 @@
- 		c->peercallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
- 		pri->ev.e = PRI_EVENT_SETUP_ACK;
- 		pri->ev.setup_ack.channel = c->channelno;
-+		pri->ev.setup_ack.call = c;
- 		return Q931_RES_HAVEEVENT;
- 	case Q931_NOTIFY:
- 		pri->ev.e = PRI_EVENT_NOTIFY;
- 		pri->ev.notify.channel = c->channelno;
- 		pri->ev.notify.info = c->notify;
- 		return Q931_RES_HAVEEVENT;
-+	case Q931_HOLD:
-+		pri->ev.e = PRI_EVENT_HOLD_REQ;
-+		pri->ev.hold_req.call = c;
-+		pri->ev.hold_req.cref = c->cr;
-+		pri->ev.hold_req.tei = c->tei;
-+		pri->ev.hold_req.channel = c->channelno;
-+		return Q931_RES_HAVEEVENT;
-+		break;
-+	case Q931_RETRIEVE:
-+		pri->ev.e = PRI_EVENT_RETRIEVE_REQ;
-+		pri->ev.retrieve_req.call = c;
-+		pri->ev.retrieve_req.cref = c->cr;
-+		pri->ev.retrieve_req.tei = c->tei;
-+		pri->ev.retrieve_req.channel = c->channelno;
-+		return Q931_RES_HAVEEVENT;
-+		break;
-+	case Q931_SUSPEND:
-+		pri->ev.e = PRI_EVENT_SUSPEND_REQ;
-+		pri->ev.suspend_req.call = c;
-+		pri->ev.suspend_req.cref = c->cr;
-+		pri->ev.suspend_req.tei = c->tei;
-+		pri->ev.suspend_req.channel = c->channelno;
-+		strncpy(pri->ev.suspend_req.callid, c->callid, sizeof(pri->ev.suspend_req.callid) - 1);
-+		// q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
-+		return Q931_RES_HAVEEVENT;
-+		break;
-+	case Q931_RESUME:
-+		if (pri->localtype == BRI_NETWORK_PTMP) {
-+		    l2c = q921_getcall(pri, c, tei);
-+		}
-+		c->newcall = 0;
-+		pri->ev.e = PRI_EVENT_RESUME_REQ;
-+		pri->ev.resume_req.call = c;
-+		pri->ev.resume_req.cref = c->cr;
-+		pri->ev.resume_req.tei = c->tei;
-+		pri->ev.resume_req.channel = c->channelno;
-+		strncpy(pri->ev.resume_req.callid, c->callid, sizeof(pri->ev.resume_req.callid) - 1);
-+		return Q931_RES_HAVEEVENT;
-+		break;
- 	case Q931_USER_INFORMATION:
- 	case Q931_SEGMENT:
- 	case Q931_CONGESTION_CONTROL:
--	case Q931_HOLD:
- 	case Q931_HOLD_ACKNOWLEDGE:
- 	case Q931_HOLD_REJECT:
--	case Q931_RETRIEVE:
- 	case Q931_RETRIEVE_ACKNOWLEDGE:
- 	case Q931_RETRIEVE_REJECT:
--	case Q931_RESUME:
- 	case Q931_RESUME_ACKNOWLEDGE:
- 	case Q931_RESUME_REJECT:
--	case Q931_SUSPEND:
- 	case Q931_SUSPEND_ACKNOWLEDGE:
- 	case Q931_SUSPEND_REJECT:
- 		pri_error("!! Not yet handling post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
-@@ -2930,7 +3954,7 @@
- 		pri_error("!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
- 		q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
- 		if (c->newcall) 
--			q931_destroycall(pri,c->cr);
-+			q931_destroycall(pri,c->cr,c->tei);
- 		return -1;
- 	}
- 	return 0;
-diff -urNad libpri-1.0.9/README /tmp/dpep.9zBkJK/libpri-1.0.9/README
---- libpri-1.0.9/README	2004-10-14 18:04:22.000000000 -0500
-+++ /tmp/dpep.9zBkJK/libpri-1.0.9/README	2005-07-30 01:24:09.000000000 -0500
-@@ -1,6 +1,7 @@
--libpri: An implementation of Primate Rate ISDN
--
--Written by Mark Spencer <markster at digium.com>
-+libpri: An implementation of Primate Rate ISDN (and BRI ISDN)
-+ 
-+Written by Mark Spencer <markster at linux-support.net>
-+Modified for BRI support by Klaus-Peter Junghanns <kpj at junghanns.net>
- 
- What is libpri?
- ===============
-@@ -9,6 +10,7 @@
- based on the Bellcore specification SR-NWT-002343 for National ISDN.  As of
- May 12, 2001, it has been tested work with NI-2, Nortel DMS-100, and 
- Lucent 5E Custom protocols on switches from Nortel and Lucent.
-+The BRI and euroISDN modifications are based on ETS 300 102-1.
- 
- What is the license for libpri?
- ===============================
-@@ -17,9 +19,8 @@
- The GNU GPL is included in the file LICENSE in this directory.
- 
- If you wish to use libpri in an application for which the GPL is not 
--appropriate (e.g. a proprietary embedded system), licenses for libpri 
--under more flexible terms can be readily obtained through Digium, Inc. 
--at reasonable cost.
-+appropriate (e.g. a proprietary embedded system), then you have to use
-+a non-standard compliant version without BRI support.
- 
- 
- How do I report bugs or contribute?
-diff -urNad libpri-1.0.9/TODO /tmp/dpep.9zBkJK/libpri-1.0.9/TODO
---- libpri-1.0.9/TODO	2001-05-12 11:53:13.000000000 -0500
-+++ /tmp/dpep.9zBkJK/libpri-1.0.9/TODO	2005-07-30 01:24:09.000000000 -0500
-@@ -2,9 +2,7 @@
- -- D-Channel Backup
- -- Test against 4e
- 
--Q.921:
---- Support unnumbered information frames
--
- Q.931:
---- Locking Shift IE
---- Implement the 11 missing Q.931 timers
-+-- Locking Shift IE (you did that already, didnt you??)
-+-- Implement the 10 missing Q.931 timers
-+-- more facilities
-\ No hay ningún carácter de nueva línea al final del fichero

Deleted: libpri/trunk/debian/patches/bristuff_2.0.0-RC8h.dpatch
===================================================================
--- libpri/trunk/debian/patches/bristuff_2.0.0-RC8h.dpatch	2005-11-01 21:30:40 UTC (rev 930)
+++ libpri/trunk/debian/patches/bristuff_2.0.0-RC8h.dpatch	2005-11-01 21:34:16 UTC (rev 931)
@@ -1,4452 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## bristuff_2.0.0-RC8h.dpatch by  <msp at debian.org>
-## Taken from http://www.junghanns.net/asterisk/downloads/bristuff-0.2.0-RC8h.tar.gz
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: No description.
-
- at DPATCH@
-diff -urNad --exclude=CVS --exclude=.svn ./libpri.h /tmp/dpep-work.PXlLuK/libpri-1.0.9/libpri.h
---- ./libpri.h	2005-04-04 08:19:59.000000000 +0100
-+++ /tmp/dpep-work.PXlLuK/libpri-1.0.9/libpri.h	2005-07-02 09:24:53.837704496 +0100
-@@ -26,8 +26,12 @@
- #define _LIBPRI_H
- 
- /* Node types */
--#define PRI_NETWORK		1
-+#define PRI_NETWORK		1	/* PTP modes, default for PRI */
- #define PRI_CPE			2
-+#define BRI_NETWORK_PTMP	3	/* PTMP modes, default for BRI */
-+#define BRI_CPE_PTMP		4	
-+#define BRI_NETWORK		5	/* PTP modes */
-+#define BRI_CPE			6	
- 
- /* Debugging */
- #define PRI_DEBUG_Q921_RAW		(1 << 0)	/* Show raw HDLC frames */
-@@ -72,6 +76,12 @@
- #define PRI_EVENT_HANGUP_REQ	15	/* Requesting the higher layer to hangup */
- #define PRI_EVENT_NOTIFY	16	/* Notification received */
- #define PRI_EVENT_PROGRESS	17	/* When we get CALL_PROCEEDING or PROGRESS */
-+#define PRI_EVENT_HOLD_REQ	18	/* R */
-+#define PRI_EVENT_RETRIEVE_REQ  19
-+#define PRI_EVENT_SUSPEND_REQ   20	/* park */
-+#define PRI_EVENT_RESUME_REQ    21	/* unpark */
-+#define PRI_EVENT_DISPLAY_RECEIVED    22
-+#define PRI_EVENT_FACILITY	23	/* Facility */
- 
- /* Simple states */
- #define PRI_STATE_DOWN		0
-@@ -231,11 +241,13 @@
- #define PRI_NSF_ATT_MULTIQUEST         0xF0
- #define PRI_NSF_CALL_REDIRECTION_SERVICE       0xF7
- 
-+typedef struct q921_call q921_call;
- typedef struct q931_call q931_call;
- 
- typedef struct pri_event_generic {
- 	/* Events with no additional information fall in this category */
- 	int e;
-+	int tei;
- } pri_event_generic;
- 
- typedef struct pri_event_error {
-@@ -258,6 +270,7 @@
- typedef struct pri_event_answer {
- 	int e;
- 	int channel;
-+	int tei;				/* belongs to this tei */
- 	int cref;
- 	q931_call *call;
- } pri_event_answer;
-@@ -275,8 +288,11 @@
- 	int e;
- 	int channel;				/* Channel requested */
- 	int callingpres;			/* Presentation of Calling CallerID */
-+	int callingpresuser;			/* Presentation of Calling CallerID */
- 	int callingplan;			/* Dialing plan of Calling entity */
--	char callingnum[256];		/* Calling number */
-+	int callingplanuser;			/* Dialing plan of Calling entity */
-+	char callingnum[256];		/* Calling number, network provided */
-+	char callingnumuser[256];		/* Calling number, user provided */
- 	char callingname[256];		/* Calling name (if provided) */
- 	int calledplan;				/* Dialing plan of Called number */
- 	int ani2;                   /* ANI II */
-@@ -289,6 +305,7 @@
- 	int layer1;				/* User layer 1 */
- 	int complete;				/* Have we seen "Complete" i.e. no more number? */
- 	q931_call *call;			/* Opaque call pointer */
-+	int tei;				/* belongs to this tei */
- 	char callingsubaddr[256];		/* Calling parties subaddress */
- } pri_event_ring;
- 
-@@ -297,6 +314,8 @@
- 	int channel;				/* Channel requested */
- 	int cause;
- 	int cref;
-+	int tei;
-+	int inband_progress;
- 	q931_call *call;			/* Opaque call pointer */
- } pri_event_hangup;	
- 
-@@ -308,11 +327,14 @@
- typedef struct pri_event_proceeding {
- 	int e;
- 	int channel;
-+	int cause;
-+	q931_call *call;			/* Opaque call pointer */
- } pri_event_proceeding;
-  
- typedef struct pri_event_setup_ack {
- 	int e;
- 	int channel;
-+	q931_call *call;			/* Opaque call pointer */
- } pri_event_setup_ack;
- 
- typedef struct pri_event_notify {
-@@ -321,20 +343,80 @@
- 	int info;
- } pri_event_notify;
- 
-+typedef struct pri_event_hold_req {
-+	int e;
-+	int channel;
-+	int cref;
-+	int tei;
-+	q931_call *call;
-+} pri_event_hold_req;
-+
-+/* euroisdn faciltiy fun */
-+typedef struct pri_event_facility_req {
-+	int e;
-+	int channel;
-+	int cref;
-+	int tei;
-+	int operation;
-+	char forwardnum[256];		/* Redirection destination */
-+	q931_call *call;
-+} pri_event_facility_req;
-+
-+typedef struct pri_event_retrieve_req {
-+	int e;
-+	int channel;
-+	int cref;
-+	int tei;
-+	q931_call *call;
-+} pri_event_retrieve_req;
-+
-+typedef struct pri_event_suspend_req {
-+	int e;
-+	int channel;
-+	int cref;
-+	int tei;
-+	q931_call *call;
-+	char callid[10];
-+} pri_event_suspend_req;
-+
-+typedef struct pri_event_resume_req {
-+	int e;
-+	int channel;
-+	int cref;
-+	int tei;
-+	q931_call *call;
-+	char callid[10];
-+} pri_event_resume_req;
-+
-+typedef struct pri_event_display {
-+	int e;
-+	int channel;		
-+	int cref;			
-+	q931_call *call;
-+	char text[256];
-+} pri_event_display;
-+
-+
- typedef union {
- 	int e;
- 	pri_event_generic gen;		/* Generic view */
- 	pri_event_restart restart;	/* Restart view */
- 	pri_event_error	  err;		/* Error view */
- 	pri_event_facname facname;	/* Caller*ID Name on Facility */
-+	pri_event_facility_req facility;	/* sservices */
- 	pri_event_ring	  ring;		/* Ring */
- 	pri_event_hangup  hangup;	/* Hang up */
- 	pri_event_ringing ringing;	/* Ringing */
--	pri_event_ringing answer;	/* Answer */
-+	pri_event_answer  answer;	/* Answer */
- 	pri_event_restart_ack restartack;	/* Restart Acknowledge */
- 	pri_event_proceeding  proceeding;	/* Call proceeding & Progress */
- 	pri_event_setup_ack   setup_ack;	/* SETUP_ACKNOWLEDGE structure */
- 	pri_event_notify notify;		/* Notification */
-+	pri_event_hold_req hold_req;
-+	pri_event_retrieve_req retrieve_req;
-+	pri_event_suspend_req suspend_req;
-+	pri_event_resume_req resume_req;
-+	pri_event_display display;
- } pri_event;
- 
- struct pri;
-@@ -389,6 +471,12 @@
- /* Send a digit in overlap mode */
- extern int pri_information(struct pri *pri, q931_call *call, char digit);
- 
-+/* Send a INFO msg with display ie  */
-+extern int pri_information_display(struct pri *pri, q931_call *call, char *display);
-+
-+/* add a display ie to a call, so it can be sent with the next message */
-+extern int pri_add_display(struct pri *pri, q931_call *call, char *display);
-+
- /* Answer the incomplete(call without called number) call on the given channel.
-    Set non-isdn to non-zero if you are not connecting to ISDN equipment */
- extern int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn);
-@@ -397,6 +485,33 @@
-    Set non-isdn to non-zero if you are not connecting to ISDN equipment */
- extern int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
- 
-+/* Ack a HOLD_REQ */
-+extern int pri_hold_acknowledge(struct pri *pri, q931_call *call);
-+
-+/* Reject a HOLD_REQ */
-+extern int pri_hold_reject(struct pri *pri, q931_call *call);
-+
-+/* Ack a RETRIEVE_REQ */
-+extern int pri_retrieve_acknowledge(struct pri *pri, q931_call *call, int channel);
-+
-+/* Reject a RETRIEVE_REQ */
-+extern int pri_retrieve_reject(struct pri *pri, q931_call *call);
-+
-+/* Ack a SUSPEND_REQ */
-+extern int pri_suspend_acknowledge(struct pri *pri, q931_call *call, char *display);
-+
-+/* Reject a SUSPEND_REQ */
-+extern int pri_suspend_reject(struct pri *pri, q931_call *call, char *display);
-+
-+/* Reject a RESUME_REQ */
-+extern int pri_resume_reject(struct pri *pri, q931_call *call, char *display);
-+
-+/* Ack a RESUME_REQ */
-+extern int pri_resume_acknowledge(struct pri *pri, q931_call *call, int channel, char *display);
-+
-+/* Send a Facility Message */
-+extern int pri_facility(struct pri *pri, q931_call *call, int operation, char *arguments);
-+
- /* Set CRV reference for GR-303 calls */
- 
- 
-diff -urNad --exclude=CVS --exclude=.svn ./Makefile /tmp/dpep-work.PXlLuK/libpri-1.0.9/Makefile
---- ./Makefile	2005-05-11 04:37:29.000000000 +0100
-+++ /tmp/dpep-work.PXlLuK/libpri-1.0.9/Makefile	2005-07-02 09:24:53.835704800 +0100
-@@ -36,7 +36,7 @@
- DYNAMIC_LIBRARY=libpri.so.1.0
- STATIC_OBJS=pri.o q921.o prisched.o q931.o
- DYNAMIC_OBJS=pri.lo q921.lo prisched.lo q931.lo
--CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g $(ALERTING) $(LIBPRI_COUNTERS)
-+CFLAGS=-Wall -Wstrict-prototypes -Wmissing-prototypes -g $(ALERTING) $(LIBPRI_COUNTERS)
- INSTALL_PREFIX=
- ifeq (${OSARCH},Linux)
- LDCONFIG_FLAGS=-n
-diff -urNad --exclude=CVS --exclude=.svn ./pri.c /tmp/dpep-work.PXlLuK/libpri-1.0.9/pri.c
---- ./pri.c	2004-12-15 18:06:38.000000000 +0000
-+++ /tmp/dpep-work.PXlLuK/libpri-1.0.9/pri.c	2005-07-02 09:24:53.837704496 +0100
-@@ -33,6 +33,14 @@
- 		return "Network";
- 	case PRI_CPE:
- 		return "CPE";
-+	case BRI_NETWORK:
-+		return "Network";
-+	case BRI_CPE:
-+		return "CPE";
-+	case BRI_NETWORK_PTMP:
-+		return "Network (PtMP)";
-+	case BRI_CPE_PTMP:
-+		return "CPE (PtMP)";
- 	default:
- 		return "Invalid value";
- 	}
-@@ -113,7 +121,7 @@
- 		}
- 		/* Start Q.921 layer, Wait if we're the network */
- 		if (p)
--			q921_start(p, p->localtype == PRI_CPE);
-+			q921_start(p, p->localtype == PRI_CPE, 0);
- 	}
- 	return p;
- }
-@@ -270,6 +278,21 @@
- 	return q931_notify(pri, call, channel, info);
- }
- 
-+int pri_information_display(struct pri *pri, q931_call *call, char *display)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_information_display(pri, call, display);
-+}
-+
-+int pri_add_display(struct pri *pri, q931_call *call, char *display)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_add_display(pri, call, display);
-+}
-+
-+
- void pri_destroycall(struct pri *pri, q931_call *call)
- {
- 	if (pri && call)
-@@ -291,6 +314,69 @@
- 	return q931_connect(pri, call, channel, nonisdn);
- }
- 
-+int pri_hold_acknowledge(struct pri *pri, q931_call *call)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_hold_acknowledge(pri, call);
-+}
-+
-+int pri_hold_reject(struct pri *pri, q931_call *call)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_hold_reject(pri, call);
-+}
-+
-+int pri_retrieve_acknowledge(struct pri *pri, q931_call *call, int channel)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_retrieve_acknowledge(pri, call, channel);
-+}
-+
-+int pri_retrieve_reject(struct pri *pri, q931_call *call)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_retrieve_reject(pri, call);
-+}
-+
-+int pri_suspend_acknowledge(struct pri *pri, q931_call *call, char *display)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_suspend_acknowledge(pri, call, display);
-+}
-+
-+int pri_suspend_reject(struct pri *pri, q931_call *call, char *display)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_suspend_reject(pri, call, display);
-+}
-+
-+int pri_resume_reject(struct pri *pri, q931_call *call, char *display)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_resume_reject(pri, call, display);
-+}
-+
-+int pri_resume_acknowledge(struct pri *pri, q931_call *call, int channel, char *display)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_resume_acknowledge(pri, call, channel, display);
-+}
-+
-+int pri_facility(struct pri *pri, q931_call *call, int operation, char *arguments)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_facility(pri, call, operation, arguments);
-+}
-+
- #if 0
- /* deprecated routines, use pri_hangup */
- int pri_release(struct pri *pri, q931_call *call, int cause)
-@@ -310,12 +396,24 @@
- 
- int pri_hangup(struct pri *pri, q931_call *call, int cause)
- {
-+	int res=0;
- 	if (!pri || !call)
- 		return -1;
- 	if (cause == -1)
- 		/* normal clear cause */
- 		cause = 16;
--	return q931_hangup(pri, call, cause);
-+	if (pri->localtype == BRI_NETWORK_PTMP) {
-+	    res = q921_hangup(pri, call, 127);
-+	    if (res) {
-+		// q921_setup might give a HANGUP_ACK, if nobody got the call
-+		q931_hangup(pri, call, cause);
-+		return res;
-+	    } else {
-+		return q931_hangup(pri, call, cause);
-+	    }
-+	} else {
-+	    return q931_hangup(pri, call, cause);
-+	}
- }
- 
- int pri_reset(struct pri *pri, int channel)
-@@ -471,13 +569,14 @@
- 	}
- 	len += sprintf(buf + len, "Q921 Outstanding: %d\n", q921outstanding);
- #endif
--	len += sprintf(buf + len, "Window Length: %d/%d\n", pri->windowlen, pri->window);
--	len += sprintf(buf + len, "Sentrej: %d\n", pri->sentrej);
--	len += sprintf(buf + len, "SolicitFbit: %d\n", pri->solicitfbit);
--	len += sprintf(buf + len, "Retrans: %d\n", pri->retrans);
--	len += sprintf(buf + len, "Busy: %d\n", pri->busy);
-+	if (pri->localtype != BRI_NETWORK_PTMP) {
-+	    len += sprintf(buf + len, "Window Length: %d/%d\n", pri->windowlen[0], pri->window[0]);
-+	    len += sprintf(buf + len, "Sentrej: %d\n", pri->sentrej[0]);
-+	    len += sprintf(buf + len, "SolicitFbit: %d\n", pri->solicitfbit[0]);
-+	    len += sprintf(buf + len, "Retrans: %d\n", pri->retrans[0]);
-+	    len += sprintf(buf + len, "Busy: %d\n", pri->busy[0]);
-+	}
- 	len += sprintf(buf + len, "Overlap Dial: %d\n", pri->overlapdial);
--
- 	return strdup(buf);
- }
- 
-diff -urNad --exclude=CVS --exclude=.svn ./pri_internal.h /tmp/dpep-work.PXlLuK/libpri-1.0.9/pri_internal.h
---- ./pri_internal.h	2004-06-26 05:37:09.000000000 +0100
-+++ /tmp/dpep-work.PXlLuK/libpri-1.0.9/pri_internal.h	2005-07-02 09:24:53.838704344 +0100
-@@ -30,7 +30,10 @@
- struct pri_sched {
- 	struct timeval when;
- 	void (*callback)(void *data);
-+	void (*callback2)(void *data, int);
- 	void *data;
-+	char hasdata2;
-+	int data2;
- };
- 
- struct q921_frame;
-@@ -38,8 +41,15 @@
- enum q931_mode;
- 
- /* No more than 128 scheduled events */
-+/* XXX is this sufficient for nfs ??? */
- #define MAX_SCHED 128
- 
-+/* this can be freely configured to support more devices .... ok, 63 would be max! */
-+#define Q921_MAX_TEIS 16
-+
-+/* dynamically allocated TEIs start here */
-+#define Q921_TEI_BASE 64
-+
- struct pri {
- 	int fd;				/* File descriptor for D-Channel */
- 	struct pri *subchannel;	/* Sub-channel if appropriate */
-@@ -57,33 +67,43 @@
- 	int protodisc;
- 	
- 	/* Q.921 State */
--	int q921_state;	
--	int window;			/* Max window size */
--	int windowlen;		/* Fullness of window */
--	int v_s;			/* Next N(S) for transmission */
--	int v_a;			/* Last acknowledged frame */
--	int v_r;			/* Next frame expected to be received */
--	int v_na;			/* What we've told our peer we've acknowledged */
--	int solicitfbit;	/* Have we sent an I or S frame with the F-bit set? */
--	int retrans;		/* Retransmissions */
--	int sentrej;		/* Are we in reject state */
--	
--	int cref;			/* Next call reference value */
--	
--	int busy;			/* Peer is busy */
-+ 	int q921_state[Q921_MAX_TEIS];	
-+ 	char dchanup;
-+ 	
-+ 	/* TEI registry */
-+     	char q921_teis[Q921_MAX_TEIS];
-+  	
-+ 	unsigned int ri; 
-+ 
-+ 	int cref;			/* Next call reference value */  // let's think about this for a while...
-+  	
-+ 	int busy[Q921_MAX_TEIS];			/* Peer is busy */
-+  
-+ 	int window[Q921_MAX_TEIS];			/* Max window size */
-+	int windowlen[Q921_MAX_TEIS];		/* Fullness of window */
-+ 	int v_s[Q921_MAX_TEIS];			/* Next N(S) for transmission */
-+ 	int v_a[Q921_MAX_TEIS];			/* Last acknowledged frame */
-+ 	int v_r[Q921_MAX_TEIS];			/* Next frame expected to be received */
-+ 	int v_na[Q921_MAX_TEIS];			/* What we've told our peer we've acknowledged */
-+ 	int solicitfbit[Q921_MAX_TEIS];	/* Have we sent an I or S frame with the F-bit set? */
-+ 	int retrans[Q921_MAX_TEIS];		/* Retransmissions */
- 
--	/* Various timers */
--	int sabme_timer;	/* SABME retransmit */
--	int t203_timer;		/* Max idle time */
--	int t200_timer;		/* T-200 retransmission timer */
-+	int sentrej[Q921_MAX_TEIS];		/* Are we in reject state */
- 	
-+	/* Various timers */
-+ 	int sabme_timer[Q921_MAX_TEIS];
-+ 	int t203_timer[Q921_MAX_TEIS];
-+ 	int t202_timer[Q921_MAX_TEIS];
-+ 	int t201_timer[Q921_MAX_TEIS];
-+ 	int t200_timer[Q921_MAX_TEIS];
-+
- 	/* Used by scheduler */
- 	struct timeval tv;
- 	int schedev;
- 	pri_event ev;		/* Static event thingy */
- 	
- 	/* Q.921 Re-transmission queue */
--	struct q921_frame *txqueue;
-+	struct q921_frame *txqueue[Q921_MAX_TEIS];
- 	
- 	/* Q.931 calls */
- 	q931_call **callpool;
-@@ -121,6 +141,7 @@
- #define PRI_SWITCH_GR303_TMC_SWITCHING	11
- 
- extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);
-+extern int pri_schedule_event2(struct pri *pri, int ms, void (*function)(void *data, int data2), void *data, int data2);
- 
- extern pri_event *pri_schedule_run(struct pri *pri);
- 
-diff -urNad --exclude=CVS --exclude=.svn ./pri_q921.h /tmp/dpep-work.PXlLuK/libpri-1.0.9/pri_q921.h
---- ./pri_q921.h	2004-10-29 15:12:45.000000000 +0100
-+++ /tmp/dpep-work.PXlLuK/libpri-1.0.9/pri_q921.h	2005-07-02 09:24:53.838704344 +0100
-@@ -39,9 +39,14 @@
- 
- #define T_WAIT_MIN	2000
- #define T_WAIT_MAX	10000
--#define T_200		1000		/* 1 second between SABME's */
-+#define T_200		3000		/* 3 second between SABME's */
-+#define T_201		2000
-+#define T_202		5000		/* 5 seconds between TEI requests */
- #define T_203		10000		/* 10 seconds with no packets max */
- #define N_200		3		/* 3 retries */
-+#define N_202		3
-+
-+#define T_303		4000
- 
- #define Q921_FRAMETYPE_MASK	0x3
- 
-@@ -50,6 +55,13 @@
- #define Q921_FRAMETYPE_S	0x1
- 
- #define Q921_TEI_GROUP				127
-+#define Q921_TEI_ID_REQUEST	0x1
-+#define Q921_TEI_ID_ASSIGNED	0x2
-+#define Q921_TEI_ID_DENIED	0x3
-+#define Q921_TEI_ID_CHK_REQ	0x4
-+#define Q921_TEI_ID_CHK_RES	0x5
-+#define Q921_TEI_ID_REMOVE	0x6
-+#define Q921_TEI_ID_VERIFY	0x7
- #define Q921_TEI_GR303_EOC_PATH			0
- #define Q921_TEI_GR303_EOC_OPS			4
- #define Q921_TEI_GR303_TMC_SWITCHING		0
-@@ -167,12 +179,14 @@
- extern void q921_dump(q921_h *h, int len, int showraw, int txrx);
- 
- /* Bring up the D-channel */
--extern void q921_start(struct pri *pri, int now);
-+extern void q921_start(struct pri *pri, int now, int tei);
- 
--extern void q921_reset(struct pri *pri);
-+extern void q921_reset(struct pri *pri, int tei);
- 
- extern pri_event *q921_receive(struct pri *pri, q921_h *h, int len);
- 
--extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr);
-+extern int q921_transmit_uframe(struct pri *pri, void *buf, int len, int cr, int tei);
-+
-+extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr, int tei);
- 
- #endif
-diff -urNad --exclude=CVS --exclude=.svn ./pri_q931.h /tmp/dpep-work.PXlLuK/libpri-1.0.9/pri_q931.h
---- ./pri_q931.h	2004-06-16 16:33:58.000000000 +0100
-+++ /tmp/dpep-work.PXlLuK/libpri-1.0.9/pri_q931.h	2005-07-02 09:24:53.838704344 +0100
-@@ -190,6 +190,10 @@
- #define Q931_IE_CODESET(x)		((x) >> 8)
- #define Q931_IE_IE(x)			((x) & 0xff)
- #define Q931_FULL_IE(codeset, ie)	(((codeset) << 8) | ((ie) & 0xff))
-+#define Q931_IE_MAX_LEN			257
-+
-+// BRI+
-+#define Q931_COLP	0x4c
- 
- #define Q931_DISPLAY					0x28
- #define Q931_IE_SEGMENTED_MSG			0x00
-@@ -217,6 +221,8 @@
- #define Q931_IE_USER_USER				0x7E
- #define Q931_IE_ESCAPE_FOR_EXT			0x7F
- 
-+#define Q931_IE_SPECIAL		0x02
-+
- 
- /* Call state stuff */
- #define Q931_CALL_STATE_NULL				0
-@@ -242,7 +248,7 @@
- /* EuroISDN  */
- #define Q931_SENDING_COMPLETE		0xa1
- 
--extern int q931_receive(struct pri *pri, q931_h *h, int len);
-+extern int q931_receive(struct pri *pri, q931_h *h, int len, int tei);
- 
- extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info);
- 
-@@ -256,6 +262,10 @@
- 
- extern int q931_information(struct pri *pri, q931_call *call, char digit);
- 
-+extern int q931_information_display(struct pri *pri, q931_call *call, char *display);
-+
-+extern int q931_add_display(struct pri *pri, q931_call *call, char *display);
-+
- extern int q931_connect(struct pri *pri, q931_call *call, int channel, int nonisdn);
- 
- extern int q931_release(struct pri *pri, q931_call *call, int cause);
-@@ -264,6 +274,10 @@
- 
- extern int q931_hangup(struct pri *pri, q931_call *call, int cause);
- 
-+extern int q921_hangup(struct pri *pri, q931_call *c, int tei);
-+
-+extern int q921_handle_hangup(struct pri *pri, q931_call *c, int tei);
-+
- extern int q931_restart(struct pri *pri, int channel);
- 
- extern int q931_call_getcrv(struct pri *pri, q931_call *call, int *callmode);
-@@ -276,5 +290,23 @@
- extern void q931_dump(q931_h *h, int len, int txrx);
- 
- extern void __q931_destroycall(struct pri *pri, q931_call *c);
-+
-+extern int q931_hold_acknowledge(struct pri *pri, q931_call *c);
-+
-+extern int q931_hold_reject(struct pri *pri, q931_call *c);
-+
-+extern int q931_retrieve_acknowledge(struct pri *pri, q931_call *c, int channel);
-+	
-+extern int q931_retrieve_reject(struct pri *pri, q931_call *c);
-+
-+extern int q931_suspend_acknowledge(struct pri *pri, q931_call *c, char *display);
- 	
-+extern int q931_suspend_reject(struct pri *pri, q931_call *c, char *display);
-+
-+extern int q931_resume_reject(struct pri *pri, q931_call *c, char *display);
-+
-+extern int q931_resume_acknowledge(struct pri *pri, q931_call *c, int channel, char *display);
-+
-+extern int q931_facility(struct pri *pri, q931_call *c, int operation, char *arguments);
-+
- #endif
-diff -urNad --exclude=CVS --exclude=.svn ./prisched.c /tmp/dpep-work.PXlLuK/libpri-1.0.9/prisched.c
---- ./prisched.c	2004-06-05 07:50:55.000000000 +0100
-+++ /tmp/dpep-work.PXlLuK/libpri-1.0.9/prisched.c	2005-07-02 09:24:53.839704192 +0100
-@@ -35,7 +35,7 @@
- 	int x;
- 	struct timeval tv;
- 	for (x=1;x<MAX_SCHED;x++)
--		if (!pri->pri_sched[x].callback)
-+		if ((!pri->pri_sched[x].callback2) && (!pri->pri_sched[x].callback))
- 			break;
- 	if (x == MAX_SCHED) {
- 		pri_error("No more room in scheduler\n");
-@@ -52,7 +52,39 @@
- 	}
- 	pri->pri_sched[x].when = tv;
- 	pri->pri_sched[x].callback = function;
-+	pri->pri_sched[x].callback2 = NULL;
- 	pri->pri_sched[x].data = data;
-+	pri->pri_sched[x].hasdata2 = 0;
-+	pri->pri_sched[x].data2 = 0;
-+	return x;
-+}
-+
-+int pri_schedule_event2(struct pri *pri, int ms, void (*function)(void *data, int data2), void *data, int data2)
-+{
-+	int x;
-+	struct timeval tv;
-+	for (x=1;x<MAX_SCHED;x++)
-+		if ((!pri->pri_sched[x].callback2) && (!pri->pri_sched[x].callback))
-+			break;
-+	if (x == MAX_SCHED) {
-+		pri_error("No more room in scheduler\n");
-+		return -1;
-+	}
-+	if (x > maxsched)
-+		maxsched = x;
-+	gettimeofday(&tv, NULL);
-+	tv.tv_sec += ms / 1000;
-+	tv.tv_usec += (ms % 1000) * 1000;
-+	if (tv.tv_usec > 1000000) {
-+		tv.tv_usec -= 1000000;
-+		tv.tv_sec += 1;
-+	}
-+	pri->pri_sched[x].when = tv;
-+	pri->pri_sched[x].callback = NULL;
-+	pri->pri_sched[x].callback2 = function;
-+	pri->pri_sched[x].data = data;
-+	pri->pri_sched[x].hasdata2 = 1;
-+	pri->pri_sched[x].data2 = data2;
- 	return x;
- }
- 
-@@ -64,7 +96,7 @@
- 	if (pri->subchannel)
- 		closest = pri_schedule_next(pri->subchannel);
- 	for (x=1;x<MAX_SCHED;x++) {
--		if (pri->pri_sched[x].callback && 
-+		if ((pri->pri_sched[x].callback || pri->pri_sched[x].callback2) && 
- 			(!closest || (closest->tv_sec > pri->pri_sched[x].when.tv_sec) ||
- 				((closest->tv_sec == pri->pri_sched[x].when.tv_sec) && 
- 				 (closest->tv_usec > pri->pri_sched[x].when.tv_usec))))
-@@ -75,26 +107,38 @@
- 
- static pri_event *__pri_schedule_run(struct pri *pri, struct timeval *tv)
- {
--	int x;
--	void (*callback)(void *);
--	void *data;
-+ 	int x;
-+ 	void (*callback)(void *);
-+	void (*callback2)(void *, int);
-+ 	void *data;
-+	int data2;
- 	pri_event *e;
-+
- 	if (pri->subchannel) {
- 		if ((e = __pri_schedule_run(pri->subchannel, tv))) {
- 			return e;
- 		}
- 	}
- 	for (x=1;x<MAX_SCHED;x++) {
--		if (pri->pri_sched[x].callback &&
-+		if ((pri->pri_sched[x].callback || pri->pri_sched[x].callback2) &&
- 			((pri->pri_sched[x].when.tv_sec < tv->tv_sec) ||
- 			 ((pri->pri_sched[x].when.tv_sec == tv->tv_sec) &&
- 			  (pri->pri_sched[x].when.tv_usec <= tv->tv_usec)))) {
- 			        pri->schedev = 0;
- 			  	callback = pri->pri_sched[x].callback;
-+			  	callback2 = pri->pri_sched[x].callback2;
- 				data = pri->pri_sched[x].data;
-+				data2 = pri->pri_sched[x].data2;
- 				pri->pri_sched[x].callback = NULL;
-+				pri->pri_sched[x].callback2 = NULL;
- 				pri->pri_sched[x].data = NULL;
--				callback(data);
-+				pri->pri_sched[x].data2 = 0;
-+				if (pri->pri_sched[x].hasdata2 == 1) {
-+				    pri->pri_sched[x].hasdata2 = 0;
-+				    callback2(data, data2);
-+				} else {
-+				    callback(data);
-+				}
-             if (pri->schedev)
-                   return &pri->ev;
- 	    }
-@@ -115,4 +159,5 @@
- 	if ((id >= MAX_SCHED) || (id < 0)) 
- 		pri_error("Asked to delete sched id %d???\n", id);
- 	pri->pri_sched[id].callback = NULL;
-+	pri->pri_sched[id].callback2 = NULL;
- }
-diff -urNad --exclude=CVS --exclude=.svn ./pritest.c /tmp/dpep-work.PXlLuK/libpri-1.0.9/pritest.c
---- ./pritest.c	2004-06-05 07:50:55.000000000 +0100
-+++ /tmp/dpep-work.PXlLuK/libpri-1.0.9/pritest.c	2005-07-02 09:24:53.839704192 +0100
-@@ -51,8 +51,8 @@
- #define PRI_DEF_NODETYPE	PRI_CPE
- #define PRI_DEF_SWITCHTYPE	PRI_SWITCH_NI2
- 
--#define MAX_CHAN		32
--#define	DCHANNEL_TIMESLOT	16
-+#define MAX_CHAN		3
-+#define	DCHANNEL_TIMESLOT	3
- 
- 
- static int offset = 0;
-@@ -60,7 +60,7 @@
- static void do_channel(ZAP *z)
- {
- 	/* This is the part that runs on a given channel */
--	zap_playf(z, "raw.ulaw", 0);
-+	zap_playf(z, "raw.alaw", 0);
- }
- 
- struct pri_chan {
-@@ -76,6 +76,14 @@
- 		return PRI_CPE;
- 	if (!strcasecmp(node, "network"))
- 		return PRI_NETWORK;
-+	if (!strcasecmp(node, "bri_cpe_ptmp"))
-+		return BRI_CPE_PTMP;
-+	if (!strcasecmp(node, "bri_network_ptmp"))
-+		return BRI_NETWORK_PTMP;
-+	if (!strcasecmp(node, "bri_cpe"))
-+		return BRI_CPE;
-+	if (!strcasecmp(node, "bri_network"))
-+		return BRI_NETWORK;
- 	return -1;
- }
- 
-@@ -285,6 +293,10 @@
- 		}
- 		
- 		break;
-+	case PRI_EVENT_HANGUP_REQ:
-+		printf("-- Hanging up channel %d\n", e->hangup.channel);
-+		hangup_channel(e->hangup.channel);
-+		break;
- 	default:
- 		fprintf(stderr, "--!! Unknown PRI event %d\n", e->e);
- 	}
-diff -urNad --exclude=CVS --exclude=.svn ./q921.c /tmp/dpep-work.PXlLuK/libpri-1.0.9/q921.c
---- ./q921.c	2004-07-23 17:04:01.000000000 +0100
-+++ /tmp/dpep-work.PXlLuK/libpri-1.0.9/q921.c	2005-07-02 09:24:53.842703736 +0100
-@@ -5,6 +5,8 @@
-  *
-  * Copyright (C) 2001, Linux Support Services, Inc.
-  * All Rights Reserved.
-+ * Copyright (C) 2003,2004,2005 Junghanns.NET GmbH
-+ * Klaus-Peter Junghanns <kpj at junghanns.net>
-  *
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License as published by
-@@ -49,19 +51,22 @@
- 	(hf).h.tei = (pri)->tei; \
- } while(0)
- 
--static void reschedule_t203(struct pri *pri);
-+static void reschedule_t203(struct pri *pri, int tei);
- 
--static void q921_discard_retransmissions(struct pri *pri)
-+static void q921_discard_retransmissions(struct pri *pri, int tei)
- {
- 	struct q921_frame *f, *p;
--	f = pri->txqueue;
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+	
-+	f = pri->txqueue[teio];
- 	while(f) {
--		p = f;
--		f = f->next;
--		/* Free frame */
--		free(p);
-+	    p = f;
-+	    f = f->next;
-+	    /* Free frame */
-+	    free(p);
- 	}
--	pri->txqueue = NULL;
-+        pri->txqueue[teio] = NULL;
- }
- 
- static int q921_transmit(struct pri *pri, q921_h *h, int len) 
-@@ -80,18 +85,22 @@
- #endif
- 	/* Just send it raw */
- 	if (pri->debug & PRI_DEBUG_Q921_DUMP)
--		q921_dump(h, len, pri->debug & PRI_DEBUG_Q921_RAW, 1);
-+		q921_dump(h, len, 1, 1);
- 	/* Write an extra two bytes for the FCS */
- 	res = write(pri->fd, h, len + 2);
- 	if (res != (len + 2)) {
- 		pri_error("Short write: %d/%d (%s)\n", res, len + 2, strerror(errno));
- 		return -1;
- 	}
--	reschedule_t203(pri);
-+	if (pri->localtype == BRI_CPE_PTMP) {
-+	    reschedule_t203(pri, pri->tei);
-+	} else if (h->h.tei != Q921_TEI_GROUP) {
-+	    reschedule_t203(pri, h->h.tei);
-+	}
- 	return 0;
- }
- 
--static void q921_send_ua(struct pri *pri, int pfbit)
-+static void q921_send_ua(struct pri *pri, int pfbit, int tei)
- {
- 	q921_h h;
- 	Q921_INIT(pri, h);
-@@ -99,6 +108,7 @@
- 	h.u.m2 = 0;		/* M2 = 0 */
- 	h.u.p_f = pfbit;	/* Final bit on */
- 	h.u.ft = Q921_FRAMETYPE_U;
-+	h.h.tei = tei;
- 	switch(pri->localtype) {
- 	case PRI_NETWORK:
- 		h.h.c_r = 0;
-@@ -106,6 +116,19 @@
- 	case PRI_CPE:
- 		h.h.c_r = 1;
- 		break;
-+	case BRI_NETWORK_PTMP:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE_PTMP:
-+		h.h.tei = pri->tei;
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_NETWORK:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE:
-+		h.h.c_r = 1;
-+		break;
- 	default:
- 		pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
- 		return;
-@@ -114,19 +137,302 @@
- 		pri_message("Sending Unnumbered Acknowledgement\n");
- 	q921_transmit(pri, &h, 3);
- }
-+/*
-+static void q921_send_disconnect(struct pri *pri, int pfbit, int tei)
-+{
-+	q921_h h;
-+	Q921_INIT(pri, h);
-+	h.u.m3 = 2;
-+	h.u.m2 = 0;
-+	h.u.p_f = pfbit;
-+	h.u.ft = Q921_FRAMETYPE_U;
-+	h.h.tei = tei;
-+	switch(pri->localtype) {
-+	case PRI_NETWORK:
-+		h.h.c_r = 0;
-+		break;
-+	case PRI_CPE:
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_NETWORK_PTMP:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE_PTMP:
-+		h.h.tei = pri->tei;
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_NETWORK:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE:
-+		h.h.c_r = 1;
-+		break;
-+	default:
-+		pri_error("Don't know how to disconnect on a type %d node\n", pri->localtype);
-+		return;
-+	}
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+		pri_message("Sending Disconnect\n");
-+	q921_transmit(pri, &h, 3);
-+}
-+*/
-+static void q921_send_dm(struct pri *pri, int pfbit, int tei)
-+{
-+	q921_h h;
-+	Q921_INIT(pri, h);
-+	h.u.m3 = 0;		/* M3 = 0 */
-+	h.u.m2 = 3;		/* M2 = 3 */
-+	h.u.p_f = pfbit;	/* Final bit on */
-+	h.u.ft = Q921_FRAMETYPE_U;
-+	h.h.tei = tei;
-+	switch(pri->localtype) {
-+	case PRI_NETWORK:
-+		h.h.c_r = 0;
-+		break;
-+	case PRI_CPE:
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_NETWORK_PTMP:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE_PTMP:
-+		h.h.tei = pri->tei;
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_NETWORK:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE:
-+		h.h.c_r = 1;
-+		break;
-+	default:
-+		pri_error("Don't know how to DM on a type %d node\n", pri->localtype);
-+		return;
-+	}
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+		pri_message("Sending DM\n");
-+	q921_transmit(pri, &h, 3);
-+}
- 
--static void q921_send_sabme_now(void *vpri);
-+static void q921_send_teireq(void *vpri) {
-+    struct pri *pri = vpri;
-+    unsigned short ri=0x6464;
-+    q921_u *f;
-+    ri = rand();
- 
--static void q921_send_sabme(void *vpri, int now)
-+    if (pri->localtype != BRI_CPE_PTMP) {
-+	pri_error("TEI req for non-ptmp???\n"); 
-+	return;
-+    }
-+    if (pri->t202_timer[0]) { 
-+	pri_schedule_del(pri, pri->t202_timer[0]);
-+	pri->t202_timer[0] = 0;
-+    }
-+
-+    pri->t202_timer[0] = pri_schedule_event(pri, T_202, q921_send_teireq, pri);
-+
-+    pri->ri = ri;
-+    f = malloc(sizeof(q921_u) + 5 + 2);
-+    memset(f,0x0,sizeof(q921_u) + 5 + 2);
-+    if (f) {
-+	f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
-+	f->h.tei = Q921_TEI_GROUP;
-+	f->h.c_r = 0;	
-+	f->h.ea1 = 0;	
-+	f->h.ea2 = 1;	
-+	f->m2 = 0;
-+	f->m3 = 0;
-+	f->ft = Q921_FRAMETYPE_U;
-+	f->data[0] = 0xf;
-+	f->data[1] = ri >> 8;
-+	f->data[2] = ri & 0xff;
-+	f->data[3] = Q921_TEI_ID_REQUEST;
-+	f->data[4] = 0xff;
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+    	    pri_message("Sending TEI Request ri=%d\n",ri);
-+	q921_transmit(pri,(q921_h *)&(f->h),8);
-+	free(f);
-+    }
-+}
-+
-+static void q921_send_teiassign(struct pri *pri,int ri,int tei) {
-+    q921_u *f;
-+
-+    if (pri->localtype != BRI_NETWORK_PTMP) {
-+	pri_error("TEI assign for non-ptmp???\n"); 
-+	return;
-+    }
-+
-+    f = malloc(sizeof(q921_u) + 5 + 2);
-+    memset(f,0x0,sizeof(q921_u) + 5 + 2);
-+    if (f) {
-+	f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
-+	f->h.tei = Q921_TEI_GROUP;
-+	f->h.c_r = 1;	
-+	f->h.ea1 = 0;	
-+	f->h.ea2 = 1;	
-+	f->m2 = 0;
-+	f->m3 = 0;
-+	f->ft = Q921_FRAMETYPE_U;
-+	f->data[0] = 0xf;
-+	f->data[1] = ri >> 8;
-+	f->data[2] = ri & 0xff;
-+	f->data[3] = Q921_TEI_ID_ASSIGNED;
-+	f->data[4] = (tei << 1) | 0x1;
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+    	    pri_message("Sending TEI assign ri=%d tei=%d\n",ri,tei);
-+	q921_transmit(pri,(q921_h *)&(f->h),8);
-+	free(f);
-+    }
-+}
-+
-+static void q921_send_teichkresp(struct pri *pri,int tei) {
-+    q921_u *f;
-+    unsigned short ri=0x6464;
-+    ri = rand();
-+
-+    if (pri->localtype != BRI_CPE_PTMP) {
-+	pri_error("TEI check response for non-ptmp???\n"); 
-+	return;
-+    }
-+
-+    f = malloc(sizeof(q921_u) + 5 + 2);
-+    memset(f,0x0,sizeof(q921_u) + 5 + 2);
-+    if (f) {
-+	f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
-+	f->h.tei = Q921_TEI_GROUP;
-+	f->h.c_r = 0; // command u->n	
-+	f->h.ea1 = 0;	
-+	f->h.ea2 = 1;	
-+	f->m2 = 0;
-+	f->m3 = 0;
-+	f->ft = Q921_FRAMETYPE_U;
-+	f->data[0] = 0xf;
-+	f->data[1] = ri >> 8;
-+	f->data[2] = ri & 0xff;
-+	f->data[3] = Q921_TEI_ID_CHK_RES;
-+	f->data[4] = (tei << 1) | 0x1;
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+    	    pri_message("Sending TEI check resp ri=%d tei=%d\n",ri,tei);
-+	q921_transmit(pri,(q921_h *)&(f->h),8);
-+	free(f);
-+    }
-+}
-+/* 
-+static void q921_send_teiverify(struct pri *pri,int tei) {
-+    q921_u *f;
-+
-+    if (pri->localtype != BRI_CPE_PTMP) {
-+	pri_error("TEI verify for non-ptmp???\n"); 
-+	return;
-+    }
-+
-+    f = malloc(sizeof(q921_u) + 5 + 2);
-+    memset(f,0x0,sizeof(q921_u) + 5 + 2);
-+    if (f) {
-+	f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
-+	f->h.tei = Q921_TEI_GROUP;
-+	f->h.c_r = 0; // command u->n	
-+	f->h.ea1 = 0;	
-+	f->h.ea2 = 1;	
-+	f->m2 = 0;
-+	f->m3 = 0;
-+	f->ft = Q921_FRAMETYPE_U;
-+	f->data[0] = 0xf;
-+	f->data[1] = 0;
-+	f->data[2] = 0;
-+	f->data[3] = Q921_TEI_ID_VERIFY;
-+	f->data[4] = (tei << 1) | 0x1;
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+    	    pri_message("Sending TEI verify tei=%d\n", tei);
-+	q921_transmit(pri,(q921_h *)&(f->h),8);
-+	free(f);
-+    }
-+}
-+*/
-+static void q921_send_teiremove(struct pri *pri, int tei) {
-+    q921_u *f;
-+    unsigned short ri=0x6464;
-+    ri = rand();
-+
-+    if (pri->localtype != BRI_NETWORK_PTMP) {
-+	pri_error("TEI remove for non-ptmp???\n"); 
-+	return;
-+    }
-+
-+    f = malloc(sizeof(q921_u) + 5 + 2);
-+    memset(f,0x0,sizeof(q921_u) + 5 + 2);
-+    if (f) {
-+	f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
-+	f->h.tei = Q921_TEI_GROUP;
-+	f->h.c_r = 1;	
-+	f->h.ea1 = 0;	
-+	f->h.ea2 = 1;	
-+	f->m2 = 0;
-+	f->m3 = 0;
-+	f->ft = Q921_FRAMETYPE_U;
-+	f->data[0] = 0xf;
-+	f->data[1] = ri >> 8;
-+	f->data[2] = ri & 0xff;
-+	f->data[3] = Q921_TEI_ID_REMOVE;
-+	f->data[4] = (tei << 1) | 0x1;
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+    	    pri_message("Sending TEI remove tei=%d\n",tei);
-+	q921_transmit(pri,(q921_h *)&(f->h),8);
-+	free(f);
-+    }
-+}
-+
-+static void q921_send_teidenied(struct pri *pri, int ri, int tei) {
-+    q921_u *f;
-+
-+    if (pri->localtype != BRI_NETWORK_PTMP) {
-+	pri_error("TEI ID denied for non-ptmp???\n"); 
-+	return;
-+    }
-+
-+    f = malloc(sizeof(q921_u) + 5 + 2);
-+    memset(f,0x0,sizeof(q921_u) + 5 + 2);
-+    if (f) {
-+	f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
-+	f->h.tei = Q921_TEI_GROUP;
-+	f->h.c_r = 1;	
-+	f->h.ea1 = 0;	
-+	f->h.ea2 = 1;	
-+	f->m2 = 0;
-+	f->m3 = 0;
-+	f->ft = Q921_FRAMETYPE_U;
-+	f->data[0] = 0xf;
-+	f->data[1] = ri >> 8;
-+	f->data[2] = ri & 0xff;
-+	f->data[3] = Q921_TEI_ID_DENIED;
-+	f->data[4] = (tei << 1) | 0x1;
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+    	    pri_message("Sending TEI ID denied tei=%d\n",tei);
-+	q921_transmit(pri,(q921_h *)&(f->h),8);
-+	free(f);
-+    }
-+}
-+
-+static void q921_send_sabme_now(void *vpri, int tei);
-+
-+static void q921_send_sabme(void *vpri, int now, int tei)
- {
- 	struct pri *pri = vpri;
- 	q921_h h;
--	pri_schedule_del(pri, pri->sabme_timer);
--	pri->sabme_timer = 0;
--	pri->sabme_timer = pri_schedule_event(pri, T_200, q921_send_sabme_now, pri);
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+
-+	if (pri->sabme_timer[teio]) {
-+	    pri_schedule_del(pri, pri->sabme_timer[teio]);
-+	    pri->sabme_timer[teio] = 0;
-+	}
-+	pri->sabme_timer[teio] = pri_schedule_event2(pri, T_200, q921_send_sabme_now, pri, tei);
- 	if (!now)
- 		return;
- 	Q921_INIT(pri, h);
-+	// XXX
-+	h.h.tei = tei;
- 	h.u.m3 = 3;	/* M3 = 3 */
- 	h.u.m2 = 3;	/* M2 = 3 */
- 	h.u.p_f = 1;	/* Poll bit set */
-@@ -138,6 +444,19 @@
- 	case PRI_CPE:
- 		h.h.c_r = 0;
- 		break;
-+	case BRI_NETWORK_PTMP:
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_CPE_PTMP:
-+		h.h.c_r = 0;
-+		h.h.tei = pri->tei;
-+		break;
-+	case BRI_NETWORK:
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_CPE:
-+		h.h.c_r = 0;
-+		break;
- 	default:
- 		pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
- 		return;
-@@ -145,18 +464,20 @@
- 	if (pri->debug & PRI_DEBUG_Q921_STATE)
- 		pri_message("Sending Set Asynchronous Balanced Mode Extended\n");
- 	q921_transmit(pri, &h, 3);
--	pri->q921_state = Q921_AWAITING_ESTABLISH;
-+	pri->q921_state[teio] = Q921_AWAITING_ESTABLISH;
- }
- 
--static void q921_send_sabme_now(void *vpri)
-+static void q921_send_sabme_now(void *vpri, int tei)
- {
--	q921_send_sabme(vpri, 1);
-+	q921_send_sabme(vpri, 1, tei);
- }
- 
--static int q921_ack_packet(struct pri *pri, int num)
-+static int q921_ack_packet(struct pri *pri, int num, int tei)
- {
- 	struct q921_frame *f, *prev = NULL;
--	f = pri->txqueue;
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+	f = pri->txqueue[teio];
- 	while(f) {
- 		if (f->h.n_s == num) {
- 			/* Cancel each packet as necessary */
-@@ -164,26 +485,26 @@
- 			if (prev)
- 				prev->next = f->next;
- 			else
--				pri->txqueue = f->next;
-+				pri->txqueue[teio] = f->next;
- 			if (pri->debug & PRI_DEBUG_Q921_STATE)
--				pri_message("-- ACKing packet %d, new txqueue is %d (-1 means empty)\n", f->h.n_s, pri->txqueue ? pri->txqueue->h.n_s : -1);
-+				pri_message("-- ACKing packet %d, new txqueue is %d (-1 means empty)\n", f->h.n_s, pri->txqueue[teio] ? pri->txqueue[teio]->h.n_s : -1);
- 			/* Update v_a */
--			pri->v_a = num;
-+			pri->v_a[teio] = num;
- 			free(f);
- 			/* Reset retransmission counter if we actually acked something */
--			pri->retrans = 0;
-+			pri->retrans[teio] = 0;
- 			/* Decrement window size */
--			pri->windowlen--;
-+			pri->windowlen[teio]--;
- 			/* Search for something to send */
--			f = pri->txqueue;
-+			f = pri->txqueue[teio];
- 			while(f) {
- 				if (!f->transmitted) {
- 					/* Send it now... */
- 					if (pri->debug & PRI_DEBUG_Q921_STATE)
- 						pri_message("-- Finally transmitting %d, since window opened up\n", f->h.n_s);
- 					f->transmitted++;
--					pri->windowlen++;
--					f->h.n_r = pri->v_r;
-+					pri->windowlen[teio]++;
-+					f->h.n_r = pri->v_r[teio];
- 					q921_transmit(pri, (q921_h *)(&f->h), f->len);
- 					break;
- 				}
-@@ -197,77 +518,85 @@
- 	return 0;
- }
- 
--static void t203_expire(void *);
--static void t200_expire(void *);
--static pri_event *q921_dchannel_down(struct pri *pri);
-+static void t203_expire(void *, int tei);
-+static void t200_expire(void *, int tei);
-+static pri_event *q921_dchannel_down(struct pri *pri, int tei);
- 
--static void reschedule_t203(struct pri *pri)
-+static void reschedule_t203(struct pri *pri, int tei)
- {
--	if (pri->t203_timer) {
--		pri_schedule_del(pri, pri->t203_timer);
--		if (pri->debug &  PRI_DEBUG_Q921_STATE)
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+	if (pri->t203_timer[teio]) {
-+		pri_schedule_del(pri, pri->t203_timer[teio]);
-+ 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
- 			pri_message("-- Restarting T203 counter\n");
- 		/* Nothing to transmit, start the T203 counter instead */
--		pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri);
-+		pri->t203_timer[teio] = pri_schedule_event2(pri, T_203, t203_expire, pri, tei);
- 	}
- }
- 
--static pri_event *q921_ack_rx(struct pri *pri, int ack)
-+static pri_event *q921_ack_rx(struct pri *pri, int ack, int tei)
- {
- 	int x;
- 	int cnt=0;
- 	pri_event *ev;
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
- 	/* Make sure the ACK was within our window */
--	for (x=pri->v_a; (x != pri->v_s) && (x != ack); Q921_INC(x));
-+	for (x=pri->v_a[teio]; (x != pri->v_s[teio]) && (x != ack); Q921_INC(x));
- 	if (x != ack) {
- 		/* ACK was outside of our window --- ignore */
--		pri_error("ACK received for '%d' outside of window of '%d' to '%d', restarting\n", ack, pri->v_a, pri->v_s);
--		ev = q921_dchannel_down(pri);
--		q921_start(pri, 1);
-+		pri_error("ACK received for '%d' outside of window of '%d' to '%d', restarting\n", ack, pri->v_a[teio], pri->v_s[teio]);
-+		ev = q921_dchannel_down(pri, tei);
-+		q921_start(pri, 1, tei);
- 		pri->schedev = 1;
- 		return ev;
- 	}
- 	/* Cancel each packet as necessary */
- 	if (pri->debug & PRI_DEBUG_Q921_STATE)
--		pri_message("-- ACKing all packets from %d to (but not including) %d\n", pri->v_a, ack);
--	for (x=pri->v_a; x != ack; Q921_INC(x)) 
--		cnt += q921_ack_packet(pri, x);	
--	if (!pri->txqueue) {
-+		pri_message("-- ACKing all packets from %d to (but not including) %d\n", pri->v_a[teio], ack);
-+	for (x=pri->v_a[teio]; x != ack; Q921_INC(x)) 
-+		cnt += q921_ack_packet(pri, x,tei);	
-+	if (!pri->txqueue[teio]) {
- 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
- 			pri_message("-- Since there was nothing left, stopping T200 counter\n");
- 		/* Something was ACK'd.  Stop T200 counter */
--		pri_schedule_del(pri, pri->t200_timer);
--		pri->t200_timer = 0;
-+		if (pri->t200_timer[teio]) {
-+		    pri_schedule_del(pri, pri->t200_timer[teio]);
-+		    pri->t200_timer[teio] = 0;
-+		}
- 	}
--	if (pri->t203_timer) {
-+	if (pri->t203_timer[teio]) {
- 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
- 			pri_message("-- Stopping T203 counter since we got an ACK\n");
--		pri_schedule_del(pri, pri->t203_timer);
--		pri->t203_timer = 0;
-+		pri_schedule_del(pri, pri->t203_timer[teio]);
-+		pri->t203_timer[teio] = 0;
- 	}
--	if (pri->txqueue) {
-+	if (pri->txqueue[teio]) {
- 		/* Something left to transmit, Start the T200 counter again if we stopped it */
- 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
--			pri_message("-- Something left to transmit (%d), restarting T200 counter\n", pri->txqueue->h.n_s);
--		if (!pri->t200_timer)
--			pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
-+			pri_message("-- Something left to transmit (%d), restarting T200 counter\n", pri->txqueue[teio]->h.n_s);
-+		if (!pri->t200_timer[teio])
-+			pri->t200_timer[teio] = pri_schedule_event2(pri, T_200, t200_expire, pri, tei);
- 	} else {
- 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
- 			pri_message("-- Nothing left, starting T203 counter\n");
- 		/* Nothing to transmit, start the T203 counter instead */
--		pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri);
-+		pri->t203_timer[teio] = pri_schedule_event2(pri, T_203, t203_expire, pri, tei);
- 	}
- 	return NULL;
- }
- 
--static void q921_reject(struct pri *pri, int pf)
-+static void q921_reject(struct pri *pri, int pf, int tei)
- {
- 	q921_h h;
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
- 	Q921_INIT(pri, h);
- 	h.s.x0 = 0;	/* Always 0 */
- 	h.s.ss = 2;	/* Reject */
- 	h.s.ft = 1;	/* Frametype (01) */
--	h.s.n_r = pri->v_r;	/* Where to start retransmission */
-+	h.s.n_r = pri->v_r[teio];	/* Where to start retransmission */
- 	h.s.p_f = pf;	
- 	switch(pri->localtype) {
- 	case PRI_NETWORK:
-@@ -276,23 +605,38 @@
- 	case PRI_CPE:
- 		h.h.c_r = 1;
- 		break;
-+	case BRI_NETWORK_PTMP:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE_PTMP:
-+		h.h.c_r = 1;
-+		h.h.tei = tei;
-+		break;
-+	case BRI_NETWORK:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE:
-+		h.h.c_r = 1;
-+		break;
- 	default:
- 		pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
- 		return;
- 	}
- 	if (pri->debug & PRI_DEBUG_Q921_STATE)
--		pri_message("Sending Reject (%d)\n", pri->v_r);
--	pri->sentrej = 1;
-+		pri_message("Sending Reject (%d)\n", pri->v_r[teio]);
-+	pri->sentrej[teio] = 1;
- 	q921_transmit(pri, &h, 4);
- }
- 
--static void q921_rr(struct pri *pri, int pbit, int cmd) {
-+static void q921_rr(struct pri *pri, int pbit, int cmd, int tei) {
- 	q921_h h;
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
- 	Q921_INIT(pri, h);
- 	h.s.x0 = 0;	/* Always 0 */
- 	h.s.ss = 0; /* Receive Ready */
- 	h.s.ft = 1;	/* Frametype (01) */
--	h.s.n_r = pri->v_r;	/* N/R */
-+	h.s.n_r = pri->v_r[teio];	/* N/R */
- 	h.s.p_f = pbit;		/* Poll/Final set appropriately */
- 	switch(pri->localtype) {
- 	case PRI_NETWORK:
-@@ -307,81 +651,153 @@
- 		else
- 			h.h.c_r = 1;
- 		break;
-+	case BRI_NETWORK_PTMP:
-+		h.h.tei = tei;
-+		if (cmd)
-+			h.h.c_r = 1;
-+		else
-+			h.h.c_r = 0;
-+		break;
-+	case BRI_CPE_PTMP:
-+		h.h.tei = tei;
-+		if (cmd)
-+			h.h.c_r = 0;
-+		else
-+			h.h.c_r = 1;
-+		break;
-+	case BRI_NETWORK:
-+		if (cmd)
-+			h.h.c_r = 1;
-+		else
-+			h.h.c_r = 0;
-+		break;
-+	case BRI_CPE:
-+		if (cmd)
-+			h.h.c_r = 0;
-+		else
-+			h.h.c_r = 1;
-+		break;
- 	default:
- 		pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
- 		return;
- 	}
--	pri->v_na = pri->v_r;	/* Make a note that we've already acked this */
-+	pri->v_na[teio] = pri->v_r[teio];	/* Make a note that we've already acked this */
- 	if (pri->debug & PRI_DEBUG_Q921_STATE)
--		pri_message("Sending Receiver Ready (%d)\n", pri->v_r);
-+		pri_message("Sending Receiver Ready (%d)\n", pri->v_r[teio]);
- 	q921_transmit(pri, &h, 4);
- }
- 
--static void t200_expire(void *vpri)
-+static void t200_expire(void *vpri, int tei)
- {
- 	struct pri *pri = vpri;
--	if (pri->txqueue) {
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+	if (pri->txqueue[teio]) {
- 		/* Retransmit first packet in the queue, setting the poll bit */
- 		if (pri->debug & PRI_DEBUG_Q921_STATE)
- 			pri_message("-- T200 counter expired, What to do...\n");
- 		/* Force Poll bit */
--		pri->txqueue->h.p_f = 1;	
-+		pri->txqueue[teio]->h.p_f = 1;	
- 		/* Update nr */
--		pri->txqueue->h.n_r = pri->v_r;
--		pri->v_na = pri->v_r;
--		pri->solicitfbit = 1;
--		pri->retrans++;
-+		pri->txqueue[teio]->h.n_r = pri->v_r[teio];
-+		pri->v_na[teio] = pri->v_r[teio];
-+		pri->solicitfbit[teio] = 1;
-+		pri->retrans[teio]++;
-       /* Up to three retransmissions */
--      if (pri->retrans < N_200) {
-+      if (pri->retrans[teio] < N_200) {
-          /* Reschedule t200_timer */
-          if (pri->debug & PRI_DEBUG_Q921_STATE)
--            pri_message("-- Retransmitting %d bytes\n", pri->txqueue->len);
--		if (pri->busy) 
--			q921_rr(pri, 1, 0);
-+            pri_message("-- Retransmitting %d bytes\n", pri->txqueue[teio]->len);
-+		if (pri->busy[teio]) 
-+			q921_rr(pri, 1, 0, tei);
- 		else {
--			if (!pri->txqueue->transmitted) 
-+			if (!pri->txqueue[teio]->transmitted) 
- 				pri_error("!! Not good - head of queue has not been transmitted yet\n");
--			q921_transmit(pri, (q921_h *)&pri->txqueue->h, pri->txqueue->len);
-+			q921_transmit(pri, (q921_h *)&pri->txqueue[teio]->h, pri->txqueue[teio]->len);
- 		}
-          if (pri->debug & PRI_DEBUG_Q921_STATE) 
--               pri_message("-- Rescheduling retransmission (%d)\n", pri->retrans);
--         pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
-+               pri_message("-- Rescheduling retransmission (%d)\n", pri->retrans[teio]);
-+         pri->t200_timer[teio] = pri_schedule_event2(pri, T_200, t200_expire, pri, tei);
-       } else {
-          if (pri->debug & PRI_DEBUG_Q921_STATE) 
-                pri_message("-- Timeout occured, restarting PRI\n");
--         pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
--      	pri->t200_timer = 0;
--         q921_dchannel_down(pri);
--         q921_start(pri, 1);
-+    	pri->q921_state[teio] = Q921_LINK_CONNECTION_RELEASED;
-+    	pri->t200_timer[teio] = 0;
-+         q921_dchannel_down(pri, tei);
-+         q921_start(pri, 1, tei);
-          pri->schedev = 1;
-       }
--	} else if (pri->solicitfbit) {
-+	} else if (pri->solicitfbit[teio]) {
-          if (pri->debug & PRI_DEBUG_Q921_STATE)
-             pri_message("-- Retrying poll with f-bit\n");
--		pri->retrans++;
--		if (pri->retrans < N_200) {
--			pri->solicitfbit = 1;
--			q921_rr(pri, 1, 1);
--			pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
-+		pri->retrans[teio]++;
-+		if (pri->retrans[teio] < N_200) {
-+			pri->solicitfbit[teio] = 1;
-+			q921_rr(pri, 1, 1, tei);
-+			pri->t200_timer[teio] = pri_schedule_event2(pri, T_200, t200_expire, pri, tei);
- 		} else {
- 			if (pri->debug & PRI_DEBUG_Q921_STATE) 
- 				pri_message("-- Timeout occured, restarting PRI\n");
--			pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
--			pri->t200_timer = 0;
--			q921_dchannel_down(pri);
--			q921_start(pri, 1);
--			pri->schedev = 1;
-+        		pri->q921_state[teio] = Q921_LINK_CONNECTION_RELEASED;
-+      			pri->t200_timer[teio] = 0;
-+			q921_dchannel_down(pri, tei);
-+        		q921_start(pri, 1, tei); 
-+        		pri->schedev = 1; 
- 		}
- 	} else {
- 		pri_error("T200 counter expired, nothing to send...\n");
--	   	pri->t200_timer = 0;
-+	   	pri->t200_timer[teio] = 0;
- 	}
- }
- 
--int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr)
-+int q921_transmit_uframe(struct pri *pri, void *buf, int len, int cr, int tei)
-+{
-+	q921_u *uf;
-+	uf = malloc(sizeof(q921_u) + len + 2);
-+	memset(uf,0,sizeof(q921_u) + len + 2);
-+
-+	uf->h.sapi = 0;
-+	uf->h.ea1 = 0;
-+	uf->h.ea2 = 1;
-+	uf->h.tei = tei;
-+	uf->m3 = 0;
-+	uf->m2 = 0;
-+	uf->ft = Q921_FRAMETYPE_U;
-+	switch(pri->localtype) {
-+	case PRI_NETWORK:
-+		uf->h.c_r = 1;
-+		break;
-+	case PRI_CPE:
-+		uf->h.c_r = 0;
-+		break;
-+	case BRI_NETWORK_PTMP:
-+		uf->h.c_r = 1;
-+		break;
-+	case BRI_CPE_PTMP:
-+		uf->h.c_r = 0;
-+		break;
-+	case BRI_NETWORK:
-+		uf->h.c_r = 1;
-+		break;
-+	case BRI_CPE:
-+		uf->h.c_r = 0;
-+		break;
-+	default:
-+		pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
-+		return -1;
-+ 	}
-+	memcpy(uf->data,buf,len);
-+	q921_transmit(pri, (q921_h*)&(uf->h), 3+len);
-+	free(uf);
-+	return 0;
-+}
-+
-+int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr, int tei)
- {
- 	q921_frame *f, *prev=NULL;
--	for (f=pri->txqueue; f; f = f->next) prev = f;
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+	for (f=pri->txqueue[teio]; f; f = f->next) prev = f;
- 	f = malloc(sizeof(q921_frame) + len + 2);
- 	if (f) {
- 		memset(f,0,sizeof(q921_frame) + len + 2);
-@@ -399,47 +815,75 @@
- 			else
- 				f->h.h.c_r = 1;
- 		break;
-+		case BRI_NETWORK_PTMP:
-+			f->h.h.tei = tei;
-+			if (cr)
-+				f->h.h.c_r = 1;
-+			else
-+				f->h.h.c_r = 0;
-+		break;
-+		case BRI_CPE_PTMP:
-+			f->h.h.tei = pri->tei;
-+			if (cr)
-+				f->h.h.c_r = 0;
-+			else
-+				f->h.h.c_r = 1;
-+		break;
-+		case BRI_NETWORK:
-+			if (cr)
-+				f->h.h.c_r = 1;
-+			else
-+				f->h.h.c_r = 0;
-+		break;
-+		case BRI_CPE:
-+			if (cr)
-+				f->h.h.c_r = 0;
-+			else
-+				f->h.h.c_r = 1;
-+		break;
- 		}
- 		f->next = NULL;
- 		f->transmitted = 0;
- 		f->len = len + 4;
- 		memcpy(f->h.data, buf, len);
--		f->h.n_s = pri->v_s;
--		f->h.n_r = pri->v_r;
--		pri->v_s++;
--		pri->v_na = pri->v_r;
-+		f->h.n_s = pri->v_s[teio];
-+		f->h.n_r = pri->v_r[teio];
-+		pri->v_s[teio]++;
-+		pri->v_na[teio] = pri->v_r[teio];
- 		f->h.p_f = 0;
- 		f->h.ft = 0;
- 		if (prev)
- 			prev->next = f;
- 		else
--			pri->txqueue = f;
-+			pri->txqueue[teio] = f;
- 		/* Immediately transmit unless we're in a recovery state, or the window
- 		   size is too big */
--		if (!pri->retrans && !pri->busy) {
--			if (pri->windowlen < pri->window) {
--				pri->windowlen++;
-+// XXXXXX think about this...
-+//		if (!pri->retrans[teio] && !pri->busy[teio]) {
-+		if (!pri->retrans[teio] && !pri->busy[teio]) {
-+			if (pri->windowlen[teio] < pri->window[teio]) {
-+				pri->windowlen[teio]++;
- 				q921_transmit(pri, (q921_h *)(&f->h), f->len);
- 				f->transmitted++;
- 			} else {
- 				if (pri->debug & PRI_DEBUG_Q921_STATE)
- 					pri_message("Delaying transmission of %d, window is %d/%d long\n", 
--						f->h.n_s, pri->windowlen, pri->window);
-+						f->h.n_s, pri->windowlen[teio], pri->window[teio]);
- 			}
- 		}
--		if (pri->t203_timer) {
-+		if (pri->t203_timer[teio]) {
- 			if (pri->debug & PRI_DEBUG_Q921_STATE)
- 				pri_message("Stopping T_203 timer\n");
--			pri_schedule_del(pri, pri->t203_timer);
--			pri->t203_timer = 0;
-+			pri_schedule_del(pri, pri->t203_timer[teio]);
-+			pri->t203_timer[teio] = 0;
- 		}
--		if (!pri->t200_timer) {
-+		if (!pri->t200_timer[teio]) {
- 			if (pri->debug & PRI_DEBUG_Q921_STATE)
- 				pri_message("Starting T_200 timer\n");
--			pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
-+			pri->t200_timer[teio] = pri_schedule_event2(pri, T_200, t200_expire, pri, tei);
- 		} else
- 			if (pri->debug & PRI_DEBUG_Q921_STATE)
--				pri_message("T_200 timer already going (%d)\n", pri->t200_timer);
-+				pri_message("T_200 timer already going (%d)\n", pri->t200_timer[teio]);
- 		
- 	} else {
- 		pri_error("!! Out of memory for Q.921 transmit\n");
-@@ -448,22 +892,25 @@
- 	return 0;
- }
- 
--static void t203_expire(void *vpri)
-+static void t203_expire(void *vpri, int tei)
- {
- 	struct pri *pri = vpri;
--	if (pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) {
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+
-+	if (pri->q921_state[teio] == Q921_LINK_CONNECTION_ESTABLISHED) {
- 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
- 			pri_message("T203 counter expired, sending RR and scheduling T203 again\n");
- 		/* Solicit an F-bit in the other's RR */
--		pri->solicitfbit = 1;
--		pri->retrans = 0;
--		q921_rr(pri, 1, 1);
-+		pri->retrans[teio] = 0;
-+		pri->solicitfbit[teio] = 1;
-+		q921_rr(pri, 1, 1, tei);
- 		/* Start timer T200 to resend our RR if we don't get it */
--		pri->t203_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
-+		pri->t203_timer[teio] = pri_schedule_event2(pri, T_200, t200_expire, pri, tei);
- 	} else {
- 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
--			pri_message("T203 counter expired in weird state %d\n", pri->q921_state);
--		pri->t203_timer = 0;
-+			pri_message("T203 counter expired in weird state %d\n", pri->q921_state[teio]);
-+		pri->t203_timer[teio] = 0;
- 	}
- }
- 
-@@ -471,26 +918,28 @@
- {
- 	int res;
- 	pri_event *ev;
-+	int teio= i->h.tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
- 	/* Make sure this is a valid packet */
--	if (i->n_s == pri->v_r) {
-+	if (i->n_s == pri->v_r[teio]) {
- 		/* Increment next expected I-frame */
--		Q921_INC(pri->v_r);
-+		Q921_INC(pri->v_r[teio]);
- 		/* Handle their ACK */
--		pri->sentrej = 0;
--		ev = q921_ack_rx(pri, i->n_r);
-+		pri->sentrej[teio] = 0;
-+		ev = q921_ack_rx(pri, i->n_r, i->h.tei);
- 		if (ev)
- 			return ev;
- 		if (i->p_f) {
- 			/* If the Poll/Final bit is set, immediate send the RR */
--			q921_rr(pri, 1, 0);
--		} else if (pri->busy) {
--			q921_rr(pri, 0, 0);
-+			q921_rr(pri, 1, 0, i->h.tei);
-+		} else if (pri->busy[teio]) {
-+			q921_rr(pri, 0, 0, i->h.tei);
- 		}
- 		/* Receive Q.931 data */
--		res = q931_receive(pri, (q931_h *)i->data, len - 4);
-+		res = q931_receive(pri, (q931_h *)i->data, len - 4, i->h.tei);
- 		/* Send an RR if one wasn't sent already */
--		if (pri->v_na != pri->v_r) 
--			q921_rr(pri, 0, 0);
-+		if (pri->v_na[teio] != pri->v_r[teio]) 
-+			q921_rr(pri, 0, 0,  i->h.tei);
- 		if (res == -1) {
- 			return NULL;
- 		}
-@@ -499,10 +948,10 @@
- 	} else {
- 		/* If we haven't already sent a reject, send it now, otherwise
- 		   we are obliged to RR */
--		if (!pri->sentrej)
--			q921_reject(pri, i->p_f);
-+		if (!pri->sentrej[teio])
-+			q921_reject(pri, i->p_f, i->h.tei);
- 		else if (i->p_f)
--			q921_rr(pri, 1, 0);
-+			q921_rr(pri, 1, 0,  i->h.tei);
- 	}
- 	return NULL;
- }
-@@ -640,62 +1089,94 @@
- 	};
- }
- 
--static pri_event *q921_dchannel_up(struct pri *pri)
-+static pri_event *q921_dchannel_up(struct pri *pri, int tei)
- {
-+	// we treat this as MFE
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+
- 	/* Reset counters, etc */
--	q921_reset(pri);
-+	q921_reset(pri, tei);
- 	
- 	/* Stop any SABME retransmissions */
--	pri_schedule_del(pri, pri->sabme_timer);
--	pri->sabme_timer = 0;
-+	if (pri->sabme_timer[teio]) {
-+	    pri_schedule_del(pri, pri->sabme_timer[teio]);
-+	    pri->sabme_timer[teio] = 0;
-+	}
-+	
-+	if (pri->t202_timer[teio]) {
-+	    pri_schedule_del(pri, pri->t202_timer[teio]);
-+	    pri->t202_timer[teio] = 0;
-+	}
- 	
- 	/* Reset any rejects */
--	pri->sentrej = 0;
-+	pri->sentrej[teio] = 0;
- 	
- 	/* Go into connection established state */
--	pri->q921_state = Q921_LINK_CONNECTION_ESTABLISHED;
-+	pri->q921_state[teio] = Q921_LINK_CONNECTION_ESTABLISHED;
- 
- 	/* Start the T203 timer */
--	pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri);
-+	pri->t203_timer[teio] = pri_schedule_event2(pri, T_203, t203_expire, pri, tei);
- 	
- 	/* Report event that D-Channel is now up */
--	pri->ev.gen.e = PRI_EVENT_DCHAN_UP;
--	return &pri->ev;
-+        pri->ev.gen.e = PRI_EVENT_DCHAN_UP;
-+        pri->ev.gen.tei = tei;
-+        return &pri->ev;
- }
- 
--static pri_event *q921_dchannel_down(struct pri *pri)
-+static pri_event *q921_dchannel_down(struct pri *pri, int tei)
- {
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+	// we treat this as MF disc
- 	/* Reset counters, reset sabme timer etc */
--	q921_reset(pri);
-+	q921_reset(pri, tei);
- 	
--	/* Report event that D-Channel is now up */
-+	/* Report event that D-Channel is now down */
-+	if (pri->localtype == BRI_NETWORK_PTMP) {
-+	    if (pri->t203_timer[teio]) {
-+		if (pri->debug & PRI_DEBUG_Q921_STATE) {
-+			pri_message("Stopping T_203 timer for TEI %d\n", tei);
-+		}
-+		pri_schedule_del(pri, pri->t203_timer[teio]);
-+		pri->t203_timer[teio] = 0;
-+	    }
-+	}
- 	pri->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
--	return &pri->ev;
-+	pri->ev.gen.tei = tei;
-+	return &pri->ev;	
- }
- 
--void q921_reset(struct pri *pri)
-+void q921_reset(struct pri *pri, int tei)
- {
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
- 	/* Having gotten a SABME we MUST reset our entire state */
--	pri->v_s = 0;
--	pri->v_a = 0;
--	pri->v_r = 0;
--	pri->v_na = 0;
--	pri->window = 7;
--	pri->windowlen = 0;
--	pri_schedule_del(pri, pri->sabme_timer);
--	pri_schedule_del(pri, pri->t203_timer);
--	pri_schedule_del(pri, pri->t200_timer);
--	pri->sabme_timer = 0;
--	pri->t203_timer = 0;
--	pri->t200_timer = 0;
--	pri->busy = 0;
--	pri->solicitfbit = 0;
--	pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
--	pri->retrans = 0;
--	pri->sentrej = 0;
--	
-+	pri->v_s[teio] = 0;
-+	pri->v_a[teio] = 0;
-+	pri->v_r[teio] = 0;
-+	pri->v_na[teio] = 0;
-+	pri->window[teio] = 7;
-+	pri->windowlen[teio] = 0;
-+	pri_schedule_del(pri, pri->sabme_timer[teio]);
-+	pri_schedule_del(pri, pri->t203_timer[teio]);
-+	pri_schedule_del(pri, pri->t200_timer[teio]);
-+	pri->sabme_timer[teio] = 0;
-+	pri->t203_timer[teio] = 0;
-+	pri->t200_timer[teio] = 0;
-+	pri_schedule_del(pri, pri->t202_timer[teio]);
-+	pri->t202_timer[teio] = 0;
-+	pri_schedule_del(pri, pri->t201_timer[teio]);
-+	pri->t201_timer[teio] = 0;
-+	// xxx HMMM?
-+	pri->busy[teio] = 0;
-+	pri->solicitfbit[teio] = 0;
-+	pri->q921_state[teio] = Q921_LINK_CONNECTION_RELEASED;
-+	pri->retrans[teio] = 0;
-+	pri->sentrej[teio] = 0;
-+
- 	/* Discard anything waiting to go out */
--	q921_discard_retransmissions(pri);
-+	q921_discard_retransmissions(pri, tei);
- }
- 
- static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
-@@ -703,12 +1184,16 @@
- 	q921_frame *f;
- 	pri_event *ev;
- 	int sendnow;
-+	int tei;
-+	int res=-1;
-+	int teio=h->h.tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
- 
- 	switch(h->h.data[0] & Q921_FRAMETYPE_MASK) {
- 	case 0:
- 	case 2:
--		if (pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED) {
--			pri_error("!! Got I-frame while link state %d\n", pri->q921_state);
-+		if (pri->q921_state[teio] != Q921_LINK_CONNECTION_ESTABLISHED) {
-+			pri_error("!! Got I-frame while link state %d\n", pri->q921_state[teio]);
- 			return NULL;
- 		}
- 		/* Informational frame */
-@@ -719,7 +1204,7 @@
- 		return q921_handle_iframe(pri, &h->i, len);	
- 		break;
- 	case 1:
--		if (pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED) {
-+		if (pri->q921_state[teio] != Q921_LINK_CONNECTION_ESTABLISHED) {
- 			pri_error("!! Got S-frame while link down\n");
- 			return NULL;
- 		}
-@@ -730,22 +1215,22 @@
- 		switch(h->s.ss) {
- 		case 0:
- 			/* Receiver Ready */
--			pri->busy = 0;
-+			pri->busy[teio] = 0;
- 			/* Acknowledge frames as necessary */
--			ev = q921_ack_rx(pri, h->s.n_r);
-+			ev = q921_ack_rx(pri, h->s.n_r, h->h.tei);
- 			if (ev)
- 				return ev;
- 			if (h->s.p_f) {
- 				/* If it's a p/f one then send back a RR in return with the p/f bit set */
--				if (pri->solicitfbit) {
-+				if (pri->solicitfbit[teio]) {
- 					if (pri->debug & PRI_DEBUG_Q921_STATE) 
- 						pri_message("-- Got RR response to our frame\n");
- 				} else {
- 					if (pri->debug & PRI_DEBUG_Q921_STATE) 
- 						pri_message("-- Unsolicited RR with P/F bit, responding\n");
--						q921_rr(pri, 1, 0);
-+						q921_rr(pri, 1, 0, h->h.tei);
- 				}
--				pri->solicitfbit = 0;
-+				pri->solicitfbit[teio] = 0;
- 			}
- 			break;
-       case 1:
-@@ -754,9 +1239,9 @@
-             pri_message("-- Got receiver not ready\n");
- 	 if(h->s.p_f) {
- 		/* Send RR if poll bit set */
--		q921_rr(pri, h->s.p_f, 0);
-+		q921_rr(pri, h->s.p_f, 0, h->h.tei);
- 	 }
--         pri->busy = 1;
-+         pri->busy[teio] = 1;
-          break;   
-       case 2:
-          /* Just retransmit */
-@@ -764,22 +1249,22 @@
-             pri_message("-- Got reject requesting packet %d...  Retransmitting.\n", h->s.n_r);
-          if (h->s.p_f) {
-             /* If it has the poll bit set, send an appropriate supervisory response */
--            q921_rr(pri, 1, 0);
-+            q921_rr(pri, 1, 0, h->h.tei);
-          }
- 		 sendnow = 0;
-          /* Resend the proper I-frame */
--         for(f=pri->txqueue;f;f=f->next) {
-+         for(f=pri->txqueue[teio];f;f=f->next) {
-                if ((sendnow || (f->h.n_s == h->s.n_r)) && f->transmitted) {
-                      /* Matches the request, or follows in our window, and has
- 					    already been transmitted. */
- 					 sendnow = 1;
- 					 pri_error("!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n", h->s.n_r, f->h.n_s);
--				     f->h.n_r = pri->v_r;
-+				     f->h.n_r = pri->v_r[teio];
-                      q921_transmit(pri, (q921_h *)(&f->h), f->len);
-                }
-          }
-          if (!sendnow) {
--               if (pri->txqueue) {
-+               if (pri->txqueue[teio]) {
-                      /* This should never happen */
- 		     if (!h->s.p_f || h->s.n_r) {
- 			pri_error("!! Got reject for frame %d, but we only have others!\n", h->s.n_r);
-@@ -787,23 +1272,23 @@
-                } else {
-                      /* Hrm, we have nothing to send, but have been REJ'd.  Reset v_a, v_s, etc */
- 				pri_error("!! Got reject for frame %d, but we have nothing -- resetting!\n", h->s.n_r);
--                     pri->v_a = h->s.n_r;
--                     pri->v_s = h->s.n_r;
-+                     pri->v_a[teio] = h->s.n_r;
-+                     pri->v_s[teio] = h->s.n_r;
-                      /* Reset t200 timer if it was somehow going */
--                     if (pri->t200_timer) {
--                           pri_schedule_del(pri, pri->t200_timer);
--                           pri->t200_timer = 0;
-+                     if (pri->t200_timer[teio]) {
-+                           pri_schedule_del(pri, pri->t200_timer[teio]);
-+                           pri->t200_timer[teio] = 0;
-                      }
-                      /* Reset and restart t203 timer */
--                     if (pri->t203_timer)
--                           pri_schedule_del(pri, pri->t203_timer);
--                     pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri);
-+                     if (pri->t203_timer[teio])
-+                           pri_schedule_del(pri, pri->t203_timer[teio]);
-+                     pri->t203_timer[teio] = pri_schedule_event2(pri, T_203, t203_expire, pri, h->h.tei);
-                }
-          }
-          break;
- 		default:
- 			pri_error("!! XXX Unknown Supervisory frame ss=0x%02x,pf=%02xnr=%02x vs=%02x, va=%02x XXX\n", h->s.ss, h->s.p_f, h->s.n_r,
--					pri->v_s, pri->v_a);
-+					pri->v_s[teio], pri->v_a[teio]);
- 		}
- 		break;
- 	case 3:
-@@ -816,12 +1301,13 @@
- 			if (h->u.m2 == 3) {
- 				if (h->u.p_f) {
- 					/* Section 5.7.1 says we should restart on receiving a DM response with the f-bit set to
-+
- 					   one, but we wait T200 first */
- 					if (pri->debug & PRI_DEBUG_Q921_STATE)
- 						pri_message("-- Got DM Mode from peer.\n");
- 					/* Disconnected mode, try again after T200 */
--					ev = q921_dchannel_down(pri);
--					q921_start(pri, 0);
-+					ev = q921_dchannel_down(pri, h->h.tei);
-+					q921_start(pri, 0, h->h.tei);
- 					return ev;
- 						
- 				} else {
-@@ -829,21 +1315,136 @@
- 						pri_message("-- Ignoring unsolicited DM with p/f set to 0\n");
- #if 0
- 					/* Requesting that we start */
--					q921_start(pri, 0);
-+					q921_start(pri, 0, h->h.tei);
- #endif					
- 				}
- 				break;
--			} else if (!h->u.m2) {
--				pri_message("XXX Unnumbered Information not implemented XXX\n");
-+			} else if (h->u.m2 == 0) {
-+				if (h->u.ft == 3) {
-+				    switch (h->u.data[0]) { /* Management Entity Identifier  */
-+					case 0x0f:
-+					/* TEI Procedure */
-+					switch (h->u.data[3]) {
-+					    case Q921_TEI_ID_VERIFY:
-+						if (pri->localtype != BRI_NETWORK_PTMP)
-+						    break;
-+						    if (pri->debug & PRI_DEBUG_Q921_STATE)
-+							pri_message("got TEI verify for TEI = %d\n",h->u.data[4] >> 1);
-+					    break;
-+					    case Q921_TEI_ID_ASSIGNED:
-+						if (pri->localtype != BRI_CPE_PTMP)
-+						    break;
-+						if (pri->tei == (h->u.data[4] >> 1)) {
-+						    // TEI already assgined, CHECK_TEI or REMOVE_TEI
-+						    pri_error("Double assgined TEI!\n");
-+						}
-+						if (pri->ri == ((unsigned short) (h->u.data[1] << 8) + h->u.data[2])) {
-+						    if (pri->t202_timer[0]) {
-+							pri_schedule_del(pri, pri->t202_timer[0]);
-+							pri->t202_timer[0] = 0;
-+						    }
-+						    pri->tei = h->u.data[4] >> 1; 
-+						    pri->ri = 0;
-+						    if (pri->debug & PRI_DEBUG_Q921_STATE)
-+							pri_message("received TEI assign TEI = %d ri=%d\n",pri->tei,(unsigned short) (h->u.data[1] << 8) + h->u.data[2]);
-+						    q921_send_sabme_now(pri, pri->tei);
-+						}
-+					    break;
-+					    case Q921_TEI_ID_REMOVE:
-+					    	if (pri->localtype != BRI_CPE_PTMP)
-+						    break;
-+						if (pri->tei == (h->u.data[4] >> 1)){ 
-+						    if (pri->debug & PRI_DEBUG_Q921_STATE)
-+							pri_message("received TEI remove TEI = %d\n",pri->tei);
-+						    pri->tei = 0;
-+						    pri->ri = 0;
-+						    // get a new TEI
-+						    q921_reset(pri,0);
-+						    q921_send_teireq(pri);
-+						}
-+					    break;
-+					    case Q921_TEI_ID_REQUEST:
-+						if (pri->localtype != BRI_NETWORK_PTMP)
-+						    break;
-+						
-+						tei = h->u.data[4] >> 1;
-+						if (tei != Q921_TEI_GROUP) {
-+						    pri_message("got TEI request for unavailable TEI..\n");
-+						    q921_send_teidenied(pri,((unsigned int)(h->u.data[1] << 8) + h->u.data[2]),h->u.data[4] >> 1);
-+						    break;
-+						}
-+						
-+						for (tei=0;tei<Q921_MAX_TEIS;tei++) {
-+						    if (pri->q921_teis[tei] == 0) {
-+						        pri->q921_teis[tei] = 1;
-+						        break;
-+						    }
-+						}
-+						if (tei < Q921_MAX_TEIS) {
-+						    q921_send_teiassign(pri,((unsigned int)(h->u.data[1] << 8) + h->u.data[2]),tei + Q921_TEI_BASE);
-+						} else {
-+						    // if you plug too many TEs into my bus it's your fault!!!
-+
-+						    pri_error("Whooopsie...general protection fault in module TEI manager.\n");
-+
-+						    // XXX IMPLEMENT TEI RECOVERY!!!
-+						    for (tei=0;tei<Q921_MAX_TEIS;tei++) {
-+							    // XXX ri should be 0?
-+						//	    q921_reset(pri, tei + Q921_TEI_BASE);
-+						//	    q921_send_teiremove(pri,((unsigned int)(h->u.data[1] << 8) + h->u.data[2]),tei + Q921_TEI_BASE);
-+						//    	    pri->q921_teis[tei] = 0;
-+							    // XXX dont forget schedulers, etc...
-+						    }
-+						    q921_send_teidenied(pri,((unsigned int)(h->u.data[1] << 8) + h->u.data[2]),h->u.data[4] >> 1);
-+						}
-+					    break;
-+					    case Q921_TEI_ID_CHK_REQ:
-+						if (pri->localtype != BRI_CPE_PTMP)
-+						    break;
-+						    if ((((h->u.data[4] >> 1) == Q921_TEI_GROUP) || ((h->u.data[4] >> 1) == 0) || ((h->u.data[4] >> 1) == pri->tei)) && (pri->tei > 0)) {
-+							pri_message("received TEI check request for TEI = %d\n",h->u.data[4] >> 1);
-+							q921_send_teichkresp(pri, pri->tei);
-+						    }
-+					    break;
-+					    default:
-+						pri_message("Ri = %d TEI msg = %x TEI = %x\n", (h->u.data[1] << 8) + h->u.data[2], h->u.data[3], h->u.data[4] >> 1);
-+					} 
-+					break;
-+					case Q931_PROTOCOL_DISCRIMINATOR:
-+					    if (pri->localtype == BRI_CPE_PTMP) {
-+					    res = q931_receive(pri, (q931_h *)h->u.data, len-3, h->h.tei);
-+					    /* Send an RR if one wasn't sent already */
-+					    if (pri->v_na[teio] != pri->v_r[teio]) 
-+						q921_rr(pri, 0, 0, pri->tei);
-+					    if (res == -1) {
-+						return NULL;
-+					    }
-+					    if (res & Q931_RES_HAVEEVENT)
-+						return &pri->ev;
-+					    }
-+					break;
-+				    }
-+				} else {
-+				    pri_message("XXX Unnumbered Information not implemented XXX\n");
-+				}
- 			}
- 			break;
- 		case 2:
- 			if (pri->debug &  PRI_DEBUG_Q921_STATE)
- 				pri_message("-- Got Disconnect from peer.\n");
- 			/* Acknowledge */
--			q921_send_ua(pri, h->u.p_f);
--			ev = q921_dchannel_down(pri);
--			q921_start(pri, 0);
-+			q921_send_ua(pri, h->u.p_f, h->h.tei);
-+			ev = q921_dchannel_down(pri, h->h.tei);
-+			if ((pri->localtype == BRI_CPE_PTMP) || (pri->localtype == BRI_CPE)) {
-+			    // keep layer 2 up
-+			    q921_send_sabme(pri, 1, pri->tei);
-+			    if (pri->t203_timer[teio])
-+				pri_schedule_del(pri, pri->t203_timer[teio]);
-+			    pri->t203_timer[teio] = 0;
-+			}
-+			if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)){
-+    			    q921_start(pri, 0, 0);
-+			}
- 			return ev;
- 		case 3:
- 			if (h->u.m2 == 3) {
-@@ -865,17 +1466,17 @@
- 					}
- 				}
- 				/* Send Unnumbered Acknowledgement */
--				q921_send_ua(pri, h->u.p_f);
--				return q921_dchannel_up(pri);
-+				q921_send_ua(pri, h->u.p_f,h->h.tei);
-+				return q921_dchannel_up(pri, h->h.tei);
- 			} else if (h->u.m2 == 0) {
- 					/* It's a UA */
--				if (pri->q921_state == Q921_AWAITING_ESTABLISH) {
-+				if (pri->q921_state[teio] == Q921_AWAITING_ESTABLISH) {
- 					if (pri->debug & PRI_DEBUG_Q921_STATE) {
- 						pri_message("-- Got UA from %s peer  Link up.\n", h->h.c_r ? "cpe" : "network");
- 					}
--					return q921_dchannel_up(pri);
-+					return q921_dchannel_up(pri, h->h.tei);
- 				} else 
--					pri_error("!! Got a UA, but i'm in state %d\n", pri->q921_state);
-+					pri_error("!! Got a UA, but i'm in state %d\n", pri->q921_state[teio]);
- 			} else 
- 				pri_error("!! Weird frame received (m3=3, m2 = %d)\n", h->u.m2);
- 			break;
-@@ -900,19 +1501,43 @@
- 	/* Discard FCS */
- 	len -= 2;
- 	
--	if (!pri->master && pri->debug & PRI_DEBUG_Q921_DUMP)
--		q921_dump(h, len, pri->debug & PRI_DEBUG_Q921_RAW, 0);
--
- 	/* Check some reject conditions -- Start by rejecting improper ea's */
- 	if (h->h.ea1 || !(h->h.ea2))
- 		return NULL;
- 
--	/* Check for broadcasts - not yet handled */
--	if (h->h.tei == Q921_TEI_GROUP)
--		return NULL;
-+	if ((pri->localtype == PRI_CPE) || (pri->localtype == PRI_NETWORK)) {
-+	    /* Check for broadcasts - not yet handled (for PRI) */
-+	    if (h->h.tei == Q921_TEI_GROUP) {
-+ 		return NULL;
-+	    }
-+	} else if ((pri->localtype == BRI_CPE) || (pri->localtype == BRI_CPE_PTMP)) {
-+    	    if ((h->h.tei != pri->tei) && (h->h.tei != Q921_TEI_GROUP)) {
-+	    	return NULL;
-+	    }
-+	} else if (pri->localtype == BRI_NETWORK_PTMP) {
-+	    /* discard anything from a strange TEI (strange == not assigned by us or the broadcast tei) */
-+    	    if (((h->h.tei < Q921_TEI_BASE) || (h->h.tei > Q921_TEI_BASE + Q921_MAX_TEIS)) && (h->h.tei != Q921_TEI_GROUP)) {
-+		if (pri->debug & PRI_DEBUG_Q921_DUMP)
-+		    pri_message("Received a Q.921 message from strange/unassigned TEI %d.\n");
-+	    	return NULL;
-+	    } else {
-+		if ((pri->q921_teis[h->h.tei - Q921_TEI_BASE] != 1) && (h->h.tei != Q921_TEI_GROUP)) {
-+		    if (pri->debug & PRI_DEBUG_Q921_DUMP)
-+			pri_message("Received a Q.921 message from unassigned TEI %d.. Sending DM and assigning.\n", h->h.tei);
-+		    // send DM 
-+		    q921_send_dm(pri, 1, h->h.tei);
-+		    pri->q921_teis[h->h.tei - Q921_TEI_BASE] = 1; 
-+		}
-+	    }
-+	}    
-+
-+	if (!pri->master && pri->debug & PRI_DEBUG_Q921_DUMP)
-+		q921_dump(h, len, pri->debug & PRI_DEBUG_Q921_RAW, 0);
- 
-+	if (pri->localtype != BRI_NETWORK_PTMP) {
- 	/* Check for SAPIs we don't yet handle */
--	if ((h->h.sapi != pri->sapi) || (h->h.tei != pri->tei)) {
-+	    if (((h->h.sapi != pri->sapi) && (h->h.sapi != Q921_SAPI_LAYER2_MANAGEMENT)) || ((h->h.tei != pri->tei) && (h->h.tei != Q921_TEI_GROUP) )) {
-+
- #ifdef PROCESS_SUBCHANNELS
- 		/* If it's not us, try any subchannels we have */
- 		if (pri->subchannel)
-@@ -920,10 +1545,16 @@
- 		else 
- #endif
- 			return NULL;
--
-+    	    }
- 	}
- 	ev = __q921_receive_qualified(pri, h, len);
--	reschedule_t203(pri);
-+
-+// Q921_GROUP_TEI
-+	if (pri->localtype == BRI_CPE_PTMP) {
-+	    reschedule_t203(pri, pri->tei);
-+	} else {
-+	    reschedule_t203(pri, h->h.tei);
-+	}
- 	return ev;
- }
- 
-@@ -937,14 +1568,51 @@
- 	return e;
- }
- 
--void q921_start(struct pri *pri, int now)
-+static void q921_start_tei(struct pri *pri, int tei)
- {
--	if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED) {
--		pri_error("!! q921_start: Not in 'Link Connection Released' state\n");
--		return;
-+    int teio=tei - Q921_TEI_BASE;
-+    if (pri->localtype != BRI_NETWORK_PTMP) { return; }
-+    if (((teio < 0) || (teio > Q921_MAX_TEIS))) { teio=0; }
-+    pri->q921_teis[teio] = 0;
-+    q921_send_teiremove(pri, tei);
-+    q921_reset(pri,tei);
-+}
-+
-+void q921_start(struct pri *pri, int now, int tei)
-+{
-+	int i=0;
-+/*	if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED) {
-+ 		pri_error("!! q921_start: Not in 'Link Connection Released' state\n");
-+ 		return;
-+	} */
-+ 	/* Reset our interface */
-+	if (pri->localtype != BRI_NETWORK_PTMP) {
-+	    q921_reset(pri,0);
-+	}
-+ 	/* Do the SABME XXX Maybe we should implement T_WAIT? XXX */
-+	if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE) || (pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_CPE)) { 
-+	    q921_send_sabme(pri, now, 0);
-+	}
-+	
-+	if (pri->localtype == BRI_NETWORK_PTMP) { 
-+	    if (tei == 0) {
-+		// initial start or complete restart
-+		q921_send_teiremove(pri, 127);
-+		pri->dchanup = 0;
-+		for (i=0;i<Q921_MAX_TEIS;i++) {
-+		    q921_start_tei(pri,Q921_TEI_BASE+i);
-+		}
-+	    } else if ((tei >= Q921_TEI_BASE) && (tei < Q921_TEI_BASE + Q921_MAX_TEIS)){
-+		// restart of a single p2p datalink
-+		q921_start_tei(pri,tei);
-+	    }
-+	} 
-+	if (pri->localtype == BRI_CPE_PTMP) { 
-+	    if (tei == 0) {
-+		/* let's get a TEI */
-+		q921_send_teireq(pri);
-+	    } else {
-+		q921_send_sabme(pri, now, tei);
-+	    }
- 	}
--	/* Reset our interface */
--	q921_reset(pri);
--	/* Do the SABME XXX Maybe we should implement T_WAIT? XXX */
--	q921_send_sabme(pri, now);
- }
-diff -urNad --exclude=CVS --exclude=.svn ./q931.c /tmp/dpep-work.PXlLuK/libpri-1.0.9/q931.c
---- ./q931.c	2005-05-29 16:10:34.000000000 +0100
-+++ /tmp/dpep-work.PXlLuK/libpri-1.0.9/q931.c	2005-07-02 09:24:53.847702976 +0100
-@@ -5,6 +5,8 @@
-  *
-  * Copyright (C) 2001, Linux Support Services, Inc.
-  * All Rights Reserved.
-+ * Copyright (C) 2003,2004,2005 Junghanns.NET GmbH
-+ * Klaus-Peter Junghanns <kpj at junghanns.net>
-  *
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License as published by
-@@ -31,6 +33,7 @@
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
-+#include <time.h>
- 
- #define MAX_MAND_IES 10
- 
-@@ -205,6 +208,13 @@
- #define T_305			30000
- #define T_313			4000
- 
-+struct q921_call {
-+    int tei;	
-+    int proc;		
-+    int channel;	
-+    q921_call *next;
-+};
-+
- struct q931_call {
- 	struct pri *pri;	/* PRI */
- 	int cr;		/* Call Reference */
-@@ -222,7 +232,11 @@
- 	int alive;			/* Whether or not the call is alive */
- 	int acked;			/* Whether setup has been acked or not */
- 	int sendhangupack;		/* Whether or not to send a hangup ack */
--	int proc;			/* Whether we've sent a call proceeding / alerting */
-+	int proc;			/* Whether we've sent a call proceeding */
-+	int alert;			/* Whether we've sent an alerting */
-+
-+	int tei;
-+	q921_call *phones;
- 	
- 	int ri;			/* Restart Indicator (Restart Indicator IE) */
- 
-@@ -240,6 +254,7 @@
- 	int progcode;			/* Progress coding */
- 	int progloc;			/* Progress Location */	
- 	int progress;			/* Progress indicator */
-+	int inband_progress;		/* inband progress available? */
- 	
- 	int notify;			/* Notification */
- 	
-@@ -253,7 +268,10 @@
- 	
- 	int callerplan;
- 	int callerpres;			/* Caller presentation */
--	char callernum[256];	/* Caller */
-+	int callerplanuser;
-+	int callerpresuser;			/* Caller presentation */
-+	char callernum[256];	/* Calling Number (network provided) */
-+	char callernumuser[256];	/* Calling Number, (user provided) */
- 	char callername[256];
- 
- 	int ani2;               /* ANI II */
-@@ -271,9 +289,19 @@
- 	int redirectingreason;	      
- 	char redirectingnum[256];
- 
-+	int t303timer;		
-+	int t303running;		
-+
-         int useruserprotocoldisc;
- 	char useruserinfo[256];
- 	char callingsubaddr[256];	/* Calling parties sub address */
-+	char callid[10];	/* call identity for SUSPEND/RESUME */
-+	char digits[256];	/* additional digits received via info msgs (cpn or keypad) */
-+	char display[256];	/* display ie received in info msgs or for sending */
-+
-+	/* euroisdn facility fun */
-+	int facility; /* FACILTIY received */
-+	int aoc;
- };
- 
- #define FUNC_DUMP(name) void ((name))(int full_ie, q931_ie *ie, int len, char prefix)
-@@ -315,6 +343,11 @@
- 	c->next = NULL;
- 	c->sentchannel = 0;
- 	c->newcall = 1;
-+	c->t303timer = 0;
-+	c->t303running = 0;
-+	c->aoc = 0;
-+	c->phones = NULL;
-+	c->inband_progress = 0;
- 	c->ourcallstate = Q931_CALL_STATE_NULL;
- 	c->peercallstate = Q931_CALL_STATE_NULL;
- }
-@@ -334,16 +367,20 @@
- {	
- 	int x;
- 	int pos=0;
--#ifdef NO_BRI_SUPPORT
-- 	if (!ie->data[0] & 0x20) {
--		pri_error("!! Not PRI type!?\n");
-- 		return -1;
-+	if ((pri->localtype != PRI_CPE) && (pri->localtype != PRI_NETWORK)) {
-+//		pri_error("!! BRI type %d!?\n",ie->data[0] & 0x03);
-+		call->channelno = ie->data[0] & 0x03;
-+		if (call->channelno == 3) {
-+		    call->channelno = -1; // any channel
-+		}
-+ 		return 0;
-  	}
--#endif
- #ifndef NOAUTO_CHANNEL_SELECTION_SUPPORT
--	if ((ie->data[0] & 3) != 1) {
-+	if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
-+	    if ((ie->data[0] & 3) != 1) {
- 		pri_error("!! Unexpected Channel selection %d\n", ie->data[0] & 3);
- 		return -1;
-+	    }
- 	}
- #endif
- 	if (ie->data[0] & 0x08)
-@@ -390,10 +427,16 @@
- {
- 	int pos=0;
- 	/* Start with standard stuff */
--	if (pri->switchtype == PRI_SWITCH_GR303_TMC)
-+	if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
- 		ie->data[pos] = 0x69;
--	else
-+	} else {
-+	    if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
- 		ie->data[pos] = 0xa1;
-+	    } else {
-+		// BRI
-+		ie->data[pos] = 0x80;
-+	    }
-+	}
- 	/* Add exclusive flag if necessary */
- 	if (call->chanflags & FLAG_EXCLUSIVE)
- 		ie->data[pos] |= 0x08;
-@@ -410,6 +453,7 @@
- 	} else
- 		pos++;
- 	if ((call->channelno > -1) || (call->slotmap != -1)) {
-+	    if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
- 		/* We'll have the octet 8.2 and 8.3's present */
- 		ie->data[pos++] = 0x83;
- 		if (call->channelno > -1) {
-@@ -425,11 +469,41 @@
- 			ie->data[pos++] = (call->slotmap & 0xff);
- 			return pos + 2;
- 		}
--	}
-+	    } else {
-+		// BRI
-+		// pri_error("channelno %d, ds1no %d data %d\n",call->channelno,call->ds1no,ie->data[pos-1]);
-+		if (pri->localtype == BRI_CPE_PTMP) {
-+		    if (msgtype == Q931_SETUP) {
-+			// network, you decide!
-+			if (call->channelno > -1) {
-+//		    	    ie->data[pos-1] = 0x83;
-+		    	    ie->data[pos-1] = 0x80 | call->channelno;
-+			}
-+		    } else {
-+			if (call->channelno > -1) {
-+		    	    ie->data[pos-1] |= call->channelno;
-+			}
-+		    }
-+		} else {
-+		    if (call->channelno > -1) {
-+		        ie->data[pos-1] |= call->channelno;
-+		    }
-+		}
-+		return pos + 2;
-+	    }	
-+        } else {
-+	    if (pri->localtype == BRI_CPE) {
-+	        ie->data[pos++] = 0x80 | 3;
-+	        return pos + 2;
-+	    }
-+	}	
- 	if (call->ds1no > 0) {
- 		/* We're done */
- 		return pos + 2;
- 	}
-+	if (msgtype == Q931_RESTART_ACKNOWLEDGE) {
-+	    return 0;
-+	}	
- 	pri_error("!! No channel map, no channel, and no ds1?  What am I supposed to identify?\n");
- 	return -1;
- }
-@@ -765,6 +839,10 @@
- 
- static void q931_get_number(unsigned char *num, int maxlen, unsigned char *src, int len)
- {
-+	if (len < 0) {
-+	    pri_error("q931_get_number received invalid len = %d\n", len);
-+	    return;
-+	}
- 	if (len > maxlen - 1) {
- 		num[0] = 0;
- 		return;
-@@ -776,44 +854,70 @@
- static FUNC_DUMP(dump_called_party_number)
- {
- 	unsigned char cnum[256];
--
--	q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
--	pri_message("%c Called Number (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d) '%s' ]\n",
--		prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f, cnum);
-+  
-+	if (len >= 3) {
-+	    q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
-+ 	    pri_message("%c Called Number (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d) '%s' ]\n",
-+ 		    prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f, cnum);
-+ 	} else {
-+ 	    pri_error("Called Number (len=%2d) too short.\n", len);
-+ 	}
- }
- 
- static FUNC_DUMP(dump_called_party_subaddr)
- {
- 	unsigned char cnum[256];
--	q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
--	pri_message("%c Called Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d) O: %d '%s' ]\n",
-+	if (len >= 3) {
-+	    q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
-+	    pri_message("%c Called Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d) O: %d '%s' ]\n",
- 		prefix, len, ie->data[0] >> 7,
- 		subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
- 		(ie->data[0] & 0x08) >> 3, cnum);
-+	} else {
-+	    pri_error("Called Party Subaddress (len=%2d) too short.\n", len);
-+	}
- }
- 
- static FUNC_DUMP(dump_calling_party_number)
- {
- 	unsigned char cnum[256];
--	if (ie->data[0] & 0x80)
-+	if ((ie->data[0] & 0x80) && (len >= 3)) {
- 		q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
--	else
--		q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
--	pri_message("%c Calling Number (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
--	if (ie->data[0] & 0x80)
-+		pri_message("%c Calling Number (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
- 		pri_message("%c                           Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(0), 0, cnum);
--	else
-+	} else if (len >= 4) {
-+		q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
-+		pri_message("%c Calling Number (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
- 		pri_message("%c                           Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum);
-+	} else {
-+	    pri_error("Calling Party Number (len=%2d) too short.\n", len);
-+	}
- }
- 
- static FUNC_DUMP(dump_calling_party_subaddr)
- {
- 	unsigned char cnum[256];
--	q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
--	pri_message("%c Calling Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d) O: %d '%s' ]\n",
-+	if (len >= 4) {
-+	    q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
-+	    pri_message("%c Calling Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d) O: %d '%s' ]\n",
- 		prefix, len, ie->data[0] >> 7,
- 		subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
- 		(ie->data[0] & 0x08) >> 3, cnum);
-+	} else {
-+	    pri_error("Calling Party Subaddress (len=%2d) too short.\n", len);
-+	}
-+}
-+
-+static FUNC_DUMP(dump_colp)
-+{
-+	unsigned char cnum[256];
-+	if (len >= 4) {
-+	    q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
-+	    pri_message("%c COLP (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
-+	    pri_message("%c                           Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum);
-+	} else {
-+	    pri_error("COLP (len=%2d) too short.\n", len);
-+	}
- }
- 
- static FUNC_DUMP(dump_redirecting_number)
-@@ -862,8 +966,12 @@
- 		}
- 	}
- 	while(!(ie->data[i++]& 0x80));
--	q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
--	pri_message(" '%s' ]\n", cnum);
-+	if ((ie->len - i) >= 0) {
-+	    q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
-+	    pri_message(" '%s' ]\n", cnum);
-+	} else {
-+	    pri_error("Connected Number (len=%2d) too short.\n", len);
-+	}
- }
- 
- 
-@@ -887,7 +995,11 @@
- 		}
- 	}
- 	while(!(ie->data[i++] & 0x80));
--	q931_get_number((unsigned char *) call->redirectingnum, sizeof(call->redirectingnum), ie->data + i, ie->len - i);
-+	if ((ie->len - i) >= 0) {
-+	    q931_get_number((unsigned char *) call->redirectingnum, sizeof(call->redirectingnum), ie->data + i, ie->len - i);
-+	} else {
-+	    pri_error("Redirecting Number (len=%2d) too short.\n", len);
-+	}
- 	return 0;
- }
- 
-@@ -895,25 +1007,41 @@
- static FUNC_DUMP(dump_redirecting_subaddr)
- {
- 	unsigned char cnum[256];
--	q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
--	pri_message("%c Redirecting Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d) O: %d '%s' ]\n",
-+	if (len >= 4) {
-+	    q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
-+	    pri_message("%c Redirecting Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d) O: %d '%s' ]\n",
- 		prefix, len, ie->data[0] >> 7,
- 		subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
- 		(ie->data[0] & 0x08) >> 3, cnum);
-+	} else {
-+	    pri_error("Redirecting Subaddress (len=%2d) too short.\n", len);
-+	}
- }
- 
- static FUNC_RECV(receive_calling_party_subaddr)
- {
- 	/* copy digits to call->callingsubaddr */
-- 	q931_get_number((unsigned char *) call->callingsubaddr, sizeof(call->callingsubaddr), ie->data + 2, len - 4);
-+ 	if (len >= 4) {
-+ 	    q931_get_number((unsigned char *) call->callingsubaddr, sizeof(call->callingsubaddr), ie->data + 2, len - 4);
-+	} else {
-+	    pri_error("Calling Party Subaddress (len=%2d) too short.\n", len);
-+	}
- 	return 0;
- }
- 
- static FUNC_RECV(receive_called_party_number)
- {
--	/* copy digits to call->callednum */
-- 	q931_get_number((unsigned char *) call->callednum, sizeof(call->callednum), ie->data + 1, len - 3);
--	call->calledplan = ie->data[0] & 0x7f;
-+	/* copy digits to call->callednum or call->digits */
-+	if (len >= 3) {
-+	    if (msgtype == Q931_INFORMATION) {
-+ 		q931_get_number((unsigned char *) call->digits, sizeof(call->digits), ie->data + 1, len - 3);
-+	    } else {
-+ 		q931_get_number((unsigned char *) call->callednum, sizeof(call->callednum), ie->data + 1, len - 3);
-+	    }
-+	    call->calledplan = ie->data[0] & 0x7f;
-+	} else {
-+	    pri_error("Called Party Number (len=%2d) too short.\n", len);
-+	}
- 	return 0;
- }
- 
-@@ -929,16 +1057,37 @@
- {
-         int extbit;
-         
--        call->callerplan = ie->data[0] & 0x7f;
--        extbit = (ie->data[0] >> 7) & 0x01;
--
-+	if (strlen(call->callernum)) {
-+ 	    call->callerplanuser = ie->data[0] & 0x7f;
-+	} else {
-+ 	    call->callerplan = ie->data[0] & 0x7f;
-+	}
-+	extbit = (ie->data[0] >> 7) & 0x01;
-         if (extbit) {
--	  q931_get_number((unsigned char *) call->callernum, sizeof(call->callernum), ie->data + 1, len - 3);
--	  call->callerpres = 0; /* PI presentation allowed
--				   SI user-provided, not screened */        
--        } else {
--	  q931_get_number((unsigned char *) call->callernum, sizeof(call->callernum), ie->data + 2, len - 4);
--	  call->callerpres = ie->data[1] & 0x7f;
-+	    if (len >= 3) {
-+		if (strlen(call->callernum)) {
-+		    /* got A NUM already (this is not 100% correct, but the network should do it this way to protect bad implementations */
-+		    q931_get_number(call->callernumuser, sizeof(call->callernumuser), ie->data + 1, len - 3);
-+	    	    call->callerpresuser = 0; /* PI presentation allowed  SI user-provided, not screened */        
-+		} else {
-+ 		     q931_get_number(call->callernum, sizeof(call->callernum), ie->data + 1, len - 3);
-+		    call->callerpres = 0; /* PI presentation allowed  SI user-provided, not screened */        
-+		}
-+	  } else {
-+		pri_error("Calling Party Number (len=%2d) too short.\n", len);
-+	  }
-+	} else {
-+	    if (len >= 4) {
-+		if (strlen(call->callernum)) {
-+	    	    q931_get_number(call->callernumuser, sizeof(call->callernumuser), ie->data + 2, len - 4);
-+		    call->callerpresuser = ie->data[1] & 0x7f;
-+		} else {
-+		    q931_get_number(call->callernum, sizeof(call->callernum), ie->data + 2, len - 4);
-+	    	    call->callerpres = ie->data[1] & 0x7f;
-+		}
-+	    } else {
-+		pri_error("Calling Party Number (len=%2d) too short.\n", len);
-+	     }
-         }
- 	return 0;
- }
-@@ -965,11 +1114,33 @@
- static FUNC_RECV(receive_user_user)
- {        
-         call->useruserprotocoldisc = ie->data[0] & 0xff;
--        if (call->useruserprotocoldisc == 4) /* IA5 */
--          q931_get_number((unsigned char *) call->useruserinfo, sizeof(call->useruserinfo), ie->data + 1, len - 3);
-+	if (call->useruserprotocoldisc == 4) { /* IA5 */
-+	    if (len >= 3) {
-+     		q931_get_number((unsigned char *) call->useruserinfo, sizeof(call->useruserinfo), ie->data + 1, len - 3);
-+	    } else {
-+		pri_error("User-User Information (len=%2d) too short.\n", len);
-+	    }
-+	}
-+	return 0;
-+}
-+
-+static FUNC_RECV(receive_call_identity)
-+{
-+	if (len >= 2) {
-+ 	    q931_get_number(call->callid, sizeof(call->callid), ie->data, len - 2);
-+	} else {
-+	    pri_error("Call Identity (len=%2d) too short.\n", len);
-+	}
- 	return 0;
- }
- 
-+static FUNC_SEND(transmit_call_identity)
-+{
-+	if (strlen(call->callid)) 
-+		memcpy(ie->data , call->callid, strlen(call->callid));
-+	return strlen(call->callednum) + 3;
-+}
-+
- static char *prog2str(int prog)
- {
- 	static struct msgtype progs[] = {
-@@ -1030,21 +1201,40 @@
- 		data++;
- 		len--;
- 	}
--	q931_get_number((unsigned char *) call->callername, sizeof(call->callername), data, len - 2);
-+	if (msgtype == Q931_SETUP) {
-+	    /* we treat display IEs in the SETUP msg as callername */
-+	    if (len >= 2) {
-+		q931_get_number((unsigned char *) call->callername, sizeof(call->callername), data, len - 2);
-+	    } else {
-+		pri_error("Display (len=%2d) too short.\n", len);
-+	    }
-+	} else {
-+	    /* in other msgs we will pass it as text to chan_zap */
-+	    if (len >= 2) {
-+		q931_get_number((unsigned char *) call->display, sizeof(call->display), data, len - 2);
-+	    } else {
-+		pri_error("Display (len=%2d) too short.\n", len);
-+	    }
-+	}
- 	return 0;
- }
- 
- static FUNC_SEND(transmit_display)
- {
- 	int i;
--	if ((pri->switchtype != PRI_SWITCH_NI1) && strlen(call->callername)) {
-+	if ((pri->switchtype != PRI_SWITCH_NI1) && strlen(call->callername) && (pri->localtype != BRI_CPE) && (pri->localtype != BRI_CPE_PTMP) && (pri->localtype != PRI_CPE)) {
- 		i = 0;
- 		if(pri->switchtype != PRI_SWITCH_EUROISDN_E1) {
- 			ie->data[0] = 0xb1;
- 			++i;
- 		}
--		memcpy(ie->data + i, call->callername, strlen(call->callername));
--		return 2 + i + strlen(call->callername);
-+	    	if (msgtype == Q931_SETUP_ACKNOWLEDGE) {
-+		    memcpy(ie->data + i, call->display, strlen(call->display));
-+		    return 2 + i + strlen(call->display);
-+	 	} else {
-+		    memcpy(ie->data + i, call->callername, strlen(call->callername));
-+		    return 2 + i + strlen(call->callername);
-+	    	}
- 	}
- 	return 0;
- }
-@@ -1054,19 +1244,113 @@
- 	call->progloc = ie->data[0] & 0xf;
- 	call->progcode = (ie->data[0] & 0x60) >> 5;
- 	call->progress = (ie->data[1] & 0x7f);
-+	if (call->progress & 0x08) {
-+	    call->inband_progress = 1;
-+	}
- 	return 0;
- }
- 
- static FUNC_RECV(receive_facility)
- {
--	if (ie->len < 14) {
--		pri_error("!! Facility message shorter than 14 bytes\n");
-+	unsigned char cpt_tag, cp_len, invoke_id_tag, invoke_id_len, operation_value_len, operation_value_tag;
-+	unsigned char arg_len = 0;
-+	unsigned char pos = 0;
-+	short invoke_id = 0, operation_value = 0;
-+	if ((ie->data[pos++] & 0x1F) == 0x11) {
-+	    /* service discriminator == supplementary services */
-+	    cpt_tag = ie->data[pos++] & 0x1F;
-+	    cp_len = ie->data[pos++];
-+	    switch (cpt_tag) {
-+		case 1: /* invoke */
-+		        invoke_id_tag = ie->data[pos++];
-+			if (invoke_id_tag != 0x02) {
-+			//    pri_error("invoke id tag != 0x02\n");
-+			    break;
-+			}
-+			invoke_id_len = ie->data[pos++]; // 4
-+		        while (invoke_id_len > 0) {
-+		    	    invoke_id = (invoke_id << 8) | (ie->data[pos++] & 0xFF);
-+			    invoke_id_len--;
-+			}
-+			operation_value_tag = ie->data[pos++];
-+			if (operation_value_tag != 0x02) {
-+			//    pri_error("operation value tag != 0x02\n");
-+			    break;
-+			}
-+			operation_value_len = ie->data[pos++];
-+		        while (operation_value_len > 0) {
-+		    	    operation_value = (operation_value << 8) | (ie->data[pos++] & 0xFF);
-+			    operation_value_len--;
-+			}
-+			arg_len = ie->len - pos;
-+			switch (operation_value) {
-+			    case 0x06:	/* ECT execute */
-+					call->facility = operation_value;
-+					break;
-+			    case 0x0D:	/* call deflection */
-+			    		call->facility = operation_value;
-+					/* dirty hack! */
-+					arg_len -= 6;
-+					if (arg_len > 0) {
-+					    pos += 6;
-+ 					    q931_get_number(call->redirectingnum, sizeof(call->redirectingnum), ie->data + pos, arg_len);
-+					}
-+					/* now retrieve the number */
-+					break;
-+			    case 0x22:  /* AOC-D */
-+					break;
-+			    case 0x24:  /* AOC-E */
-+					break;
-+			}
-+		        break;
-+		case 2: /* return result */
-+			break;
-+	        case 3: /* return error */
-+ 			break;
-+		case 4: /* reject */
-+			break;
-+	    }
-+	} else {
-+	    /* OLD DIRTY ULAW HACK */
-+	    if (ie->len < 14) {
-+  		pri_error("!! Facility message shorter than 14 bytes\n");
- 		return 0;
-+	    }
-+	    if (ie->data[13] + 14 == ie->len) {
-+		q931_get_number(call->callername, sizeof(call->callername) - 1, ie->data + 14, ie->len - 14);
-+	    } 
-+	    call->facility = 0x0;
- 	}
--	if (ie->data[13] + 14 == ie->len) {
--		q931_get_number((unsigned char *) call->callername, sizeof(call->callername) - 1, ie->data + 14, ie->len - 14);
--	} 
--	return 0;
-+  	return 0;
-+}
-+
-+static FUNC_SEND(transmit_facility)
-+{
-+	int i = 0;
-+	return i;
-+	if (call->aoc && (pri->switchtype == PRI_SWITCH_EUROISDN_E1) && ((pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_NETWORK_PTMP) || (pri->localtype == PRI_NETWORK))) {
-+	    ie->data[0] = 0x90;  /* PP remote operations */
-+	    ie->data[i++] = 0x00; /* component tag */
-+	    ie->data[i++] = 0x02; /* invoke id tag */
-+	    ie->data[i++] = 0x02; /* invoke id len */
-+	    ie->data[i++] = 0x34; /* invoke id */
-+	    ie->data[i++] = 0x56; /* invoke id */
-+	    ie->data[i++] = 0x02; /* operation value tag */
-+	    ie->data[i++] = 0x01; /* operation value len */
-+	    switch (msgtype) {
-+		case Q931_SETUP:
-+		    ie->data[i++] = 0x26; /* operation value AOC-S */
-+		    break;
-+		case Q931_DISCONNECT:
-+		    ie->data[i++] = 0x24; /* operation value AOC-E */
-+		    break;
-+		default:
-+		    ie->data[i++] = 0x22; /* operation value AOC-D */
-+		    break;
-+	    }
-+	    // ARGUMENTS!	
-+	}
-+//	return 2 + i;
- }
- 
- static FUNC_SEND(transmit_progress_indicator)
-@@ -1075,6 +1359,7 @@
- 	if (!pri->subchannel && (call->progress > 0)) {
- 		ie->data[0] = 0x80 | (call->progcode << 5)  | (call->progloc);
- 		ie->data[1] = 0x80 | (call->progress);
-+//		ie->data[1] = 0x88;
- 		return 4;
- 	} else {
- 		/* Leave off */
-@@ -1156,6 +1441,26 @@
- 	pri_message(" ]\n");
- }
- 
-+static FUNC_RECV(receive_time_date)
-+{
-+    return 0;
-+}
-+
-+static FUNC_SEND(transmit_time_date) {
-+    time_t now;
-+    struct tm *timedate;
-+    time(&now);
-+    timedate = localtime(&now);
-+    ie->data[0] = timedate->tm_year - 100; // 1900+
-+    ie->data[1] = timedate->tm_mon + 1;
-+    ie->data[2] = timedate->tm_mday;
-+    ie->data[3] = timedate->tm_hour;
-+    ie->data[4] = timedate->tm_min;
-+    return 7;
-+}
-+
-+
-+
- static FUNC_DUMP(dump_display)
- {
- 	int x, y;
-@@ -1175,6 +1480,32 @@
- 	}
- }
- 
-+static FUNC_RECV(receive_keypad_facility)
-+{
-+	/* copy digits to call->callednum or call->digits */
-+	if (msgtype == Q931_SETUP) {
-+	    if (len >= 2) {
-+ 		q931_get_number(call->digits, sizeof(call->digits), ie->data , len - 2);
-+	    } else {
-+		pri_error("Keypad facility (len=%2d) too short.\n", len);
-+	    }
-+	} else {
-+	    // XXX we assume 1 byte keypad
-+	    call->digits[0] = ie->data[0] & 0x7f;
-+	    call->digits[1] = '\0';
-+	}
-+	return 0;
-+}
-+
-+static FUNC_DUMP(dump_keypad_facility)
-+{
-+	int x;
-+	pri_message("%c Keypad Facility (len=%2d) [ ", prefix, len);
-+	for (x=0;x<ie->len;x++) 
-+		pri_message("%c", ie->data[x] & 0x7f);
-+	pri_message(" ]\n");
-+}
-+
- static void dump_ie_data(unsigned char *c, int len)
- {
- 	char tmp[1024] = "";
-@@ -1432,7 +1763,53 @@
- #endif
- 	return 0;
- }
-+/*
-+static int transmit_special(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
-+{
-+// 1C 02 95 81 97 02 02 32 39 04 01 80 05 02 01 5B
-+	ie->data[0] = 0x1c;
-+	ie->data[1] = 0x02;
-+	ie->data[2] = 0x95;
-+	ie->data[3] = 0x81;
-+	ie->data[4] = 0x97;
-+	ie->data[5] = 0x02;
-+	ie->data[6] = 0x02;
-+	ie->data[7] = 0x32;
- 
-+	ie->data[8] = 0x39;
-+	ie->data[9] = 0x04;
-+	ie->data[10] = 0x01;
-+	ie->data[11] = 0x80;
-+	ie->data[12] = 0x05;
-+	ie->data[13] = 0x02;
-+	ie->data[14] = 0x01;
-+	ie->data[15] = 0x5B;
-+
-+
-+	return 17;
-+}
-+
-+static int receive_special(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len) 
-+{
-+    return 0;
-+}
-+
-+static void dump_special(q931_ie *ie, int len, char prefix)
-+{
-+	int x=0;
-+	pri_message("%c SPECIAL (len=%2d) [ ", prefix, ie->len);
-+	for (x=0;x<ie->len;x++) 
-+		pri_message("%2x ", ie->data[x]);
-+	pri_message("]\n");
-+}
-+
-+static int transmit_my_paging_signal(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
-+{
-+	ie->data[0] = 0x47;
-+	return 3;
-+}
-+
-+*/
- struct ie ies[] = {
- 	/* Codeset 0 - Common */
- 	{ NATIONAL_CHANGE_STATUS, "Change Status" },
-@@ -1461,20 +1838,21 @@
- 	{ Q931_LOW_LAYER_COMPAT, "Low-layer Compatibility" },
- 	{ Q931_HIGH_LAYER_COMPAT, "High-layer Compatibility" },
- 	{ Q931_PACKET_SIZE, "Packet Size" },
--	{ Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility },
-+	{ Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility, transmit_facility },
- 	{ Q931_IE_REDIRECTION_NUMBER, "Redirection Number" },
- 	{ Q931_IE_REDIRECTION_SUBADDR, "Redirection Subaddress" },
- 	{ Q931_IE_FEATURE_ACTIVATE, "Feature Activation" },
- 	{ Q931_IE_INFO_REQUEST, "Feature Request" },
- 	{ Q931_IE_FEATURE_IND, "Feature Indication" },
- 	{ Q931_IE_SEGMENTED_MSG, "Segmented Message" },
--	{ Q931_IE_CALL_IDENTITY, "Call Identity", dump_call_identity },
-+	{ Q931_IE_CALL_IDENTITY, "Call Identity", dump_call_identity, receive_call_identity, transmit_call_identity },
- 	{ Q931_IE_ENDPOINT_ID, "Endpoint Identification" },
- 	{ Q931_IE_NOTIFY_IND, "Notification Indicator", dump_notify, receive_notify, transmit_notify },
- 	{ Q931_DISPLAY, "Display", dump_display, receive_display, transmit_display },
--	{ Q931_IE_TIME_DATE, "Date/Time", dump_time_date },
--	{ Q931_IE_KEYPAD_FACILITY, "Keypad Facility" },
--	{ Q931_IE_SIGNAL, "Signal" },
-+	{ Q931_IE_TIME_DATE, "Date/Time", dump_time_date, receive_time_date, transmit_time_date },
-+	{ Q931_IE_KEYPAD_FACILITY, "Keypad Facility" , dump_keypad_facility, receive_keypad_facility},
-+	{ Q931_IE_SIGNAL, "Signal"},
-+//	{ Q931_IE_SIGNAL, "Signal",dump_special, receive_special, transmit_my_paging_signal},
- 	{ Q931_IE_SWITCHHOOK, "Switch-hook" },
- 	{ Q931_IE_USER_USER, "User-User", dump_user_user, receive_user_user },
- 	{ Q931_IE_ESCAPE_FOR_EXT, "Escape for Extension" },
-@@ -1485,6 +1863,7 @@
- 	{ Q931_IE_ORIGINAL_CALLED_NUMBER, "Original Called Number" },
- 	{ Q931_IE_USER_USER_FACILITY, "User-User Facility" },
- 	{ Q931_IE_UPDATE, "Update" },
-+	{ Q931_COLP, "Connect Line ID Presentation", dump_colp},
- 	{ Q931_SENDING_COMPLETE, "Sending Complete", dump_sending_complete, receive_sending_complete, transmit_sending_complete },
- 	/* Codeset 6 - Network specific */
- 	{ Q931_IE_FACILITY | Q931_CODESET(6), "Facility", dump_facility, receive_facility },
-@@ -1548,7 +1927,7 @@
- {
- 	if ((ie->ie & 0x80) != 0)
- 		return 1;
--	else
-+	else 
- 		return 2 + ie->len;
- }
- 
-@@ -1578,13 +1957,13 @@
- 			break;
- 		case 1:
- 			cr = h->crv[0];
--			if (cr & 0x80) {
-+		/*	if (cr & 0x80) {
- 				cr &= ~0x80;
- 				cr |= 0x8000;
--			}
-+			} */
- 			break;
--		default:
--			pri_error("Call Reference Length not supported: %d\n", h->crlen);
-+		// default:
-+		//	pri_error("Call Reference Length not supported: %d\n", h->crlen);
- 	}
- 	return cr;
- }
-@@ -1595,6 +1974,11 @@
- 	int full_ie = Q931_FULL_IE(codeset, ie->ie);
- 	int base_ie;
- 
-+	if (ielen(ie) > Q931_IE_MAX_LEN) {
-+	    pri_error("!! %c Invalid IE length %d (len = %d)\n", prefix, base_ie, ielen(ie));
-+	    return;
-+	}
-+
- 	pri_message("%c [", prefix);
- 	pri_message("%02x", ie->ie);
- 	if (!(ie->ie & 0x80)) {
-@@ -1622,14 +2006,46 @@
- 	pri_error("!! %c Unknown IE %d (len = %d)\n", prefix, base_ie, ielen(ie));
- }
- 
--static q931_call *q931_getcall(struct pri *pri, int cr)
-+static q921_call *q921_getcall(struct pri *pri, struct q931_call *c, int tei)
-+{
-+	q921_call *cur;
-+	cur = c->phones;
-+	while(cur) {
-+	    if (cur->tei == tei) {
-+		    return cur;
-+	    } 
-+	    cur = cur->next;
-+	}
-+	/* No call exists, make a new one */
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+		pri_message("-- Making new q921 call for cref %d tei %d\n", c->cr, tei);
-+	cur = malloc(sizeof(struct q921_call));
-+	memset(cur, 0, sizeof(cur));
-+	cur->tei = tei;
-+	cur->proc = 0;
-+	cur->channel = -1;
-+	cur->next = c->phones;
-+	c->phones = cur;
-+	return cur;
-+}
-+
-+static q931_call *q931_getcall(struct pri *pri, int cr, int tei)
- {
- 	q931_call *cur, *prev;
- 	cur = *pri->callpool;
- 	prev = NULL;
- 	while(cur) {
--		if (cur->cr == cr)
--			return cur;
-+		if ((pri->localtype == BRI_NETWORK_PTMP) && (tei >= 0)) {
-+		    // hmm...ok, we might be the 1st responding to the setup
-+		    // or it is really our call
-+		    if ((cur->cr == cr) && ((cur->tei == tei) || (cur->tei == 127)))
-+			    return cur;
-+	    	    // or we might not be the 1st responding, then we need to clone
-+		    // the call struct to hangup properly
-+		} else {
-+		    if (cur->cr == cr)
-+			    return cur;
-+		}
- 		prev = cur;
- 		cur = cur->next;
- 	}
-@@ -1642,6 +2058,7 @@
- 		/* Call reference */
- 		cur->cr = cr;
- 		cur->pri = pri;
-+		cur->tei = tei;
- 		/* Append to end of list */
- 		if (prev)
- 			prev->next = cur;
-@@ -1657,24 +2074,42 @@
- 	do {
- 		cur = *pri->callpool;
- 		pri->cref++;
--		if (pri->cref > 32767)
--			pri->cref = 1;
-+		if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
-+		    if (pri->cref > 32767)
-+			    pri->cref = 1;
-+		} else {
-+		    // BRI
-+		    if (pri->cref > 255)
-+			    pri->cref = 1;
-+		}
- 		while(cur) {
--			if (cur->cr == (0x8000 | pri->cref))
--				break;
-+			if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
-+			    if (cur->cr == (0x8000 | pri->cref))
-+				    break;
-+			} else {
-+			    // BRIs have only 1 bye cref
-+			    if (cur->cr == (0x80 | pri->cref))
-+				    break;
-+			}
- 			cur = cur->next;
- 		}
- 	} while(cur);
--	return q931_getcall(pri, pri->cref | 0x8000);
-+	if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
-+	    return q931_getcall(pri, pri->cref | 0x8000, 0);
-+	} else {
-+	    // BRI
-+	    return q931_getcall(pri, pri->cref | 0x80, 0);
-+	}
- }
- 
--static void q931_destroy(struct pri *pri, int cr, q931_call *c)
-+static void q931_destroy(struct pri *pri, int cr, q931_call *c, int tei)
- {
- 	q931_call *cur, *prev;
- 	prev = NULL;
- 	cur = *pri->callpool;
- 	while(cur) {
--		if ((c && (cur == c)) || (!c && (cur->cr == cr))) {
-+//		if ((c && (cur == c)) || (!c && (cur->cr == cr))) {
-+		if ((c && (cur == c)) || (!c && ((cur->cr == cr) && ((pri->localtype != BRI_NETWORK_PTMP) || (cur->tei == tei))))) {
- 			if (prev)
- 				prev->next = cur->next;
- 			else
-@@ -1683,6 +2118,8 @@
- 				pri_message("NEW_HANGUP DEBUG: Destroying the call, ourstate %s, peerstate %s\n",callstate2str(cur->ourcallstate),callstate2str(cur->peercallstate));
- 			if (cur->retranstimer)
- 				pri_schedule_del(pri, cur->retranstimer);
-+			if (cur->t303timer)
-+				pri_schedule_del(pri, cur->t303timer);
- 			free(cur);
- 			return;
- 		}
-@@ -1692,16 +2129,17 @@
- 	pri_error("Can't destroy call %d!\n", cr);
- }
- 
--static void q931_destroycall(struct pri *pri, int cr)
-+
-+static void q931_destroycall(struct pri *pri, int cr, int tei)
- {
--	return q931_destroy(pri, cr, NULL);
-+	return q931_destroy(pri, cr, NULL, tei);
- }
- 
- 
- void __q931_destroycall(struct pri *pri, q931_call *c) 
- {
- 	if (pri && c)
--		q931_destroy(pri,0, c);
-+		q931_destroy(pri,0, c, c->tei);
- 	return;
- }
- 
-@@ -1799,6 +2237,10 @@
- {
- 	unsigned int x;
- 	int full_ie = Q931_FULL_IE(codeset, ie->ie);
-+	if (ielen(ie) > Q931_IE_MAX_LEN) {
-+	    pri_error("!! Invalid IE length %d (len = %d)\n", full_ie, ielen(ie));
-+	    return -1;
-+	}
- 	if (pri->debug & PRI_DEBUG_Q931_STATE)
- 		pri_message("-- Processing IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));
- 	for (x=0;x<sizeof(ies) / sizeof(ies[0]);x++) {
-@@ -1816,21 +2258,36 @@
- 	return -1;
- }
- 
--static void init_header(struct pri *pri, q931_call *call, unsigned char *buf, q931_h **hb, q931_mh **mhb, int *len)
-+static void init_header(struct pri *pri, q931_call *call, unsigned char *buf, q931_h **hb, q931_mh **mhb, int *len, int briflag)
- {
- 	/* Returns header and message header and modifies length in place */
-+	q931_mh *mh;
- 	q931_h *h = (q931_h *)buf;
--	q931_mh * mh = (q931_mh *)(h->contents + 2);
- 	h->pd = pri->protodisc;
- 	h->x0 = 0;		/* Reserved 0 */
--	h->crlen = 2;	/* Two bytes of Call Reference.  Invert the top bit to make it from our sense */
--	if (call->cr || call->forceinvert) {
-+
-+	if (briflag == 1) {
-+	    mh = (q931_mh *)(h->contents + 1);
-+ 	    h->crlen = 1;	/* One bytes of Call Reference.  Invert the top bit to make it from our sense */
-+	    if (call->cr || call->forceinvert) {
-+		h->crv[0] = (call->cr ^ 0x80);
-+	    } else {
-+		/* Unless of course this has no call reference */
-+		h->crv[0] = 0;
-+	    }
-+	    *len -= 4;
-+	} else {
-+	    mh = (q931_mh *)(h->contents + 2);
-+ 	    h->crlen = 2;	/* Two bytes of Call Reference.  Invert the top bit to make it from our sense */
-+	    if (call->cr || call->forceinvert) {
- 		h->crv[0] = ((call->cr ^ 0x8000) & 0xff00) >> 8;
- 		h->crv[1] = (call->cr & 0xff);
--	} else {
-+	    } else {
- 		/* Unless of course this has no call reference */
- 		h->crv[0] = 0;
- 		h->crv[1] = 0;
-+	    }
-+	    *len -= 5;
- 	}
- 	if (pri->subchannel) {
- 		/* On GR-303, top bit is always 0 */
-@@ -1839,13 +2296,37 @@
- 	mh->f = 0;
- 	*hb = h;
- 	*mhb = mh;
--	*len -= 5;
--	
- }
- 
--static int q931_xmit(struct pri *pri, q931_h *h, int len, int cr)
-+static int q931_xmit(struct pri *pri, q931_h *h, int len, int cr, int tei)
- {
--	q921_transmit_iframe(pri, h, len, cr);
-+	q931_mh *mh;
-+	if (pri->localtype == BRI_NETWORK_PTMP) {
-+	    mh = (q931_mh *)(h->contents + 1);
-+	    if (mh->msg == Q931_SETUP) {
-+		q921_transmit_uframe(pri, h, len, cr, tei);
-+	    } else {
-+		q921_transmit_iframe(pri, h, len, cr, tei);
-+	    }
-+	} else if (pri->localtype == BRI_CPE_PTMP) {
-+	    mh = (q931_mh *)(h->contents + 1);
-+	    if ((pri->state == Q921_LINK_CONNECTION_RELEASED) && (mh->msg == Q931_SETUP)) {
-+	        // no MFE
-+	/*        if (pri->tei == 0) {
-+		    pri_error("no tei\n");
-+		    q921_send_teireq(pri);
-+		} else {
-+		    q921_send_sabme(pri,1,pri->tei);
-+		    pri->q921_state[tei - Q921_TEI_BASE] = Q921_AWAITING_ESTABLISH;
-+		}
-+		q921_reset(pri, pri->tei); */
-+	    }
-+	    // XXX D    IRTY!, we rely on the fact that the L3 frames will be retransmitted
-+	    // if they dont get ACKed. however this is supposed to work.
-+	     q921_transmit_iframe(pri, h, len, cr, pri->tei);
-+	} else {
-+	    q921_transmit_iframe(pri, h, len, cr, tei);
-+	}
- 	/* The transmit operation might dump the q921 header, so logging the q931
- 	   message body after the transmit puts the sections of the message in the
- 	   right order in the log */
-@@ -1869,7 +2350,11 @@
- 	int codeset;
- 	memset(buf, 0, sizeof(buf));
- 	len = sizeof(buf);
--	init_header(pri, c, buf, &h, &mh, &len);
-+	if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
-+	    init_header(pri, c, buf, &h, &mh, &len, 0);
-+	} else {
-+	    init_header(pri, c, buf, &h, &mh, &len, 1);
-+	}
- 	mh->msg = msgtype;
- 	x=0;
- 	codeset = 0;
-@@ -1885,11 +2370,33 @@
- 	}
- 	/* Invert the logic */
- 	len = sizeof(buf) - len;
--	q931_xmit(pri, h, len, 1);
-+	if (pri->localtype == BRI_CPE_PTMP) {
-+	    q931_xmit(pri, h, len, 1, pri->tei);
-+	} else {
-+	    q931_xmit(pri, h, len, 1, c->tei);
-+	}
- 	c->acked = 1;
- 	return 0;
- }
- 
-+static int facility_ies[] = { Q931_IE_FACILITY, -1 };
-+
-+int q931_facility(struct pri *pri, q931_call *c, int operation, char *arguments)
-+{
-+	switch (operation) {
-+	    case 0x26:	c->aoc = 1;
-+			break;
-+	    case 0x24:	c->aoc = 1;
-+			break;
-+	    case 0x22:	c->aoc = 1;
-+			break;
-+	    default:
-+		return -1;
-+	}
-+	return send_message(pri, c, Q931_FACILITY, facility_ies);
-+}
-+
-+
- static int status_ies[] = { Q931_CAUSE, Q931_CALL_STATE, -1 };
- 
- static int q931_status(struct pri *pri, q931_call *c, int cause)
-@@ -1927,12 +2434,42 @@
- 	return send_message(pri, c, Q931_INFORMATION, information_ies);
- }
- 
-+static int information_display_ies[] = { Q931_DISPLAY, -1 };
-+
-+int q931_information_display(struct pri *pri, q931_call *c, char *display)
-+{
-+	int res=0;
-+	char temp[256];
-+	if (!display) return -1;
-+	strncpy(temp, c->callername, sizeof(temp));
-+	strncpy(c->callername, display, sizeof(c->callername));
-+	res = send_message(pri, c, Q931_INFORMATION, information_display_ies);
-+	strncpy(c->callername, temp, sizeof(c->callername));
-+	return res;
-+}
-+
-+int q931_add_display(struct pri *pri, q931_call *c, char *display)
-+{
-+	strncpy(c->display, display, sizeof(c->display));
-+	return 0;
-+}
-+
-+/* static int information_special_ies[] = { Q931_IE_SPECIAL, -1 };
-+static int q931_information_special(struct pri *pri, q931_call *c)
-+{
-+	return send_message(pri, c, Q931_FACILITY, information_special_ies);
-+}
-+*/
-+
-+
- static int restart_ack_ies[] = { Q931_CHANNEL_IDENT, Q931_RESTART_INDICATOR, -1 };
- 
- static int restart_ack(struct pri *pri, q931_call *c)
- {
- 	c->ourcallstate = Q931_CALL_STATE_NULL;
- 	c->peercallstate = Q931_CALL_STATE_NULL;
-+        c->chanflags &= ~FLAG_PREFERRED;
-+        c->chanflags |= FLAG_EXCLUSIVE;
- 	return send_message(pri, c, Q931_RESTART_ACKNOWLEDGE, restart_ack_ies);
- }
- 
-@@ -2003,8 +2540,14 @@
- static int alerting_ies[] = { -1 };
- #endif
- 
-+// static int alerting_BRI_ies[] = { -1 };
-+
- int q931_alerting(struct pri *pri, q931_call *c, int channel, int info)
- {
-+	// never send two ALERTINGs!
-+	if (c->alert > 0) return 0;		
-+	// XXX novo vox hack
-+//	if ((!c->proc) && (pri->localtype != BRI_CPE_PTMP))
- 	if (!c->proc) 
- 		q931_call_proceeding(pri, c, channel, 0);
- 	if (info) {
-@@ -2015,11 +2558,126 @@
- 		c->progress = -1;
- 	c->ourcallstate = Q931_CALL_STATE_CALL_RECEIVED;
- 	c->peercallstate = Q931_CALL_STATE_CALL_DELIVERED;
-+	c->alert = 1;
- 	c->alive = 1;
- 	return send_message(pri, c, Q931_ALERTING, alerting_ies);
-+/*	if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
-+	    return send_message(pri, c, Q931_ALERTING, alerting_ies);
-+	} else {
-+	    if ((pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_NETWORK_PTMP)) {
-+		return send_message(pri, c, Q931_ALERTING, alerting_ies);
-+    	    } else {
-+		// no PROGRESS_IND for BRI please
-+		return send_message(pri, c, Q931_ALERTING, alerting_BRI_ies);
-+	    }
-+	} */
- }
- 
--static int connect_ies[] = {  Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, -1 };
-+static int hold_acknowledge_ies[] = { -1 };
-+
-+int q931_hold_acknowledge(struct pri *pri, q931_call *c)
-+{
-+	return send_message(pri, c, Q931_HOLD_ACKNOWLEDGE, hold_acknowledge_ies);
-+}
-+
-+static int hold_reject_ies[] = { Q931_CAUSE, -1 };
-+
-+int q931_hold_reject(struct pri *pri, q931_call *c)
-+{
-+	c->cause = 12;
-+	c->causecode = CODE_CCITT;
-+	c->causeloc = LOC_PRIV_NET_LOCAL_USER;
-+	return send_message(pri, c, Q931_HOLD_REJECT, hold_reject_ies);
-+}
-+
-+static int retrieve_acknowledge_ies[] = { Q931_CHANNEL_IDENT, -1 };
-+
-+int q931_retrieve_acknowledge(struct pri *pri, q931_call *c, int channel)
-+{
-+	if (channel)
-+		c->channelno = channel;
-+	c->chanflags &= ~FLAG_PREFERRED;
-+	c->chanflags |= FLAG_EXCLUSIVE;
-+	return send_message(pri, c, Q931_RETRIEVE_ACKNOWLEDGE, retrieve_acknowledge_ies);
-+}
-+
-+static int retrieve_reject_ies[] = { -1 };
-+
-+int q931_retrieve_reject(struct pri *pri, q931_call *c)
-+{
-+	return send_message(pri, c, Q931_RETRIEVE_REJECT, retrieve_reject_ies);
-+}
-+
-+static int suspend_acknowledge_ies[] = { Q931_DISPLAY, -1 };
-+
-+int q931_suspend_acknowledge(struct pri *pri, q931_call *c, char *display)
-+{
-+	char tempcallername[256];
-+	int res;
-+	c->ourcallstate = Q931_CALL_STATE_NULL;
-+	c->peercallstate = Q931_CALL_STATE_NULL;
-+	strncpy(tempcallername,c->callername,sizeof(tempcallername));
-+	strncpy(c->callername,display,sizeof(c->callername));
-+	res = send_message(pri, c, Q931_SUSPEND_ACKNOWLEDGE, suspend_acknowledge_ies);
-+	strncpy(c->callername,tempcallername,sizeof(c->callername));
-+	return res;
-+}
-+
-+static int suspend_reject_ies[] = { Q931_DISPLAY, Q931_CAUSE, -1 };
-+
-+int q931_suspend_reject(struct pri *pri, q931_call *c, char *display)
-+{
-+	char tempcallername[256];
-+	int res;
-+	strncpy(tempcallername,c->callername,sizeof(tempcallername));
-+	strncpy(c->callername,display,sizeof(c->callername));
-+	c->cause = 12;
-+	c->causecode = CODE_CCITT;
-+	c->causeloc = LOC_PRIV_NET_LOCAL_USER;
-+	res = send_message(pri, c, Q931_SUSPEND_REJECT, suspend_reject_ies);
-+	strncpy(c->callername,tempcallername,sizeof(c->callername));
-+	return res;
-+}
-+
-+static int resume_reject_ies[] = { Q931_CAUSE, Q931_DISPLAY,  -1 };
-+
-+int q931_resume_reject(struct pri *pri, q931_call *c, char *display)
-+{
-+	char tempcallername[256];
-+	int res;
-+	c->cause = 12;
-+	c->causecode = CODE_CCITT;
-+	c->causeloc = LOC_PRIV_NET_LOCAL_USER;
-+	strncpy(tempcallername,c->callername,sizeof(tempcallername));
-+	strncpy(c->callername,display,sizeof(c->callername));
-+	res = send_message(pri, c, Q931_RESUME_REJECT, resume_reject_ies);
-+	strncpy(c->callername,tempcallername,sizeof(c->callername));
-+	return res;
-+}
-+
-+static int resume_acknowledge_ies[] = { Q931_CHANNEL_IDENT, Q931_DISPLAY,  -1 };
-+
-+int q931_resume_acknowledge(struct pri *pri, q931_call *c, int channel, char *display)
-+{
-+	char tempcallername[256];
-+	int res;
-+	if (channel)
-+		c->channelno = channel;
-+	c->chanflags &= ~FLAG_PREFERRED;
-+	c->chanflags |= FLAG_EXCLUSIVE;
-+	c->alive = 1;
-+	c->ourcallstate = Q931_CALL_STATE_ACTIVE;
-+	c->peercallstate = Q931_CALL_STATE_ACTIVE;
-+	strncpy(tempcallername,c->callername,sizeof(tempcallername));
-+	strncpy(c->callername,display,sizeof(c->callername));
-+	res = send_message(pri, c, Q931_RESUME_ACKNOWLEDGE, resume_acknowledge_ies);
-+	strncpy(c->callername,tempcallername,sizeof(c->callername));
-+	return res;
-+}
-+
-+
-+static int connect_ies[] = {  Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, Q931_DISPLAY, -1 };
-+static int connect_NET_ies[] = {  Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, Q931_IE_TIME_DATE, -1 };
-  
- int q931_setup_ack(struct pri *pri, q931_call *c, int channel, int nonisdn)
- {
-@@ -2039,9 +2697,34 @@
- 	c->ourcallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
- 	c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;
- 	c->alive = 1;
-+	if (pri->localtype == BRI_NETWORK_PTMP) {
-+		c->progloc = LOC_PRIV_NET_LOCAL_USER;
-+		c->progcode = CODE_CCITT;
-+		c->progress = Q931_PROG_INBAND_AVAILABLE;
-+	}
- 	return send_message(pri, c, Q931_SETUP_ACKNOWLEDGE, connect_ies);
- }
- 
-+static void pri_setup_response_timeout(void *data)
-+{
-+	struct q931_call *c = data;
-+	struct pri *pri = NULL;
-+	if (!c) return;
-+	pri = c->pri;
-+	if (!pri) return;
-+	c->alive = 1;
-+	c->cause = PRI_CAUSE_NO_USER_RESPONSE;
-+	if (pri->debug & PRI_DEBUG_Q931_STATE)
-+		pri_message("No response to SETUP message\n");
-+	pri->schedev = 1;
-+	pri->ev.e = PRI_EVENT_HANGUP;
-+	pri->ev.hangup.channel = c->channelno;
-+	pri->ev.hangup.cref = c->cr;
-+	pri->ev.hangup.cause = c->cause;
-+	pri->ev.hangup.call = c;
-+	q931_hangup(pri, c, c->cause);
-+}
-+
- static void pri_connect_timeout(void *data)
- {
- 	struct q931_call *c = data;
-@@ -2116,7 +2799,12 @@
- 	c->retranstimer = 0;
- 	if ((pri->localtype == PRI_CPE) && (!pri->subchannel))
- 		c->retranstimer = pri_schedule_event(pri, T_313, pri_connect_timeout, c);
--	return send_message(pri, c, Q931_CONNECT, connect_ies);
-+	if ((pri->localtype != PRI_CPE) && (pri->localtype != BRI_CPE) && (pri->localtype != BRI_CPE_PTMP)) {
-+	    // networks may send datetime
-+	    return send_message(pri, c, Q931_CONNECT, connect_NET_ies);
-+	} else {
-+	    return send_message(pri, c, Q931_CONNECT, connect_ies);
-+	}
- }
- 
- static int release_ies[] = { Q931_CAUSE, -1 };
-@@ -2150,7 +2838,7 @@
- int q931_restart(struct pri *pri, int channel)
- {
- 	struct q931_call *c;
--	c = q931_getcall(pri, 0 | 0x8000);
-+	c = q931_getcall(pri, 0 | 0x8000, 0);
- 	if (!c)
- 		return -1;
- 	if (!channel)
-@@ -2186,15 +2874,24 @@
- 		return 0;
- }
- 
-+//static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_DISPLAY, Q931_PROGRESS_INDICATOR,
-+//	 Q931_IE_SIGNAL, Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_SENDING_COMPLETE, -1 };
-+
- static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, Q931_NETWORK_SPEC_FAC, Q931_DISPLAY,
- 	Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_SENDING_COMPLETE, Q931_IE_ORIGINATING_LINE_INFO, -1 };
- 
- static int gr303_setup_ies[] =  { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, -1 };
- 
-+
- int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
- {
- 	int res;
- 	
-+	if (pri->localtype == BRI_NETWORK_PTMP) {
-+	    c->tei = 127;
-+	} else {
-+	    c->tei = 0;
-+	}
- 	
- 	c->transcapability = req->transmode;
- 	c->transmoderate = TRANS_MODE_64_CIRCUIT;
-@@ -2251,12 +2948,17 @@
- 		res = send_message(pri, c, Q931_SETUP, gr303_setup_ies);
- 	else
- 		res = send_message(pri, c, Q931_SETUP, setup_ies);
-+
- 	if (!res) {
- 		c->alive = 1;
- 		/* make sure we call PRI_EVENT_HANGUP_ACK once we send/receive RELEASE_COMPLETE */
- 		c->sendhangupack = 1;
- 		c->ourcallstate = Q931_CALL_STATE_CALL_INITIATED;
- 		c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;	
-+		if ((pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_NETWORK_PTMP) || (pri->localtype == PRI_NETWORK)) {
-+		    c->t303timer = pri_schedule_event(pri, T_303, pri_setup_response_timeout, c);
-+		    c->t303running = 1;
-+		}
- 	}
- 	return res;
- 	
-@@ -2297,6 +2999,118 @@
- 	return 0;
- }
- 
-+
-+
-+/* here we cleanly hangup the phones that responded to our call but didnt get the call  */
-+int q921_hangup(struct pri *pri, q931_call *c, int tei)
-+{
-+    q921_call *cur,*prev;
-+    int tc;
-+    int ttei;
-+    int res=0;
-+
-+    if (!pri || !c)
-+	return -1;
-+    
-+    if (pri->localtype != BRI_NETWORK_PTMP){
-+	return 0;
-+    }
-+//	pri_error("q921_hangup(%d, %d)\n", c->cr, tei);
-+
-+    if (tei == 127) {
-+	tei = c->tei;
-+    }
-+//	pri_error("tei %d\n", tei);
-+
-+    cur = c->phones;
-+    
-+    tc = c->cause;
-+    ttei = c->tei;
-+    while (cur) {
-+	if (cur->tei != tei) {
-+	    c->cause = PRI_CAUSE_NORMAL_CLEARING;
-+	    c->tei = cur->tei;
-+	    if (pri->debug & PRI_DEBUG_Q921_STATE)
-+		pri_message("sending RELEASE for TEI %d\n", cur->tei);
-+	    send_message(pri, c, Q931_RELEASE, release_ies);
-+	}
-+	prev = cur;
-+	cur = cur->next;
-+	if (prev) {
-+	    free(prev);
-+	    prev = NULL;
-+	}
-+    }
-+    c->phones = NULL;
-+    c->tei = ttei;
-+    c->cause = tc;
-+
-+    if (c->tei == 127) {
-+	q931_destroycall(pri, c->cr, c->tei);
-+	// make sure * frees the channel
-+/*	pri_error("returning PRI_EVENT_HANGUP_ACK\n");
-+	res = Q931_RES_HAVEEVENT;
-+	pri->ev.hangup.channel = c->channelno;
-+	pri->ev.e = PRI_EVENT_HANGUP_ACK;  */
-+    } 
-+    return res; 
-+}
-+
-+/* here we handle release_completes from the phones 
-+   because some (elmeg) phones do not send a disconnect
-+   message when the phone is busy */
-+int q921_handle_hangup(struct pri *pri, q931_call *c, int tei)
-+{
-+    q921_call *cur,*match,*prev=NULL;
-+    int left=0;
-+    int res=0;
-+    
-+    if (!pri || !c)
-+	return -1;
-+
-+    if (pri->localtype != BRI_NETWORK_PTMP){
-+	return 0;
-+    }
-+
-+    cur = c->phones;
-+    
-+    while (cur) {
-+	if (cur->tei == tei) {
-+	    match = cur;
-+	    if (prev) {
-+		prev->next = cur->next;
-+		cur = prev;
-+	    } else {
-+		c->phones = cur->next;
-+	    }
-+	    free(match);
-+	}
-+	prev = cur;
-+	if (cur) cur = cur->next;
-+    }
-+
-+    cur = c->phones;
-+    
-+    while (cur) {
-+	left++;
-+	cur = cur->next;
-+    }
-+    
-+    // if all phones have signalled busy AND the timer is not running anymore!
-+    if ((left==0) && (c->cause == PRI_CAUSE_USER_BUSY) && (c->t303running == 0)) {
-+//	pri_error("q921_handle_hangup(%d, %d, %d)\n", c->cr, tei, c->tei);
-+	// make sure * frees the channel
-+	res = Q931_RES_HAVEEVENT;
-+	pri->ev.hangup.cause = PRI_CAUSE_USER_BUSY;
-+	pri->ev.hangup.channel = c->channelno | (c->ds1no << 8);
-+	pri->ev.hangup.cref = c->cr;          		
-+	pri->ev.hangup.call = c;
-+	pri->ev.e = PRI_EVENT_HANGUP; 
-+    } 
-+    return res; 
-+}
-+
-+
- int q931_hangup(struct pri *pri, q931_call *c, int cause)
- {
- 	int disconnect = 1;
-@@ -2322,7 +3136,7 @@
- 	case Q931_CALL_STATE_NULL:
- 		if (c->peercallstate == Q931_CALL_STATE_NULL)
- 			/* free the resources if we receive or send REL_COMPL */
--			q931_destroycall(pri, c->cr);
-+			q931_destroycall(pri, c->cr, c->tei);
- 		else if (c->peercallstate == Q931_CALL_STATE_RELEASE_REQUEST)
- 			q931_release_complete(pri,c,cause);
- 		break;
-@@ -2348,14 +3162,21 @@
- 		/* received SETUP_ACKNOWLEDGE */
- 		/* send DISCONNECT in general */
- 		if (c->peercallstate != Q931_CALL_STATE_NULL && c->peercallstate != Q931_CALL_STATE_DISCONNECT_REQUEST && c->peercallstate != Q931_CALL_STATE_DISCONNECT_INDICATION && c->peercallstate != Q931_CALL_STATE_RELEASE_REQUEST && c->peercallstate != Q931_CALL_STATE_RESTART_REQUEST && c->peercallstate != Q931_CALL_STATE_RESTART) {
--			if (disconnect)
-+			if (pri->localtype == BRI_NETWORK_PTMP) {
-+			    if (c->tei == 127) {
-+			        break;
-+			    }
-+			} 
-+			if (disconnect) {
- 				q931_disconnect(pri,c,cause);
--			else if (release_compl)
-+			} else if (release_compl) {
- 				q931_release_complete(pri,c,cause);
--			else
-+			} else {
- 				q931_release(pri,c,cause);
--		} else 
-+			}
-+		} else {
- 			pri_error("Wierd, doing nothing but this shouldn't happen, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate));
-+		}
- 		break;
- 	case Q931_CALL_STATE_DISCONNECT_REQUEST:
- 		/* sent DISCONNECT */
-@@ -2363,8 +3184,14 @@
- 		break;
- 	case Q931_CALL_STATE_DISCONNECT_INDICATION:
- 		/* received DISCONNECT */
-+		if (pri->localtype == BRI_NETWORK_PTMP) {
-+		    if (c->tei == 127) {
-+			break;
-+		    }
-+		} 
- 		if (c->peercallstate == Q931_CALL_STATE_DISCONNECT_REQUEST) {
- 			c->alive = 1;
-+//		    pri_error("sending release to %d\n", c->tei);
- 			q931_release(pri,c,cause);
- 		}
- 		break;
-@@ -2385,9 +3212,10 @@
- 	return 0;
- }
- 
--int q931_receive(struct pri *pri, q931_h *h, int len)
-+int q931_receive(struct pri *pri, q931_h *h, int len, int tei)
- {
- 	q931_mh *mh;
-+	q921_call *l2c;
- 	q931_call *c;
- 	q931_ie *ie;
- 	unsigned int x;
-@@ -2410,13 +3238,14 @@
- 		   KLUDGE this by changing byte 4 from a 0xf (SERVICE) 
- 		   to a 0x7 (SERVICE ACKNOWLEDGE) */
- 		h->raw[h->crlen + 2] -= 0x8;
--		q931_xmit(pri, h, len, 1);
-+		q931_xmit(pri, h, len, 1, tei);
- 		return 0;
- 	} else if (h->pd != pri->protodisc) {
- 		pri_error("Warning: unknown/inappropriate protocol discriminator received (%02x/%d)\n", h->pd, h->pd);
- 		return 0;
- 	}
--	c = q931_getcall(pri, q931_cr(h));
-+//	pri_error("searching for cref %d tei %d\n", q931_cr(h), tei);
-+	c = q931_getcall(pri, q931_cr(h), tei);
- 	if (!c) {
- 		pri_error("Unable to locate call %d\n", q931_cr(h));
- 		return -1;
-@@ -2439,6 +3268,7 @@
- 	case Q931_SETUP:
- 		if (pri->debug & PRI_DEBUG_Q931_STATE)
- 			pri_message("-- Processing Q.931 Call Setup\n");
-+		c->tei = tei;
- 		c->channelno = -1;
- 		c->slotmap = -1;
- 		c->chanflags = 0;
-@@ -2463,11 +3293,25 @@
- 		strcpy(c->redirectingnum, "");
-                 c->useruserprotocoldisc = -1; 
- 		strcpy(c->useruserinfo, "");
-+		strcpy(c->digits, "");
-+		strcpy(c->display, "");
- 		c->complete = 0;
- 		break;
- 	case Q931_CONNECT:
-+		if (c->t303timer) {
-+		    c->t303running = 0;
-+		    pri_schedule_del(pri, c->t303timer);
-+    		}
-+		c->t303timer = 0;
-+		c->progress = -1;
-+		break;
- 	case Q931_ALERTING:
- 	case Q931_PROGRESS:
-+		if (c->t303timer) {
-+		    c->t303running = 0;
-+		    pri_schedule_del(pri, c->t303timer);
-+		}
-+		c->t303timer = 0;
- 		c->progress = -1;
- 		break;
- 	case Q931_CONNECT_ACKNOWLEDGE:
-@@ -2486,10 +3330,15 @@
- 		if (c->retranstimer)
- 			pri_schedule_del(pri, c->retranstimer);
- 		c->retranstimer = 0;
-+		if (c->t303timer) {
-+		    c->t303running = 0;
-+		    pri_schedule_del(pri, c->t303timer);
-+    		}
-+		c->t303timer = 0;
- 		break;
- 	case Q931_RELEASE_COMPLETE:
- 		if (c->retranstimer)
--			pri_schedule_del(pri, c->retranstimer);
-+		    pri_schedule_del(pri, c->retranstimer);
- 		c->retranstimer = 0;
- 	case Q931_STATUS:
- 		c->cause = -1;
-@@ -2505,22 +3354,32 @@
- 	case Q931_STATUS_ENQUIRY:
- 		break;
- 	case Q931_SETUP_ACKNOWLEDGE:
-+		if (c->t303timer) {
-+		    c->t303running = 0;
-+		    pri_schedule_del(pri, c->t303timer);
-+		}
-+		c->t303timer = 0;
- 		break;
- 	case Q931_NOTIFY:
- 		break;
-+	case Q931_HOLD:
-+		break;
-+	case Q931_RETRIEVE:
-+		break;
-+	case Q931_RESUME:
-+		c->tei = tei;
-+		break;
-+	case Q931_SUSPEND:
-+		break;
- 	case Q931_USER_INFORMATION:
- 	case Q931_SEGMENT:
- 	case Q931_CONGESTION_CONTROL:
--	case Q931_HOLD:
- 	case Q931_HOLD_ACKNOWLEDGE:
- 	case Q931_HOLD_REJECT:
--	case Q931_RETRIEVE:
- 	case Q931_RETRIEVE_ACKNOWLEDGE:
- 	case Q931_RETRIEVE_REJECT:
--	case Q931_RESUME:
- 	case Q931_RESUME_ACKNOWLEDGE:
- 	case Q931_RESUME_REJECT:
--	case Q931_SUSPEND:
- 	case Q931_SUSPEND_ACKNOWLEDGE:
- 	case Q931_SUSPEND_REJECT:
- 		pri_error("!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
-@@ -2529,7 +3388,7 @@
- 		pri_error("!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
- 		q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
- 		if (c->newcall) 
--			q931_destroycall(pri,c->cr);
-+			q931_destroycall(pri,c->cr, c->tei);
- 		return -1;
- 	}
- 	memset(mandies, 0, sizeof(mandies));
-@@ -2610,7 +3469,7 @@
- 	for (x=0;x<MAX_MAND_IES;x++) {
- 		if (mandies[x]) {
- 			/* check if there is no channel identification when we're configured as network -> that's not an error */
--			if ((pri->localtype != PRI_NETWORK) || (mh->msg != Q931_SETUP) || (mandies[x] != Q931_CHANNEL_IDENT)) {
-+			if (((pri->localtype != PRI_NETWORK) || (pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_NETWORK_PTMP)) && ((mh->msg != Q931_SETUP) || (mandies[x] != Q931_CHANNEL_IDENT))) {
- 				pri_error("XXX Missing handling for mandatory IE %d (cs%d, %s) XXX\n", Q931_IE_IE(mandies[x]), Q931_IE_CODESET(mandies[x]), ie2str(mandies[x]));
- 				missingmand++;
- 			}
-@@ -2622,7 +3481,7 @@
- 	case Q931_RESTART:
- 		if (missingmand) {
- 			q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
--			q931_destroycall(pri, c->cr);
-+			q931_destroycall(pri, c->cr, c->tei);
- 			break;
- 		}
- 		c->ourcallstate = Q931_CALL_STATE_RESTART;
-@@ -2640,7 +3499,8 @@
- 		}
- 		/* Must be new call */
- 		if (!c->newcall) {
--			break;
-+			pri_error("received SETUP message for call that is not a new call, wicked!!! going on ...\n");
-+//			break;
- 		}
- 		c->newcall = 0;
- 		c->ourcallstate = Q931_CALL_STATE_CALL_PRESENT;
-@@ -2660,8 +3520,9 @@
-                 strncpy(pri->ev.ring.redirectingnum, c->redirectingnum, sizeof(pri->ev.ring.redirectingnum) - 1);
-                 strncpy(pri->ev.ring.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo) - 1);
- 		pri->ev.ring.flexible = ! (c->chanflags & FLAG_EXCLUSIVE);
--		pri->ev.ring.cref = c->cr;
-+		pri->ev.ring.tei = c->tei;
- 		pri->ev.ring.call = c;
-+		pri->ev.ring.cref = c->cr;
- 		pri->ev.ring.layer1 = c->userl1;
- 		pri->ev.ring.complete = c->complete; 
- 		pri->ev.ring.ctype = c->transcapability;
-@@ -2675,6 +3536,9 @@
- 			q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
- 			break;
- 		}
-+		if (pri->localtype == BRI_NETWORK_PTMP) {
-+		    l2c = q921_getcall(pri, c, tei);
-+		}
- 		c->ourcallstate = Q931_CALL_STATE_CALL_DELIVERED;
- 		c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED;
- 		pri->ev.e = PRI_EVENT_RINGING;
-@@ -2691,36 +3555,65 @@
- 			q931_status(pri, c, PRI_CAUSE_WRONG_MESSAGE);
- 			break;
- 		}
-+		// tei got the call
-+		c->tei = tei;
- 		c->ourcallstate = Q931_CALL_STATE_ACTIVE;
- 		c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST;
- 		pri->ev.e = PRI_EVENT_ANSWER;
- 		pri->ev.answer.channel = c->channelno | (c->ds1no << 8);
- 		pri->ev.answer.cref = c->cr;
-+		pri->ev.answer.tei = c->tei;
- 		pri->ev.answer.call = c;
- 		q931_connect_acknowledge(pri, c);
-+	
-+		if (pri->localtype == BRI_NETWORK_PTMP) {
-+		    q921_hangup(pri, c, tei);
-+		}
- 		return Q931_RES_HAVEEVENT;
- 	case Q931_FACILITY:
- 		if (c->newcall) {
--			q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-+			if ((pri->localtype == PRI_CPE) || (pri->localtype == PRI_NETWORK)) {
-+			    q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-+			} else {
-+			    // BRI uses the dummy cref for sservices like ccnr
-+			}
- 			break;
- 		}
--		pri->ev.e = PRI_EVENT_FACNAME;
--		strncpy(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname) - 1);
--		strncpy(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingname) - 1);
--		pri->ev.facname.channel = c->channelno | (c->ds1no << 8);
--		pri->ev.facname.cref = c->cr;
--		pri->ev.facname.call = c;
--#if 0
--		pri_message("Sending facility event (%s/%s)\n", pri->ev.facname.callingname, pri->ev.facname.callingnum);
--#endif
-+		if (c->facility > 0) {
-+		    pri->ev.e = PRI_EVENT_FACILITY;
-+		    pri->ev.facility.channel = c->channelno | (c->ds1no << 8);
-+		    pri->ev.facility.cref = c->cr;
-+		    pri->ev.facility.tei = c->tei;
-+		    pri->ev.facility.call = c; 
-+		    switch (c->facility) {
-+			case 0x06: /* ECT execute */
-+				pri->ev.facility.operation = 0x06; 
-+			    break;
-+			case 0x0D:
-+				pri->ev.facility.operation = 0x0D; 
-+				strncpy(pri->ev.facility.forwardnum, c->redirectingnum,  sizeof(pri->ev.facility.forwardnum) - 1);
-+			    break;
-+			default:
-+				pri->ev.facility.operation = c->facility; 
-+		    }
-+		} else {
-+		    pri->ev.e = PRI_EVENT_FACNAME;
-+		    strncpy(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname) - 1);
-+		    strncpy(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingname) - 1);
-+		    pri->ev.facname.channel = c->channelno | (c->ds1no << 8);
-+		    pri->ev.facname.cref = c->cr;
-+		    pri->ev.facname.call = c; 
-+		}
-+
- 		return Q931_RES_HAVEEVENT;
- 	case Q931_PROGRESS:
- 		if (missingmand) {
- 			q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
--			q931_destroycall(pri, c->cr);
-+			q931_destroycall(pri, c->cr, c->tei);
- 			break;
- 		}
- 		pri->ev.e = PRI_EVENT_PROGRESS;
-+		pri->ev.proceeding.cause = c->cause;
- 		/* Fall through */
- 	case Q931_CALL_PROCEEDING:
- 		if (c->newcall) {
-@@ -2734,7 +3627,13 @@
- 			q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE);
- 			break;
- 		}
-+		if (pri->localtype == BRI_NETWORK_PTMP) {
-+		    l2c = q921_getcall(pri, c, tei);
-+		    l2c->proc = 1;
-+		    l2c->channel = c->channelno;
-+		}
- 		pri->ev.proceeding.channel = c->channelno | (c->ds1no << 8);
-+		pri->ev.proceeding.call = c;
- 		if (mh->msg == Q931_CALL_PROCEEDING) {
- 			pri->ev.e = PRI_EVENT_PROCEEDING;
- 			c->ourcallstate = Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING;
-@@ -2756,7 +3655,7 @@
- 	case Q931_STATUS:
- 		if (missingmand) {
- 			q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
--			q931_destroycall(pri, c->cr);
-+			q931_destroycall(pri, c->cr, c->tei);
- 			break;
- 		}
- 		if (c->newcall) {
-@@ -2794,27 +3693,42 @@
- 		}
- 		break;
- 	case Q931_RELEASE_COMPLETE:
--		c->ourcallstate = Q931_CALL_STATE_NULL;
--		c->peercallstate = Q931_CALL_STATE_NULL;
--		pri->ev.hangup.channel = c->channelno | (c->ds1no << 8);
--		pri->ev.hangup.cref = c->cr;          		
--		pri->ev.hangup.cause = c->cause;      		
--		pri->ev.hangup.call = c;              		
--		/* Free resources */
--		if (c->alive) {
-+		if (c->cause != PRI_CAUSE_INCOMPATIBLE_DESTINATION) {
-+		    if (c->t303timer) {
-+			c->t303running = 0;
-+			pri_schedule_del(pri, c->t303timer);
-+    		    }
-+		    c->t303timer = 0;
-+		}
-+		if ((pri->localtype != BRI_NETWORK_PTMP) || (c->tei == tei)) {
-+		    c->ourcallstate = Q931_CALL_STATE_NULL;
-+		    c->peercallstate = Q931_CALL_STATE_NULL;
-+		    pri->ev.hangup.channel = c->channelno | (c->ds1no << 8);
-+		    pri->ev.hangup.cref = c->cr;          		
-+		    pri->ev.hangup.cause = c->cause;      		
-+		    pri->ev.hangup.call = c;              		
-+		    /* Free resources */
-+		    if (c->alive) {
- 			pri->ev.e = PRI_EVENT_HANGUP;
- 			res = Q931_RES_HAVEEVENT;
- 			c->alive = 0;
--		} else if (c->sendhangupack) {
-+		    } else if (c->sendhangupack) {
- 			res = Q931_RES_HAVEEVENT;
- 			pri->ev.e = PRI_EVENT_HANGUP_ACK;
- 			pri_hangup(pri, c, c->cause);
--		} else
-+		    } else
- 			res = 0;
--		if (res)
-+		    if (res)
- 			return res;
--		else
-+		    else
- 			q931_hangup(pri,c,c->cause);
-+		} else {
-+		    // BRI_NET_PTMP
-+		    // ignoring relase_complete
-+		    res = q921_handle_hangup(pri,c,tei);
-+		    if (res)
-+			return res;
-+		}
- 		break;
- 	case Q931_RELEASE:
- 		if (missingmand) {
-@@ -2830,6 +3744,7 @@
- 		pri->ev.e = PRI_EVENT_HANGUP;
- 		pri->ev.hangup.channel = c->channelno | (c->ds1no << 8);
- 		pri->ev.hangup.cref = c->cr;
-+		pri->ev.hangup.tei = c->tei;
- 		pri->ev.hangup.cause = c->cause;
- 		pri->ev.hangup.call = c;
- 		/* Don't send release complete if they send us release 
-@@ -2855,8 +3770,14 @@
- 		pri->ev.e = PRI_EVENT_HANGUP_REQ;
- 		pri->ev.hangup.channel = c->channelno | (c->ds1no << 8);
- 		pri->ev.hangup.cref = c->cr;
-+		pri->ev.hangup.tei = c->tei;
- 		pri->ev.hangup.cause = c->cause;
- 		pri->ev.hangup.call = c;
-+		if (c->inband_progress) {
-+		    pri->ev.hangup.inband_progress = 1;
-+		} else {
-+		    pri->ev.hangup.inband_progress = 0;
-+		}
- 		if (c->alive)
- 			return Q931_RES_HAVEEVENT;
- 		else
-@@ -2877,15 +3798,35 @@
- 			q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
- 			break;
- 		}
-+
- 		if (c->ourcallstate!=Q931_CALL_STATE_OVERLAP_RECEIVING)
- 			break;
--		pri->ev.e = PRI_EVENT_INFO_RECEIVED;
--		pri->ev.ring.call = c;
--		pri->ev.ring.channel = c->channelno | (c->ds1no << 8);
--		strncpy(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum) - 1);
--		strncpy(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr) - 1);
--		pri->ev.ring.complete = c->complete; 	/* this covers IE 33 (Sending Complete) */
--		return Q931_RES_HAVEEVENT;
-+		if ((pri->localtype != BRI_NETWORK_PTMP) && (pri->localtype != BRI_NETWORK)) {
-+		    if ((c->ourcallstate!=Q931_CALL_STATE_OVERLAP_RECEIVING) && (c->ourcallstate!=Q931_CALL_STATE_ACTIVE))
-+		    break;
-+		} else {
-+		    // we want to use keypad and information ies for out of band dtmf, also when not using overlapdial
-+		}
-+		if (strlen(c->digits)) {
-+		    pri->ev.e = PRI_EVENT_INFO_RECEIVED;
-+		    pri->ev.ring.call = c;
-+		    pri->ev.ring.channel = c->channelno | (c->ds1no << 8);
-+		    strncpy(pri->ev.ring.callednum, c->digits, sizeof(pri->ev.ring.callednum) - 1);
-+		    strncpy(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr) - 1);
-+		    pri->ev.ring.complete = c->complete; 	/* this covers IE 33 (Sending Complete) */
-+		    return Q931_RES_HAVEEVENT;
-+		} else if (strlen(c->display)) {
-+		    pri->ev.e = PRI_EVENT_DISPLAY_RECEIVED;
-+		    pri->ev.display.call = c;
-+		    pri->ev.display.channel = c->channelno | (c->ds1no << 8);
-+		    strncpy(pri->ev.display.text, c->display, sizeof(pri->ev.display.text) - 1);
-+		    return Q931_RES_HAVEEVENT;
-+		} else {
-+		    if (pri->debug & PRI_DEBUG_Q931_STATE)
-+			pri_message("ignoring INFORMATION msg without Called Party Number, Keypad Facility or Display\n");
-+		}
-+		strcpy(c->digits, "");
-+		strcpy(c->display, "");
- 		break;
- 	case Q931_STATUS_ENQUIRY:
- 		if (c->newcall) {
-@@ -2902,25 +3843,61 @@
- 		c->peercallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
- 		pri->ev.e = PRI_EVENT_SETUP_ACK;
- 		pri->ev.setup_ack.channel = c->channelno;
-+		pri->ev.setup_ack.call = c;
- 		return Q931_RES_HAVEEVENT;
- 	case Q931_NOTIFY:
- 		pri->ev.e = PRI_EVENT_NOTIFY;
- 		pri->ev.notify.channel = c->channelno;
- 		pri->ev.notify.info = c->notify;
- 		return Q931_RES_HAVEEVENT;
-+	case Q931_HOLD:
-+		pri->ev.e = PRI_EVENT_HOLD_REQ;
-+		pri->ev.hold_req.call = c;
-+		pri->ev.hold_req.cref = c->cr;
-+		pri->ev.hold_req.tei = c->tei;
-+		pri->ev.hold_req.channel = c->channelno;
-+		return Q931_RES_HAVEEVENT;
-+		break;
-+	case Q931_RETRIEVE:
-+		pri->ev.e = PRI_EVENT_RETRIEVE_REQ;
-+		pri->ev.retrieve_req.call = c;
-+		pri->ev.retrieve_req.cref = c->cr;
-+		pri->ev.retrieve_req.tei = c->tei;
-+		pri->ev.retrieve_req.channel = c->channelno;
-+		return Q931_RES_HAVEEVENT;
-+		break;
-+	case Q931_SUSPEND:
-+		pri->ev.e = PRI_EVENT_SUSPEND_REQ;
-+		pri->ev.suspend_req.call = c;
-+		pri->ev.suspend_req.cref = c->cr;
-+		pri->ev.suspend_req.tei = c->tei;
-+		pri->ev.suspend_req.channel = c->channelno;
-+		strncpy(pri->ev.suspend_req.callid, c->callid, sizeof(pri->ev.suspend_req.callid) - 1);
-+		// q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
-+		return Q931_RES_HAVEEVENT;
-+		break;
-+	case Q931_RESUME:
-+		if (pri->localtype == BRI_NETWORK_PTMP) {
-+		    l2c = q921_getcall(pri, c, tei);
-+		}
-+		c->newcall = 0;
-+		pri->ev.e = PRI_EVENT_RESUME_REQ;
-+		pri->ev.resume_req.call = c;
-+		pri->ev.resume_req.cref = c->cr;
-+		pri->ev.resume_req.tei = c->tei;
-+		pri->ev.resume_req.channel = c->channelno;
-+		strncpy(pri->ev.resume_req.callid, c->callid, sizeof(pri->ev.resume_req.callid) - 1);
-+		return Q931_RES_HAVEEVENT;
-+		break;
- 	case Q931_USER_INFORMATION:
- 	case Q931_SEGMENT:
- 	case Q931_CONGESTION_CONTROL:
--	case Q931_HOLD:
- 	case Q931_HOLD_ACKNOWLEDGE:
- 	case Q931_HOLD_REJECT:
--	case Q931_RETRIEVE:
- 	case Q931_RETRIEVE_ACKNOWLEDGE:
- 	case Q931_RETRIEVE_REJECT:
--	case Q931_RESUME:
- 	case Q931_RESUME_ACKNOWLEDGE:
- 	case Q931_RESUME_REJECT:
--	case Q931_SUSPEND:
- 	case Q931_SUSPEND_ACKNOWLEDGE:
- 	case Q931_SUSPEND_REJECT:
- 		pri_error("!! Not yet handling post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
-@@ -2930,7 +3907,7 @@
- 		pri_error("!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
- 		q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
- 		if (c->newcall) 
--			q931_destroycall(pri,c->cr);
-+			q931_destroycall(pri,c->cr,c->tei);
- 		return -1;
- 	}
- 	return 0;
-diff -urNad --exclude=CVS --exclude=.svn ./README /tmp/dpep-work.PXlLuK/libpri-1.0.9/README
---- ./README	2004-10-15 00:04:22.000000000 +0100
-+++ /tmp/dpep-work.PXlLuK/libpri-1.0.9/README	2005-07-02 09:24:53.836704648 +0100
-@@ -1,6 +1,7 @@
--libpri: An implementation of Primate Rate ISDN
--
--Written by Mark Spencer <markster at digium.com>
-+libpri: An implementation of Primate Rate ISDN (and BRI ISDN)
-+ 
-+Written by Mark Spencer <markster at linux-support.net>
-+Modified for BRI support by Klaus-Peter Junghanns <kpj at junghanns.net>
- 
- What is libpri?
- ===============
-@@ -9,6 +10,7 @@
- based on the Bellcore specification SR-NWT-002343 for National ISDN.  As of
- May 12, 2001, it has been tested work with NI-2, Nortel DMS-100, and 
- Lucent 5E Custom protocols on switches from Nortel and Lucent.
-+The BRI and euroISDN modifications are based on ETS 300 102-1.
- 
- What is the license for libpri?
- ===============================
-@@ -17,9 +19,8 @@
- The GNU GPL is included in the file LICENSE in this directory.
- 
- If you wish to use libpri in an application for which the GPL is not 
--appropriate (e.g. a proprietary embedded system), licenses for libpri 
--under more flexible terms can be readily obtained through Digium, Inc. 
--at reasonable cost.
-+appropriate (e.g. a proprietary embedded system), then you have to use
-+a non-standard compliant version without BRI support.
- 
- 
- How do I report bugs or contribute?
-diff -urNad --exclude=CVS --exclude=.svn ./TODO /tmp/dpep-work.PXlLuK/libpri-1.0.9/TODO
---- ./TODO	2001-05-12 17:53:13.000000000 +0100
-+++ /tmp/dpep-work.PXlLuK/libpri-1.0.9/TODO	2005-07-02 09:24:53.836704648 +0100
-@@ -2,9 +2,7 @@
- -- D-Channel Backup
- -- Test against 4e
- 
--Q.921:
---- Support unnumbered information frames
--
- Q.931:
---- Locking Shift IE
---- Implement the 11 missing Q.931 timers
-+-- Locking Shift IE (you did that already, didnt you??)
-+-- Implement the 10 missing Q.931 timers
-+-- more facilities
-\ No newline at end of file

Deleted: libpri/trunk/debian/patches/bristuff_2.0.0-RC8j.dpatch
===================================================================
--- libpri/trunk/debian/patches/bristuff_2.0.0-RC8j.dpatch	2005-11-01 21:30:40 UTC (rev 930)
+++ libpri/trunk/debian/patches/bristuff_2.0.0-RC8j.dpatch	2005-11-01 21:34:16 UTC (rev 931)
@@ -1,4451 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## bristuff_2.0.0-RC8j.dpatch by  <msp at debian.org>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: bristuff from http://www.junghanns.net/asterisk/
-
- at DPATCH@
-diff -urNad --exclude=CVS --exclude=.svn ./libpri.h /tmp/dpep-work.aULY0X/libpri-1.0.9/libpri.h
---- ./libpri.h	2005-07-14 12:30:35.000000000 +0100
-+++ /tmp/dpep-work.aULY0X/libpri-1.0.9/libpri.h	2005-07-14 12:31:07.928276872 +0100
-@@ -26,8 +26,12 @@
- #define _LIBPRI_H
- 
- /* Node types */
--#define PRI_NETWORK		1
-+#define PRI_NETWORK		1	/* PTP modes, default for PRI */
- #define PRI_CPE			2
-+#define BRI_NETWORK_PTMP	3	/* PTMP modes, default for BRI */
-+#define BRI_CPE_PTMP		4	
-+#define BRI_NETWORK		5	/* PTP modes */
-+#define BRI_CPE			6	
- 
- /* Debugging */
- #define PRI_DEBUG_Q921_RAW		(1 << 0)	/* Show raw HDLC frames */
-@@ -72,6 +76,12 @@
- #define PRI_EVENT_HANGUP_REQ	15	/* Requesting the higher layer to hangup */
- #define PRI_EVENT_NOTIFY	16	/* Notification received */
- #define PRI_EVENT_PROGRESS	17	/* When we get CALL_PROCEEDING or PROGRESS */
-+#define PRI_EVENT_HOLD_REQ	18	/* R */
-+#define PRI_EVENT_RETRIEVE_REQ  19
-+#define PRI_EVENT_SUSPEND_REQ   20	/* park */
-+#define PRI_EVENT_RESUME_REQ    21	/* unpark */
-+#define PRI_EVENT_DISPLAY_RECEIVED    22
-+#define PRI_EVENT_FACILITY	23	/* Facility */
- 
- /* Simple states */
- #define PRI_STATE_DOWN		0
-@@ -231,11 +241,13 @@
- #define PRI_NSF_ATT_MULTIQUEST         0xF0
- #define PRI_NSF_CALL_REDIRECTION_SERVICE       0xF7
- 
-+typedef struct q921_call q921_call;
- typedef struct q931_call q931_call;
- 
- typedef struct pri_event_generic {
- 	/* Events with no additional information fall in this category */
- 	int e;
-+	int tei;
- } pri_event_generic;
- 
- typedef struct pri_event_error {
-@@ -258,6 +270,7 @@
- typedef struct pri_event_answer {
- 	int e;
- 	int channel;
-+	int tei;				/* belongs to this tei */
- 	int cref;
- 	q931_call *call;
- } pri_event_answer;
-@@ -275,8 +288,11 @@
- 	int e;
- 	int channel;				/* Channel requested */
- 	int callingpres;			/* Presentation of Calling CallerID */
-+	int callingpresuser;			/* Presentation of Calling CallerID */
- 	int callingplan;			/* Dialing plan of Calling entity */
--	char callingnum[256];		/* Calling number */
-+	int callingplanuser;			/* Dialing plan of Calling entity */
-+	char callingnum[256];		/* Calling number, network provided */
-+	char callingnumuser[256];		/* Calling number, user provided */
- 	char callingname[256];		/* Calling name (if provided) */
- 	int calledplan;				/* Dialing plan of Called number */
- 	int ani2;                   /* ANI II */
-@@ -289,6 +305,7 @@
- 	int layer1;				/* User layer 1 */
- 	int complete;				/* Have we seen "Complete" i.e. no more number? */
- 	q931_call *call;			/* Opaque call pointer */
-+	int tei;				/* belongs to this tei */
- 	char callingsubaddr[256];		/* Calling parties subaddress */
- } pri_event_ring;
- 
-@@ -297,6 +314,8 @@
- 	int channel;				/* Channel requested */
- 	int cause;
- 	int cref;
-+	int tei;
-+	int inband_progress;
- 	q931_call *call;			/* Opaque call pointer */
- } pri_event_hangup;	
- 
-@@ -308,11 +327,14 @@
- typedef struct pri_event_proceeding {
- 	int e;
- 	int channel;
-+	int cause;
-+	q931_call *call;			/* Opaque call pointer */
- } pri_event_proceeding;
-  
- typedef struct pri_event_setup_ack {
- 	int e;
- 	int channel;
-+	q931_call *call;			/* Opaque call pointer */
- } pri_event_setup_ack;
- 
- typedef struct pri_event_notify {
-@@ -321,20 +343,80 @@
- 	int info;
- } pri_event_notify;
- 
-+typedef struct pri_event_hold_req {
-+	int e;
-+	int channel;
-+	int cref;
-+	int tei;
-+	q931_call *call;
-+} pri_event_hold_req;
-+
-+/* euroisdn faciltiy fun */
-+typedef struct pri_event_facility_req {
-+	int e;
-+	int channel;
-+	int cref;
-+	int tei;
-+	int operation;
-+	char forwardnum[256];		/* Redirection destination */
-+	q931_call *call;
-+} pri_event_facility_req;
-+
-+typedef struct pri_event_retrieve_req {
-+	int e;
-+	int channel;
-+	int cref;
-+	int tei;
-+	q931_call *call;
-+} pri_event_retrieve_req;
-+
-+typedef struct pri_event_suspend_req {
-+	int e;
-+	int channel;
-+	int cref;
-+	int tei;
-+	q931_call *call;
-+	char callid[10];
-+} pri_event_suspend_req;
-+
-+typedef struct pri_event_resume_req {
-+	int e;
-+	int channel;
-+	int cref;
-+	int tei;
-+	q931_call *call;
-+	char callid[10];
-+} pri_event_resume_req;
-+
-+typedef struct pri_event_display {
-+	int e;
-+	int channel;		
-+	int cref;			
-+	q931_call *call;
-+	char text[256];
-+} pri_event_display;
-+
-+
- typedef union {
- 	int e;
- 	pri_event_generic gen;		/* Generic view */
- 	pri_event_restart restart;	/* Restart view */
- 	pri_event_error	  err;		/* Error view */
- 	pri_event_facname facname;	/* Caller*ID Name on Facility */
-+	pri_event_facility_req facility;	/* sservices */
- 	pri_event_ring	  ring;		/* Ring */
- 	pri_event_hangup  hangup;	/* Hang up */
- 	pri_event_ringing ringing;	/* Ringing */
--	pri_event_ringing answer;	/* Answer */
-+	pri_event_answer  answer;	/* Answer */
- 	pri_event_restart_ack restartack;	/* Restart Acknowledge */
- 	pri_event_proceeding  proceeding;	/* Call proceeding & Progress */
- 	pri_event_setup_ack   setup_ack;	/* SETUP_ACKNOWLEDGE structure */
- 	pri_event_notify notify;		/* Notification */
-+	pri_event_hold_req hold_req;
-+	pri_event_retrieve_req retrieve_req;
-+	pri_event_suspend_req suspend_req;
-+	pri_event_resume_req resume_req;
-+	pri_event_display display;
- } pri_event;
- 
- struct pri;
-@@ -389,6 +471,12 @@
- /* Send a digit in overlap mode */
- extern int pri_information(struct pri *pri, q931_call *call, char digit);
- 
-+/* Send a INFO msg with display ie  */
-+extern int pri_information_display(struct pri *pri, q931_call *call, char *display);
-+
-+/* add a display ie to a call, so it can be sent with the next message */
-+extern int pri_add_display(struct pri *pri, q931_call *call, char *display);
-+
- /* Answer the incomplete(call without called number) call on the given channel.
-    Set non-isdn to non-zero if you are not connecting to ISDN equipment */
- extern int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn);
-@@ -397,6 +485,33 @@
-    Set non-isdn to non-zero if you are not connecting to ISDN equipment */
- extern int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
- 
-+/* Ack a HOLD_REQ */
-+extern int pri_hold_acknowledge(struct pri *pri, q931_call *call);
-+
-+/* Reject a HOLD_REQ */
-+extern int pri_hold_reject(struct pri *pri, q931_call *call);
-+
-+/* Ack a RETRIEVE_REQ */
-+extern int pri_retrieve_acknowledge(struct pri *pri, q931_call *call, int channel);
-+
-+/* Reject a RETRIEVE_REQ */
-+extern int pri_retrieve_reject(struct pri *pri, q931_call *call);
-+
-+/* Ack a SUSPEND_REQ */
-+extern int pri_suspend_acknowledge(struct pri *pri, q931_call *call, char *display);
-+
-+/* Reject a SUSPEND_REQ */
-+extern int pri_suspend_reject(struct pri *pri, q931_call *call, char *display);
-+
-+/* Reject a RESUME_REQ */
-+extern int pri_resume_reject(struct pri *pri, q931_call *call, char *display);
-+
-+/* Ack a RESUME_REQ */
-+extern int pri_resume_acknowledge(struct pri *pri, q931_call *call, int channel, char *display);
-+
-+/* Send a Facility Message */
-+extern int pri_facility(struct pri *pri, q931_call *call, int operation, char *arguments);
-+
- /* Set CRV reference for GR-303 calls */
- 
- 
-diff -urNad --exclude=CVS --exclude=.svn ./Makefile /tmp/dpep-work.aULY0X/libpri-1.0.9/Makefile
---- ./Makefile	2005-07-14 12:30:58.281743368 +0100
-+++ /tmp/dpep-work.aULY0X/libpri-1.0.9/Makefile	2005-07-14 12:31:07.927277024 +0100
-@@ -36,7 +36,7 @@
- DYNAMIC_LIBRARY=libpri.so.1.0
- STATIC_OBJS=pri.o q921.o prisched.o q931.o
- DYNAMIC_OBJS=pri.lo q921.lo prisched.lo q931.lo
--CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g $(ALERTING) $(LIBPRI_COUNTERS)
-+CFLAGS=-Wall -Wstrict-prototypes -Wmissing-prototypes -g $(ALERTING) $(LIBPRI_COUNTERS)
- INSTALL_PREFIX=
- ifeq (${OSARCH},Linux)
- LDCONFIG_FLAGS=-n
-diff -urNad --exclude=CVS --exclude=.svn ./pri.c /tmp/dpep-work.aULY0X/libpri-1.0.9/pri.c
---- ./pri.c	2005-07-14 12:30:35.000000000 +0100
-+++ /tmp/dpep-work.aULY0X/libpri-1.0.9/pri.c	2005-07-14 12:31:07.929276720 +0100
-@@ -33,6 +33,14 @@
- 		return "Network";
- 	case PRI_CPE:
- 		return "CPE";
-+	case BRI_NETWORK:
-+		return "Network";
-+	case BRI_CPE:
-+		return "CPE";
-+	case BRI_NETWORK_PTMP:
-+		return "Network (PtMP)";
-+	case BRI_CPE_PTMP:
-+		return "CPE (PtMP)";
- 	default:
- 		return "Invalid value";
- 	}
-@@ -113,7 +121,7 @@
- 		}
- 		/* Start Q.921 layer, Wait if we're the network */
- 		if (p)
--			q921_start(p, p->localtype == PRI_CPE);
-+			q921_start(p, p->localtype == PRI_CPE, 0);
- 	}
- 	return p;
- }
-@@ -270,6 +278,21 @@
- 	return q931_notify(pri, call, channel, info);
- }
- 
-+int pri_information_display(struct pri *pri, q931_call *call, char *display)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_information_display(pri, call, display);
-+}
-+
-+int pri_add_display(struct pri *pri, q931_call *call, char *display)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_add_display(pri, call, display);
-+}
-+
-+
- void pri_destroycall(struct pri *pri, q931_call *call)
- {
- 	if (pri && call)
-@@ -291,6 +314,69 @@
- 	return q931_connect(pri, call, channel, nonisdn);
- }
- 
-+int pri_hold_acknowledge(struct pri *pri, q931_call *call)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_hold_acknowledge(pri, call);
-+}
-+
-+int pri_hold_reject(struct pri *pri, q931_call *call)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_hold_reject(pri, call);
-+}
-+
-+int pri_retrieve_acknowledge(struct pri *pri, q931_call *call, int channel)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_retrieve_acknowledge(pri, call, channel);
-+}
-+
-+int pri_retrieve_reject(struct pri *pri, q931_call *call)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_retrieve_reject(pri, call);
-+}
-+
-+int pri_suspend_acknowledge(struct pri *pri, q931_call *call, char *display)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_suspend_acknowledge(pri, call, display);
-+}
-+
-+int pri_suspend_reject(struct pri *pri, q931_call *call, char *display)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_suspend_reject(pri, call, display);
-+}
-+
-+int pri_resume_reject(struct pri *pri, q931_call *call, char *display)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_resume_reject(pri, call, display);
-+}
-+
-+int pri_resume_acknowledge(struct pri *pri, q931_call *call, int channel, char *display)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_resume_acknowledge(pri, call, channel, display);
-+}
-+
-+int pri_facility(struct pri *pri, q931_call *call, int operation, char *arguments)
-+{
-+	if (!pri || !call)
-+		return -1;
-+	return q931_facility(pri, call, operation, arguments);
-+}
-+
- #if 0
- /* deprecated routines, use pri_hangup */
- int pri_release(struct pri *pri, q931_call *call, int cause)
-@@ -310,12 +396,24 @@
- 
- int pri_hangup(struct pri *pri, q931_call *call, int cause)
- {
-+	int res=0;
- 	if (!pri || !call)
- 		return -1;
- 	if (cause == -1)
- 		/* normal clear cause */
- 		cause = 16;
--	return q931_hangup(pri, call, cause);
-+	if (pri->localtype == BRI_NETWORK_PTMP) {
-+	    res = q921_hangup(pri, call, 127);
-+	    if (res) {
-+		// q921_setup might give a HANGUP_ACK, if nobody got the call
-+		q931_hangup(pri, call, cause);
-+		return res;
-+	    } else {
-+		return q931_hangup(pri, call, cause);
-+	    }
-+	} else {
-+	    return q931_hangup(pri, call, cause);
-+	}
- }
- 
- int pri_reset(struct pri *pri, int channel)
-@@ -471,13 +569,14 @@
- 	}
- 	len += sprintf(buf + len, "Q921 Outstanding: %d\n", q921outstanding);
- #endif
--	len += sprintf(buf + len, "Window Length: %d/%d\n", pri->windowlen, pri->window);
--	len += sprintf(buf + len, "Sentrej: %d\n", pri->sentrej);
--	len += sprintf(buf + len, "SolicitFbit: %d\n", pri->solicitfbit);
--	len += sprintf(buf + len, "Retrans: %d\n", pri->retrans);
--	len += sprintf(buf + len, "Busy: %d\n", pri->busy);
-+	if (pri->localtype != BRI_NETWORK_PTMP) {
-+	    len += sprintf(buf + len, "Window Length: %d/%d\n", pri->windowlen[0], pri->window[0]);
-+	    len += sprintf(buf + len, "Sentrej: %d\n", pri->sentrej[0]);
-+	    len += sprintf(buf + len, "SolicitFbit: %d\n", pri->solicitfbit[0]);
-+	    len += sprintf(buf + len, "Retrans: %d\n", pri->retrans[0]);
-+	    len += sprintf(buf + len, "Busy: %d\n", pri->busy[0]);
-+	}
- 	len += sprintf(buf + len, "Overlap Dial: %d\n", pri->overlapdial);
--
- 	return strdup(buf);
- }
- 
-diff -urNad --exclude=CVS --exclude=.svn ./pri_internal.h /tmp/dpep-work.aULY0X/libpri-1.0.9/pri_internal.h
---- ./pri_internal.h	2005-07-14 12:30:35.000000000 +0100
-+++ /tmp/dpep-work.aULY0X/libpri-1.0.9/pri_internal.h	2005-07-14 12:31:07.929276720 +0100
-@@ -30,7 +30,10 @@
- struct pri_sched {
- 	struct timeval when;
- 	void (*callback)(void *data);
-+	void (*callback2)(void *data, int);
- 	void *data;
-+	char hasdata2;
-+	int data2;
- };
- 
- struct q921_frame;
-@@ -38,8 +41,15 @@
- enum q931_mode;
- 
- /* No more than 128 scheduled events */
-+/* XXX is this sufficient for nfs ??? */
- #define MAX_SCHED 128
- 
-+/* this can be freely configured to support more devices .... ok, 63 would be max! */
-+#define Q921_MAX_TEIS 16
-+
-+/* dynamically allocated TEIs start here */
-+#define Q921_TEI_BASE 64
-+
- struct pri {
- 	int fd;				/* File descriptor for D-Channel */
- 	struct pri *subchannel;	/* Sub-channel if appropriate */
-@@ -57,33 +67,43 @@
- 	int protodisc;
- 	
- 	/* Q.921 State */
--	int q921_state;	
--	int window;			/* Max window size */
--	int windowlen;		/* Fullness of window */
--	int v_s;			/* Next N(S) for transmission */
--	int v_a;			/* Last acknowledged frame */
--	int v_r;			/* Next frame expected to be received */
--	int v_na;			/* What we've told our peer we've acknowledged */
--	int solicitfbit;	/* Have we sent an I or S frame with the F-bit set? */
--	int retrans;		/* Retransmissions */
--	int sentrej;		/* Are we in reject state */
--	
--	int cref;			/* Next call reference value */
--	
--	int busy;			/* Peer is busy */
-+ 	int q921_state[Q921_MAX_TEIS];	
-+ 	char dchanup;
-+ 	
-+ 	/* TEI registry */
-+     	char q921_teis[Q921_MAX_TEIS];
-+  	
-+ 	unsigned int ri; 
-+ 
-+ 	int cref;			/* Next call reference value */  // let's think about this for a while...
-+  	
-+ 	int busy[Q921_MAX_TEIS];			/* Peer is busy */
-+  
-+ 	int window[Q921_MAX_TEIS];			/* Max window size */
-+	int windowlen[Q921_MAX_TEIS];		/* Fullness of window */
-+ 	int v_s[Q921_MAX_TEIS];			/* Next N(S) for transmission */
-+ 	int v_a[Q921_MAX_TEIS];			/* Last acknowledged frame */
-+ 	int v_r[Q921_MAX_TEIS];			/* Next frame expected to be received */
-+ 	int v_na[Q921_MAX_TEIS];			/* What we've told our peer we've acknowledged */
-+ 	int solicitfbit[Q921_MAX_TEIS];	/* Have we sent an I or S frame with the F-bit set? */
-+ 	int retrans[Q921_MAX_TEIS];		/* Retransmissions */
- 
--	/* Various timers */
--	int sabme_timer;	/* SABME retransmit */
--	int t203_timer;		/* Max idle time */
--	int t200_timer;		/* T-200 retransmission timer */
-+	int sentrej[Q921_MAX_TEIS];		/* Are we in reject state */
- 	
-+	/* Various timers */
-+ 	int sabme_timer[Q921_MAX_TEIS];
-+ 	int t203_timer[Q921_MAX_TEIS];
-+ 	int t202_timer[Q921_MAX_TEIS];
-+ 	int t201_timer[Q921_MAX_TEIS];
-+ 	int t200_timer[Q921_MAX_TEIS];
-+
- 	/* Used by scheduler */
- 	struct timeval tv;
- 	int schedev;
- 	pri_event ev;		/* Static event thingy */
- 	
- 	/* Q.921 Re-transmission queue */
--	struct q921_frame *txqueue;
-+	struct q921_frame *txqueue[Q921_MAX_TEIS];
- 	
- 	/* Q.931 calls */
- 	q931_call **callpool;
-@@ -121,6 +141,7 @@
- #define PRI_SWITCH_GR303_TMC_SWITCHING	11
- 
- extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);
-+extern int pri_schedule_event2(struct pri *pri, int ms, void (*function)(void *data, int data2), void *data, int data2);
- 
- extern pri_event *pri_schedule_run(struct pri *pri);
- 
-diff -urNad --exclude=CVS --exclude=.svn ./pri_q921.h /tmp/dpep-work.aULY0X/libpri-1.0.9/pri_q921.h
---- ./pri_q921.h	2005-07-14 12:30:35.000000000 +0100
-+++ /tmp/dpep-work.aULY0X/libpri-1.0.9/pri_q921.h	2005-07-14 12:31:07.930276568 +0100
-@@ -39,9 +39,14 @@
- 
- #define T_WAIT_MIN	2000
- #define T_WAIT_MAX	10000
--#define T_200		1000		/* 1 second between SABME's */
-+#define T_200		3000		/* 3 second between SABME's */
-+#define T_201		2000
-+#define T_202		5000		/* 5 seconds between TEI requests */
- #define T_203		10000		/* 10 seconds with no packets max */
- #define N_200		3		/* 3 retries */
-+#define N_202		3
-+
-+#define T_303		4000
- 
- #define Q921_FRAMETYPE_MASK	0x3
- 
-@@ -50,6 +55,13 @@
- #define Q921_FRAMETYPE_S	0x1
- 
- #define Q921_TEI_GROUP				127
-+#define Q921_TEI_ID_REQUEST	0x1
-+#define Q921_TEI_ID_ASSIGNED	0x2
-+#define Q921_TEI_ID_DENIED	0x3
-+#define Q921_TEI_ID_CHK_REQ	0x4
-+#define Q921_TEI_ID_CHK_RES	0x5
-+#define Q921_TEI_ID_REMOVE	0x6
-+#define Q921_TEI_ID_VERIFY	0x7
- #define Q921_TEI_GR303_EOC_PATH			0
- #define Q921_TEI_GR303_EOC_OPS			4
- #define Q921_TEI_GR303_TMC_SWITCHING		0
-@@ -167,12 +179,14 @@
- extern void q921_dump(q921_h *h, int len, int showraw, int txrx);
- 
- /* Bring up the D-channel */
--extern void q921_start(struct pri *pri, int now);
-+extern void q921_start(struct pri *pri, int now, int tei);
- 
--extern void q921_reset(struct pri *pri);
-+extern void q921_reset(struct pri *pri, int tei);
- 
- extern pri_event *q921_receive(struct pri *pri, q921_h *h, int len);
- 
--extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr);
-+extern int q921_transmit_uframe(struct pri *pri, void *buf, int len, int cr, int tei);
-+
-+extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr, int tei);
- 
- #endif
-diff -urNad --exclude=CVS --exclude=.svn ./pri_q931.h /tmp/dpep-work.aULY0X/libpri-1.0.9/pri_q931.h
---- ./pri_q931.h	2005-07-14 12:30:35.000000000 +0100
-+++ /tmp/dpep-work.aULY0X/libpri-1.0.9/pri_q931.h	2005-07-14 12:31:07.930276568 +0100
-@@ -190,6 +190,10 @@
- #define Q931_IE_CODESET(x)		((x) >> 8)
- #define Q931_IE_IE(x)			((x) & 0xff)
- #define Q931_FULL_IE(codeset, ie)	(((codeset) << 8) | ((ie) & 0xff))
-+#define Q931_IE_MAX_LEN			257
-+
-+// BRI+
-+#define Q931_COLP	0x4c
- 
- #define Q931_DISPLAY					0x28
- #define Q931_IE_SEGMENTED_MSG			0x00
-@@ -217,6 +221,8 @@
- #define Q931_IE_USER_USER				0x7E
- #define Q931_IE_ESCAPE_FOR_EXT			0x7F
- 
-+#define Q931_IE_SPECIAL		0x02
-+
- 
- /* Call state stuff */
- #define Q931_CALL_STATE_NULL				0
-@@ -242,7 +248,7 @@
- /* EuroISDN  */
- #define Q931_SENDING_COMPLETE		0xa1
- 
--extern int q931_receive(struct pri *pri, q931_h *h, int len);
-+extern int q931_receive(struct pri *pri, q931_h *h, int len, int tei);
- 
- extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info);
- 
-@@ -256,6 +262,10 @@
- 
- extern int q931_information(struct pri *pri, q931_call *call, char digit);
- 
-+extern int q931_information_display(struct pri *pri, q931_call *call, char *display);
-+
-+extern int q931_add_display(struct pri *pri, q931_call *call, char *display);
-+
- extern int q931_connect(struct pri *pri, q931_call *call, int channel, int nonisdn);
- 
- extern int q931_release(struct pri *pri, q931_call *call, int cause);
-@@ -264,6 +274,10 @@
- 
- extern int q931_hangup(struct pri *pri, q931_call *call, int cause);
- 
-+extern int q921_hangup(struct pri *pri, q931_call *c, int tei);
-+
-+extern int q921_handle_hangup(struct pri *pri, q931_call *c, int tei);
-+
- extern int q931_restart(struct pri *pri, int channel);
- 
- extern int q931_call_getcrv(struct pri *pri, q931_call *call, int *callmode);
-@@ -276,5 +290,23 @@
- extern void q931_dump(q931_h *h, int len, int txrx);
- 
- extern void __q931_destroycall(struct pri *pri, q931_call *c);
-+
-+extern int q931_hold_acknowledge(struct pri *pri, q931_call *c);
-+
-+extern int q931_hold_reject(struct pri *pri, q931_call *c);
-+
-+extern int q931_retrieve_acknowledge(struct pri *pri, q931_call *c, int channel);
-+	
-+extern int q931_retrieve_reject(struct pri *pri, q931_call *c);
-+
-+extern int q931_suspend_acknowledge(struct pri *pri, q931_call *c, char *display);
- 	
-+extern int q931_suspend_reject(struct pri *pri, q931_call *c, char *display);
-+
-+extern int q931_resume_reject(struct pri *pri, q931_call *c, char *display);
-+
-+extern int q931_resume_acknowledge(struct pri *pri, q931_call *c, int channel, char *display);
-+
-+extern int q931_facility(struct pri *pri, q931_call *c, int operation, char *arguments);
-+
- #endif
-diff -urNad --exclude=CVS --exclude=.svn ./prisched.c /tmp/dpep-work.aULY0X/libpri-1.0.9/prisched.c
---- ./prisched.c	2005-07-14 12:30:35.000000000 +0100
-+++ /tmp/dpep-work.aULY0X/libpri-1.0.9/prisched.c	2005-07-14 12:31:07.930276568 +0100
-@@ -35,7 +35,7 @@
- 	int x;
- 	struct timeval tv;
- 	for (x=1;x<MAX_SCHED;x++)
--		if (!pri->pri_sched[x].callback)
-+		if ((!pri->pri_sched[x].callback2) && (!pri->pri_sched[x].callback))
- 			break;
- 	if (x == MAX_SCHED) {
- 		pri_error("No more room in scheduler\n");
-@@ -52,7 +52,39 @@
- 	}
- 	pri->pri_sched[x].when = tv;
- 	pri->pri_sched[x].callback = function;
-+	pri->pri_sched[x].callback2 = NULL;
- 	pri->pri_sched[x].data = data;
-+	pri->pri_sched[x].hasdata2 = 0;
-+	pri->pri_sched[x].data2 = 0;
-+	return x;
-+}
-+
-+int pri_schedule_event2(struct pri *pri, int ms, void (*function)(void *data, int data2), void *data, int data2)
-+{
-+	int x;
-+	struct timeval tv;
-+	for (x=1;x<MAX_SCHED;x++)
-+		if ((!pri->pri_sched[x].callback2) && (!pri->pri_sched[x].callback))
-+			break;
-+	if (x == MAX_SCHED) {
-+		pri_error("No more room in scheduler\n");
-+		return -1;
-+	}
-+	if (x > maxsched)
-+		maxsched = x;
-+	gettimeofday(&tv, NULL);
-+	tv.tv_sec += ms / 1000;
-+	tv.tv_usec += (ms % 1000) * 1000;
-+	if (tv.tv_usec > 1000000) {
-+		tv.tv_usec -= 1000000;
-+		tv.tv_sec += 1;
-+	}
-+	pri->pri_sched[x].when = tv;
-+	pri->pri_sched[x].callback = NULL;
-+	pri->pri_sched[x].callback2 = function;
-+	pri->pri_sched[x].data = data;
-+	pri->pri_sched[x].hasdata2 = 1;
-+	pri->pri_sched[x].data2 = data2;
- 	return x;
- }
- 
-@@ -64,7 +96,7 @@
- 	if (pri->subchannel)
- 		closest = pri_schedule_next(pri->subchannel);
- 	for (x=1;x<MAX_SCHED;x++) {
--		if (pri->pri_sched[x].callback && 
-+		if ((pri->pri_sched[x].callback || pri->pri_sched[x].callback2) && 
- 			(!closest || (closest->tv_sec > pri->pri_sched[x].when.tv_sec) ||
- 				((closest->tv_sec == pri->pri_sched[x].when.tv_sec) && 
- 				 (closest->tv_usec > pri->pri_sched[x].when.tv_usec))))
-@@ -75,26 +107,38 @@
- 
- static pri_event *__pri_schedule_run(struct pri *pri, struct timeval *tv)
- {
--	int x;
--	void (*callback)(void *);
--	void *data;
-+ 	int x;
-+ 	void (*callback)(void *);
-+	void (*callback2)(void *, int);
-+ 	void *data;
-+	int data2;
- 	pri_event *e;
-+
- 	if (pri->subchannel) {
- 		if ((e = __pri_schedule_run(pri->subchannel, tv))) {
- 			return e;
- 		}
- 	}
- 	for (x=1;x<MAX_SCHED;x++) {
--		if (pri->pri_sched[x].callback &&
-+		if ((pri->pri_sched[x].callback || pri->pri_sched[x].callback2) &&
- 			((pri->pri_sched[x].when.tv_sec < tv->tv_sec) ||
- 			 ((pri->pri_sched[x].when.tv_sec == tv->tv_sec) &&
- 			  (pri->pri_sched[x].when.tv_usec <= tv->tv_usec)))) {
- 			        pri->schedev = 0;
- 			  	callback = pri->pri_sched[x].callback;
-+			  	callback2 = pri->pri_sched[x].callback2;
- 				data = pri->pri_sched[x].data;
-+				data2 = pri->pri_sched[x].data2;
- 				pri->pri_sched[x].callback = NULL;
-+				pri->pri_sched[x].callback2 = NULL;
- 				pri->pri_sched[x].data = NULL;
--				callback(data);
-+				pri->pri_sched[x].data2 = 0;
-+				if (pri->pri_sched[x].hasdata2 == 1) {
-+				    pri->pri_sched[x].hasdata2 = 0;
-+				    callback2(data, data2);
-+				} else {
-+				    callback(data);
-+				}
-             if (pri->schedev)
-                   return &pri->ev;
- 	    }
-@@ -115,4 +159,5 @@
- 	if ((id >= MAX_SCHED) || (id < 0)) 
- 		pri_error("Asked to delete sched id %d???\n", id);
- 	pri->pri_sched[id].callback = NULL;
-+	pri->pri_sched[id].callback2 = NULL;
- }
-diff -urNad --exclude=CVS --exclude=.svn ./pritest.c /tmp/dpep-work.aULY0X/libpri-1.0.9/pritest.c
---- ./pritest.c	2005-07-14 12:30:35.000000000 +0100
-+++ /tmp/dpep-work.aULY0X/libpri-1.0.9/pritest.c	2005-07-14 12:31:07.931276416 +0100
-@@ -51,8 +51,8 @@
- #define PRI_DEF_NODETYPE	PRI_CPE
- #define PRI_DEF_SWITCHTYPE	PRI_SWITCH_NI2
- 
--#define MAX_CHAN		32
--#define	DCHANNEL_TIMESLOT	16
-+#define MAX_CHAN		3
-+#define	DCHANNEL_TIMESLOT	3
- 
- 
- static int offset = 0;
-@@ -60,7 +60,7 @@
- static void do_channel(ZAP *z)
- {
- 	/* This is the part that runs on a given channel */
--	zap_playf(z, "raw.ulaw", 0);
-+	zap_playf(z, "raw.alaw", 0);
- }
- 
- struct pri_chan {
-@@ -76,6 +76,14 @@
- 		return PRI_CPE;
- 	if (!strcasecmp(node, "network"))
- 		return PRI_NETWORK;
-+	if (!strcasecmp(node, "bri_cpe_ptmp"))
-+		return BRI_CPE_PTMP;
-+	if (!strcasecmp(node, "bri_network_ptmp"))
-+		return BRI_NETWORK_PTMP;
-+	if (!strcasecmp(node, "bri_cpe"))
-+		return BRI_CPE;
-+	if (!strcasecmp(node, "bri_network"))
-+		return BRI_NETWORK;
- 	return -1;
- }
- 
-@@ -285,6 +293,10 @@
- 		}
- 		
- 		break;
-+	case PRI_EVENT_HANGUP_REQ:
-+		printf("-- Hanging up channel %d\n", e->hangup.channel);
-+		hangup_channel(e->hangup.channel);
-+		break;
- 	default:
- 		fprintf(stderr, "--!! Unknown PRI event %d\n", e->e);
- 	}
-diff -urNad --exclude=CVS --exclude=.svn ./q921.c /tmp/dpep-work.aULY0X/libpri-1.0.9/q921.c
---- ./q921.c	2005-07-14 12:30:35.000000000 +0100
-+++ /tmp/dpep-work.aULY0X/libpri-1.0.9/q921.c	2005-07-14 12:31:07.935275808 +0100
-@@ -5,6 +5,8 @@
-  *
-  * Copyright (C) 2001, Linux Support Services, Inc.
-  * All Rights Reserved.
-+ * Copyright (C) 2003,2004,2005 Junghanns.NET GmbH
-+ * Klaus-Peter Junghanns <kpj at junghanns.net>
-  *
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License as published by
-@@ -49,19 +51,22 @@
- 	(hf).h.tei = (pri)->tei; \
- } while(0)
- 
--static void reschedule_t203(struct pri *pri);
-+static void reschedule_t203(struct pri *pri, int tei);
- 
--static void q921_discard_retransmissions(struct pri *pri)
-+static void q921_discard_retransmissions(struct pri *pri, int tei)
- {
- 	struct q921_frame *f, *p;
--	f = pri->txqueue;
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+	
-+	f = pri->txqueue[teio];
- 	while(f) {
--		p = f;
--		f = f->next;
--		/* Free frame */
--		free(p);
-+	    p = f;
-+	    f = f->next;
-+	    /* Free frame */
-+	    free(p);
- 	}
--	pri->txqueue = NULL;
-+        pri->txqueue[teio] = NULL;
- }
- 
- static int q921_transmit(struct pri *pri, q921_h *h, int len) 
-@@ -80,18 +85,22 @@
- #endif
- 	/* Just send it raw */
- 	if (pri->debug & PRI_DEBUG_Q921_DUMP)
--		q921_dump(h, len, pri->debug & PRI_DEBUG_Q921_RAW, 1);
-+		q921_dump(h, len, 1, 1);
- 	/* Write an extra two bytes for the FCS */
- 	res = write(pri->fd, h, len + 2);
- 	if (res != (len + 2)) {
- 		pri_error("Short write: %d/%d (%s)\n", res, len + 2, strerror(errno));
- 		return -1;
- 	}
--	reschedule_t203(pri);
-+	if (pri->localtype == BRI_CPE_PTMP) {
-+	    reschedule_t203(pri, pri->tei);
-+	} else if (h->h.tei != Q921_TEI_GROUP) {
-+	    reschedule_t203(pri, h->h.tei);
-+	}
- 	return 0;
- }
- 
--static void q921_send_ua(struct pri *pri, int pfbit)
-+static void q921_send_ua(struct pri *pri, int pfbit, int tei)
- {
- 	q921_h h;
- 	Q921_INIT(pri, h);
-@@ -99,6 +108,7 @@
- 	h.u.m2 = 0;		/* M2 = 0 */
- 	h.u.p_f = pfbit;	/* Final bit on */
- 	h.u.ft = Q921_FRAMETYPE_U;
-+	h.h.tei = tei;
- 	switch(pri->localtype) {
- 	case PRI_NETWORK:
- 		h.h.c_r = 0;
-@@ -106,6 +116,19 @@
- 	case PRI_CPE:
- 		h.h.c_r = 1;
- 		break;
-+	case BRI_NETWORK_PTMP:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE_PTMP:
-+		h.h.tei = pri->tei;
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_NETWORK:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE:
-+		h.h.c_r = 1;
-+		break;
- 	default:
- 		pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
- 		return;
-@@ -114,19 +137,302 @@
- 		pri_message("Sending Unnumbered Acknowledgement\n");
- 	q921_transmit(pri, &h, 3);
- }
-+/*
-+static void q921_send_disconnect(struct pri *pri, int pfbit, int tei)
-+{
-+	q921_h h;
-+	Q921_INIT(pri, h);
-+	h.u.m3 = 2;
-+	h.u.m2 = 0;
-+	h.u.p_f = pfbit;
-+	h.u.ft = Q921_FRAMETYPE_U;
-+	h.h.tei = tei;
-+	switch(pri->localtype) {
-+	case PRI_NETWORK:
-+		h.h.c_r = 0;
-+		break;
-+	case PRI_CPE:
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_NETWORK_PTMP:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE_PTMP:
-+		h.h.tei = pri->tei;
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_NETWORK:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE:
-+		h.h.c_r = 1;
-+		break;
-+	default:
-+		pri_error("Don't know how to disconnect on a type %d node\n", pri->localtype);
-+		return;
-+	}
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+		pri_message("Sending Disconnect\n");
-+	q921_transmit(pri, &h, 3);
-+}
-+*/
-+static void q921_send_dm(struct pri *pri, int pfbit, int tei)
-+{
-+	q921_h h;
-+	Q921_INIT(pri, h);
-+	h.u.m3 = 0;		/* M3 = 0 */
-+	h.u.m2 = 3;		/* M2 = 3 */
-+	h.u.p_f = pfbit;	/* Final bit on */
-+	h.u.ft = Q921_FRAMETYPE_U;
-+	h.h.tei = tei;
-+	switch(pri->localtype) {
-+	case PRI_NETWORK:
-+		h.h.c_r = 0;
-+		break;
-+	case PRI_CPE:
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_NETWORK_PTMP:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE_PTMP:
-+		h.h.tei = pri->tei;
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_NETWORK:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE:
-+		h.h.c_r = 1;
-+		break;
-+	default:
-+		pri_error("Don't know how to DM on a type %d node\n", pri->localtype);
-+		return;
-+	}
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+		pri_message("Sending DM\n");
-+	q921_transmit(pri, &h, 3);
-+}
- 
--static void q921_send_sabme_now(void *vpri);
-+static void q921_send_teireq(void *vpri) {
-+    struct pri *pri = vpri;
-+    unsigned short ri=0x6464;
-+    q921_u *f;
-+    ri = rand();
- 
--static void q921_send_sabme(void *vpri, int now)
-+    if (pri->localtype != BRI_CPE_PTMP) {
-+	pri_error("TEI req for non-ptmp???\n"); 
-+	return;
-+    }
-+    if (pri->t202_timer[0]) { 
-+	pri_schedule_del(pri, pri->t202_timer[0]);
-+	pri->t202_timer[0] = 0;
-+    }
-+
-+    pri->t202_timer[0] = pri_schedule_event(pri, T_202, q921_send_teireq, pri);
-+
-+    pri->ri = ri;
-+    f = malloc(sizeof(q921_u) + 5 + 2);
-+    memset(f,0x0,sizeof(q921_u) + 5 + 2);
-+    if (f) {
-+	f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
-+	f->h.tei = Q921_TEI_GROUP;
-+	f->h.c_r = 0;	
-+	f->h.ea1 = 0;	
-+	f->h.ea2 = 1;	
-+	f->m2 = 0;
-+	f->m3 = 0;
-+	f->ft = Q921_FRAMETYPE_U;
-+	f->data[0] = 0xf;
-+	f->data[1] = ri >> 8;
-+	f->data[2] = ri & 0xff;
-+	f->data[3] = Q921_TEI_ID_REQUEST;
-+	f->data[4] = 0xff;
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+    	    pri_message("Sending TEI Request ri=%d\n",ri);
-+	q921_transmit(pri,(q921_h *)&(f->h),8);
-+	free(f);
-+    }
-+}
-+
-+static void q921_send_teiassign(struct pri *pri,int ri,int tei) {
-+    q921_u *f;
-+
-+    if (pri->localtype != BRI_NETWORK_PTMP) {
-+	pri_error("TEI assign for non-ptmp???\n"); 
-+	return;
-+    }
-+
-+    f = malloc(sizeof(q921_u) + 5 + 2);
-+    memset(f,0x0,sizeof(q921_u) + 5 + 2);
-+    if (f) {
-+	f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
-+	f->h.tei = Q921_TEI_GROUP;
-+	f->h.c_r = 1;	
-+	f->h.ea1 = 0;	
-+	f->h.ea2 = 1;	
-+	f->m2 = 0;
-+	f->m3 = 0;
-+	f->ft = Q921_FRAMETYPE_U;
-+	f->data[0] = 0xf;
-+	f->data[1] = ri >> 8;
-+	f->data[2] = ri & 0xff;
-+	f->data[3] = Q921_TEI_ID_ASSIGNED;
-+	f->data[4] = (tei << 1) | 0x1;
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+    	    pri_message("Sending TEI assign ri=%d tei=%d\n",ri,tei);
-+	q921_transmit(pri,(q921_h *)&(f->h),8);
-+	free(f);
-+    }
-+}
-+
-+static void q921_send_teichkresp(struct pri *pri,int tei) {
-+    q921_u *f;
-+    unsigned short ri=0x6464;
-+    ri = rand();
-+
-+    if (pri->localtype != BRI_CPE_PTMP) {
-+	pri_error("TEI check response for non-ptmp???\n"); 
-+	return;
-+    }
-+
-+    f = malloc(sizeof(q921_u) + 5 + 2);
-+    memset(f,0x0,sizeof(q921_u) + 5 + 2);
-+    if (f) {
-+	f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
-+	f->h.tei = Q921_TEI_GROUP;
-+	f->h.c_r = 0; // command u->n	
-+	f->h.ea1 = 0;	
-+	f->h.ea2 = 1;	
-+	f->m2 = 0;
-+	f->m3 = 0;
-+	f->ft = Q921_FRAMETYPE_U;
-+	f->data[0] = 0xf;
-+	f->data[1] = ri >> 8;
-+	f->data[2] = ri & 0xff;
-+	f->data[3] = Q921_TEI_ID_CHK_RES;
-+	f->data[4] = (tei << 1) | 0x1;
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+    	    pri_message("Sending TEI check resp ri=%d tei=%d\n",ri,tei);
-+	q921_transmit(pri,(q921_h *)&(f->h),8);
-+	free(f);
-+    }
-+}
-+/* 
-+static void q921_send_teiverify(struct pri *pri,int tei) {
-+    q921_u *f;
-+
-+    if (pri->localtype != BRI_CPE_PTMP) {
-+	pri_error("TEI verify for non-ptmp???\n"); 
-+	return;
-+    }
-+
-+    f = malloc(sizeof(q921_u) + 5 + 2);
-+    memset(f,0x0,sizeof(q921_u) + 5 + 2);
-+    if (f) {
-+	f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
-+	f->h.tei = Q921_TEI_GROUP;
-+	f->h.c_r = 0; // command u->n	
-+	f->h.ea1 = 0;	
-+	f->h.ea2 = 1;	
-+	f->m2 = 0;
-+	f->m3 = 0;
-+	f->ft = Q921_FRAMETYPE_U;
-+	f->data[0] = 0xf;
-+	f->data[1] = 0;
-+	f->data[2] = 0;
-+	f->data[3] = Q921_TEI_ID_VERIFY;
-+	f->data[4] = (tei << 1) | 0x1;
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+    	    pri_message("Sending TEI verify tei=%d\n", tei);
-+	q921_transmit(pri,(q921_h *)&(f->h),8);
-+	free(f);
-+    }
-+}
-+*/
-+static void q921_send_teiremove(struct pri *pri, int tei) {
-+    q921_u *f;
-+    unsigned short ri=0x6464;
-+    ri = rand();
-+
-+    if (pri->localtype != BRI_NETWORK_PTMP) {
-+	pri_error("TEI remove for non-ptmp???\n"); 
-+	return;
-+    }
-+
-+    f = malloc(sizeof(q921_u) + 5 + 2);
-+    memset(f,0x0,sizeof(q921_u) + 5 + 2);
-+    if (f) {
-+	f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
-+	f->h.tei = Q921_TEI_GROUP;
-+	f->h.c_r = 1;	
-+	f->h.ea1 = 0;	
-+	f->h.ea2 = 1;	
-+	f->m2 = 0;
-+	f->m3 = 0;
-+	f->ft = Q921_FRAMETYPE_U;
-+	f->data[0] = 0xf;
-+	f->data[1] = ri >> 8;
-+	f->data[2] = ri & 0xff;
-+	f->data[3] = Q921_TEI_ID_REMOVE;
-+	f->data[4] = (tei << 1) | 0x1;
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+    	    pri_message("Sending TEI remove tei=%d\n",tei);
-+	q921_transmit(pri,(q921_h *)&(f->h),8);
-+	free(f);
-+    }
-+}
-+
-+static void q921_send_teidenied(struct pri *pri, int ri, int tei) {
-+    q921_u *f;
-+
-+    if (pri->localtype != BRI_NETWORK_PTMP) {
-+	pri_error("TEI ID denied for non-ptmp???\n"); 
-+	return;
-+    }
-+
-+    f = malloc(sizeof(q921_u) + 5 + 2);
-+    memset(f,0x0,sizeof(q921_u) + 5 + 2);
-+    if (f) {
-+	f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
-+	f->h.tei = Q921_TEI_GROUP;
-+	f->h.c_r = 1;	
-+	f->h.ea1 = 0;	
-+	f->h.ea2 = 1;	
-+	f->m2 = 0;
-+	f->m3 = 0;
-+	f->ft = Q921_FRAMETYPE_U;
-+	f->data[0] = 0xf;
-+	f->data[1] = ri >> 8;
-+	f->data[2] = ri & 0xff;
-+	f->data[3] = Q921_TEI_ID_DENIED;
-+	f->data[4] = (tei << 1) | 0x1;
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+    	    pri_message("Sending TEI ID denied tei=%d\n",tei);
-+	q921_transmit(pri,(q921_h *)&(f->h),8);
-+	free(f);
-+    }
-+}
-+
-+static void q921_send_sabme_now(void *vpri, int tei);
-+
-+static void q921_send_sabme(void *vpri, int now, int tei)
- {
- 	struct pri *pri = vpri;
- 	q921_h h;
--	pri_schedule_del(pri, pri->sabme_timer);
--	pri->sabme_timer = 0;
--	pri->sabme_timer = pri_schedule_event(pri, T_200, q921_send_sabme_now, pri);
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+
-+	if (pri->sabme_timer[teio]) {
-+	    pri_schedule_del(pri, pri->sabme_timer[teio]);
-+	    pri->sabme_timer[teio] = 0;
-+	}
-+	pri->sabme_timer[teio] = pri_schedule_event2(pri, T_200, q921_send_sabme_now, pri, tei);
- 	if (!now)
- 		return;
- 	Q921_INIT(pri, h);
-+	// XXX
-+	h.h.tei = tei;
- 	h.u.m3 = 3;	/* M3 = 3 */
- 	h.u.m2 = 3;	/* M2 = 3 */
- 	h.u.p_f = 1;	/* Poll bit set */
-@@ -138,6 +444,19 @@
- 	case PRI_CPE:
- 		h.h.c_r = 0;
- 		break;
-+	case BRI_NETWORK_PTMP:
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_CPE_PTMP:
-+		h.h.c_r = 0;
-+		h.h.tei = pri->tei;
-+		break;
-+	case BRI_NETWORK:
-+		h.h.c_r = 1;
-+		break;
-+	case BRI_CPE:
-+		h.h.c_r = 0;
-+		break;
- 	default:
- 		pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
- 		return;
-@@ -145,18 +464,20 @@
- 	if (pri->debug & PRI_DEBUG_Q921_STATE)
- 		pri_message("Sending Set Asynchronous Balanced Mode Extended\n");
- 	q921_transmit(pri, &h, 3);
--	pri->q921_state = Q921_AWAITING_ESTABLISH;
-+	pri->q921_state[teio] = Q921_AWAITING_ESTABLISH;
- }
- 
--static void q921_send_sabme_now(void *vpri)
-+static void q921_send_sabme_now(void *vpri, int tei)
- {
--	q921_send_sabme(vpri, 1);
-+	q921_send_sabme(vpri, 1, tei);
- }
- 
--static int q921_ack_packet(struct pri *pri, int num)
-+static int q921_ack_packet(struct pri *pri, int num, int tei)
- {
- 	struct q921_frame *f, *prev = NULL;
--	f = pri->txqueue;
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+	f = pri->txqueue[teio];
- 	while(f) {
- 		if (f->h.n_s == num) {
- 			/* Cancel each packet as necessary */
-@@ -164,26 +485,26 @@
- 			if (prev)
- 				prev->next = f->next;
- 			else
--				pri->txqueue = f->next;
-+				pri->txqueue[teio] = f->next;
- 			if (pri->debug & PRI_DEBUG_Q921_STATE)
--				pri_message("-- ACKing packet %d, new txqueue is %d (-1 means empty)\n", f->h.n_s, pri->txqueue ? pri->txqueue->h.n_s : -1);
-+				pri_message("-- ACKing packet %d, new txqueue is %d (-1 means empty)\n", f->h.n_s, pri->txqueue[teio] ? pri->txqueue[teio]->h.n_s : -1);
- 			/* Update v_a */
--			pri->v_a = num;
-+			pri->v_a[teio] = num;
- 			free(f);
- 			/* Reset retransmission counter if we actually acked something */
--			pri->retrans = 0;
-+			pri->retrans[teio] = 0;
- 			/* Decrement window size */
--			pri->windowlen--;
-+			pri->windowlen[teio]--;
- 			/* Search for something to send */
--			f = pri->txqueue;
-+			f = pri->txqueue[teio];
- 			while(f) {
- 				if (!f->transmitted) {
- 					/* Send it now... */
- 					if (pri->debug & PRI_DEBUG_Q921_STATE)
- 						pri_message("-- Finally transmitting %d, since window opened up\n", f->h.n_s);
- 					f->transmitted++;
--					pri->windowlen++;
--					f->h.n_r = pri->v_r;
-+					pri->windowlen[teio]++;
-+					f->h.n_r = pri->v_r[teio];
- 					q921_transmit(pri, (q921_h *)(&f->h), f->len);
- 					break;
- 				}
-@@ -197,77 +518,85 @@
- 	return 0;
- }
- 
--static void t203_expire(void *);
--static void t200_expire(void *);
--static pri_event *q921_dchannel_down(struct pri *pri);
-+static void t203_expire(void *, int tei);
-+static void t200_expire(void *, int tei);
-+static pri_event *q921_dchannel_down(struct pri *pri, int tei);
- 
--static void reschedule_t203(struct pri *pri)
-+static void reschedule_t203(struct pri *pri, int tei)
- {
--	if (pri->t203_timer) {
--		pri_schedule_del(pri, pri->t203_timer);
--		if (pri->debug &  PRI_DEBUG_Q921_STATE)
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+	if (pri->t203_timer[teio]) {
-+		pri_schedule_del(pri, pri->t203_timer[teio]);
-+ 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
- 			pri_message("-- Restarting T203 counter\n");
- 		/* Nothing to transmit, start the T203 counter instead */
--		pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri);
-+		pri->t203_timer[teio] = pri_schedule_event2(pri, T_203, t203_expire, pri, tei);
- 	}
- }
- 
--static pri_event *q921_ack_rx(struct pri *pri, int ack)
-+static pri_event *q921_ack_rx(struct pri *pri, int ack, int tei)
- {
- 	int x;
- 	int cnt=0;
- 	pri_event *ev;
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
- 	/* Make sure the ACK was within our window */
--	for (x=pri->v_a; (x != pri->v_s) && (x != ack); Q921_INC(x));
-+	for (x=pri->v_a[teio]; (x != pri->v_s[teio]) && (x != ack); Q921_INC(x));
- 	if (x != ack) {
- 		/* ACK was outside of our window --- ignore */
--		pri_error("ACK received for '%d' outside of window of '%d' to '%d', restarting\n", ack, pri->v_a, pri->v_s);
--		ev = q921_dchannel_down(pri);
--		q921_start(pri, 1);
-+		pri_error("ACK received for '%d' outside of window of '%d' to '%d', restarting\n", ack, pri->v_a[teio], pri->v_s[teio]);
-+		ev = q921_dchannel_down(pri, tei);
-+		q921_start(pri, 1, tei);
- 		pri->schedev = 1;
- 		return ev;
- 	}
- 	/* Cancel each packet as necessary */
- 	if (pri->debug & PRI_DEBUG_Q921_STATE)
--		pri_message("-- ACKing all packets from %d to (but not including) %d\n", pri->v_a, ack);
--	for (x=pri->v_a; x != ack; Q921_INC(x)) 
--		cnt += q921_ack_packet(pri, x);	
--	if (!pri->txqueue) {
-+		pri_message("-- ACKing all packets from %d to (but not including) %d\n", pri->v_a[teio], ack);
-+	for (x=pri->v_a[teio]; x != ack; Q921_INC(x)) 
-+		cnt += q921_ack_packet(pri, x,tei);	
-+	if (!pri->txqueue[teio]) {
- 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
- 			pri_message("-- Since there was nothing left, stopping T200 counter\n");
- 		/* Something was ACK'd.  Stop T200 counter */
--		pri_schedule_del(pri, pri->t200_timer);
--		pri->t200_timer = 0;
-+		if (pri->t200_timer[teio]) {
-+		    pri_schedule_del(pri, pri->t200_timer[teio]);
-+		    pri->t200_timer[teio] = 0;
-+		}
- 	}
--	if (pri->t203_timer) {
-+	if (pri->t203_timer[teio]) {
- 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
- 			pri_message("-- Stopping T203 counter since we got an ACK\n");
--		pri_schedule_del(pri, pri->t203_timer);
--		pri->t203_timer = 0;
-+		pri_schedule_del(pri, pri->t203_timer[teio]);
-+		pri->t203_timer[teio] = 0;
- 	}
--	if (pri->txqueue) {
-+	if (pri->txqueue[teio]) {
- 		/* Something left to transmit, Start the T200 counter again if we stopped it */
- 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
--			pri_message("-- Something left to transmit (%d), restarting T200 counter\n", pri->txqueue->h.n_s);
--		if (!pri->t200_timer)
--			pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
-+			pri_message("-- Something left to transmit (%d), restarting T200 counter\n", pri->txqueue[teio]->h.n_s);
-+		if (!pri->t200_timer[teio])
-+			pri->t200_timer[teio] = pri_schedule_event2(pri, T_200, t200_expire, pri, tei);
- 	} else {
- 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
- 			pri_message("-- Nothing left, starting T203 counter\n");
- 		/* Nothing to transmit, start the T203 counter instead */
--		pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri);
-+		pri->t203_timer[teio] = pri_schedule_event2(pri, T_203, t203_expire, pri, tei);
- 	}
- 	return NULL;
- }
- 
--static void q921_reject(struct pri *pri, int pf)
-+static void q921_reject(struct pri *pri, int pf, int tei)
- {
- 	q921_h h;
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
- 	Q921_INIT(pri, h);
- 	h.s.x0 = 0;	/* Always 0 */
- 	h.s.ss = 2;	/* Reject */
- 	h.s.ft = 1;	/* Frametype (01) */
--	h.s.n_r = pri->v_r;	/* Where to start retransmission */
-+	h.s.n_r = pri->v_r[teio];	/* Where to start retransmission */
- 	h.s.p_f = pf;	
- 	switch(pri->localtype) {
- 	case PRI_NETWORK:
-@@ -276,23 +605,38 @@
- 	case PRI_CPE:
- 		h.h.c_r = 1;
- 		break;
-+	case BRI_NETWORK_PTMP:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE_PTMP:
-+		h.h.c_r = 1;
-+		h.h.tei = tei;
-+		break;
-+	case BRI_NETWORK:
-+		h.h.c_r = 0;
-+		break;
-+	case BRI_CPE:
-+		h.h.c_r = 1;
-+		break;
- 	default:
- 		pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
- 		return;
- 	}
- 	if (pri->debug & PRI_DEBUG_Q921_STATE)
--		pri_message("Sending Reject (%d)\n", pri->v_r);
--	pri->sentrej = 1;
-+		pri_message("Sending Reject (%d)\n", pri->v_r[teio]);
-+	pri->sentrej[teio] = 1;
- 	q921_transmit(pri, &h, 4);
- }
- 
--static void q921_rr(struct pri *pri, int pbit, int cmd) {
-+static void q921_rr(struct pri *pri, int pbit, int cmd, int tei) {
- 	q921_h h;
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
- 	Q921_INIT(pri, h);
- 	h.s.x0 = 0;	/* Always 0 */
- 	h.s.ss = 0; /* Receive Ready */
- 	h.s.ft = 1;	/* Frametype (01) */
--	h.s.n_r = pri->v_r;	/* N/R */
-+	h.s.n_r = pri->v_r[teio];	/* N/R */
- 	h.s.p_f = pbit;		/* Poll/Final set appropriately */
- 	switch(pri->localtype) {
- 	case PRI_NETWORK:
-@@ -307,81 +651,153 @@
- 		else
- 			h.h.c_r = 1;
- 		break;
-+	case BRI_NETWORK_PTMP:
-+		h.h.tei = tei;
-+		if (cmd)
-+			h.h.c_r = 1;
-+		else
-+			h.h.c_r = 0;
-+		break;
-+	case BRI_CPE_PTMP:
-+		h.h.tei = tei;
-+		if (cmd)
-+			h.h.c_r = 0;
-+		else
-+			h.h.c_r = 1;
-+		break;
-+	case BRI_NETWORK:
-+		if (cmd)
-+			h.h.c_r = 1;
-+		else
-+			h.h.c_r = 0;
-+		break;
-+	case BRI_CPE:
-+		if (cmd)
-+			h.h.c_r = 0;
-+		else
-+			h.h.c_r = 1;
-+		break;
- 	default:
- 		pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
- 		return;
- 	}
--	pri->v_na = pri->v_r;	/* Make a note that we've already acked this */
-+	pri->v_na[teio] = pri->v_r[teio];	/* Make a note that we've already acked this */
- 	if (pri->debug & PRI_DEBUG_Q921_STATE)
--		pri_message("Sending Receiver Ready (%d)\n", pri->v_r);
-+		pri_message("Sending Receiver Ready (%d)\n", pri->v_r[teio]);
- 	q921_transmit(pri, &h, 4);
- }
- 
--static void t200_expire(void *vpri)
-+static void t200_expire(void *vpri, int tei)
- {
- 	struct pri *pri = vpri;
--	if (pri->txqueue) {
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+	if (pri->txqueue[teio]) {
- 		/* Retransmit first packet in the queue, setting the poll bit */
- 		if (pri->debug & PRI_DEBUG_Q921_STATE)
- 			pri_message("-- T200 counter expired, What to do...\n");
- 		/* Force Poll bit */
--		pri->txqueue->h.p_f = 1;	
-+		pri->txqueue[teio]->h.p_f = 1;	
- 		/* Update nr */
--		pri->txqueue->h.n_r = pri->v_r;
--		pri->v_na = pri->v_r;
--		pri->solicitfbit = 1;
--		pri->retrans++;
-+		pri->txqueue[teio]->h.n_r = pri->v_r[teio];
-+		pri->v_na[teio] = pri->v_r[teio];
-+		pri->solicitfbit[teio] = 1;
-+		pri->retrans[teio]++;
-       /* Up to three retransmissions */
--      if (pri->retrans < N_200) {
-+      if (pri->retrans[teio] < N_200) {
-          /* Reschedule t200_timer */
-          if (pri->debug & PRI_DEBUG_Q921_STATE)
--            pri_message("-- Retransmitting %d bytes\n", pri->txqueue->len);
--		if (pri->busy) 
--			q921_rr(pri, 1, 0);
-+            pri_message("-- Retransmitting %d bytes\n", pri->txqueue[teio]->len);
-+		if (pri->busy[teio]) 
-+			q921_rr(pri, 1, 0, tei);
- 		else {
--			if (!pri->txqueue->transmitted) 
-+			if (!pri->txqueue[teio]->transmitted) 
- 				pri_error("!! Not good - head of queue has not been transmitted yet\n");
--			q921_transmit(pri, (q921_h *)&pri->txqueue->h, pri->txqueue->len);
-+			q921_transmit(pri, (q921_h *)&pri->txqueue[teio]->h, pri->txqueue[teio]->len);
- 		}
-          if (pri->debug & PRI_DEBUG_Q921_STATE) 
--               pri_message("-- Rescheduling retransmission (%d)\n", pri->retrans);
--         pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
-+               pri_message("-- Rescheduling retransmission (%d)\n", pri->retrans[teio]);
-+         pri->t200_timer[teio] = pri_schedule_event2(pri, T_200, t200_expire, pri, tei);
-       } else {
-          if (pri->debug & PRI_DEBUG_Q921_STATE) 
-                pri_message("-- Timeout occured, restarting PRI\n");
--         pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
--      	pri->t200_timer = 0;
--         q921_dchannel_down(pri);
--         q921_start(pri, 1);
-+    	pri->q921_state[teio] = Q921_LINK_CONNECTION_RELEASED;
-+    	pri->t200_timer[teio] = 0;
-+         q921_dchannel_down(pri, tei);
-+         q921_start(pri, 1, tei);
-          pri->schedev = 1;
-       }
--	} else if (pri->solicitfbit) {
-+	} else if (pri->solicitfbit[teio]) {
-          if (pri->debug & PRI_DEBUG_Q921_STATE)
-             pri_message("-- Retrying poll with f-bit\n");
--		pri->retrans++;
--		if (pri->retrans < N_200) {
--			pri->solicitfbit = 1;
--			q921_rr(pri, 1, 1);
--			pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
-+		pri->retrans[teio]++;
-+		if (pri->retrans[teio] < N_200) {
-+			pri->solicitfbit[teio] = 1;
-+			q921_rr(pri, 1, 1, tei);
-+			pri->t200_timer[teio] = pri_schedule_event2(pri, T_200, t200_expire, pri, tei);
- 		} else {
- 			if (pri->debug & PRI_DEBUG_Q921_STATE) 
- 				pri_message("-- Timeout occured, restarting PRI\n");
--			pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
--			pri->t200_timer = 0;
--			q921_dchannel_down(pri);
--			q921_start(pri, 1);
--			pri->schedev = 1;
-+        		pri->q921_state[teio] = Q921_LINK_CONNECTION_RELEASED;
-+      			pri->t200_timer[teio] = 0;
-+			q921_dchannel_down(pri, tei);
-+        		q921_start(pri, 1, tei); 
-+        		pri->schedev = 1; 
- 		}
- 	} else {
- 		pri_error("T200 counter expired, nothing to send...\n");
--	   	pri->t200_timer = 0;
-+	   	pri->t200_timer[teio] = 0;
- 	}
- }
- 
--int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr)
-+int q921_transmit_uframe(struct pri *pri, void *buf, int len, int cr, int tei)
-+{
-+	q921_u *uf;
-+	uf = malloc(sizeof(q921_u) + len + 2);
-+	memset(uf,0,sizeof(q921_u) + len + 2);
-+
-+	uf->h.sapi = 0;
-+	uf->h.ea1 = 0;
-+	uf->h.ea2 = 1;
-+	uf->h.tei = tei;
-+	uf->m3 = 0;
-+	uf->m2 = 0;
-+	uf->ft = Q921_FRAMETYPE_U;
-+	switch(pri->localtype) {
-+	case PRI_NETWORK:
-+		uf->h.c_r = 1;
-+		break;
-+	case PRI_CPE:
-+		uf->h.c_r = 0;
-+		break;
-+	case BRI_NETWORK_PTMP:
-+		uf->h.c_r = 1;
-+		break;
-+	case BRI_CPE_PTMP:
-+		uf->h.c_r = 0;
-+		break;
-+	case BRI_NETWORK:
-+		uf->h.c_r = 1;
-+		break;
-+	case BRI_CPE:
-+		uf->h.c_r = 0;
-+		break;
-+	default:
-+		pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
-+		return -1;
-+ 	}
-+	memcpy(uf->data,buf,len);
-+	q921_transmit(pri, (q921_h*)&(uf->h), 3+len);
-+	free(uf);
-+	return 0;
-+}
-+
-+int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr, int tei)
- {
- 	q921_frame *f, *prev=NULL;
--	for (f=pri->txqueue; f; f = f->next) prev = f;
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+	for (f=pri->txqueue[teio]; f; f = f->next) prev = f;
- 	f = malloc(sizeof(q921_frame) + len + 2);
- 	if (f) {
- 		memset(f,0,sizeof(q921_frame) + len + 2);
-@@ -399,47 +815,75 @@
- 			else
- 				f->h.h.c_r = 1;
- 		break;
-+		case BRI_NETWORK_PTMP:
-+			f->h.h.tei = tei;
-+			if (cr)
-+				f->h.h.c_r = 1;
-+			else
-+				f->h.h.c_r = 0;
-+		break;
-+		case BRI_CPE_PTMP:
-+			f->h.h.tei = pri->tei;
-+			if (cr)
-+				f->h.h.c_r = 0;
-+			else
-+				f->h.h.c_r = 1;
-+		break;
-+		case BRI_NETWORK:
-+			if (cr)
-+				f->h.h.c_r = 1;
-+			else
-+				f->h.h.c_r = 0;
-+		break;
-+		case BRI_CPE:
-+			if (cr)
-+				f->h.h.c_r = 0;
-+			else
-+				f->h.h.c_r = 1;
-+		break;
- 		}
- 		f->next = NULL;
- 		f->transmitted = 0;
- 		f->len = len + 4;
- 		memcpy(f->h.data, buf, len);
--		f->h.n_s = pri->v_s;
--		f->h.n_r = pri->v_r;
--		pri->v_s++;
--		pri->v_na = pri->v_r;
-+		f->h.n_s = pri->v_s[teio];
-+		f->h.n_r = pri->v_r[teio];
-+		pri->v_s[teio]++;
-+		pri->v_na[teio] = pri->v_r[teio];
- 		f->h.p_f = 0;
- 		f->h.ft = 0;
- 		if (prev)
- 			prev->next = f;
- 		else
--			pri->txqueue = f;
-+			pri->txqueue[teio] = f;
- 		/* Immediately transmit unless we're in a recovery state, or the window
- 		   size is too big */
--		if (!pri->retrans && !pri->busy) {
--			if (pri->windowlen < pri->window) {
--				pri->windowlen++;
-+// XXXXXX think about this...
-+//		if (!pri->retrans[teio] && !pri->busy[teio]) {
-+		if (!pri->retrans[teio] && !pri->busy[teio]) {
-+			if (pri->windowlen[teio] < pri->window[teio]) {
-+				pri->windowlen[teio]++;
- 				q921_transmit(pri, (q921_h *)(&f->h), f->len);
- 				f->transmitted++;
- 			} else {
- 				if (pri->debug & PRI_DEBUG_Q921_STATE)
- 					pri_message("Delaying transmission of %d, window is %d/%d long\n", 
--						f->h.n_s, pri->windowlen, pri->window);
-+						f->h.n_s, pri->windowlen[teio], pri->window[teio]);
- 			}
- 		}
--		if (pri->t203_timer) {
-+		if (pri->t203_timer[teio]) {
- 			if (pri->debug & PRI_DEBUG_Q921_STATE)
- 				pri_message("Stopping T_203 timer\n");
--			pri_schedule_del(pri, pri->t203_timer);
--			pri->t203_timer = 0;
-+			pri_schedule_del(pri, pri->t203_timer[teio]);
-+			pri->t203_timer[teio] = 0;
- 		}
--		if (!pri->t200_timer) {
-+		if (!pri->t200_timer[teio]) {
- 			if (pri->debug & PRI_DEBUG_Q921_STATE)
- 				pri_message("Starting T_200 timer\n");
--			pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
-+			pri->t200_timer[teio] = pri_schedule_event2(pri, T_200, t200_expire, pri, tei);
- 		} else
- 			if (pri->debug & PRI_DEBUG_Q921_STATE)
--				pri_message("T_200 timer already going (%d)\n", pri->t200_timer);
-+				pri_message("T_200 timer already going (%d)\n", pri->t200_timer[teio]);
- 		
- 	} else {
- 		pri_error("!! Out of memory for Q.921 transmit\n");
-@@ -448,22 +892,25 @@
- 	return 0;
- }
- 
--static void t203_expire(void *vpri)
-+static void t203_expire(void *vpri, int tei)
- {
- 	struct pri *pri = vpri;
--	if (pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) {
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+
-+	if (pri->q921_state[teio] == Q921_LINK_CONNECTION_ESTABLISHED) {
- 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
- 			pri_message("T203 counter expired, sending RR and scheduling T203 again\n");
- 		/* Solicit an F-bit in the other's RR */
--		pri->solicitfbit = 1;
--		pri->retrans = 0;
--		q921_rr(pri, 1, 1);
-+		pri->retrans[teio] = 0;
-+		pri->solicitfbit[teio] = 1;
-+		q921_rr(pri, 1, 1, tei);
- 		/* Start timer T200 to resend our RR if we don't get it */
--		pri->t203_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
-+		pri->t203_timer[teio] = pri_schedule_event2(pri, T_200, t200_expire, pri, tei);
- 	} else {
- 		if (pri->debug &  PRI_DEBUG_Q921_STATE)
--			pri_message("T203 counter expired in weird state %d\n", pri->q921_state);
--		pri->t203_timer = 0;
-+			pri_message("T203 counter expired in weird state %d\n", pri->q921_state[teio]);
-+		pri->t203_timer[teio] = 0;
- 	}
- }
- 
-@@ -471,26 +918,28 @@
- {
- 	int res;
- 	pri_event *ev;
-+	int teio= i->h.tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
- 	/* Make sure this is a valid packet */
--	if (i->n_s == pri->v_r) {
-+	if (i->n_s == pri->v_r[teio]) {
- 		/* Increment next expected I-frame */
--		Q921_INC(pri->v_r);
-+		Q921_INC(pri->v_r[teio]);
- 		/* Handle their ACK */
--		pri->sentrej = 0;
--		ev = q921_ack_rx(pri, i->n_r);
-+		pri->sentrej[teio] = 0;
-+		ev = q921_ack_rx(pri, i->n_r, i->h.tei);
- 		if (ev)
- 			return ev;
- 		if (i->p_f) {
- 			/* If the Poll/Final bit is set, immediate send the RR */
--			q921_rr(pri, 1, 0);
--		} else if (pri->busy) {
--			q921_rr(pri, 0, 0);
-+			q921_rr(pri, 1, 0, i->h.tei);
-+		} else if (pri->busy[teio]) {
-+			q921_rr(pri, 0, 0, i->h.tei);
- 		}
- 		/* Receive Q.931 data */
--		res = q931_receive(pri, (q931_h *)i->data, len - 4);
-+		res = q931_receive(pri, (q931_h *)i->data, len - 4, i->h.tei);
- 		/* Send an RR if one wasn't sent already */
--		if (pri->v_na != pri->v_r) 
--			q921_rr(pri, 0, 0);
-+		if (pri->v_na[teio] != pri->v_r[teio]) 
-+			q921_rr(pri, 0, 0,  i->h.tei);
- 		if (res == -1) {
- 			return NULL;
- 		}
-@@ -499,10 +948,10 @@
- 	} else {
- 		/* If we haven't already sent a reject, send it now, otherwise
- 		   we are obliged to RR */
--		if (!pri->sentrej)
--			q921_reject(pri, i->p_f);
-+		if (!pri->sentrej[teio])
-+			q921_reject(pri, i->p_f, i->h.tei);
- 		else if (i->p_f)
--			q921_rr(pri, 1, 0);
-+			q921_rr(pri, 1, 0,  i->h.tei);
- 	}
- 	return NULL;
- }
-@@ -640,62 +1089,94 @@
- 	};
- }
- 
--static pri_event *q921_dchannel_up(struct pri *pri)
-+static pri_event *q921_dchannel_up(struct pri *pri, int tei)
- {
-+	// we treat this as MFE
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+
- 	/* Reset counters, etc */
--	q921_reset(pri);
-+	q921_reset(pri, tei);
- 	
- 	/* Stop any SABME retransmissions */
--	pri_schedule_del(pri, pri->sabme_timer);
--	pri->sabme_timer = 0;
-+	if (pri->sabme_timer[teio]) {
-+	    pri_schedule_del(pri, pri->sabme_timer[teio]);
-+	    pri->sabme_timer[teio] = 0;
-+	}
-+	
-+	if (pri->t202_timer[teio]) {
-+	    pri_schedule_del(pri, pri->t202_timer[teio]);
-+	    pri->t202_timer[teio] = 0;
-+	}
- 	
- 	/* Reset any rejects */
--	pri->sentrej = 0;
-+	pri->sentrej[teio] = 0;
- 	
- 	/* Go into connection established state */
--	pri->q921_state = Q921_LINK_CONNECTION_ESTABLISHED;
-+	pri->q921_state[teio] = Q921_LINK_CONNECTION_ESTABLISHED;
- 
- 	/* Start the T203 timer */
--	pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri);
-+	pri->t203_timer[teio] = pri_schedule_event2(pri, T_203, t203_expire, pri, tei);
- 	
- 	/* Report event that D-Channel is now up */
--	pri->ev.gen.e = PRI_EVENT_DCHAN_UP;
--	return &pri->ev;
-+        pri->ev.gen.e = PRI_EVENT_DCHAN_UP;
-+        pri->ev.gen.tei = tei;
-+        return &pri->ev;
- }
- 
--static pri_event *q921_dchannel_down(struct pri *pri)
-+static pri_event *q921_dchannel_down(struct pri *pri, int tei)
- {
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
-+	// we treat this as MF disc
- 	/* Reset counters, reset sabme timer etc */
--	q921_reset(pri);
-+	q921_reset(pri, tei);
- 	
--	/* Report event that D-Channel is now up */
-+	/* Report event that D-Channel is now down */
-+	if (pri->localtype == BRI_NETWORK_PTMP) {
-+	    if (pri->t203_timer[teio]) {
-+		if (pri->debug & PRI_DEBUG_Q921_STATE) {
-+			pri_message("Stopping T_203 timer for TEI %d\n", tei);
-+		}
-+		pri_schedule_del(pri, pri->t203_timer[teio]);
-+		pri->t203_timer[teio] = 0;
-+	    }
-+	}
- 	pri->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
--	return &pri->ev;
-+	pri->ev.gen.tei = tei;
-+	return &pri->ev;	
- }
- 
--void q921_reset(struct pri *pri)
-+void q921_reset(struct pri *pri, int tei)
- {
-+	int teio=tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
- 	/* Having gotten a SABME we MUST reset our entire state */
--	pri->v_s = 0;
--	pri->v_a = 0;
--	pri->v_r = 0;
--	pri->v_na = 0;
--	pri->window = 7;
--	pri->windowlen = 0;
--	pri_schedule_del(pri, pri->sabme_timer);
--	pri_schedule_del(pri, pri->t203_timer);
--	pri_schedule_del(pri, pri->t200_timer);
--	pri->sabme_timer = 0;
--	pri->t203_timer = 0;
--	pri->t200_timer = 0;
--	pri->busy = 0;
--	pri->solicitfbit = 0;
--	pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
--	pri->retrans = 0;
--	pri->sentrej = 0;
--	
-+	pri->v_s[teio] = 0;
-+	pri->v_a[teio] = 0;
-+	pri->v_r[teio] = 0;
-+	pri->v_na[teio] = 0;
-+	pri->window[teio] = 7;
-+	pri->windowlen[teio] = 0;
-+	pri_schedule_del(pri, pri->sabme_timer[teio]);
-+	pri_schedule_del(pri, pri->t203_timer[teio]);
-+	pri_schedule_del(pri, pri->t200_timer[teio]);
-+	pri->sabme_timer[teio] = 0;
-+	pri->t203_timer[teio] = 0;
-+	pri->t200_timer[teio] = 0;
-+	pri_schedule_del(pri, pri->t202_timer[teio]);
-+	pri->t202_timer[teio] = 0;
-+	pri_schedule_del(pri, pri->t201_timer[teio]);
-+	pri->t201_timer[teio] = 0;
-+	// xxx HMMM?
-+	pri->busy[teio] = 0;
-+	pri->solicitfbit[teio] = 0;
-+	pri->q921_state[teio] = Q921_LINK_CONNECTION_RELEASED;
-+	pri->retrans[teio] = 0;
-+	pri->sentrej[teio] = 0;
-+
- 	/* Discard anything waiting to go out */
--	q921_discard_retransmissions(pri);
-+	q921_discard_retransmissions(pri, tei);
- }
- 
- static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
-@@ -703,12 +1184,16 @@
- 	q921_frame *f;
- 	pri_event *ev;
- 	int sendnow;
-+	int tei;
-+	int res=-1;
-+	int teio=h->h.tei - Q921_TEI_BASE;
-+	if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
- 
- 	switch(h->h.data[0] & Q921_FRAMETYPE_MASK) {
- 	case 0:
- 	case 2:
--		if (pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED) {
--			pri_error("!! Got I-frame while link state %d\n", pri->q921_state);
-+		if (pri->q921_state[teio] != Q921_LINK_CONNECTION_ESTABLISHED) {
-+			pri_error("!! Got I-frame while link state %d\n", pri->q921_state[teio]);
- 			return NULL;
- 		}
- 		/* Informational frame */
-@@ -719,7 +1204,7 @@
- 		return q921_handle_iframe(pri, &h->i, len);	
- 		break;
- 	case 1:
--		if (pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED) {
-+		if (pri->q921_state[teio] != Q921_LINK_CONNECTION_ESTABLISHED) {
- 			pri_error("!! Got S-frame while link down\n");
- 			return NULL;
- 		}
-@@ -730,22 +1215,22 @@
- 		switch(h->s.ss) {
- 		case 0:
- 			/* Receiver Ready */
--			pri->busy = 0;
-+			pri->busy[teio] = 0;
- 			/* Acknowledge frames as necessary */
--			ev = q921_ack_rx(pri, h->s.n_r);
-+			ev = q921_ack_rx(pri, h->s.n_r, h->h.tei);
- 			if (ev)
- 				return ev;
- 			if (h->s.p_f) {
- 				/* If it's a p/f one then send back a RR in return with the p/f bit set */
--				if (pri->solicitfbit) {
-+				if (pri->solicitfbit[teio]) {
- 					if (pri->debug & PRI_DEBUG_Q921_STATE) 
- 						pri_message("-- Got RR response to our frame\n");
- 				} else {
- 					if (pri->debug & PRI_DEBUG_Q921_STATE) 
- 						pri_message("-- Unsolicited RR with P/F bit, responding\n");
--						q921_rr(pri, 1, 0);
-+						q921_rr(pri, 1, 0, h->h.tei);
- 				}
--				pri->solicitfbit = 0;
-+				pri->solicitfbit[teio] = 0;
- 			}
- 			break;
-       case 1:
-@@ -754,9 +1239,9 @@
-             pri_message("-- Got receiver not ready\n");
- 	 if(h->s.p_f) {
- 		/* Send RR if poll bit set */
--		q921_rr(pri, h->s.p_f, 0);
-+		q921_rr(pri, h->s.p_f, 0, h->h.tei);
- 	 }
--         pri->busy = 1;
-+         pri->busy[teio] = 1;
-          break;   
-       case 2:
-          /* Just retransmit */
-@@ -764,22 +1249,22 @@
-             pri_message("-- Got reject requesting packet %d...  Retransmitting.\n", h->s.n_r);
-          if (h->s.p_f) {
-             /* If it has the poll bit set, send an appropriate supervisory response */
--            q921_rr(pri, 1, 0);
-+            q921_rr(pri, 1, 0, h->h.tei);
-          }
- 		 sendnow = 0;
-          /* Resend the proper I-frame */
--         for(f=pri->txqueue;f;f=f->next) {
-+         for(f=pri->txqueue[teio];f;f=f->next) {
-                if ((sendnow || (f->h.n_s == h->s.n_r)) && f->transmitted) {
-                      /* Matches the request, or follows in our window, and has
- 					    already been transmitted. */
- 					 sendnow = 1;
- 					 pri_error("!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n", h->s.n_r, f->h.n_s);
--				     f->h.n_r = pri->v_r;
-+				     f->h.n_r = pri->v_r[teio];
-                      q921_transmit(pri, (q921_h *)(&f->h), f->len);
-                }
-          }
-          if (!sendnow) {
--               if (pri->txqueue) {
-+               if (pri->txqueue[teio]) {
-                      /* This should never happen */
- 		     if (!h->s.p_f || h->s.n_r) {
- 			pri_error("!! Got reject for frame %d, but we only have others!\n", h->s.n_r);
-@@ -787,23 +1272,23 @@
-                } else {
-                      /* Hrm, we have nothing to send, but have been REJ'd.  Reset v_a, v_s, etc */
- 				pri_error("!! Got reject for frame %d, but we have nothing -- resetting!\n", h->s.n_r);
--                     pri->v_a = h->s.n_r;
--                     pri->v_s = h->s.n_r;
-+                     pri->v_a[teio] = h->s.n_r;
-+                     pri->v_s[teio] = h->s.n_r;
-                      /* Reset t200 timer if it was somehow going */
--                     if (pri->t200_timer) {
--                           pri_schedule_del(pri, pri->t200_timer);
--                           pri->t200_timer = 0;
-+                     if (pri->t200_timer[teio]) {
-+                           pri_schedule_del(pri, pri->t200_timer[teio]);
-+                           pri->t200_timer[teio] = 0;
-                      }
-                      /* Reset and restart t203 timer */
--                     if (pri->t203_timer)
--                           pri_schedule_del(pri, pri->t203_timer);
--                     pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri);
-+                     if (pri->t203_timer[teio])
-+                           pri_schedule_del(pri, pri->t203_timer[teio]);
-+                     pri->t203_timer[teio] = pri_schedule_event2(pri, T_203, t203_expire, pri, h->h.tei);
-                }
-          }
-          break;
- 		default:
- 			pri_error("!! XXX Unknown Supervisory frame ss=0x%02x,pf=%02xnr=%02x vs=%02x, va=%02x XXX\n", h->s.ss, h->s.p_f, h->s.n_r,
--					pri->v_s, pri->v_a);
-+					pri->v_s[teio], pri->v_a[teio]);
- 		}
- 		break;
- 	case 3:
-@@ -816,12 +1301,13 @@
- 			if (h->u.m2 == 3) {
- 				if (h->u.p_f) {
- 					/* Section 5.7.1 says we should restart on receiving a DM response with the f-bit set to
-+
- 					   one, but we wait T200 first */
- 					if (pri->debug & PRI_DEBUG_Q921_STATE)
- 						pri_message("-- Got DM Mode from peer.\n");
- 					/* Disconnected mode, try again after T200 */
--					ev = q921_dchannel_down(pri);
--					q921_start(pri, 0);
-+					ev = q921_dchannel_down(pri, h->h.tei);
-+					q921_start(pri, 0, h->h.tei);
- 					return ev;
- 						
- 				} else {
-@@ -829,21 +1315,136 @@
- 						pri_message("-- Ignoring unsolicited DM with p/f set to 0\n");
- #if 0
- 					/* Requesting that we start */
--					q921_start(pri, 0);
-+					q921_start(pri, 0, h->h.tei);
- #endif					
- 				}
- 				break;
--			} else if (!h->u.m2) {
--				pri_message("XXX Unnumbered Information not implemented XXX\n");
-+			} else if (h->u.m2 == 0) {
-+				if (h->u.ft == 3) {
-+				    switch (h->u.data[0]) { /* Management Entity Identifier  */
-+					case 0x0f:
-+					/* TEI Procedure */
-+					switch (h->u.data[3]) {
-+					    case Q921_TEI_ID_VERIFY:
-+						if (pri->localtype != BRI_NETWORK_PTMP)
-+						    break;
-+						    if (pri->debug & PRI_DEBUG_Q921_STATE)
-+							pri_message("got TEI verify for TEI = %d\n",h->u.data[4] >> 1);
-+					    break;
-+					    case Q921_TEI_ID_ASSIGNED:
-+						if (pri->localtype != BRI_CPE_PTMP)
-+						    break;
-+						if (pri->tei == (h->u.data[4] >> 1)) {
-+						    // TEI already assgined, CHECK_TEI or REMOVE_TEI
-+						    pri_error("Double assgined TEI!\n");
-+						}
-+						if (pri->ri == ((unsigned short) (h->u.data[1] << 8) + h->u.data[2])) {
-+						    if (pri->t202_timer[0]) {
-+							pri_schedule_del(pri, pri->t202_timer[0]);
-+							pri->t202_timer[0] = 0;
-+						    }
-+						    pri->tei = h->u.data[4] >> 1; 
-+						    pri->ri = 0;
-+						    if (pri->debug & PRI_DEBUG_Q921_STATE)
-+							pri_message("received TEI assign TEI = %d ri=%d\n",pri->tei,(unsigned short) (h->u.data[1] << 8) + h->u.data[2]);
-+						    q921_send_sabme_now(pri, pri->tei);
-+						}
-+					    break;
-+					    case Q921_TEI_ID_REMOVE:
-+					    	if (pri->localtype != BRI_CPE_PTMP)
-+						    break;
-+						if (pri->tei == (h->u.data[4] >> 1)){ 
-+						    if (pri->debug & PRI_DEBUG_Q921_STATE)
-+							pri_message("received TEI remove TEI = %d\n",pri->tei);
-+						    pri->tei = 0;
-+						    pri->ri = 0;
-+						    // get a new TEI
-+						    q921_reset(pri,0);
-+						    q921_send_teireq(pri);
-+						}
-+					    break;
-+					    case Q921_TEI_ID_REQUEST:
-+						if (pri->localtype != BRI_NETWORK_PTMP)
-+						    break;
-+						
-+						tei = h->u.data[4] >> 1;
-+						if (tei != Q921_TEI_GROUP) {
-+						    pri_message("got TEI request for unavailable TEI..\n");
-+						    q921_send_teidenied(pri,((unsigned int)(h->u.data[1] << 8) + h->u.data[2]),h->u.data[4] >> 1);
-+						    break;
-+						}
-+						
-+						for (tei=0;tei<Q921_MAX_TEIS;tei++) {
-+						    if (pri->q921_teis[tei] == 0) {
-+						        pri->q921_teis[tei] = 1;
-+						        break;
-+						    }
-+						}
-+						if (tei < Q921_MAX_TEIS) {
-+						    q921_send_teiassign(pri,((unsigned int)(h->u.data[1] << 8) + h->u.data[2]),tei + Q921_TEI_BASE);
-+						} else {
-+						    // if you plug too many TEs into my bus it's your fault!!!
-+
-+						    pri_error("Whooopsie...general protection fault in module TEI manager.\n");
-+
-+						    // XXX IMPLEMENT TEI RECOVERY!!!
-+						    for (tei=0;tei<Q921_MAX_TEIS;tei++) {
-+							    // XXX ri should be 0?
-+						//	    q921_reset(pri, tei + Q921_TEI_BASE);
-+						//	    q921_send_teiremove(pri,((unsigned int)(h->u.data[1] << 8) + h->u.data[2]),tei + Q921_TEI_BASE);
-+						//    	    pri->q921_teis[tei] = 0;
-+							    // XXX dont forget schedulers, etc...
-+						    }
-+						    q921_send_teidenied(pri,((unsigned int)(h->u.data[1] << 8) + h->u.data[2]),h->u.data[4] >> 1);
-+						}
-+					    break;
-+					    case Q921_TEI_ID_CHK_REQ:
-+						if (pri->localtype != BRI_CPE_PTMP)
-+						    break;
-+						    if ((((h->u.data[4] >> 1) == Q921_TEI_GROUP) || ((h->u.data[4] >> 1) == 0) || ((h->u.data[4] >> 1) == pri->tei)) && (pri->tei > 0)) {
-+							pri_message("received TEI check request for TEI = %d\n",h->u.data[4] >> 1);
-+							q921_send_teichkresp(pri, pri->tei);
-+						    }
-+					    break;
-+					    default:
-+						pri_message("Ri = %d TEI msg = %x TEI = %x\n", (h->u.data[1] << 8) + h->u.data[2], h->u.data[3], h->u.data[4] >> 1);
-+					} 
-+					break;
-+					case Q931_PROTOCOL_DISCRIMINATOR:
-+					    if (pri->localtype == BRI_CPE_PTMP) {
-+					    res = q931_receive(pri, (q931_h *)h->u.data, len-3, h->h.tei);
-+					    /* Send an RR if one wasn't sent already */
-+					    if (pri->v_na[teio] != pri->v_r[teio]) 
-+						q921_rr(pri, 0, 0, pri->tei);
-+					    if (res == -1) {
-+						return NULL;
-+					    }
-+					    if (res & Q931_RES_HAVEEVENT)
-+						return &pri->ev;
-+					    }
-+					break;
-+				    }
-+				} else {
-+				    pri_message("XXX Unnumbered Information not implemented XXX\n");
-+				}
- 			}
- 			break;
- 		case 2:
- 			if (pri->debug &  PRI_DEBUG_Q921_STATE)
- 				pri_message("-- Got Disconnect from peer.\n");
- 			/* Acknowledge */
--			q921_send_ua(pri, h->u.p_f);
--			ev = q921_dchannel_down(pri);
--			q921_start(pri, 0);
-+			q921_send_ua(pri, h->u.p_f, h->h.tei);
-+			ev = q921_dchannel_down(pri, h->h.tei);
-+			if ((pri->localtype == BRI_CPE_PTMP) || (pri->localtype == BRI_CPE)) {
-+			    // keep layer 2 up
-+			    q921_send_sabme(pri, 1, pri->tei);
-+			    if (pri->t203_timer[teio])
-+				pri_schedule_del(pri, pri->t203_timer[teio]);
-+			    pri->t203_timer[teio] = 0;
-+			}
-+			if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)){
-+    			    q921_start(pri, 0, 0);
-+			}
- 			return ev;
- 		case 3:
- 			if (h->u.m2 == 3) {
-@@ -865,17 +1466,17 @@
- 					}
- 				}
- 				/* Send Unnumbered Acknowledgement */
--				q921_send_ua(pri, h->u.p_f);
--				return q921_dchannel_up(pri);
-+				q921_send_ua(pri, h->u.p_f,h->h.tei);
-+				return q921_dchannel_up(pri, h->h.tei);
- 			} else if (h->u.m2 == 0) {
- 					/* It's a UA */
--				if (pri->q921_state == Q921_AWAITING_ESTABLISH) {
-+				if (pri->q921_state[teio] == Q921_AWAITING_ESTABLISH) {
- 					if (pri->debug & PRI_DEBUG_Q921_STATE) {
- 						pri_message("-- Got UA from %s peer  Link up.\n", h->h.c_r ? "cpe" : "network");
- 					}
--					return q921_dchannel_up(pri);
-+					return q921_dchannel_up(pri, h->h.tei);
- 				} else 
--					pri_error("!! Got a UA, but i'm in state %d\n", pri->q921_state);
-+					pri_error("!! Got a UA, but i'm in state %d\n", pri->q921_state[teio]);
- 			} else 
- 				pri_error("!! Weird frame received (m3=3, m2 = %d)\n", h->u.m2);
- 			break;
-@@ -900,19 +1501,43 @@
- 	/* Discard FCS */
- 	len -= 2;
- 	
--	if (!pri->master && pri->debug & PRI_DEBUG_Q921_DUMP)
--		q921_dump(h, len, pri->debug & PRI_DEBUG_Q921_RAW, 0);
--
- 	/* Check some reject conditions -- Start by rejecting improper ea's */
- 	if (h->h.ea1 || !(h->h.ea2))
- 		return NULL;
- 
--	/* Check for broadcasts - not yet handled */
--	if (h->h.tei == Q921_TEI_GROUP)
--		return NULL;
-+	if ((pri->localtype == PRI_CPE) || (pri->localtype == PRI_NETWORK)) {
-+	    /* Check for broadcasts - not yet handled (for PRI) */
-+	    if (h->h.tei == Q921_TEI_GROUP) {
-+ 		return NULL;
-+	    }
-+	} else if ((pri->localtype == BRI_CPE) || (pri->localtype == BRI_CPE_PTMP)) {
-+    	    if ((h->h.tei != pri->tei) && (h->h.tei != Q921_TEI_GROUP)) {
-+	    	return NULL;
-+	    }
-+	} else if (pri->localtype == BRI_NETWORK_PTMP) {
-+	    /* discard anything from a strange TEI (strange == not assigned by us or the broadcast tei) */
-+    	    if (((h->h.tei < Q921_TEI_BASE) || (h->h.tei > Q921_TEI_BASE + Q921_MAX_TEIS)) && (h->h.tei != Q921_TEI_GROUP)) {
-+		if (pri->debug & PRI_DEBUG_Q921_DUMP)
-+		    pri_message("Received a Q.921 message from strange/unassigned TEI %d.\n");
-+	    	return NULL;
-+	    } else {
-+		if ((pri->q921_teis[h->h.tei - Q921_TEI_BASE] != 1) && (h->h.tei != Q921_TEI_GROUP)) {
-+		    if (pri->debug & PRI_DEBUG_Q921_DUMP)
-+			pri_message("Received a Q.921 message from unassigned TEI %d.. Sending DM and assigning.\n", h->h.tei);
-+		    // send DM 
-+		    q921_send_dm(pri, 1, h->h.tei);
-+		    pri->q921_teis[h->h.tei - Q921_TEI_BASE] = 1; 
-+		}
-+	    }
-+	}    
-+
-+	if (!pri->master && pri->debug & PRI_DEBUG_Q921_DUMP)
-+		q921_dump(h, len, pri->debug & PRI_DEBUG_Q921_RAW, 0);
- 
-+	if (pri->localtype != BRI_NETWORK_PTMP) {
- 	/* Check for SAPIs we don't yet handle */
--	if ((h->h.sapi != pri->sapi) || (h->h.tei != pri->tei)) {
-+	    if (((h->h.sapi != pri->sapi) && (h->h.sapi != Q921_SAPI_LAYER2_MANAGEMENT)) || ((h->h.tei != pri->tei) && (h->h.tei != Q921_TEI_GROUP) )) {
-+
- #ifdef PROCESS_SUBCHANNELS
- 		/* If it's not us, try any subchannels we have */
- 		if (pri->subchannel)
-@@ -920,10 +1545,16 @@
- 		else 
- #endif
- 			return NULL;
--
-+    	    }
- 	}
- 	ev = __q921_receive_qualified(pri, h, len);
--	reschedule_t203(pri);
-+
-+// Q921_GROUP_TEI
-+	if (pri->localtype == BRI_CPE_PTMP) {
-+	    reschedule_t203(pri, pri->tei);
-+	} else {
-+	    reschedule_t203(pri, h->h.tei);
-+	}
- 	return ev;
- }
- 
-@@ -937,14 +1568,51 @@
- 	return e;
- }
- 
--void q921_start(struct pri *pri, int now)
-+static void q921_start_tei(struct pri *pri, int tei)
- {
--	if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED) {
--		pri_error("!! q921_start: Not in 'Link Connection Released' state\n");
--		return;
-+    int teio=tei - Q921_TEI_BASE;
-+    if (pri->localtype != BRI_NETWORK_PTMP) { return; }
-+    if (((teio < 0) || (teio > Q921_MAX_TEIS))) { teio=0; }
-+    pri->q921_teis[teio] = 0;
-+    q921_send_teiremove(pri, tei);
-+    q921_reset(pri,tei);
-+}
-+
-+void q921_start(struct pri *pri, int now, int tei)
-+{
-+	int i=0;
-+/*	if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED) {
-+ 		pri_error("!! q921_start: Not in 'Link Connection Released' state\n");
-+ 		return;
-+	} */
-+ 	/* Reset our interface */
-+	if (pri->localtype != BRI_NETWORK_PTMP) {
-+	    q921_reset(pri,0);
-+	}
-+ 	/* Do the SABME XXX Maybe we should implement T_WAIT? XXX */
-+	if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE) || (pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_CPE)) { 
-+	    q921_send_sabme(pri, now, 0);
-+	}
-+	
-+	if (pri->localtype == BRI_NETWORK_PTMP) { 
-+	    if (tei == 0) {
-+		// initial start or complete restart
-+		q921_send_teiremove(pri, 127);
-+		pri->dchanup = 0;
-+		for (i=0;i<Q921_MAX_TEIS;i++) {
-+		    q921_start_tei(pri,Q921_TEI_BASE+i);
-+		}
-+	    } else if ((tei >= Q921_TEI_BASE) && (tei < Q921_TEI_BASE + Q921_MAX_TEIS)){
-+		// restart of a single p2p datalink
-+		q921_start_tei(pri,tei);
-+	    }
-+	} 
-+	if (pri->localtype == BRI_CPE_PTMP) { 
-+	    if (tei == 0) {
-+		/* let's get a TEI */
-+		q921_send_teireq(pri);
-+	    } else {
-+		q921_send_sabme(pri, now, tei);
-+	    }
- 	}
--	/* Reset our interface */
--	q921_reset(pri);
--	/* Do the SABME XXX Maybe we should implement T_WAIT? XXX */
--	q921_send_sabme(pri, now);
- }
-diff -urNad --exclude=CVS --exclude=.svn ./q931.c /tmp/dpep-work.aULY0X/libpri-1.0.9/q931.c
---- ./q931.c	2005-07-14 12:30:35.000000000 +0100
-+++ /tmp/dpep-work.aULY0X/libpri-1.0.9/q931.c	2005-07-14 12:31:07.940275048 +0100
-@@ -5,6 +5,8 @@
-  *
-  * Copyright (C) 2001, Linux Support Services, Inc.
-  * All Rights Reserved.
-+ * Copyright (C) 2003,2004,2005 Junghanns.NET GmbH
-+ * Klaus-Peter Junghanns <kpj at junghanns.net>
-  *
-  * This program is free software; you can redistribute it and/or modify
-  * it under the terms of the GNU General Public License as published by
-@@ -31,6 +33,7 @@
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
-+#include <time.h>
- 
- #define MAX_MAND_IES 10
- 
-@@ -205,6 +208,13 @@
- #define T_305			30000
- #define T_313			4000
- 
-+struct q921_call {
-+    int tei;	
-+    int proc;		
-+    int channel;	
-+    q921_call *next;
-+};
-+
- struct q931_call {
- 	struct pri *pri;	/* PRI */
- 	int cr;		/* Call Reference */
-@@ -222,7 +232,11 @@
- 	int alive;			/* Whether or not the call is alive */
- 	int acked;			/* Whether setup has been acked or not */
- 	int sendhangupack;		/* Whether or not to send a hangup ack */
--	int proc;			/* Whether we've sent a call proceeding / alerting */
-+	int proc;			/* Whether we've sent a call proceeding */
-+	int alert;			/* Whether we've sent an alerting */
-+
-+	int tei;
-+	q921_call *phones;
- 	
- 	int ri;			/* Restart Indicator (Restart Indicator IE) */
- 
-@@ -240,6 +254,7 @@
- 	int progcode;			/* Progress coding */
- 	int progloc;			/* Progress Location */	
- 	int progress;			/* Progress indicator */
-+	int inband_progress;		/* inband progress available? */
- 	
- 	int notify;			/* Notification */
- 	
-@@ -253,7 +268,10 @@
- 	
- 	int callerplan;
- 	int callerpres;			/* Caller presentation */
--	char callernum[256];	/* Caller */
-+	int callerplanuser;
-+	int callerpresuser;			/* Caller presentation */
-+	char callernum[256];	/* Calling Number (network provided) */
-+	char callernumuser[256];	/* Calling Number, (user provided) */
- 	char callername[256];
- 
- 	int ani2;               /* ANI II */
-@@ -271,9 +289,19 @@
- 	int redirectingreason;	      
- 	char redirectingnum[256];
- 
-+	int t303timer;		
-+	int t303running;		
-+
-         int useruserprotocoldisc;
- 	char useruserinfo[256];
- 	char callingsubaddr[256];	/* Calling parties sub address */
-+	char callid[10];	/* call identity for SUSPEND/RESUME */
-+	char digits[256];	/* additional digits received via info msgs (cpn or keypad) */
-+	char display[256];	/* display ie received in info msgs or for sending */
-+
-+	/* euroisdn facility fun */
-+	int facility; /* FACILTIY received */
-+	int aoc;
- };
- 
- #define FUNC_DUMP(name) void ((name))(int full_ie, q931_ie *ie, int len, char prefix)
-@@ -315,6 +343,11 @@
- 	c->next = NULL;
- 	c->sentchannel = 0;
- 	c->newcall = 1;
-+	c->t303timer = 0;
-+	c->t303running = 0;
-+	c->aoc = 0;
-+	c->phones = NULL;
-+	c->inband_progress = 0;
- 	c->ourcallstate = Q931_CALL_STATE_NULL;
- 	c->peercallstate = Q931_CALL_STATE_NULL;
- }
-@@ -334,16 +367,20 @@
- {	
- 	int x;
- 	int pos=0;
--#ifdef NO_BRI_SUPPORT
-- 	if (!ie->data[0] & 0x20) {
--		pri_error("!! Not PRI type!?\n");
-- 		return -1;
-+	if ((pri->localtype != PRI_CPE) && (pri->localtype != PRI_NETWORK)) {
-+//		pri_error("!! BRI type %d!?\n",ie->data[0] & 0x03);
-+		call->channelno = ie->data[0] & 0x03;
-+		if (call->channelno == 3) {
-+		    call->channelno = -1; // any channel
-+		}
-+ 		return 0;
-  	}
--#endif
- #ifndef NOAUTO_CHANNEL_SELECTION_SUPPORT
--	if ((ie->data[0] & 3) != 1) {
-+	if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
-+	    if ((ie->data[0] & 3) != 1) {
- 		pri_error("!! Unexpected Channel selection %d\n", ie->data[0] & 3);
- 		return -1;
-+	    }
- 	}
- #endif
- 	if (ie->data[0] & 0x08)
-@@ -390,10 +427,16 @@
- {
- 	int pos=0;
- 	/* Start with standard stuff */
--	if (pri->switchtype == PRI_SWITCH_GR303_TMC)
-+	if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
- 		ie->data[pos] = 0x69;
--	else
-+	} else {
-+	    if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
- 		ie->data[pos] = 0xa1;
-+	    } else {
-+		// BRI
-+		ie->data[pos] = 0x80;
-+	    }
-+	}
- 	/* Add exclusive flag if necessary */
- 	if (call->chanflags & FLAG_EXCLUSIVE)
- 		ie->data[pos] |= 0x08;
-@@ -410,6 +453,7 @@
- 	} else
- 		pos++;
- 	if ((call->channelno > -1) || (call->slotmap != -1)) {
-+	    if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
- 		/* We'll have the octet 8.2 and 8.3's present */
- 		ie->data[pos++] = 0x83;
- 		if (call->channelno > -1) {
-@@ -425,11 +469,41 @@
- 			ie->data[pos++] = (call->slotmap & 0xff);
- 			return pos + 2;
- 		}
--	}
-+	    } else {
-+		// BRI
-+		// pri_error("channelno %d, ds1no %d data %d\n",call->channelno,call->ds1no,ie->data[pos-1]);
-+		if (pri->localtype == BRI_CPE_PTMP) {
-+		    if (msgtype == Q931_SETUP) {
-+			// network, you decide!
-+			if (call->channelno > -1) {
-+//		    	    ie->data[pos-1] = 0x83;
-+		    	    ie->data[pos-1] = 0x80 | call->channelno;
-+			}
-+		    } else {
-+			if (call->channelno > -1) {
-+		    	    ie->data[pos-1] |= call->channelno;
-+			}
-+		    }
-+		} else {
-+		    if (call->channelno > -1) {
-+		        ie->data[pos-1] |= call->channelno;
-+		    }
-+		}
-+		return pos + 2;
-+	    }	
-+        } else {
-+	    if (pri->localtype == BRI_CPE) {
-+	        ie->data[pos++] = 0x80 | 3;
-+	        return pos + 2;
-+	    }
-+	}	
- 	if (call->ds1no > 0) {
- 		/* We're done */
- 		return pos + 2;
- 	}
-+	if (msgtype == Q931_RESTART_ACKNOWLEDGE) {
-+	    return 0;
-+	}	
- 	pri_error("!! No channel map, no channel, and no ds1?  What am I supposed to identify?\n");
- 	return -1;
- }
-@@ -765,6 +839,10 @@
- 
- static void q931_get_number(unsigned char *num, int maxlen, unsigned char *src, int len)
- {
-+	if (len < 0) {
-+	    pri_error("q931_get_number received invalid len = %d\n", len);
-+	    return;
-+	}
- 	if (len > maxlen - 1) {
- 		num[0] = 0;
- 		return;
-@@ -776,44 +854,70 @@
- static FUNC_DUMP(dump_called_party_number)
- {
- 	unsigned char cnum[256];
--
--	q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
--	pri_message("%c Called Number (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d) '%s' ]\n",
--		prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f, cnum);
-+  
-+	if (len >= 3) {
-+	    q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
-+ 	    pri_message("%c Called Number (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d) '%s' ]\n",
-+ 		    prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f, cnum);
-+ 	} else {
-+ 	    pri_error("Called Number (len=%2d) too short.\n", len);
-+ 	}
- }
- 
- static FUNC_DUMP(dump_called_party_subaddr)
- {
- 	unsigned char cnum[256];
--	q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
--	pri_message("%c Called Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d) O: %d '%s' ]\n",
-+	if (len >= 3) {
-+	    q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
-+	    pri_message("%c Called Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d) O: %d '%s' ]\n",
- 		prefix, len, ie->data[0] >> 7,
- 		subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
- 		(ie->data[0] & 0x08) >> 3, cnum);
-+	} else {
-+	    pri_error("Called Party Subaddress (len=%2d) too short.\n", len);
-+	}
- }
- 
- static FUNC_DUMP(dump_calling_party_number)
- {
- 	unsigned char cnum[256];
--	if (ie->data[0] & 0x80)
-+	if ((ie->data[0] & 0x80) && (len >= 3)) {
- 		q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
--	else
--		q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
--	pri_message("%c Calling Number (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
--	if (ie->data[0] & 0x80)
-+		pri_message("%c Calling Number (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
- 		pri_message("%c                           Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(0), 0, cnum);
--	else
-+	} else if (len >= 4) {
-+		q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
-+		pri_message("%c Calling Number (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
- 		pri_message("%c                           Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum);
-+	} else {
-+	    pri_error("Calling Party Number (len=%2d) too short.\n", len);
-+	}
- }
- 
- static FUNC_DUMP(dump_calling_party_subaddr)
- {
- 	unsigned char cnum[256];
--	q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
--	pri_message("%c Calling Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d) O: %d '%s' ]\n",
-+	if (len >= 4) {
-+	    q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
-+	    pri_message("%c Calling Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d) O: %d '%s' ]\n",
- 		prefix, len, ie->data[0] >> 7,
- 		subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
- 		(ie->data[0] & 0x08) >> 3, cnum);
-+	} else {
-+	    pri_error("Calling Party Subaddress (len=%2d) too short.\n", len);
-+	}
-+}
-+
-+static FUNC_DUMP(dump_colp)
-+{
-+	unsigned char cnum[256];
-+	if (len >= 4) {
-+	    q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
-+	    pri_message("%c COLP (len=%2d) [ Ext: %d  TON: %s (%d)  NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
-+	    pri_message("%c                           Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum);
-+	} else {
-+	    pri_error("COLP (len=%2d) too short.\n", len);
-+	}
- }
- 
- static FUNC_DUMP(dump_redirecting_number)
-@@ -862,8 +966,12 @@
- 		}
- 	}
- 	while(!(ie->data[i++]& 0x80));
--	q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
--	pri_message(" '%s' ]\n", cnum);
-+	if ((ie->len - i) >= 0) {
-+	    q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
-+	    pri_message(" '%s' ]\n", cnum);
-+	} else {
-+	    pri_error("Connected Number (len=%2d) too short.\n", len);
-+	}
- }
- 
- 
-@@ -887,7 +995,11 @@
- 		}
- 	}
- 	while(!(ie->data[i++] & 0x80));
--	q931_get_number((unsigned char *) call->redirectingnum, sizeof(call->redirectingnum), ie->data + i, ie->len - i);
-+	if ((ie->len - i) >= 0) {
-+	    q931_get_number((unsigned char *) call->redirectingnum, sizeof(call->redirectingnum), ie->data + i, ie->len - i);
-+	} else {
-+	    pri_error("Redirecting Number (len=%2d) too short.\n", len);
-+	}
- 	return 0;
- }
- 
-@@ -895,25 +1007,41 @@
- static FUNC_DUMP(dump_redirecting_subaddr)
- {
- 	unsigned char cnum[256];
--	q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
--	pri_message("%c Redirecting Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d) O: %d '%s' ]\n",
-+	if (len >= 4) {
-+	    q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
-+	    pri_message("%c Redirecting Sub-Address (len=%2d) [ Ext: %d  Type: %s (%d) O: %d '%s' ]\n",
- 		prefix, len, ie->data[0] >> 7,
- 		subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
- 		(ie->data[0] & 0x08) >> 3, cnum);
-+	} else {
-+	    pri_error("Redirecting Subaddress (len=%2d) too short.\n", len);
-+	}
- }
- 
- static FUNC_RECV(receive_calling_party_subaddr)
- {
- 	/* copy digits to call->callingsubaddr */
-- 	q931_get_number((unsigned char *) call->callingsubaddr, sizeof(call->callingsubaddr), ie->data + 2, len - 4);
-+ 	if (len >= 4) {
-+ 	    q931_get_number((unsigned char *) call->callingsubaddr, sizeof(call->callingsubaddr), ie->data + 2, len - 4);
-+	} else {
-+	    pri_error("Calling Party Subaddress (len=%2d) too short.\n", len);
-+	}
- 	return 0;
- }
- 
- static FUNC_RECV(receive_called_party_number)
- {
--	/* copy digits to call->callednum */
-- 	q931_get_number((unsigned char *) call->callednum, sizeof(call->callednum), ie->data + 1, len - 3);
--	call->calledplan = ie->data[0] & 0x7f;
-+	/* copy digits to call->callednum or call->digits */
-+	if (len >= 3) {
-+	    if (msgtype == Q931_INFORMATION) {
-+ 		q931_get_number((unsigned char *) call->digits, sizeof(call->digits), ie->data + 1, len - 3);
-+	    } else {
-+ 		q931_get_number((unsigned char *) call->callednum, sizeof(call->callednum), ie->data + 1, len - 3);
-+	    }
-+	    call->calledplan = ie->data[0] & 0x7f;
-+	} else {
-+	    pri_error("Called Party Number (len=%2d) too short.\n", len);
-+	}
- 	return 0;
- }
- 
-@@ -929,16 +1057,37 @@
- {
-         int extbit;
-         
--        call->callerplan = ie->data[0] & 0x7f;
--        extbit = (ie->data[0] >> 7) & 0x01;
--
-+	if (strlen(call->callernum)) {
-+ 	    call->callerplanuser = ie->data[0] & 0x7f;
-+	} else {
-+ 	    call->callerplan = ie->data[0] & 0x7f;
-+	}
-+	extbit = (ie->data[0] >> 7) & 0x01;
-         if (extbit) {
--	  q931_get_number((unsigned char *) call->callernum, sizeof(call->callernum), ie->data + 1, len - 3);
--	  call->callerpres = 0; /* PI presentation allowed
--				   SI user-provided, not screened */        
--        } else {
--	  q931_get_number((unsigned char *) call->callernum, sizeof(call->callernum), ie->data + 2, len - 4);
--	  call->callerpres = ie->data[1] & 0x7f;
-+	    if (len >= 3) {
-+		if (strlen(call->callernum)) {
-+		    /* got A NUM already (this is not 100% correct, but the network should do it this way to protect bad implementations */
-+		    q931_get_number(call->callernumuser, sizeof(call->callernumuser), ie->data + 1, len - 3);
-+	    	    call->callerpresuser = 0; /* PI presentation allowed  SI user-provided, not screened */        
-+		} else {
-+ 		     q931_get_number(call->callernum, sizeof(call->callernum), ie->data + 1, len - 3);
-+		    call->callerpres = 0; /* PI presentation allowed  SI user-provided, not screened */        
-+		}
-+	  } else {
-+		pri_error("Calling Party Number (len=%2d) too short.\n", len);
-+	  }
-+	} else {
-+	    if (len >= 4) {
-+		if (strlen(call->callernum)) {
-+	    	    q931_get_number(call->callernumuser, sizeof(call->callernumuser), ie->data + 2, len - 4);
-+		    call->callerpresuser = ie->data[1] & 0x7f;
-+		} else {
-+		    q931_get_number(call->callernum, sizeof(call->callernum), ie->data + 2, len - 4);
-+	    	    call->callerpres = ie->data[1] & 0x7f;
-+		}
-+	    } else {
-+		pri_error("Calling Party Number (len=%2d) too short.\n", len);
-+	     }
-         }
- 	return 0;
- }
-@@ -965,11 +1114,33 @@
- static FUNC_RECV(receive_user_user)
- {        
-         call->useruserprotocoldisc = ie->data[0] & 0xff;
--        if (call->useruserprotocoldisc == 4) /* IA5 */
--          q931_get_number((unsigned char *) call->useruserinfo, sizeof(call->useruserinfo), ie->data + 1, len - 3);
-+	if (call->useruserprotocoldisc == 4) { /* IA5 */
-+	    if (len >= 3) {
-+     		q931_get_number((unsigned char *) call->useruserinfo, sizeof(call->useruserinfo), ie->data + 1, len - 3);
-+	    } else {
-+		pri_error("User-User Information (len=%2d) too short.\n", len);
-+	    }
-+	}
-+	return 0;
-+}
-+
-+static FUNC_RECV(receive_call_identity)
-+{
-+	if (len >= 2) {
-+ 	    q931_get_number(call->callid, sizeof(call->callid), ie->data, len - 2);
-+	} else {
-+	    pri_error("Call Identity (len=%2d) too short.\n", len);
-+	}
- 	return 0;
- }
- 
-+static FUNC_SEND(transmit_call_identity)
-+{
-+	if (strlen(call->callid)) 
-+		memcpy(ie->data , call->callid, strlen(call->callid));
-+	return strlen(call->callednum) + 3;
-+}
-+
- static char *prog2str(int prog)
- {
- 	static struct msgtype progs[] = {
-@@ -1030,21 +1201,40 @@
- 		data++;
- 		len--;
- 	}
--	q931_get_number((unsigned char *) call->callername, sizeof(call->callername), data, len - 2);
-+	if (msgtype == Q931_SETUP) {
-+	    /* we treat display IEs in the SETUP msg as callername */
-+	    if (len >= 2) {
-+		q931_get_number((unsigned char *) call->callername, sizeof(call->callername), data, len - 2);
-+	    } else {
-+		pri_error("Display (len=%2d) too short.\n", len);
-+	    }
-+	} else {
-+	    /* in other msgs we will pass it as text to chan_zap */
-+	    if (len >= 2) {
-+		q931_get_number((unsigned char *) call->display, sizeof(call->display), data, len - 2);
-+	    } else {
-+		pri_error("Display (len=%2d) too short.\n", len);
-+	    }
-+	}
- 	return 0;
- }
- 
- static FUNC_SEND(transmit_display)
- {
- 	int i;
--	if ((pri->switchtype != PRI_SWITCH_NI1) && strlen(call->callername)) {
-+	if ((pri->switchtype != PRI_SWITCH_NI1) && strlen(call->callername) && (pri->localtype != BRI_CPE) && (pri->localtype != BRI_CPE_PTMP) && (pri->localtype != PRI_CPE)) {
- 		i = 0;
- 		if(pri->switchtype != PRI_SWITCH_EUROISDN_E1) {
- 			ie->data[0] = 0xb1;
- 			++i;
- 		}
--		memcpy(ie->data + i, call->callername, strlen(call->callername));
--		return 2 + i + strlen(call->callername);
-+	    	if (msgtype == Q931_SETUP_ACKNOWLEDGE) {
-+		    memcpy(ie->data + i, call->display, strlen(call->display));
-+		    return 2 + i + strlen(call->display);
-+	 	} else {
-+		    memcpy(ie->data + i, call->callername, strlen(call->callername));
-+		    return 2 + i + strlen(call->callername);
-+	    	}
- 	}
- 	return 0;
- }
-@@ -1054,19 +1244,113 @@
- 	call->progloc = ie->data[0] & 0xf;
- 	call->progcode = (ie->data[0] & 0x60) >> 5;
- 	call->progress = (ie->data[1] & 0x7f);
-+	if (call->progress & 0x08) {
-+	    call->inband_progress = 1;
-+	}
- 	return 0;
- }
- 
- static FUNC_RECV(receive_facility)
- {
--	if (ie->len < 14) {
--		pri_error("!! Facility message shorter than 14 bytes\n");
-+	unsigned char cpt_tag, cp_len, invoke_id_tag, invoke_id_len, operation_value_len, operation_value_tag;
-+	unsigned char arg_len = 0;
-+	unsigned char pos = 0;
-+	short invoke_id = 0, operation_value = 0;
-+	if ((ie->data[pos++] & 0x1F) == 0x11) {
-+	    /* service discriminator == supplementary services */
-+	    cpt_tag = ie->data[pos++] & 0x1F;
-+	    cp_len = ie->data[pos++];
-+	    switch (cpt_tag) {
-+		case 1: /* invoke */
-+		        invoke_id_tag = ie->data[pos++];
-+			if (invoke_id_tag != 0x02) {
-+			//    pri_error("invoke id tag != 0x02\n");
-+			    break;
-+			}
-+			invoke_id_len = ie->data[pos++]; // 4
-+		        while (invoke_id_len > 0) {
-+		    	    invoke_id = (invoke_id << 8) | (ie->data[pos++] & 0xFF);
-+			    invoke_id_len--;
-+			}
-+			operation_value_tag = ie->data[pos++];
-+			if (operation_value_tag != 0x02) {
-+			//    pri_error("operation value tag != 0x02\n");
-+			    break;
-+			}
-+			operation_value_len = ie->data[pos++];
-+		        while (operation_value_len > 0) {
-+		    	    operation_value = (operation_value << 8) | (ie->data[pos++] & 0xFF);
-+			    operation_value_len--;
-+			}
-+			arg_len = ie->len - pos;
-+			switch (operation_value) {
-+			    case 0x06:	/* ECT execute */
-+					call->facility = operation_value;
-+					break;
-+			    case 0x0D:	/* call deflection */
-+			    		call->facility = operation_value;
-+					/* dirty hack! */
-+					arg_len -= 6;
-+					if (arg_len > 0) {
-+					    pos += 6;
-+ 					    q931_get_number(call->redirectingnum, sizeof(call->redirectingnum), ie->data + pos, arg_len);
-+					}
-+					/* now retrieve the number */
-+					break;
-+			    case 0x22:  /* AOC-D */
-+					break;
-+			    case 0x24:  /* AOC-E */
-+					break;
-+			}
-+		        break;
-+		case 2: /* return result */
-+			break;
-+	        case 3: /* return error */
-+ 			break;
-+		case 4: /* reject */
-+			break;
-+	    }
-+	} else {
-+	    /* OLD DIRTY ULAW HACK */
-+	    if (ie->len < 14) {
-+  		pri_error("!! Facility message shorter than 14 bytes\n");
- 		return 0;
-+	    }
-+	    if (ie->data[13] + 14 == ie->len) {
-+		q931_get_number(call->callername, sizeof(call->callername) - 1, ie->data + 14, ie->len - 14);
-+	    } 
-+	    call->facility = 0x0;
- 	}
--	if (ie->data[13] + 14 == ie->len) {
--		q931_get_number((unsigned char *) call->callername, sizeof(call->callername) - 1, ie->data + 14, ie->len - 14);
--	} 
--	return 0;
-+  	return 0;
-+}
-+
-+static FUNC_SEND(transmit_facility)
-+{
-+	int i = 0;
-+	return i;
-+	if (call->aoc && (pri->switchtype == PRI_SWITCH_EUROISDN_E1) && ((pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_NETWORK_PTMP) || (pri->localtype == PRI_NETWORK))) {
-+	    ie->data[0] = 0x90;  /* PP remote operations */
-+	    ie->data[i++] = 0x00; /* component tag */
-+	    ie->data[i++] = 0x02; /* invoke id tag */
-+	    ie->data[i++] = 0x02; /* invoke id len */
-+	    ie->data[i++] = 0x34; /* invoke id */
-+	    ie->data[i++] = 0x56; /* invoke id */
-+	    ie->data[i++] = 0x02; /* operation value tag */
-+	    ie->data[i++] = 0x01; /* operation value len */
-+	    switch (msgtype) {
-+		case Q931_SETUP:
-+		    ie->data[i++] = 0x26; /* operation value AOC-S */
-+		    break;
-+		case Q931_DISCONNECT:
-+		    ie->data[i++] = 0x24; /* operation value AOC-E */
-+		    break;
-+		default:
-+		    ie->data[i++] = 0x22; /* operation value AOC-D */
-+		    break;
-+	    }
-+	    // ARGUMENTS!	
-+	}
-+//	return 2 + i;
- }
- 
- static FUNC_SEND(transmit_progress_indicator)
-@@ -1075,6 +1359,7 @@
- 	if (!pri->subchannel && (call->progress > 0)) {
- 		ie->data[0] = 0x80 | (call->progcode << 5)  | (call->progloc);
- 		ie->data[1] = 0x80 | (call->progress);
-+//		ie->data[1] = 0x88;
- 		return 4;
- 	} else {
- 		/* Leave off */
-@@ -1156,6 +1441,26 @@
- 	pri_message(" ]\n");
- }
- 
-+static FUNC_RECV(receive_time_date)
-+{
-+    return 0;
-+}
-+
-+static FUNC_SEND(transmit_time_date) {
-+    time_t now;
-+    struct tm *timedate;
-+    time(&now);
-+    timedate = localtime(&now);
-+    ie->data[0] = timedate->tm_year - 100; // 1900+
-+    ie->data[1] = timedate->tm_mon + 1;
-+    ie->data[2] = timedate->tm_mday;
-+    ie->data[3] = timedate->tm_hour;
-+    ie->data[4] = timedate->tm_min;
-+    return 7;
-+}
-+
-+
-+
- static FUNC_DUMP(dump_display)
- {
- 	int x, y;
-@@ -1175,6 +1480,32 @@
- 	}
- }
- 
-+static FUNC_RECV(receive_keypad_facility)
-+{
-+	/* copy digits to call->callednum or call->digits */
-+	if (msgtype == Q931_SETUP) {
-+	    if (len >= 2) {
-+ 		q931_get_number(call->digits, sizeof(call->digits), ie->data , len - 2);
-+	    } else {
-+		pri_error("Keypad facility (len=%2d) too short.\n", len);
-+	    }
-+	} else {
-+	    // XXX we assume 1 byte keypad
-+	    call->digits[0] = ie->data[0] & 0x7f;
-+	    call->digits[1] = '\0';
-+	}
-+	return 0;
-+}
-+
-+static FUNC_DUMP(dump_keypad_facility)
-+{
-+	int x;
-+	pri_message("%c Keypad Facility (len=%2d) [ ", prefix, len);
-+	for (x=0;x<ie->len;x++) 
-+		pri_message("%c", ie->data[x] & 0x7f);
-+	pri_message(" ]\n");
-+}
-+
- static void dump_ie_data(unsigned char *c, int len)
- {
- 	char tmp[1024] = "";
-@@ -1432,7 +1763,53 @@
- #endif
- 	return 0;
- }
-+/*
-+static int transmit_special(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
-+{
-+// 1C 02 95 81 97 02 02 32 39 04 01 80 05 02 01 5B
-+	ie->data[0] = 0x1c;
-+	ie->data[1] = 0x02;
-+	ie->data[2] = 0x95;
-+	ie->data[3] = 0x81;
-+	ie->data[4] = 0x97;
-+	ie->data[5] = 0x02;
-+	ie->data[6] = 0x02;
-+	ie->data[7] = 0x32;
- 
-+	ie->data[8] = 0x39;
-+	ie->data[9] = 0x04;
-+	ie->data[10] = 0x01;
-+	ie->data[11] = 0x80;
-+	ie->data[12] = 0x05;
-+	ie->data[13] = 0x02;
-+	ie->data[14] = 0x01;
-+	ie->data[15] = 0x5B;
-+
-+
-+	return 17;
-+}
-+
-+static int receive_special(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len) 
-+{
-+    return 0;
-+}
-+
-+static void dump_special(q931_ie *ie, int len, char prefix)
-+{
-+	int x=0;
-+	pri_message("%c SPECIAL (len=%2d) [ ", prefix, ie->len);
-+	for (x=0;x<ie->len;x++) 
-+		pri_message("%2x ", ie->data[x]);
-+	pri_message("]\n");
-+}
-+
-+static int transmit_my_paging_signal(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
-+{
-+	ie->data[0] = 0x47;
-+	return 3;
-+}
-+
-+*/
- struct ie ies[] = {
- 	/* Codeset 0 - Common */
- 	{ NATIONAL_CHANGE_STATUS, "Change Status" },
-@@ -1461,20 +1838,21 @@
- 	{ Q931_LOW_LAYER_COMPAT, "Low-layer Compatibility" },
- 	{ Q931_HIGH_LAYER_COMPAT, "High-layer Compatibility" },
- 	{ Q931_PACKET_SIZE, "Packet Size" },
--	{ Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility },
-+	{ Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility, transmit_facility },
- 	{ Q931_IE_REDIRECTION_NUMBER, "Redirection Number" },
- 	{ Q931_IE_REDIRECTION_SUBADDR, "Redirection Subaddress" },
- 	{ Q931_IE_FEATURE_ACTIVATE, "Feature Activation" },
- 	{ Q931_IE_INFO_REQUEST, "Feature Request" },
- 	{ Q931_IE_FEATURE_IND, "Feature Indication" },
- 	{ Q931_IE_SEGMENTED_MSG, "Segmented Message" },
--	{ Q931_IE_CALL_IDENTITY, "Call Identity", dump_call_identity },
-+	{ Q931_IE_CALL_IDENTITY, "Call Identity", dump_call_identity, receive_call_identity, transmit_call_identity },
- 	{ Q931_IE_ENDPOINT_ID, "Endpoint Identification" },
- 	{ Q931_IE_NOTIFY_IND, "Notification Indicator", dump_notify, receive_notify, transmit_notify },
- 	{ Q931_DISPLAY, "Display", dump_display, receive_display, transmit_display },
--	{ Q931_IE_TIME_DATE, "Date/Time", dump_time_date },
--	{ Q931_IE_KEYPAD_FACILITY, "Keypad Facility" },
--	{ Q931_IE_SIGNAL, "Signal" },
-+	{ Q931_IE_TIME_DATE, "Date/Time", dump_time_date, receive_time_date, transmit_time_date },
-+	{ Q931_IE_KEYPAD_FACILITY, "Keypad Facility" , dump_keypad_facility, receive_keypad_facility},
-+	{ Q931_IE_SIGNAL, "Signal"},
-+//	{ Q931_IE_SIGNAL, "Signal",dump_special, receive_special, transmit_my_paging_signal},
- 	{ Q931_IE_SWITCHHOOK, "Switch-hook" },
- 	{ Q931_IE_USER_USER, "User-User", dump_user_user, receive_user_user },
- 	{ Q931_IE_ESCAPE_FOR_EXT, "Escape for Extension" },
-@@ -1485,6 +1863,7 @@
- 	{ Q931_IE_ORIGINAL_CALLED_NUMBER, "Original Called Number" },
- 	{ Q931_IE_USER_USER_FACILITY, "User-User Facility" },
- 	{ Q931_IE_UPDATE, "Update" },
-+	{ Q931_COLP, "Connect Line ID Presentation", dump_colp},
- 	{ Q931_SENDING_COMPLETE, "Sending Complete", dump_sending_complete, receive_sending_complete, transmit_sending_complete },
- 	/* Codeset 6 - Network specific */
- 	{ Q931_IE_FACILITY | Q931_CODESET(6), "Facility", dump_facility, receive_facility },
-@@ -1548,7 +1927,7 @@
- {
- 	if ((ie->ie & 0x80) != 0)
- 		return 1;
--	else
-+	else 
- 		return 2 + ie->len;
- }
- 
-@@ -1578,13 +1957,13 @@
- 			break;
- 		case 1:
- 			cr = h->crv[0];
--			if (cr & 0x80) {
-+		/*	if (cr & 0x80) {
- 				cr &= ~0x80;
- 				cr |= 0x8000;
--			}
-+			} */
- 			break;
--		default:
--			pri_error("Call Reference Length not supported: %d\n", h->crlen);
-+		// default:
-+		//	pri_error("Call Reference Length not supported: %d\n", h->crlen);
- 	}
- 	return cr;
- }
-@@ -1595,6 +1974,11 @@
- 	int full_ie = Q931_FULL_IE(codeset, ie->ie);
- 	int base_ie;
- 
-+	if (ielen(ie) > Q931_IE_MAX_LEN) {
-+	    pri_error("!! %c Invalid IE length %d (len = %d)\n", prefix, base_ie, ielen(ie));
-+	    return;
-+	}
-+
- 	pri_message("%c [", prefix);
- 	pri_message("%02x", ie->ie);
- 	if (!(ie->ie & 0x80)) {
-@@ -1622,14 +2006,46 @@
- 	pri_error("!! %c Unknown IE %d (len = %d)\n", prefix, base_ie, ielen(ie));
- }
- 
--static q931_call *q931_getcall(struct pri *pri, int cr)
-+static q921_call *q921_getcall(struct pri *pri, struct q931_call *c, int tei)
-+{
-+	q921_call *cur;
-+	cur = c->phones;
-+	while(cur) {
-+	    if (cur->tei == tei) {
-+		    return cur;
-+	    } 
-+	    cur = cur->next;
-+	}
-+	/* No call exists, make a new one */
-+	if (pri->debug & PRI_DEBUG_Q921_STATE)
-+		pri_message("-- Making new q921 call for cref %d tei %d\n", c->cr, tei);
-+	cur = malloc(sizeof(struct q921_call));
-+	memset(cur, 0, sizeof(cur));
-+	cur->tei = tei;
-+	cur->proc = 0;
-+	cur->channel = -1;
-+	cur->next = c->phones;
-+	c->phones = cur;
-+	return cur;
-+}
-+
-+static q931_call *q931_getcall(struct pri *pri, int cr, int tei)
- {
- 	q931_call *cur, *prev;
- 	cur = *pri->callpool;
- 	prev = NULL;
- 	while(cur) {
--		if (cur->cr == cr)
--			return cur;
-+		if ((pri->localtype == BRI_NETWORK_PTMP) && (tei >= 0)) {
-+		    // hmm...ok, we might be the 1st responding to the setup
-+		    // or it is really our call
-+		    if ((cur->cr == cr) && ((cur->tei == tei) || (cur->tei == 127)))
-+			    return cur;
-+	    	    // or we might not be the 1st responding, then we need to clone
-+		    // the call struct to hangup properly
-+		} else {
-+		    if (cur->cr == cr)
-+			    return cur;
-+		}
- 		prev = cur;
- 		cur = cur->next;
- 	}
-@@ -1642,6 +2058,7 @@
- 		/* Call reference */
- 		cur->cr = cr;
- 		cur->pri = pri;
-+		cur->tei = tei;
- 		/* Append to end of list */
- 		if (prev)
- 			prev->next = cur;
-@@ -1657,24 +2074,42 @@
- 	do {
- 		cur = *pri->callpool;
- 		pri->cref++;
--		if (pri->cref > 32767)
--			pri->cref = 1;
-+		if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
-+		    if (pri->cref > 32767)
-+			    pri->cref = 1;
-+		} else {
-+		    // BRI
-+		    if (pri->cref > 255)
-+			    pri->cref = 1;
-+		}
- 		while(cur) {
--			if (cur->cr == (0x8000 | pri->cref))
--				break;
-+			if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
-+			    if (cur->cr == (0x8000 | pri->cref))
-+				    break;
-+			} else {
-+			    // BRIs have only 1 bye cref
-+			    if (cur->cr == (0x80 | pri->cref))
-+				    break;
-+			}
- 			cur = cur->next;
- 		}
- 	} while(cur);
--	return q931_getcall(pri, pri->cref | 0x8000);
-+	if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
-+	    return q931_getcall(pri, pri->cref | 0x8000, 0);
-+	} else {
-+	    // BRI
-+	    return q931_getcall(pri, pri->cref | 0x80, 0);
-+	}
- }
- 
--static void q931_destroy(struct pri *pri, int cr, q931_call *c)
-+static void q931_destroy(struct pri *pri, int cr, q931_call *c, int tei)
- {
- 	q931_call *cur, *prev;
- 	prev = NULL;
- 	cur = *pri->callpool;
- 	while(cur) {
--		if ((c && (cur == c)) || (!c && (cur->cr == cr))) {
-+//		if ((c && (cur == c)) || (!c && (cur->cr == cr))) {
-+		if ((c && (cur == c)) || (!c && ((cur->cr == cr) && ((pri->localtype != BRI_NETWORK_PTMP) || (cur->tei == tei))))) {
- 			if (prev)
- 				prev->next = cur->next;
- 			else
-@@ -1683,6 +2118,8 @@
- 				pri_message("NEW_HANGUP DEBUG: Destroying the call, ourstate %s, peerstate %s\n",callstate2str(cur->ourcallstate),callstate2str(cur->peercallstate));
- 			if (cur->retranstimer)
- 				pri_schedule_del(pri, cur->retranstimer);
-+			if (cur->t303timer)
-+				pri_schedule_del(pri, cur->t303timer);
- 			free(cur);
- 			return;
- 		}
-@@ -1692,16 +2129,17 @@
- 	pri_error("Can't destroy call %d!\n", cr);
- }
- 
--static void q931_destroycall(struct pri *pri, int cr)
-+
-+static void q931_destroycall(struct pri *pri, int cr, int tei)
- {
--	return q931_destroy(pri, cr, NULL);
-+	return q931_destroy(pri, cr, NULL, tei);
- }
- 
- 
- void __q931_destroycall(struct pri *pri, q931_call *c) 
- {
- 	if (pri && c)
--		q931_destroy(pri,0, c);
-+		q931_destroy(pri,0, c, c->tei);
- 	return;
- }
- 
-@@ -1799,6 +2237,10 @@
- {
- 	unsigned int x;
- 	int full_ie = Q931_FULL_IE(codeset, ie->ie);
-+	if (ielen(ie) > Q931_IE_MAX_LEN) {
-+	    pri_error("!! Invalid IE length %d (len = %d)\n", full_ie, ielen(ie));
-+	    return -1;
-+	}
- 	if (pri->debug & PRI_DEBUG_Q931_STATE)
- 		pri_message("-- Processing IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));
- 	for (x=0;x<sizeof(ies) / sizeof(ies[0]);x++) {
-@@ -1816,21 +2258,36 @@
- 	return -1;
- }
- 
--static void init_header(struct pri *pri, q931_call *call, unsigned char *buf, q931_h **hb, q931_mh **mhb, int *len)
-+static void init_header(struct pri *pri, q931_call *call, unsigned char *buf, q931_h **hb, q931_mh **mhb, int *len, int briflag)
- {
- 	/* Returns header and message header and modifies length in place */
-+	q931_mh *mh;
- 	q931_h *h = (q931_h *)buf;
--	q931_mh * mh = (q931_mh *)(h->contents + 2);
- 	h->pd = pri->protodisc;
- 	h->x0 = 0;		/* Reserved 0 */
--	h->crlen = 2;	/* Two bytes of Call Reference.  Invert the top bit to make it from our sense */
--	if (call->cr || call->forceinvert) {
-+
-+	if (briflag == 1) {
-+	    mh = (q931_mh *)(h->contents + 1);
-+ 	    h->crlen = 1;	/* One bytes of Call Reference.  Invert the top bit to make it from our sense */
-+	    if (call->cr || call->forceinvert) {
-+		h->crv[0] = (call->cr ^ 0x80);
-+	    } else {
-+		/* Unless of course this has no call reference */
-+		h->crv[0] = 0;
-+	    }
-+	    *len -= 4;
-+	} else {
-+	    mh = (q931_mh *)(h->contents + 2);
-+ 	    h->crlen = 2;	/* Two bytes of Call Reference.  Invert the top bit to make it from our sense */
-+	    if (call->cr || call->forceinvert) {
- 		h->crv[0] = ((call->cr ^ 0x8000) & 0xff00) >> 8;
- 		h->crv[1] = (call->cr & 0xff);
--	} else {
-+	    } else {
- 		/* Unless of course this has no call reference */
- 		h->crv[0] = 0;
- 		h->crv[1] = 0;
-+	    }
-+	    *len -= 5;
- 	}
- 	if (pri->subchannel) {
- 		/* On GR-303, top bit is always 0 */
-@@ -1839,13 +2296,37 @@
- 	mh->f = 0;
- 	*hb = h;
- 	*mhb = mh;
--	*len -= 5;
--	
- }
- 
--static int q931_xmit(struct pri *pri, q931_h *h, int len, int cr)
-+static int q931_xmit(struct pri *pri, q931_h *h, int len, int cr, int tei)
- {
--	q921_transmit_iframe(pri, h, len, cr);
-+	q931_mh *mh;
-+	if (pri->localtype == BRI_NETWORK_PTMP) {
-+	    mh = (q931_mh *)(h->contents + 1);
-+	    if (mh->msg == Q931_SETUP) {
-+		q921_transmit_uframe(pri, h, len, cr, tei);
-+	    } else {
-+		q921_transmit_iframe(pri, h, len, cr, tei);
-+	    }
-+	} else if (pri->localtype == BRI_CPE_PTMP) {
-+	    mh = (q931_mh *)(h->contents + 1);
-+	    if ((pri->state == Q921_LINK_CONNECTION_RELEASED) && (mh->msg == Q931_SETUP)) {
-+	        // no MFE
-+	/*        if (pri->tei == 0) {
-+		    pri_error("no tei\n");
-+		    q921_send_teireq(pri);
-+		} else {
-+		    q921_send_sabme(pri,1,pri->tei);
-+		    pri->q921_state[tei - Q921_TEI_BASE] = Q921_AWAITING_ESTABLISH;
-+		}
-+		q921_reset(pri, pri->tei); */
-+	    }
-+	    // XXX D    IRTY!, we rely on the fact that the L3 frames will be retransmitted
-+	    // if they dont get ACKed. however this is supposed to work.
-+	     q921_transmit_iframe(pri, h, len, cr, pri->tei);
-+	} else {
-+	    q921_transmit_iframe(pri, h, len, cr, tei);
-+	}
- 	/* The transmit operation might dump the q921 header, so logging the q931
- 	   message body after the transmit puts the sections of the message in the
- 	   right order in the log */
-@@ -1869,7 +2350,11 @@
- 	int codeset;
- 	memset(buf, 0, sizeof(buf));
- 	len = sizeof(buf);
--	init_header(pri, c, buf, &h, &mh, &len);
-+	if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
-+	    init_header(pri, c, buf, &h, &mh, &len, 0);
-+	} else {
-+	    init_header(pri, c, buf, &h, &mh, &len, 1);
-+	}
- 	mh->msg = msgtype;
- 	x=0;
- 	codeset = 0;
-@@ -1885,11 +2370,33 @@
- 	}
- 	/* Invert the logic */
- 	len = sizeof(buf) - len;
--	q931_xmit(pri, h, len, 1);
-+	if (pri->localtype == BRI_CPE_PTMP) {
-+	    q931_xmit(pri, h, len, 1, pri->tei);
-+	} else {
-+	    q931_xmit(pri, h, len, 1, c->tei);
-+	}
- 	c->acked = 1;
- 	return 0;
- }
- 
-+static int facility_ies[] = { Q931_IE_FACILITY, -1 };
-+
-+int q931_facility(struct pri *pri, q931_call *c, int operation, char *arguments)
-+{
-+	switch (operation) {
-+	    case 0x26:	c->aoc = 1;
-+			break;
-+	    case 0x24:	c->aoc = 1;
-+			break;
-+	    case 0x22:	c->aoc = 1;
-+			break;
-+	    default:
-+		return -1;
-+	}
-+	return send_message(pri, c, Q931_FACILITY, facility_ies);
-+}
-+
-+
- static int status_ies[] = { Q931_CAUSE, Q931_CALL_STATE, -1 };
- 
- static int q931_status(struct pri *pri, q931_call *c, int cause)
-@@ -1927,12 +2434,42 @@
- 	return send_message(pri, c, Q931_INFORMATION, information_ies);
- }
- 
-+static int information_display_ies[] = { Q931_DISPLAY, -1 };
-+
-+int q931_information_display(struct pri *pri, q931_call *c, char *display)
-+{
-+	int res=0;
-+	char temp[256];
-+	if (!display) return -1;
-+	strncpy(temp, c->callername, sizeof(temp));
-+	strncpy(c->callername, display, sizeof(c->callername));
-+	res = send_message(pri, c, Q931_INFORMATION, information_display_ies);
-+	strncpy(c->callername, temp, sizeof(c->callername));
-+	return res;
-+}
-+
-+int q931_add_display(struct pri *pri, q931_call *c, char *display)
-+{
-+	strncpy(c->display, display, sizeof(c->display));
-+	return 0;
-+}
-+
-+/* static int information_special_ies[] = { Q931_IE_SPECIAL, -1 };
-+static int q931_information_special(struct pri *pri, q931_call *c)
-+{
-+	return send_message(pri, c, Q931_FACILITY, information_special_ies);
-+}
-+*/
-+
-+
- static int restart_ack_ies[] = { Q931_CHANNEL_IDENT, Q931_RESTART_INDICATOR, -1 };
- 
- static int restart_ack(struct pri *pri, q931_call *c)
- {
- 	c->ourcallstate = Q931_CALL_STATE_NULL;
- 	c->peercallstate = Q931_CALL_STATE_NULL;
-+        c->chanflags &= ~FLAG_PREFERRED;
-+        c->chanflags |= FLAG_EXCLUSIVE;
- 	return send_message(pri, c, Q931_RESTART_ACKNOWLEDGE, restart_ack_ies);
- }
- 
-@@ -2003,8 +2540,14 @@
- static int alerting_ies[] = { -1 };
- #endif
- 
-+// static int alerting_BRI_ies[] = { -1 };
-+
- int q931_alerting(struct pri *pri, q931_call *c, int channel, int info)
- {
-+	// never send two ALERTINGs!
-+	if (c->alert > 0) return 0;		
-+	// XXX novo vox hack
-+//	if ((!c->proc) && (pri->localtype != BRI_CPE_PTMP))
- 	if (!c->proc) 
- 		q931_call_proceeding(pri, c, channel, 0);
- 	if (info) {
-@@ -2015,11 +2558,126 @@
- 		c->progress = -1;
- 	c->ourcallstate = Q931_CALL_STATE_CALL_RECEIVED;
- 	c->peercallstate = Q931_CALL_STATE_CALL_DELIVERED;
-+	c->alert = 1;
- 	c->alive = 1;
- 	return send_message(pri, c, Q931_ALERTING, alerting_ies);
-+/*	if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
-+	    return send_message(pri, c, Q931_ALERTING, alerting_ies);
-+	} else {
-+	    if ((pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_NETWORK_PTMP)) {
-+		return send_message(pri, c, Q931_ALERTING, alerting_ies);
-+    	    } else {
-+		// no PROGRESS_IND for BRI please
-+		return send_message(pri, c, Q931_ALERTING, alerting_BRI_ies);
-+	    }
-+	} */
- }
- 
--static int connect_ies[] = {  Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, -1 };
-+static int hold_acknowledge_ies[] = { -1 };
-+
-+int q931_hold_acknowledge(struct pri *pri, q931_call *c)
-+{
-+	return send_message(pri, c, Q931_HOLD_ACKNOWLEDGE, hold_acknowledge_ies);
-+}
-+
-+static int hold_reject_ies[] = { Q931_CAUSE, -1 };
-+
-+int q931_hold_reject(struct pri *pri, q931_call *c)
-+{
-+	c->cause = 12;
-+	c->causecode = CODE_CCITT;
-+	c->causeloc = LOC_PRIV_NET_LOCAL_USER;
-+	return send_message(pri, c, Q931_HOLD_REJECT, hold_reject_ies);
-+}
-+
-+static int retrieve_acknowledge_ies[] = { Q931_CHANNEL_IDENT, -1 };
-+
-+int q931_retrieve_acknowledge(struct pri *pri, q931_call *c, int channel)
-+{
-+	if (channel)
-+		c->channelno = channel;
-+	c->chanflags &= ~FLAG_PREFERRED;
-+	c->chanflags |= FLAG_EXCLUSIVE;
-+	return send_message(pri, c, Q931_RETRIEVE_ACKNOWLEDGE, retrieve_acknowledge_ies);
-+}
-+
-+static int retrieve_reject_ies[] = { -1 };
-+
-+int q931_retrieve_reject(struct pri *pri, q931_call *c)
-+{
-+	return send_message(pri, c, Q931_RETRIEVE_REJECT, retrieve_reject_ies);
-+}
-+
-+static int suspend_acknowledge_ies[] = { Q931_DISPLAY, -1 };
-+
-+int q931_suspend_acknowledge(struct pri *pri, q931_call *c, char *display)
-+{
-+	char tempcallername[256];
-+	int res;
-+	c->ourcallstate = Q931_CALL_STATE_NULL;
-+	c->peercallstate = Q931_CALL_STATE_NULL;
-+	strncpy(tempcallername,c->callername,sizeof(tempcallername));
-+	strncpy(c->callername,display,sizeof(c->callername));
-+	res = send_message(pri, c, Q931_SUSPEND_ACKNOWLEDGE, suspend_acknowledge_ies);
-+	strncpy(c->callername,tempcallername,sizeof(c->callername));
-+	return res;
-+}
-+
-+static int suspend_reject_ies[] = { Q931_DISPLAY, Q931_CAUSE, -1 };
-+
-+int q931_suspend_reject(struct pri *pri, q931_call *c, char *display)
-+{
-+	char tempcallername[256];
-+	int res;
-+	strncpy(tempcallername,c->callername,sizeof(tempcallername));
-+	strncpy(c->callername,display,sizeof(c->callername));
-+	c->cause = 12;
-+	c->causecode = CODE_CCITT;
-+	c->causeloc = LOC_PRIV_NET_LOCAL_USER;
-+	res = send_message(pri, c, Q931_SUSPEND_REJECT, suspend_reject_ies);
-+	strncpy(c->callername,tempcallername,sizeof(c->callername));
-+	return res;
-+}
-+
-+static int resume_reject_ies[] = { Q931_CAUSE, Q931_DISPLAY,  -1 };
-+
-+int q931_resume_reject(struct pri *pri, q931_call *c, char *display)
-+{
-+	char tempcallername[256];
-+	int res;
-+	c->cause = 12;
-+	c->causecode = CODE_CCITT;
-+	c->causeloc = LOC_PRIV_NET_LOCAL_USER;
-+	strncpy(tempcallername,c->callername,sizeof(tempcallername));
-+	strncpy(c->callername,display,sizeof(c->callername));
-+	res = send_message(pri, c, Q931_RESUME_REJECT, resume_reject_ies);
-+	strncpy(c->callername,tempcallername,sizeof(c->callername));
-+	return res;
-+}
-+
-+static int resume_acknowledge_ies[] = { Q931_CHANNEL_IDENT, Q931_DISPLAY,  -1 };
-+
-+int q931_resume_acknowledge(struct pri *pri, q931_call *c, int channel, char *display)
-+{
-+	char tempcallername[256];
-+	int res;
-+	if (channel)
-+		c->channelno = channel;
-+	c->chanflags &= ~FLAG_PREFERRED;
-+	c->chanflags |= FLAG_EXCLUSIVE;
-+	c->alive = 1;
-+	c->ourcallstate = Q931_CALL_STATE_ACTIVE;
-+	c->peercallstate = Q931_CALL_STATE_ACTIVE;
-+	strncpy(tempcallername,c->callername,sizeof(tempcallername));
-+	strncpy(c->callername,display,sizeof(c->callername));
-+	res = send_message(pri, c, Q931_RESUME_ACKNOWLEDGE, resume_acknowledge_ies);
-+	strncpy(c->callername,tempcallername,sizeof(c->callername));
-+	return res;
-+}
-+
-+
-+static int connect_ies[] = {  Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, Q931_DISPLAY, -1 };
-+static int connect_NET_ies[] = {  Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, Q931_IE_TIME_DATE, -1 };
-  
- int q931_setup_ack(struct pri *pri, q931_call *c, int channel, int nonisdn)
- {
-@@ -2039,9 +2697,34 @@
- 	c->ourcallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
- 	c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;
- 	c->alive = 1;
-+	if (pri->localtype == BRI_NETWORK_PTMP) {
-+		c->progloc = LOC_PRIV_NET_LOCAL_USER;
-+		c->progcode = CODE_CCITT;
-+		c->progress = Q931_PROG_INBAND_AVAILABLE;
-+	}
- 	return send_message(pri, c, Q931_SETUP_ACKNOWLEDGE, connect_ies);
- }
- 
-+static void pri_setup_response_timeout(void *data)
-+{
-+	struct q931_call *c = data;
-+	struct pri *pri = NULL;
-+	if (!c) return;
-+	pri = c->pri;
-+	if (!pri) return;
-+	c->alive = 1;
-+	c->cause = PRI_CAUSE_NO_USER_RESPONSE;
-+	if (pri->debug & PRI_DEBUG_Q931_STATE)
-+		pri_message("No response to SETUP message\n");
-+	pri->schedev = 1;
-+	pri->ev.e = PRI_EVENT_HANGUP;
-+	pri->ev.hangup.channel = c->channelno;
-+	pri->ev.hangup.cref = c->cr;
-+	pri->ev.hangup.cause = c->cause;
-+	pri->ev.hangup.call = c;
-+	q931_hangup(pri, c, c->cause);
-+}
-+
- static void pri_connect_timeout(void *data)
- {
- 	struct q931_call *c = data;
-@@ -2116,7 +2799,12 @@
- 	c->retranstimer = 0;
- 	if ((pri->localtype == PRI_CPE) && (!pri->subchannel))
- 		c->retranstimer = pri_schedule_event(pri, T_313, pri_connect_timeout, c);
--	return send_message(pri, c, Q931_CONNECT, connect_ies);
-+	if ((pri->localtype != PRI_CPE) && (pri->localtype != BRI_CPE) && (pri->localtype != BRI_CPE_PTMP)) {
-+	    // networks may send datetime
-+	    return send_message(pri, c, Q931_CONNECT, connect_NET_ies);
-+	} else {
-+	    return send_message(pri, c, Q931_CONNECT, connect_ies);
-+	}
- }
- 
- static int release_ies[] = { Q931_CAUSE, -1 };
-@@ -2150,7 +2838,7 @@
- int q931_restart(struct pri *pri, int channel)
- {
- 	struct q931_call *c;
--	c = q931_getcall(pri, 0 | 0x8000);
-+	c = q931_getcall(pri, 0 | 0x8000, 0);
- 	if (!c)
- 		return -1;
- 	if (!channel)
-@@ -2186,15 +2874,24 @@
- 		return 0;
- }
- 
-+//static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_DISPLAY, Q931_PROGRESS_INDICATOR,
-+//	 Q931_IE_SIGNAL, Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_SENDING_COMPLETE, -1 };
-+
- static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, Q931_NETWORK_SPEC_FAC, Q931_DISPLAY,
- 	Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_SENDING_COMPLETE, Q931_IE_ORIGINATING_LINE_INFO, -1 };
- 
- static int gr303_setup_ies[] =  { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, -1 };
- 
-+
- int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
- {
- 	int res;
- 	
-+	if (pri->localtype == BRI_NETWORK_PTMP) {
-+	    c->tei = 127;
-+	} else {
-+	    c->tei = 0;
-+	}
- 	
- 	c->transcapability = req->transmode;
- 	c->transmoderate = TRANS_MODE_64_CIRCUIT;
-@@ -2251,12 +2948,17 @@
- 		res = send_message(pri, c, Q931_SETUP, gr303_setup_ies);
- 	else
- 		res = send_message(pri, c, Q931_SETUP, setup_ies);
-+
- 	if (!res) {
- 		c->alive = 1;
- 		/* make sure we call PRI_EVENT_HANGUP_ACK once we send/receive RELEASE_COMPLETE */
- 		c->sendhangupack = 1;
- 		c->ourcallstate = Q931_CALL_STATE_CALL_INITIATED;
- 		c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;	
-+		if ((pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_NETWORK_PTMP) || (pri->localtype == PRI_NETWORK)) {
-+		    c->t303timer = pri_schedule_event(pri, T_303, pri_setup_response_timeout, c);
-+		    c->t303running = 1;
-+		}
- 	}
- 	return res;
- 	
-@@ -2297,6 +2999,118 @@
- 	return 0;
- }
- 
-+
-+
-+/* here we cleanly hangup the phones that responded to our call but didnt get the call  */
-+int q921_hangup(struct pri *pri, q931_call *c, int tei)
-+{
-+    q921_call *cur,*prev;
-+    int tc;
-+    int ttei;
-+    int res=0;
-+
-+    if (!pri || !c)
-+	return -1;
-+    
-+    if (pri->localtype != BRI_NETWORK_PTMP){
-+	return 0;
-+    }
-+//	pri_error("q921_hangup(%d, %d)\n", c->cr, tei);
-+
-+    if (tei == 127) {
-+	tei = c->tei;
-+    }
-+//	pri_error("tei %d\n", tei);
-+
-+    cur = c->phones;
-+    
-+    tc = c->cause;
-+    ttei = c->tei;
-+    while (cur) {
-+	if (cur->tei != tei) {
-+	    c->cause = PRI_CAUSE_NORMAL_CLEARING;
-+	    c->tei = cur->tei;
-+	    if (pri->debug & PRI_DEBUG_Q921_STATE)
-+		pri_message("sending RELEASE for TEI %d\n", cur->tei);
-+	    send_message(pri, c, Q931_RELEASE, release_ies);
-+	}
-+	prev = cur;
-+	cur = cur->next;
-+	if (prev) {
-+	    free(prev);
-+	    prev = NULL;
-+	}
-+    }
-+    c->phones = NULL;
-+    c->tei = ttei;
-+    c->cause = tc;
-+
-+    if (c->tei == 127) {
-+	q931_destroycall(pri, c->cr, c->tei);
-+	// make sure * frees the channel
-+/*	pri_error("returning PRI_EVENT_HANGUP_ACK\n");
-+	res = Q931_RES_HAVEEVENT;
-+	pri->ev.hangup.channel = c->channelno;
-+	pri->ev.e = PRI_EVENT_HANGUP_ACK;  */
-+    } 
-+    return res; 
-+}
-+
-+/* here we handle release_completes from the phones 
-+   because some (elmeg) phones do not send a disconnect
-+   message when the phone is busy */
-+int q921_handle_hangup(struct pri *pri, q931_call *c, int tei)
-+{
-+    q921_call *cur,*match,*prev=NULL;
-+    int left=0;
-+    int res=0;
-+    
-+    if (!pri || !c)
-+	return -1;
-+
-+    if (pri->localtype != BRI_NETWORK_PTMP){
-+	return 0;
-+    }
-+
-+    cur = c->phones;
-+    
-+    while (cur) {
-+	if (cur->tei == tei) {
-+	    match = cur;
-+	    if (prev) {
-+		prev->next = cur->next;
-+		cur = prev;
-+	    } else {
-+		c->phones = cur->next;
-+	    }
-+	    free(match);
-+	}
-+	prev = cur;
-+	if (cur) cur = cur->next;
-+    }
-+
-+    cur = c->phones;
-+    
-+    while (cur) {
-+	left++;
-+	cur = cur->next;
-+    }
-+    
-+    // if all phones have signalled busy AND the timer is not running anymore!
-+    if ((left==0) && (c->cause == PRI_CAUSE_USER_BUSY) && (c->t303running == 0)) {
-+//	pri_error("q921_handle_hangup(%d, %d, %d)\n", c->cr, tei, c->tei);
-+	// make sure * frees the channel
-+	res = Q931_RES_HAVEEVENT;
-+	pri->ev.hangup.cause = PRI_CAUSE_USER_BUSY;
-+	pri->ev.hangup.channel = c->channelno | (c->ds1no << 8);
-+	pri->ev.hangup.cref = c->cr;          		
-+	pri->ev.hangup.call = c;
-+	pri->ev.e = PRI_EVENT_HANGUP; 
-+    } 
-+    return res; 
-+}
-+
-+
- int q931_hangup(struct pri *pri, q931_call *c, int cause)
- {
- 	int disconnect = 1;
-@@ -2322,7 +3136,7 @@
- 	case Q931_CALL_STATE_NULL:
- 		if (c->peercallstate == Q931_CALL_STATE_NULL)
- 			/* free the resources if we receive or send REL_COMPL */
--			q931_destroycall(pri, c->cr);
-+			q931_destroycall(pri, c->cr, c->tei);
- 		else if (c->peercallstate == Q931_CALL_STATE_RELEASE_REQUEST)
- 			q931_release_complete(pri,c,cause);
- 		break;
-@@ -2348,14 +3162,21 @@
- 		/* received SETUP_ACKNOWLEDGE */
- 		/* send DISCONNECT in general */
- 		if (c->peercallstate != Q931_CALL_STATE_NULL && c->peercallstate != Q931_CALL_STATE_DISCONNECT_REQUEST && c->peercallstate != Q931_CALL_STATE_DISCONNECT_INDICATION && c->peercallstate != Q931_CALL_STATE_RELEASE_REQUEST && c->peercallstate != Q931_CALL_STATE_RESTART_REQUEST && c->peercallstate != Q931_CALL_STATE_RESTART) {
--			if (disconnect)
-+			if (pri->localtype == BRI_NETWORK_PTMP) {
-+			    if (c->tei == 127) {
-+			        break;
-+			    }
-+			} 
-+			if (disconnect) {
- 				q931_disconnect(pri,c,cause);
--			else if (release_compl)
-+			} else if (release_compl) {
- 				q931_release_complete(pri,c,cause);
--			else
-+			} else {
- 				q931_release(pri,c,cause);
--		} else 
-+			}
-+		} else {
- 			pri_error("Wierd, doing nothing but this shouldn't happen, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate));
-+		}
- 		break;
- 	case Q931_CALL_STATE_DISCONNECT_REQUEST:
- 		/* sent DISCONNECT */
-@@ -2363,8 +3184,14 @@
- 		break;
- 	case Q931_CALL_STATE_DISCONNECT_INDICATION:
- 		/* received DISCONNECT */
-+		if (pri->localtype == BRI_NETWORK_PTMP) {
-+		    if (c->tei == 127) {
-+			break;
-+		    }
-+		} 
- 		if (c->peercallstate == Q931_CALL_STATE_DISCONNECT_REQUEST) {
- 			c->alive = 1;
-+//		    pri_error("sending release to %d\n", c->tei);
- 			q931_release(pri,c,cause);
- 		}
- 		break;
-@@ -2385,9 +3212,10 @@
- 	return 0;
- }
- 
--int q931_receive(struct pri *pri, q931_h *h, int len)
-+int q931_receive(struct pri *pri, q931_h *h, int len, int tei)
- {
- 	q931_mh *mh;
-+	q921_call *l2c;
- 	q931_call *c;
- 	q931_ie *ie;
- 	unsigned int x;
-@@ -2410,13 +3238,14 @@
- 		   KLUDGE this by changing byte 4 from a 0xf (SERVICE) 
- 		   to a 0x7 (SERVICE ACKNOWLEDGE) */
- 		h->raw[h->crlen + 2] -= 0x8;
--		q931_xmit(pri, h, len, 1);
-+		q931_xmit(pri, h, len, 1, tei);
- 		return 0;
- 	} else if (h->pd != pri->protodisc) {
- 		pri_error("Warning: unknown/inappropriate protocol discriminator received (%02x/%d)\n", h->pd, h->pd);
- 		return 0;
- 	}
--	c = q931_getcall(pri, q931_cr(h));
-+//	pri_error("searching for cref %d tei %d\n", q931_cr(h), tei);
-+	c = q931_getcall(pri, q931_cr(h), tei);
- 	if (!c) {
- 		pri_error("Unable to locate call %d\n", q931_cr(h));
- 		return -1;
-@@ -2439,6 +3268,7 @@
- 	case Q931_SETUP:
- 		if (pri->debug & PRI_DEBUG_Q931_STATE)
- 			pri_message("-- Processing Q.931 Call Setup\n");
-+		c->tei = tei;
- 		c->channelno = -1;
- 		c->slotmap = -1;
- 		c->chanflags = 0;
-@@ -2463,11 +3293,25 @@
- 		strcpy(c->redirectingnum, "");
-                 c->useruserprotocoldisc = -1; 
- 		strcpy(c->useruserinfo, "");
-+		strcpy(c->digits, "");
-+		strcpy(c->display, "");
- 		c->complete = 0;
- 		break;
- 	case Q931_CONNECT:
-+		if (c->t303timer) {
-+		    c->t303running = 0;
-+		    pri_schedule_del(pri, c->t303timer);
-+    		}
-+		c->t303timer = 0;
-+		c->progress = -1;
-+		break;
- 	case Q931_ALERTING:
- 	case Q931_PROGRESS:
-+		if (c->t303timer) {
-+		    c->t303running = 0;
-+		    pri_schedule_del(pri, c->t303timer);
-+		}
-+		c->t303timer = 0;
- 		c->progress = -1;
- 		break;
- 	case Q931_CONNECT_ACKNOWLEDGE:
-@@ -2486,10 +3330,15 @@
- 		if (c->retranstimer)
- 			pri_schedule_del(pri, c->retranstimer);
- 		c->retranstimer = 0;
-+		if (c->t303timer) {
-+		    c->t303running = 0;
-+		    pri_schedule_del(pri, c->t303timer);
-+    		}
-+		c->t303timer = 0;
- 		break;
- 	case Q931_RELEASE_COMPLETE:
- 		if (c->retranstimer)
--			pri_schedule_del(pri, c->retranstimer);
-+		    pri_schedule_del(pri, c->retranstimer);
- 		c->retranstimer = 0;
- 	case Q931_STATUS:
- 		c->cause = -1;
-@@ -2505,22 +3354,32 @@
- 	case Q931_STATUS_ENQUIRY:
- 		break;
- 	case Q931_SETUP_ACKNOWLEDGE:
-+		if (c->t303timer) {
-+		    c->t303running = 0;
-+		    pri_schedule_del(pri, c->t303timer);
-+		}
-+		c->t303timer = 0;
- 		break;
- 	case Q931_NOTIFY:
- 		break;
-+	case Q931_HOLD:
-+		break;
-+	case Q931_RETRIEVE:
-+		break;
-+	case Q931_RESUME:
-+		c->tei = tei;
-+		break;
-+	case Q931_SUSPEND:
-+		break;
- 	case Q931_USER_INFORMATION:
- 	case Q931_SEGMENT:
- 	case Q931_CONGESTION_CONTROL:
--	case Q931_HOLD:
- 	case Q931_HOLD_ACKNOWLEDGE:
- 	case Q931_HOLD_REJECT:
--	case Q931_RETRIEVE:
- 	case Q931_RETRIEVE_ACKNOWLEDGE:
- 	case Q931_RETRIEVE_REJECT:
--	case Q931_RESUME:
- 	case Q931_RESUME_ACKNOWLEDGE:
- 	case Q931_RESUME_REJECT:
--	case Q931_SUSPEND:
- 	case Q931_SUSPEND_ACKNOWLEDGE:
- 	case Q931_SUSPEND_REJECT:
- 		pri_error("!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
-@@ -2529,7 +3388,7 @@
- 		pri_error("!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
- 		q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
- 		if (c->newcall) 
--			q931_destroycall(pri,c->cr);
-+			q931_destroycall(pri,c->cr, c->tei);
- 		return -1;
- 	}
- 	memset(mandies, 0, sizeof(mandies));
-@@ -2610,7 +3469,7 @@
- 	for (x=0;x<MAX_MAND_IES;x++) {
- 		if (mandies[x]) {
- 			/* check if there is no channel identification when we're configured as network -> that's not an error */
--			if ((pri->localtype != PRI_NETWORK) || (mh->msg != Q931_SETUP) || (mandies[x] != Q931_CHANNEL_IDENT)) {
-+			if (((pri->localtype != PRI_NETWORK) || (pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_NETWORK_PTMP)) && ((mh->msg != Q931_SETUP) || (mandies[x] != Q931_CHANNEL_IDENT))) {
- 				pri_error("XXX Missing handling for mandatory IE %d (cs%d, %s) XXX\n", Q931_IE_IE(mandies[x]), Q931_IE_CODESET(mandies[x]), ie2str(mandies[x]));
- 				missingmand++;
- 			}
-@@ -2622,7 +3481,7 @@
- 	case Q931_RESTART:
- 		if (missingmand) {
- 			q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
--			q931_destroycall(pri, c->cr);
-+			q931_destroycall(pri, c->cr, c->tei);
- 			break;
- 		}
- 		c->ourcallstate = Q931_CALL_STATE_RESTART;
-@@ -2640,7 +3499,8 @@
- 		}
- 		/* Must be new call */
- 		if (!c->newcall) {
--			break;
-+			pri_error("received SETUP message for call that is not a new call, wicked!!! going on ...\n");
-+//			break;
- 		}
- 		c->newcall = 0;
- 		c->ourcallstate = Q931_CALL_STATE_CALL_PRESENT;
-@@ -2660,8 +3520,9 @@
-                 strncpy(pri->ev.ring.redirectingnum, c->redirectingnum, sizeof(pri->ev.ring.redirectingnum) - 1);
-                 strncpy(pri->ev.ring.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo) - 1);
- 		pri->ev.ring.flexible = ! (c->chanflags & FLAG_EXCLUSIVE);
--		pri->ev.ring.cref = c->cr;
-+		pri->ev.ring.tei = c->tei;
- 		pri->ev.ring.call = c;
-+		pri->ev.ring.cref = c->cr;
- 		pri->ev.ring.layer1 = c->userl1;
- 		pri->ev.ring.complete = c->complete; 
- 		pri->ev.ring.ctype = c->transcapability;
-@@ -2675,6 +3536,9 @@
- 			q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
- 			break;
- 		}
-+		if (pri->localtype == BRI_NETWORK_PTMP) {
-+		    l2c = q921_getcall(pri, c, tei);
-+		}
- 		c->ourcallstate = Q931_CALL_STATE_CALL_DELIVERED;
- 		c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED;
- 		pri->ev.e = PRI_EVENT_RINGING;
-@@ -2691,36 +3555,65 @@
- 			q931_status(pri, c, PRI_CAUSE_WRONG_MESSAGE);
- 			break;
- 		}
-+		// tei got the call
-+		c->tei = tei;
- 		c->ourcallstate = Q931_CALL_STATE_ACTIVE;
- 		c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST;
- 		pri->ev.e = PRI_EVENT_ANSWER;
- 		pri->ev.answer.channel = c->channelno | (c->ds1no << 8);
- 		pri->ev.answer.cref = c->cr;
-+		pri->ev.answer.tei = c->tei;
- 		pri->ev.answer.call = c;
- 		q931_connect_acknowledge(pri, c);
-+	
-+		if (pri->localtype == BRI_NETWORK_PTMP) {
-+		    q921_hangup(pri, c, tei);
-+		}
- 		return Q931_RES_HAVEEVENT;
- 	case Q931_FACILITY:
- 		if (c->newcall) {
--			q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-+			if ((pri->localtype == PRI_CPE) || (pri->localtype == PRI_NETWORK)) {
-+			    q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
-+			} else {
-+			    // BRI uses the dummy cref for sservices like ccnr
-+			}
- 			break;
- 		}
--		pri->ev.e = PRI_EVENT_FACNAME;
--		strncpy(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname) - 1);
--		strncpy(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingname) - 1);
--		pri->ev.facname.channel = c->channelno | (c->ds1no << 8);
--		pri->ev.facname.cref = c->cr;
--		pri->ev.facname.call = c;
--#if 0
--		pri_message("Sending facility event (%s/%s)\n", pri->ev.facname.callingname, pri->ev.facname.callingnum);
--#endif
-+		if (c->facility > 0) {
-+		    pri->ev.e = PRI_EVENT_FACILITY;
-+		    pri->ev.facility.channel = c->channelno | (c->ds1no << 8);
-+		    pri->ev.facility.cref = c->cr;
-+		    pri->ev.facility.tei = c->tei;
-+		    pri->ev.facility.call = c; 
-+		    switch (c->facility) {
-+			case 0x06: /* ECT execute */
-+				pri->ev.facility.operation = 0x06; 
-+			    break;
-+			case 0x0D:
-+				pri->ev.facility.operation = 0x0D; 
-+				strncpy(pri->ev.facility.forwardnum, c->redirectingnum,  sizeof(pri->ev.facility.forwardnum) - 1);
-+			    break;
-+			default:
-+				pri->ev.facility.operation = c->facility; 
-+		    }
-+		} else {
-+		    pri->ev.e = PRI_EVENT_FACNAME;
-+		    strncpy(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname) - 1);
-+		    strncpy(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingname) - 1);
-+		    pri->ev.facname.channel = c->channelno | (c->ds1no << 8);
-+		    pri->ev.facname.cref = c->cr;
-+		    pri->ev.facname.call = c; 
-+		}
-+
- 		return Q931_RES_HAVEEVENT;
- 	case Q931_PROGRESS:
- 		if (missingmand) {
- 			q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
--			q931_destroycall(pri, c->cr);
-+			q931_destroycall(pri, c->cr, c->tei);
- 			break;
- 		}
- 		pri->ev.e = PRI_EVENT_PROGRESS;
-+		pri->ev.proceeding.cause = c->cause;
- 		/* Fall through */
- 	case Q931_CALL_PROCEEDING:
- 		if (c->newcall) {
-@@ -2734,7 +3627,13 @@
- 			q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE);
- 			break;
- 		}
-+		if (pri->localtype == BRI_NETWORK_PTMP) {
-+		    l2c = q921_getcall(pri, c, tei);
-+		    l2c->proc = 1;
-+		    l2c->channel = c->channelno;
-+		}
- 		pri->ev.proceeding.channel = c->channelno | (c->ds1no << 8);
-+		pri->ev.proceeding.call = c;
- 		if (mh->msg == Q931_CALL_PROCEEDING) {
- 			pri->ev.e = PRI_EVENT_PROCEEDING;
- 			c->ourcallstate = Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING;
-@@ -2756,7 +3655,7 @@
- 	case Q931_STATUS:
- 		if (missingmand) {
- 			q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
--			q931_destroycall(pri, c->cr);
-+			q931_destroycall(pri, c->cr, c->tei);
- 			break;
- 		}
- 		if (c->newcall) {
-@@ -2794,27 +3693,42 @@
- 		}
- 		break;
- 	case Q931_RELEASE_COMPLETE:
--		c->ourcallstate = Q931_CALL_STATE_NULL;
--		c->peercallstate = Q931_CALL_STATE_NULL;
--		pri->ev.hangup.channel = c->channelno | (c->ds1no << 8);
--		pri->ev.hangup.cref = c->cr;          		
--		pri->ev.hangup.cause = c->cause;      		
--		pri->ev.hangup.call = c;              		
--		/* Free resources */
--		if (c->alive) {
-+		if (c->cause != PRI_CAUSE_INCOMPATIBLE_DESTINATION) {
-+		    if (c->t303timer) {
-+			c->t303running = 0;
-+			pri_schedule_del(pri, c->t303timer);
-+    		    }
-+		    c->t303timer = 0;
-+		}
-+		if ((pri->localtype != BRI_NETWORK_PTMP) || (c->tei == tei)) {
-+		    c->ourcallstate = Q931_CALL_STATE_NULL;
-+		    c->peercallstate = Q931_CALL_STATE_NULL;
-+		    pri->ev.hangup.channel = c->channelno | (c->ds1no << 8);
-+		    pri->ev.hangup.cref = c->cr;          		
-+		    pri->ev.hangup.cause = c->cause;      		
-+		    pri->ev.hangup.call = c;              		
-+		    /* Free resources */
-+		    if (c->alive) {
- 			pri->ev.e = PRI_EVENT_HANGUP;
- 			res = Q931_RES_HAVEEVENT;
- 			c->alive = 0;
--		} else if (c->sendhangupack) {
-+		    } else if (c->sendhangupack) {
- 			res = Q931_RES_HAVEEVENT;
- 			pri->ev.e = PRI_EVENT_HANGUP_ACK;
- 			pri_hangup(pri, c, c->cause);
--		} else
-+		    } else
- 			res = 0;
--		if (res)
-+		    if (res)
- 			return res;
--		else
-+		    else
- 			q931_hangup(pri,c,c->cause);
-+		} else {
-+		    // BRI_NET_PTMP
-+		    // ignoring relase_complete
-+		    res = q921_handle_hangup(pri,c,tei);
-+		    if (res)
-+			return res;
-+		}
- 		break;
- 	case Q931_RELEASE:
- 		if (missingmand) {
-@@ -2830,6 +3744,7 @@
- 		pri->ev.e = PRI_EVENT_HANGUP;
- 		pri->ev.hangup.channel = c->channelno | (c->ds1no << 8);
- 		pri->ev.hangup.cref = c->cr;
-+		pri->ev.hangup.tei = c->tei;
- 		pri->ev.hangup.cause = c->cause;
- 		pri->ev.hangup.call = c;
- 		/* Don't send release complete if they send us release 
-@@ -2855,8 +3770,14 @@
- 		pri->ev.e = PRI_EVENT_HANGUP_REQ;
- 		pri->ev.hangup.channel = c->channelno | (c->ds1no << 8);
- 		pri->ev.hangup.cref = c->cr;
-+		pri->ev.hangup.tei = c->tei;
- 		pri->ev.hangup.cause = c->cause;
- 		pri->ev.hangup.call = c;
-+		if (c->inband_progress) {
-+		    pri->ev.hangup.inband_progress = 1;
-+		} else {
-+		    pri->ev.hangup.inband_progress = 0;
-+		}
- 		if (c->alive)
- 			return Q931_RES_HAVEEVENT;
- 		else
-@@ -2877,15 +3798,35 @@
- 			q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
- 			break;
- 		}
-+
- 		if (c->ourcallstate!=Q931_CALL_STATE_OVERLAP_RECEIVING)
- 			break;
--		pri->ev.e = PRI_EVENT_INFO_RECEIVED;
--		pri->ev.ring.call = c;
--		pri->ev.ring.channel = c->channelno | (c->ds1no << 8);
--		strncpy(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum) - 1);
--		strncpy(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr) - 1);
--		pri->ev.ring.complete = c->complete; 	/* this covers IE 33 (Sending Complete) */
--		return Q931_RES_HAVEEVENT;
-+		if ((pri->localtype != BRI_NETWORK_PTMP) && (pri->localtype != BRI_NETWORK)) {
-+		    if ((c->ourcallstate!=Q931_CALL_STATE_OVERLAP_RECEIVING) && (c->ourcallstate!=Q931_CALL_STATE_ACTIVE))
-+		    break;
-+		} else {
-+		    // we want to use keypad and information ies for out of band dtmf, also when not using overlapdial
-+		}
-+		if (strlen(c->digits)) {
-+		    pri->ev.e = PRI_EVENT_INFO_RECEIVED;
-+		    pri->ev.ring.call = c;
-+		    pri->ev.ring.channel = c->channelno | (c->ds1no << 8);
-+		    strncpy(pri->ev.ring.callednum, c->digits, sizeof(pri->ev.ring.callednum) - 1);
-+		    strncpy(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr) - 1);
-+		    pri->ev.ring.complete = c->complete; 	/* this covers IE 33 (Sending Complete) */
-+		    return Q931_RES_HAVEEVENT;
-+		} else if (strlen(c->display)) {
-+		    pri->ev.e = PRI_EVENT_DISPLAY_RECEIVED;
-+		    pri->ev.display.call = c;
-+		    pri->ev.display.channel = c->channelno | (c->ds1no << 8);
-+		    strncpy(pri->ev.display.text, c->display, sizeof(pri->ev.display.text) - 1);
-+		    return Q931_RES_HAVEEVENT;
-+		} else {
-+		    if (pri->debug & PRI_DEBUG_Q931_STATE)
-+			pri_message("ignoring INFORMATION msg without Called Party Number, Keypad Facility or Display\n");
-+		}
-+		strcpy(c->digits, "");
-+		strcpy(c->display, "");
- 		break;
- 	case Q931_STATUS_ENQUIRY:
- 		if (c->newcall) {
-@@ -2902,25 +3843,61 @@
- 		c->peercallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
- 		pri->ev.e = PRI_EVENT_SETUP_ACK;
- 		pri->ev.setup_ack.channel = c->channelno;
-+		pri->ev.setup_ack.call = c;
- 		return Q931_RES_HAVEEVENT;
- 	case Q931_NOTIFY:
- 		pri->ev.e = PRI_EVENT_NOTIFY;
- 		pri->ev.notify.channel = c->channelno;
- 		pri->ev.notify.info = c->notify;
- 		return Q931_RES_HAVEEVENT;
-+	case Q931_HOLD:
-+		pri->ev.e = PRI_EVENT_HOLD_REQ;
-+		pri->ev.hold_req.call = c;
-+		pri->ev.hold_req.cref = c->cr;
-+		pri->ev.hold_req.tei = c->tei;
-+		pri->ev.hold_req.channel = c->channelno;
-+		return Q931_RES_HAVEEVENT;
-+		break;
-+	case Q931_RETRIEVE:
-+		pri->ev.e = PRI_EVENT_RETRIEVE_REQ;
-+		pri->ev.retrieve_req.call = c;
-+		pri->ev.retrieve_req.cref = c->cr;
-+		pri->ev.retrieve_req.tei = c->tei;
-+		pri->ev.retrieve_req.channel = c->channelno;
-+		return Q931_RES_HAVEEVENT;
-+		break;
-+	case Q931_SUSPEND:
-+		pri->ev.e = PRI_EVENT_SUSPEND_REQ;
-+		pri->ev.suspend_req.call = c;
-+		pri->ev.suspend_req.cref = c->cr;
-+		pri->ev.suspend_req.tei = c->tei;
-+		pri->ev.suspend_req.channel = c->channelno;
-+		strncpy(pri->ev.suspend_req.callid, c->callid, sizeof(pri->ev.suspend_req.callid) - 1);
-+		// q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
-+		return Q931_RES_HAVEEVENT;
-+		break;
-+	case Q931_RESUME:
-+		if (pri->localtype == BRI_NETWORK_PTMP) {
-+		    l2c = q921_getcall(pri, c, tei);
-+		}
-+		c->newcall = 0;
-+		pri->ev.e = PRI_EVENT_RESUME_REQ;
-+		pri->ev.resume_req.call = c;
-+		pri->ev.resume_req.cref = c->cr;
-+		pri->ev.resume_req.tei = c->tei;
-+		pri->ev.resume_req.channel = c->channelno;
-+		strncpy(pri->ev.resume_req.callid, c->callid, sizeof(pri->ev.resume_req.callid) - 1);
-+		return Q931_RES_HAVEEVENT;
-+		break;
- 	case Q931_USER_INFORMATION:
- 	case Q931_SEGMENT:
- 	case Q931_CONGESTION_CONTROL:
--	case Q931_HOLD:
- 	case Q931_HOLD_ACKNOWLEDGE:
- 	case Q931_HOLD_REJECT:
--	case Q931_RETRIEVE:
- 	case Q931_RETRIEVE_ACKNOWLEDGE:
- 	case Q931_RETRIEVE_REJECT:
--	case Q931_RESUME:
- 	case Q931_RESUME_ACKNOWLEDGE:
- 	case Q931_RESUME_REJECT:
--	case Q931_SUSPEND:
- 	case Q931_SUSPEND_ACKNOWLEDGE:
- 	case Q931_SUSPEND_REJECT:
- 		pri_error("!! Not yet handling post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
-@@ -2930,7 +3907,7 @@
- 		pri_error("!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
- 		q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
- 		if (c->newcall) 
--			q931_destroycall(pri,c->cr);
-+			q931_destroycall(pri,c->cr,c->tei);
- 		return -1;
- 	}
- 	return 0;
-diff -urNad --exclude=CVS --exclude=.svn ./README /tmp/dpep-work.aULY0X/libpri-1.0.9/README
---- ./README	2005-07-14 12:30:35.000000000 +0100
-+++ /tmp/dpep-work.aULY0X/libpri-1.0.9/README	2005-07-14 12:31:07.927277024 +0100
-@@ -1,6 +1,7 @@
--libpri: An implementation of Primate Rate ISDN
--
--Written by Mark Spencer <markster at digium.com>
-+libpri: An implementation of Primate Rate ISDN (and BRI ISDN)
-+ 
-+Written by Mark Spencer <markster at linux-support.net>
-+Modified for BRI support by Klaus-Peter Junghanns <kpj at junghanns.net>
- 
- What is libpri?
- ===============
-@@ -9,6 +10,7 @@
- based on the Bellcore specification SR-NWT-002343 for National ISDN.  As of
- May 12, 2001, it has been tested work with NI-2, Nortel DMS-100, and 
- Lucent 5E Custom protocols on switches from Nortel and Lucent.
-+The BRI and euroISDN modifications are based on ETS 300 102-1.
- 
- What is the license for libpri?
- ===============================
-@@ -17,9 +19,8 @@
- The GNU GPL is included in the file LICENSE in this directory.
- 
- If you wish to use libpri in an application for which the GPL is not 
--appropriate (e.g. a proprietary embedded system), licenses for libpri 
--under more flexible terms can be readily obtained through Digium, Inc. 
--at reasonable cost.
-+appropriate (e.g. a proprietary embedded system), then you have to use
-+a non-standard compliant version without BRI support.
- 
- 
- How do I report bugs or contribute?
-diff -urNad --exclude=CVS --exclude=.svn ./TODO /tmp/dpep-work.aULY0X/libpri-1.0.9/TODO
---- ./TODO	2005-07-14 12:30:35.000000000 +0100
-+++ /tmp/dpep-work.aULY0X/libpri-1.0.9/TODO	2005-07-14 12:31:07.927277024 +0100
-@@ -2,9 +2,7 @@
- -- D-Channel Backup
- -- Test against 4e
- 
--Q.921:
---- Support unnumbered information frames
--
- Q.931:
---- Locking Shift IE
---- Implement the 11 missing Q.931 timers
-+-- Locking Shift IE (you did that already, didnt you??)
-+-- Implement the 10 missing Q.931 timers
-+-- more facilities
-\ No newline at end of file




More information about the Pkg-voip-commits mailing list