[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