]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/libpri.patch
Update:
[people/teissler/ipfire-2.x.git] / src / patches / libpri.patch
1 diff -urN libpri-1.2.3.orig/Makefile libpri-1.2.3/Makefile
2 --- libpri-1.2.3.orig/Makefile 2006-04-30 17:17:47.000000000 +0200
3 +++ libpri-1.2.3/Makefile 2006-07-27 17:45:09.000000000 +0200
4 @@ -27,6 +27,13 @@
5 # Uncomment if you want libpri to count number of Q921/Q931 sent/received
6 #LIBPRI_COUNTERS=-DLIBPRI_COUNTERS
7
8 +# Uncomment if you want libpri to always keep layer 2 up
9 +#LAYER2ALWAYSUP=-DLAYER2ALWAYSUP
10 +
11 +# Uncomment if you want libpri to hangup a call to an NT (p2mp) port if one
12 +# device sends a RELEASE COMPLETE with cause 17
13 +#FASTBUSYONBUSY=-DFASTBUSYONBUSY
14 +
15 CC=gcc
16
17 OSARCH=$(shell uname -s)
18 @@ -38,7 +45,7 @@
19 DYNAMIC_LIBRARY=libpri.so.1.0
20 STATIC_OBJS=copy_string.o pri.o q921.o prisched.o q931.o pri_facility.o
21 DYNAMIC_OBJS=copy_string.lo pri.lo q921.lo prisched.lo q931.lo pri_facility.lo
22 -CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g $(ALERTING) $(LIBPRI_COUNTERS)
23 +CFLAGS=-Wall -Wstrict-prototypes -Wmissing-prototypes -g $(ALERTING) $(LIBPRI_COUNTERS) $(LAYER2ALWAYSUP) $(FASTBUSYONBUSY) -DRELAX_TRB
24 INSTALL_PREFIX=$(DESTDIR)
25 INSTALL_BASE=/usr
26 SOFLAGS = -Wl,-hlibpri.so.1.0
27 diff -urN libpri-1.2.3.orig/README libpri-1.2.3/README
28 --- libpri-1.2.3.orig/README 2006-02-15 18:59:38.000000000 +0100
29 +++ libpri-1.2.3/README 2006-01-18 12:28:07.000000000 +0100
30 @@ -1,6 +1,7 @@
31 -libpri: An implementation of Primary Rate ISDN
32 -
33 -Written by Mark Spencer <markster@digium.com>
34 +libpri: An implementation of Primate Rate ISDN (and BRI ISDN)
35 +
36 +Written by Mark Spencer <markster@linux-support.net>
37 +Modified for BRI support by Klaus-Peter Junghanns <kpj@junghanns.net>
38
39 What is libpri?
40 ===============
41 @@ -9,6 +10,7 @@
42 based on the Bellcore specification SR-NWT-002343 for National ISDN. As of
43 May 12, 2001, it has been tested work with NI-2, Nortel DMS-100, and
44 Lucent 5E Custom protocols on switches from Nortel and Lucent.
45 +The BRI and euroISDN modifications are based on ETS 300 102-1.
46
47 What is the license for libpri?
48 ===============================
49 @@ -22,9 +24,8 @@
50 or the GPL of libpri.
51
52 If you wish to use libpri in an application for which the GPL is not
53 -appropriate (e.g. a proprietary embedded system), licenses for libpri
54 -under more flexible terms can be readily obtained through Digium, Inc.
55 -at reasonable cost.
56 +appropriate (e.g. a proprietary embedded system), then you have to use
57 +a non-standard compliant version without BRI support.
58
59
60 How do I report bugs or contribute?
61 diff -urN libpri-1.2.3.orig/TODO libpri-1.2.3/TODO
62 --- libpri-1.2.3.orig/TODO 2005-11-29 19:39:18.000000000 +0100
63 +++ libpri-1.2.3/TODO 2006-01-18 12:28:07.000000000 +0100
64 @@ -2,9 +2,7 @@
65 -- D-Channel Backup
66 -- Test against 4e
67
68 -Q.921:
69 --- Support unnumbered information frames
70 -
71 Q.931:
72 --- Locking Shift IE
73 --- Implement the 11 missing Q.931 timers
74 +-- Locking Shift IE (you did that already, didnt you??)
75 +-- Implement the 10 missing Q.931 timers
76 +-- more facilities
77 diff -urN libpri-1.2.3.orig/libpri.h libpri-1.2.3/libpri.h
78 --- libpri-1.2.3.orig/libpri.h 2006-04-27 18:08:39.000000000 +0200
79 +++ libpri-1.2.3/libpri.h 2006-07-11 11:34:59.000000000 +0200
80 @@ -5,6 +5,8 @@
81 *
82 * Copyright (C) 2001, Linux Support Services, Inc.
83 * All Rights Reserved.
84 + * Copyright (C) 2003-2006 Junghanns.NET GmbH
85 + * Klaus-Peter Junghanns <kpj@junghanns.net>
86 *
87 * This program is free software; you can redistribute it and/or modify
88 * it under the terms of the GNU General Public License as published by
89 @@ -26,8 +28,12 @@
90 #define _LIBPRI_H
91
92 /* Node types */
93 -#define PRI_NETWORK 1
94 +#define PRI_NETWORK 1 /* PTP modes, default for PRI */
95 #define PRI_CPE 2
96 +#define BRI_NETWORK_PTMP 3 /* PTMP modes, default for BRI */
97 +#define BRI_CPE_PTMP 4
98 +#define BRI_NETWORK 5 /* PTP modes */
99 +#define BRI_CPE 6
100
101 /* Debugging */
102 #define PRI_DEBUG_Q921_RAW (1 << 0) /* Show raw HDLC frames */
103 @@ -76,6 +82,12 @@
104 #define PRI_EVENT_NOTIFY 16 /* Notification received */
105 #define PRI_EVENT_PROGRESS 17 /* When we get CALL_PROCEEDING or PROGRESS */
106 #define PRI_EVENT_KEYPAD_DIGIT 18 /* When we receive during ACTIVE state */
107 +#define PRI_EVENT_HOLD_REQ 19 /* R */
108 +#define PRI_EVENT_RETRIEVE_REQ 20
109 +#define PRI_EVENT_SUSPEND_REQ 21 /* park */
110 +#define PRI_EVENT_RESUME_REQ 22 /* unpark */
111 +#define PRI_EVENT_DISPLAY_RECEIVED 23
112 +#define PRI_EVENT_FACILITY 24 /* Facility */
113
114 /* Simple states */
115 #define PRI_STATE_DOWN 0
116 @@ -250,11 +262,17 @@
117 #define PRI_NSF_ATT_MULTIQUEST 0xF0
118 #define PRI_NSF_CALL_REDIRECTION_SERVICE 0xF7
119
120 +#ifdef RELAX_TRB
121 +#define PRI_RELAX_TRB
122 +#endif
123 +
124 +typedef struct q921_call q921_call;
125 typedef struct q931_call q931_call;
126
127 typedef struct pri_event_generic {
128 /* Events with no additional information fall in this category */
129 int e;
130 + int tei;
131 } pri_event_generic;
132
133 typedef struct pri_event_error {
134 @@ -273,18 +291,19 @@
135 int cref;
136 int progress;
137 int progressmask;
138 - q931_call *call;
139 char useruserinfo[260]; /* User->User info */
140 + q931_call *call;
141 } pri_event_ringing;
142
143 typedef struct pri_event_answer {
144 int e;
145 int channel;
146 + int tei; /* belongs to this tei */
147 int cref;
148 int progress;
149 int progressmask;
150 - q931_call *call;
151 char useruserinfo[260]; /* User->User info */
152 + q931_call *call;
153 } pri_event_answer;
154
155 typedef struct pri_event_facname {
156 @@ -302,32 +321,37 @@
157 int e;
158 int channel; /* Channel requested */
159 int callingpres; /* Presentation of Calling CallerID */
160 - int callingplanani; /* Dialing plan of Calling entity ANI */
161 + int callingpresuser; /* Presentation of Calling CallerID */
162 int callingplan; /* Dialing plan of Calling entity */
163 - char callingani[256]; /* Calling ANI */
164 - char callingnum[256]; /* Calling number */
165 + int callingplanuser; /* Dialing plan of Calling entity */
166 + int callingplanani; /* Dialing plan of Calling entity ANI */
167 + char callingnum[256]; /* Calling number, network provided */
168 + char callingani[256]; /* Calling number, user provided */
169 char callingname[256]; /* Calling name (if provided) */
170 int calledplan; /* Dialing plan of Called number */
171 int ani2; /* ANI II */
172 char callednum[256]; /* Called number */
173 - char redirectingnum[256]; /* Redirecting number */
174 - char redirectingname[256]; /* Redirecting name */
175 - int redirectingreason; /* Reason for redirect */
176 + char redirectingnum[256]; /* Redirecting number */
177 + char redirectingname[256]; /* Redirecting name */
178 + int redirectingreason; /* Reason for redirect */
179 int callingplanrdnis; /* Dialing plan of Redirecting Number */
180 - char useruserinfo[260]; /* User->User info */
181 + char useruserinfo[260]; /* User->User info */
182 int flexible; /* Are we flexible with our channel selection? */
183 int cref; /* Call Reference Number */
184 int ctype; /* Call type (see PRI_TRANS_CAP_* */
185 - int layer1; /* User layer 1 */
186 + int layer1; /* User layer 1 */
187 int complete; /* Have we seen "Complete" i.e. no more number? */
188 q931_call *call; /* Opaque call pointer */
189 - char callingsubaddr[256]; /* Calling parties subaddress */
190 + int tei; /* belongs to this tei */
191 + char callingsubaddr[256]; /* Calling parties subaddress */
192 int progress;
193 int progressmask;
194 char origcalledname[256];
195 char origcallednum[256];
196 int callingplanorigcalled; /* Dialing plan of Originally Called Number */
197 int origredirectingreason;
198 + char lowlayercompat[16];
199 + char highlayercompat[4];
200 } pri_event_ring;
201
202 typedef struct pri_event_hangup {
203 @@ -335,6 +359,8 @@
204 int channel; /* Channel requested */
205 int cause;
206 int cref;
207 + int tei;
208 + int inband_progress;
209 q931_call *call; /* Opaque call pointer */
210 long aoc_units; /* Advise of Charge number of charged units */
211 char useruserinfo[260]; /* User->User info */
212 @@ -375,20 +401,80 @@
213 char digits[64];
214 } pri_event_keypad_digit;
215
216 +typedef struct pri_event_hold_req {
217 + int e;
218 + int channel;
219 + int cref;
220 + int tei;
221 + q931_call *call;
222 +} pri_event_hold_req;
223 +
224 +/* euroisdn faciltiy fun */
225 +typedef struct pri_event_facility_req {
226 + int e;
227 + int channel;
228 + int cref;
229 + int tei;
230 + int operation;
231 + char forwardnum[256]; /* Redirection destination */
232 + q931_call *call;
233 +} pri_event_facility_req;
234 +
235 +typedef struct pri_event_retrieve_req {
236 + int e;
237 + int channel;
238 + int cref;
239 + int tei;
240 + q931_call *call;
241 +} pri_event_retrieve_req;
242 +
243 +typedef struct pri_event_suspend_req {
244 + int e;
245 + int channel;
246 + int cref;
247 + int tei;
248 + q931_call *call;
249 + char callid[10];
250 +} pri_event_suspend_req;
251 +
252 +typedef struct pri_event_resume_req {
253 + int e;
254 + int channel;
255 + int cref;
256 + int tei;
257 + q931_call *call;
258 + char callid[10];
259 +} pri_event_resume_req;
260 +
261 +typedef struct pri_event_display {
262 + int e;
263 + int channel;
264 + int cref;
265 + q931_call *call;
266 + char text[256];
267 +} pri_event_display;
268 +
269 +
270 typedef union {
271 int e;
272 pri_event_generic gen; /* Generic view */
273 pri_event_restart restart; /* Restart view */
274 pri_event_error err; /* Error view */
275 pri_event_facname facname; /* Caller*ID Name on Facility */
276 + pri_event_facility_req facility; /* sservices */
277 pri_event_ring ring; /* Ring */
278 pri_event_hangup hangup; /* Hang up */
279 pri_event_ringing ringing; /* Ringing */
280 - pri_event_ringing answer; /* Answer */
281 + pri_event_answer answer; /* Answer */
282 pri_event_restart_ack restartack; /* Restart Acknowledge */
283 pri_event_proceeding proceeding; /* Call proceeding & Progress */
284 pri_event_setup_ack setup_ack; /* SETUP_ACKNOWLEDGE structure */
285 pri_event_notify notify; /* Notification */
286 + pri_event_hold_req hold_req;
287 + pri_event_retrieve_req retrieve_req;
288 + pri_event_suspend_req suspend_req;
289 + pri_event_resume_req resume_req;
290 + pri_event_display display;
291 pri_event_keypad_digit digit; /* Digits that come during a call */
292 } pri_event;
293
294 @@ -403,7 +489,9 @@
295 channel operating in HDLC mode with FCS computed by the fd's driver. Also it
296 must be NON-BLOCKING! Frames received on the fd should include FCS. Nodetype
297 must be one of PRI_NETWORK or PRI_CPE. switchtype should be PRI_SWITCH_* */
298 -extern struct pri *pri_new(int fd, int nodetype, int switchtype);
299 +extern struct pri *pri_new(int fd, int nodetype, int switchtype, int span);
300 +
301 +extern void pri_shutdown(struct pri *pri);
302
303 /* Create D-channel just as above with user defined I/O callbacks and data */
304 extern struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata);
305 @@ -427,6 +515,9 @@
306 /* Enable transmission support of Facility IEs on the pri */
307 extern void pri_facility_enable(struct pri *pri);
308
309 +/* Set file descriptor for debugging to a file */
310 +extern void pri_set_debug_fd(struct pri *pri, int fd);
311 +
312 /* Run PRI on the given D-channel, taking care of any events that
313 need to be handled. If block is set, it will block until an event
314 occurs which needs to be handled */
315 @@ -463,6 +554,12 @@
316 /* Send a digit in overlap mode */
317 extern int pri_information(struct pri *pri, q931_call *call, char digit);
318
319 +/* Send a INFO msg with display ie */
320 +extern int pri_information_display(struct pri *pri, q931_call *call, char *display);
321 +
322 +/* add a display ie to a call, so it can be sent with the next message */
323 +extern int pri_add_display(struct pri *pri, q931_call *call, char *display);
324 +
325 /* Answer the incomplete(call without called number) call on the given channel.
326 Set non-isdn to non-zero if you are not connecting to ISDN equipment */
327 extern int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn);
328 @@ -471,6 +568,35 @@
329 Set non-isdn to non-zero if you are not connecting to ISDN equipment */
330 extern int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
331
332 +extern int pri_deflect(struct pri *pri, q931_call *call, char *destination);
333 +
334 +/* Ack a HOLD_REQ */
335 +extern int pri_hold_acknowledge(struct pri *pri, q931_call *call);
336 +
337 +/* Reject a HOLD_REQ */
338 +extern int pri_hold_reject(struct pri *pri, q931_call *call);
339 +
340 +/* Ack a RETRIEVE_REQ */
341 +extern int pri_retrieve_acknowledge(struct pri *pri, q931_call *call, int channel);
342 +
343 +/* Reject a RETRIEVE_REQ */
344 +extern int pri_retrieve_reject(struct pri *pri, q931_call *call);
345 +
346 +/* Ack a SUSPEND_REQ */
347 +extern int pri_suspend_acknowledge(struct pri *pri, q931_call *call, char *display);
348 +
349 +/* Reject a SUSPEND_REQ */
350 +extern int pri_suspend_reject(struct pri *pri, q931_call *call, char *display);
351 +
352 +/* Reject a RESUME_REQ */
353 +extern int pri_resume_reject(struct pri *pri, q931_call *call, char *display);
354 +
355 +/* Ack a RESUME_REQ */
356 +extern int pri_resume_acknowledge(struct pri *pri, q931_call *call, int channel, char *display);
357 +
358 +/* Send a Facility Message */
359 +extern int pri_facility(struct pri *pri, q931_call *call, int operation, char *arguments);
360 +
361 /* Set CRV reference for GR-303 calls */
362
363
364 @@ -479,14 +605,14 @@
365
366 /* backwards compatibility for those who don't use asterisk with libpri */
367 #define pri_release(a,b,c) \
368 - pri_hangup(a,b,c)
369 + pri_hangup(a,b,c, -1)
370
371 #define pri_disconnect(a,b,c) \
372 - pri_hangup(a,b,c)
373 + pri_hangup(a,b,c, -1)
374
375 /* Hangup a call */
376 #define PRI_HANGUP
377 -extern int pri_hangup(struct pri *pri, q931_call *call, int cause);
378 +extern int pri_hangup(struct pri *pri, q931_call *call, int cause, int aocunits);
379
380 #define PRI_DESTROYCALL
381 extern void pri_destroycall(struct pri *pri, q931_call *call);
382 @@ -519,14 +645,13 @@
383 extern void pri_sr_free(struct pri_sr *sr);
384
385 extern int pri_sr_set_channel(struct pri_sr *sr, int channel, int exclusive, int nonisdn);
386 -extern int pri_sr_set_bearer(struct pri_sr *sr, int transmode, int userl1);
387 +extern int pri_sr_set_bearer(struct pri_sr *sr, int transmode, int userl1, char *llc);
388 extern int pri_sr_set_called(struct pri_sr *sr, char *called, int calledplan, int complete);
389 extern int pri_sr_set_caller(struct pri_sr *sr, char *caller, char *callername, int callerplan, int callerpres);
390 extern int pri_sr_set_redirecting(struct pri_sr *sr, char *num, int plan, int pres, int reason);
391 #define PRI_USER_USER_TX
392 /* Set the user user field. Warning! don't send binary data accross this field */
393 extern void pri_sr_set_useruser(struct pri_sr *sr, char *userchars);
394 -
395 extern void pri_call_set_useruser(q931_call *sr, char *userchars);
396
397 extern int pri_setup(struct pri *pri, q931_call *call, struct pri_sr *req);
398 @@ -547,8 +672,8 @@
399
400 /* Override message and error stuff */
401 #define PRI_NEW_SET_API
402 -extern void pri_set_message(void (*__pri_error)(struct pri *pri, char *));
403 -extern void pri_set_error(void (*__pri_error)(struct pri *pri, char *));
404 +extern void pri_set_message(void (*__pri_error)(char *, int span));
405 +extern void pri_set_error(void (*__pri_error)(char *, int span));
406
407 /* Set overlap mode */
408 #define PRI_SET_OVERLAPDIAL
409 diff -urN libpri-1.2.3.orig/pri.c libpri-1.2.3/pri.c
410 --- libpri-1.2.3.orig/pri.c 2005-11-29 19:39:18.000000000 +0100
411 +++ libpri-1.2.3/pri.c 2006-07-11 12:39:20.000000000 +0200
412 @@ -1,24 +1,14 @@
413 /*
414 * libpri: An implementation of Primary Rate ISDN
415 *
416 - * Written by Mark Spencer <markster@digium.com>
417 + * Written by Mark Spencer <markster@linux-suppot.net>
418 *
419 - * Copyright (C) 2001-2005, Digium
420 - * All Rights Reserved.
421 + * This program is confidential ( <- I dont think so! )
422 *
423 - * This program is free software; you can redistribute it and/or modify
424 - * it under the terms of the GNU General Public License as published by
425 - * the Free Software Foundation; either version 2 of the License, or
426 - * (at your option) any later version.
427 - *
428 - * This program is distributed in the hope that it will be useful,
429 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
430 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
431 - * GNU General Public License for more details.
432 - *
433 - * You should have received a copy of the GNU General Public License
434 - * along with this program; if not, write to the Free Software
435 - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
436 + * Copyright (C) 2001, Linux Support Services, Inc.
437 + * All Rights Reserved.
438 + * Copyright (C) 2003-2006 Junghanns.NET GmbH
439 + * Klaus-Peter Junghanns <kpj@junghanns.net>
440 *
441 */
442
443 @@ -48,6 +38,14 @@
444 return "Network";
445 case PRI_CPE:
446 return "CPE";
447 + case BRI_NETWORK:
448 + return "Network";
449 + case BRI_CPE:
450 + return "CPE";
451 + case BRI_NETWORK_PTMP:
452 + return "Network (PtMP)";
453 + case BRI_CPE_PTMP:
454 + return "CPE (PtMP)";
455 default:
456 return "Invalid value";
457 }
458 @@ -187,7 +185,7 @@
459 return res;
460 }
461
462 -static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata)
463 +static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata, int span)
464 {
465 struct pri *p;
466 p = malloc(sizeof(struct pri));
467 @@ -207,6 +205,8 @@
468 p->master = master;
469 p->callpool = &p->localpool;
470 pri_default_timers(p, switchtype);
471 + p->debugfd = -1;
472 + p->span = span;
473 #ifdef LIBPRI_COUNTERS
474 p->q921_rxcount = 0;
475 p->q921_txcount = 0;
476 @@ -217,7 +217,7 @@
477 p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
478 p->sapi = Q921_SAPI_GR303_EOC;
479 p->tei = Q921_TEI_GR303_EOC_OPS;
480 - p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_EOC_PATH, p, NULL, NULL, NULL);
481 + p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_EOC_PATH, p, NULL, NULL, NULL, span);
482 if (!p->subchannel) {
483 free(p);
484 p = NULL;
485 @@ -226,7 +226,7 @@
486 p->protodisc = GR303_PROTOCOL_DISCRIMINATOR;
487 p->sapi = Q921_SAPI_GR303_TMC_CALLPROC;
488 p->tei = Q921_TEI_GR303_TMC_CALLPROC;
489 - p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_TMC_SWITCHING, p, NULL, NULL, NULL);
490 + p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_TMC_SWITCHING, p, NULL, NULL, NULL, span);
491 if (!p->subchannel) {
492 free(p);
493 p = NULL;
494 @@ -242,7 +242,7 @@
495 }
496 /* Start Q.921 layer, Wait if we're the network */
497 if (p)
498 - q921_start(p, p->localtype == PRI_CPE);
499 + q921_start(p, p->localtype == PRI_CPE, 0);
500 }
501 return p;
502 }
503 @@ -262,15 +262,16 @@
504 {
505 /* Restart Q.921 layer */
506 if (pri) {
507 - q921_reset(pri);
508 - q921_start(pri, pri->localtype == PRI_CPE);
509 +// XXX q921_reset(pri);
510 +// q921_start(pri, pri->localtype == PRI_CPE);
511 }
512 return 0;
513 }
514
515 -struct pri *pri_new(int fd, int nodetype, int switchtype)
516 +
517 +struct pri *pri_new(int fd, int nodetype, int switchtype, int span)
518 {
519 - return __pri_new(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL);
520 + return __pri_new(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL, span);
521 }
522
523 struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata)
524 @@ -279,7 +280,7 @@
525 io_read = __pri_read;
526 if (!io_write)
527 io_write = __pri_write;
528 - return __pri_new(fd, nodetype, switchtype, NULL, io_read, io_write, userdata);
529 + return __pri_new(fd, nodetype, switchtype, NULL, io_read, io_write, userdata, -1);
530 }
531
532 void *pri_get_userdata(struct pri *pri)
533 @@ -443,6 +444,15 @@
534 return;
535 }
536
537 +void pri_set_debug_fd(struct pri *pri, int fd)
538 +{
539 + if (!pri)
540 + return;
541 + pri->debugfd = fd;
542 + if (pri->subchannel)
543 + pri_set_debug_fd(pri->subchannel, fd);
544 +}
545 +
546 int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int info)
547 {
548 if (!pri || !call)
549 @@ -478,6 +488,21 @@
550 return q931_notify(pri, call, channel, info);
551 }
552
553 +int pri_information_display(struct pri *pri, q931_call *call, char *display)
554 +{
555 + if (!pri || !call)
556 + return -1;
557 + return q931_information_display(pri, call, display);
558 +}
559 +
560 +int pri_add_display(struct pri *pri, q931_call *call, char *display)
561 +{
562 + if (!pri || !call)
563 + return -1;
564 + return q931_add_display(pri, call, display);
565 +}
566 +
567 +
568 void pri_destroycall(struct pri *pri, q931_call *call)
569 {
570 if (pri && call)
571 @@ -499,6 +524,76 @@
572 return q931_connect(pri, call, channel, nonisdn);
573 }
574
575 +int pri_hold_acknowledge(struct pri *pri, q931_call *call)
576 +{
577 + if (!pri || !call)
578 + return -1;
579 + return q931_hold_acknowledge(pri, call);
580 +}
581 +
582 +int pri_hold_reject(struct pri *pri, q931_call *call)
583 +{
584 + if (!pri || !call)
585 + return -1;
586 + return q931_hold_reject(pri, call);
587 +}
588 +
589 +int pri_retrieve_acknowledge(struct pri *pri, q931_call *call, int channel)
590 +{
591 + if (!pri || !call)
592 + return -1;
593 + return q931_retrieve_acknowledge(pri, call, channel);
594 +}
595 +
596 +int pri_retrieve_reject(struct pri *pri, q931_call *call)
597 +{
598 + if (!pri || !call)
599 + return -1;
600 + return q931_retrieve_reject(pri, call);
601 +}
602 +
603 +int pri_suspend_acknowledge(struct pri *pri, q931_call *call, char *display)
604 +{
605 + if (!pri || !call)
606 + return -1;
607 + return q931_suspend_acknowledge(pri, call, display);
608 +}
609 +
610 +int pri_suspend_reject(struct pri *pri, q931_call *call, char *display)
611 +{
612 + if (!pri || !call)
613 + return -1;
614 + return q931_suspend_reject(pri, call, display);
615 +}
616 +
617 +int pri_resume_reject(struct pri *pri, q931_call *call, char *display)
618 +{
619 + if (!pri || !call)
620 + return -1;
621 + return q931_resume_reject(pri, call, display);
622 +}
623 +
624 +int pri_resume_acknowledge(struct pri *pri, q931_call *call, int channel, char *display)
625 +{
626 + if (!pri || !call)
627 + return -1;
628 + return q931_resume_acknowledge(pri, call, channel, display);
629 +}
630 +
631 +int pri_facility(struct pri *pri, q931_call *call, int operation, char *arguments)
632 +{
633 + if (!pri || !call)
634 + return -1;
635 +// return q931_facility(pri, call, operation, arguments);
636 + return q931_facility(pri, call);
637 +}
638 +
639 +int pri_deflect(struct pri *pri, q931_call *call, char *destination)
640 +{
641 + add_call_deflection_facility_ie(pri, call, destination);
642 + return q931_facility(pri, call);
643 +}
644 +
645 #if 0
646 /* deprecated routines, use pri_hangup */
647 int pri_release(struct pri *pri, q931_call *call, int cause)
648 @@ -541,14 +636,35 @@
649 return 0;
650 }
651
652 -int pri_hangup(struct pri *pri, q931_call *call, int cause)
653 +int pri_hangup(struct pri *pri, q931_call *call, int cause, int aocunits)
654 {
655 + int res=0;
656 if (!pri || !call)
657 return -1;
658 if (cause == -1)
659 /* normal clear cause */
660 cause = 16;
661 - return q931_hangup(pri, call, cause);
662 + if ((cause == 34 || cause == 44 || cause == 82 || cause == 1 || cause == 81 || cause == 17) && (call->ourcallstate == Q931_CALL_STATE_ACTIVE)) {
663 + pri_error(pri, "Cause code %d not allowed when disconnecting an active call. Changing to cause 16.\n", cause);
664 + cause = 16;
665 + }
666 +
667 + if (aocunits > -1) {
668 + call->aoc_units = aocunits;
669 + }
670 +
671 + if (pri->localtype == BRI_NETWORK_PTMP) {
672 + res = q921_hangup(pri, call, 127);
673 + if (res) {
674 + // q921_setup might give a HANGUP_ACK, if nobody got the call
675 + q931_hangup(pri, call, cause);
676 + return res;
677 + } else {
678 + return q931_hangup(pri, call, cause);
679 + }
680 + } else {
681 + return q931_hangup(pri, call, cause);
682 + }
683 }
684
685 int pri_reset(struct pri *pri, int channel)
686 @@ -688,15 +804,15 @@
687 return q931_setup(pri, c, &req);
688 }
689
690 -static void (*__pri_error)(struct pri *pri, char *stuff);
691 -static void (*__pri_message)(struct pri *pri, char *stuff);
692 +static void (*__pri_error)(char *stuff,int span);
693 +static void (*__pri_message)(char *stuff,int span);
694
695 -void pri_set_message(void (*func)(struct pri *pri, char *stuff))
696 +void pri_set_message(void (*func)(char *stuff,int span))
697 {
698 __pri_message = func;
699 }
700
701 -void pri_set_error(void (*func)(struct pri *pri, char *stuff))
702 +void pri_set_error(void (*func)(char *stuff,int span))
703 {
704 __pri_error = func;
705 }
706 @@ -708,10 +824,14 @@
707 va_start(ap, fmt);
708 vsnprintf(tmp, sizeof(tmp), fmt, ap);
709 va_end(ap);
710 - if (__pri_message)
711 - __pri_message(pri, tmp);
712 - else
713 - fputs(tmp, stdout);
714 + if (__pri_message && pri) {
715 + if (pri->debugfd >= 0)
716 + write(pri->debugfd, tmp, strlen(tmp));
717 + else
718 + __pri_message(tmp, pri->span);
719 + } else {
720 + fputs(tmp, stdout);
721 + }
722 }
723
724 void pri_error(struct pri *pri, char *fmt, ...)
725 @@ -721,10 +841,14 @@
726 va_start(ap, fmt);
727 vsnprintf(tmp, sizeof(tmp), fmt, ap);
728 va_end(ap);
729 - if (__pri_error)
730 - __pri_error(pri, tmp);
731 - else
732 - fputs(tmp, stderr);
733 + if (__pri_error && pri) {
734 + if (pri->debugfd >= 0)
735 + write(pri->debugfd, tmp, strlen(tmp));
736 + else
737 + __pri_error(tmp, pri->span);
738 + } else {
739 + fputs(tmp, stderr);
740 + }
741 }
742
743 /* Set overlap mode */
744 @@ -765,11 +889,13 @@
745 }
746 len += sprintf(buf + len, "Q921 Outstanding: %d\n", q921outstanding);
747 #endif
748 - len += sprintf(buf + len, "Window Length: %d/%d\n", pri->windowlen, pri->window);
749 - len += sprintf(buf + len, "Sentrej: %d\n", pri->sentrej);
750 - len += sprintf(buf + len, "SolicitFbit: %d\n", pri->solicitfbit);
751 - len += sprintf(buf + len, "Retrans: %d\n", pri->retrans);
752 - len += sprintf(buf + len, "Busy: %d\n", pri->busy);
753 + if (pri->localtype != BRI_NETWORK_PTMP) {
754 + len += sprintf(buf + len, "Window Length: %d/%d\n", pri->windowlen[0], pri->window[0]);
755 + len += sprintf(buf + len, "Sentrej: %d\n", pri->sentrej[0]);
756 + len += sprintf(buf + len, "SolicitFbit: %d\n", pri->solicitfbit[0]);
757 + len += sprintf(buf + len, "Retrans: %d\n", pri->retrans[0]);
758 + len += sprintf(buf + len, "Busy: %d\n", pri->busy[0]);
759 + }
760 len += sprintf(buf + len, "Overlap Dial: %d\n", pri->overlapdial);
761 len += sprintf(buf + len, "T200 Timer: %d\n", pri->timers[PRI_TIMER_T200]);
762 len += sprintf(buf + len, "T203 Timer: %d\n", pri->timers[PRI_TIMER_T203]);
763 @@ -778,6 +904,7 @@
764 len += sprintf(buf + len, "T313 Timer: %d\n", pri->timers[PRI_TIMER_T313]);
765 len += sprintf(buf + len, "N200 Counter: %d\n", pri->timers[PRI_TIMER_N200]);
766
767 +
768 return strdup(buf);
769 }
770
771 @@ -819,10 +946,11 @@
772 return 0;
773 }
774
775 -int pri_sr_set_bearer(struct pri_sr *sr, int transmode, int userl1)
776 +int pri_sr_set_bearer(struct pri_sr *sr, int transmode, int userl1, char *llc)
777 {
778 sr->transmode = transmode;
779 sr->userl1 = userl1;
780 + sr->llc = llc;
781 return 0;
782 }
783
784 @@ -851,3 +979,14 @@
785 sr->redirectingreason = reason;
786 return 0;
787 }
788 +
789 +void pri_shutdown(struct pri *pri)
790 +{
791 +#ifndef LAYER2ALWAYSUP
792 +#ifndef RELAX_TRB
793 + if ((pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_CPE) || (pri->localtype == BRI_CPE_PTMP)) {
794 + q921_reset(pri, pri->tei, 1);
795 + }
796 +#endif
797 +#endif
798 +}
799 diff -urN libpri-1.2.3.orig/pri_facility.c libpri-1.2.3/pri_facility.c
800 --- libpri-1.2.3.orig/pri_facility.c 2006-02-14 00:06:02.000000000 +0100
801 +++ libpri-1.2.3/pri_facility.c 2006-06-06 14:26:01.000000000 +0200
802 @@ -1,26 +1,17 @@
803 -/*
804 - * libpri: An implementation of Primary Rate ISDN
805 - *
806 - * Written by Matthew Fredrickson <creslin@digium.com>
807 - *
808 - * Copyright (C) 2004-2005, Digium
809 - * All Rights Reserved.
810 - *
811 - * This program is free software; you can redistribute it and/or modify
812 - * it under the terms of the GNU General Public License as published by
813 - * the Free Software Foundation; either version 2 of the License, or
814 - * (at your option) any later version.
815 - *
816 - * This program is distributed in the hope that it will be useful,
817 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
818 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
819 - * GNU General Public License for more details.
820 - *
821 - * You should have received a copy of the GNU General Public License
822 - * along with this program; if not, write to the Free Software
823 - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
824 - *
825 - */
826 +/*
827 + This file and it's contents are licensed under the terms and conditions
828 + of the GNU Public License. See http://www.gnu.org for details.
829 +
830 + Routines for dealing with facility messages and their respective
831 + components (ROSE)
832 +
833 + by Matthew Fredrickson <creslin@digium.com>
834 + Copyright (C) 2004-2005 Digium, Inc
835 +
836 + Copyright (C) 2005-2006 Junghanns.NET GmbH
837 + Klaus-Peter Junghanns <kpj@junghanns.net>
838 +
839 +*/
840
841 #include "compat.h"
842 #include "libpri.h"
843 @@ -208,9 +199,9 @@
844 if (datalen > buflen) {
845 /* Truncate */
846 datalen = buflen;
847 + memcpy(namebuf, comp->data, datalen);
848 }
849 - memcpy(namebuf, comp->data, datalen);
850 - return res + 2;
851 + return res;
852 }
853
854 int asn1_string_encode(unsigned char asn1_type, void *data, int len, int max_len, void *src, int src_len)
855 @@ -305,12 +296,55 @@
856 return -1;
857 value->ton = ton;
858
859 - return res + 3;
860 + return res + 2;
861
862 } while(0);
863 return -1;
864 }
865
866 +static int rose_cd_destination_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
867 +{
868 + unsigned char *vdata = data;
869 + struct rose_component *comp1 = NULL, *comp2 = NULL;
870 + int pos1 = 0, pos2, sublen2;
871 +
872 + if (pri->debug & PRI_DEBUG_AOC)
873 + dump_apdu (pri, data, len);
874 +
875 + do {
876 + GET_COMPONENT(comp1, pos1, vdata, len);
877 + CHECK_COMPONENT(comp1, ASN1_SEQUENCE, "!! Invalid CD destination argument. Expected Sequence (0x30) but Received 0x%02X\n");
878 + SUB_COMPONENT(comp1, pos1);
879 + GET_COMPONENT(comp1, pos1, vdata, len);
880 + switch (comp1->type) {
881 + case (ASN1_SEQUENCE | ASN1_CONSTRUCTOR):
882 + sublen2 = comp1->len;
883 + pos2 = pos1;
884 + comp2 = comp1;
885 + SUB_COMPONENT(comp2, pos2);
886 + do {
887 + GET_COMPONENT(comp2, pos2, vdata, len);
888 + switch (comp2->type) {
889 + case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0):
890 + memcpy(call->redirectingnum, comp2->data, comp2->len);
891 + call->redirectingnum[comp2->len] = '\0';
892 + return 0;
893 + break;
894 + default:
895 + pri_message(pri, "!! Don't know how to handle 0x%02X in CD destination argument\n", comp2->type);
896 + }
897 + NEXT_COMPONENT(comp2, pos2);
898 + } while (pos2 < sublen2);
899 + break;
900 + default:
901 + pri_message(pri, "!! Invalid CD destination argument. Expected Sequence (0x30) or Object Identifier (0x81/0x01) but received 0x%02X\n", comp1->type);
902 + }
903 + NEXT_COMPONENT(comp1, pos1);
904 + } while (pos1 < len);
905 +
906 + return 0;
907 +}
908 +
909 static int rose_address_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
910 {
911 int i = 0;
912 @@ -375,11 +409,10 @@
913 pri_message(pri, "!! Unknown Party number component received 0x%X\n", comp->type);
914 return -1;
915 }
916 - ASN1_FIXUP_LEN(comp, res);
917 NEXT_COMPONENT(comp, i);
918 if(i < len)
919 pri_message(pri, "!! not all information is handled from Address component\n");
920 - return res + 2;
921 + return res;
922 }
923 while (0);
924
925 @@ -389,7 +422,6 @@
926 static int rose_presented_number_unscreened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value)
927 {
928 int i = 0;
929 - int size = 0;
930 struct rose_component *comp = NULL;
931 unsigned char *vdata = data;
932
933 @@ -404,9 +436,7 @@
934 switch(comp->type) {
935 case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] presentationAllowedNumber */
936 value->pres = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
937 - size = rose_address_decode(pri, call, comp->data, comp->len, value);
938 - ASN1_FIXUP_LEN(comp, size);
939 - return size + 2;
940 + return rose_address_decode(pri, call, comp->data, comp->len, value) + 2;
941 case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* [1] IMPLICIT presentationRestricted */
942 if (comp->len != 0) { /* must be NULL */
943 pri_error(pri, "!! Invalid PresentationRestricted component received (len != 0)\n");
944 @@ -423,9 +453,7 @@
945 return 2;
946 case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] presentationRestrictedNumber */
947 value->pres = PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
948 - size = rose_address_decode(pri, call, comp->data, comp->len, value) + 2;
949 - ASN1_FIXUP_LEN(comp, size);
950 - return size + 2;
951 + return rose_address_decode(pri, call, comp->data, comp->len, value) + 2;
952 default:
953 pri_message(pri, "Invalid PresentedNumberUnscreened component 0x%X\n", comp->type);
954 }
955 @@ -436,7 +464,7 @@
956 return -1;
957 }
958
959 -static int rose_diverting_leg_information2_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len)
960 +static int rose_diverting_leg_information2_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
961 {
962 int i = 0;
963 int diversion_counter;
964 @@ -445,21 +473,9 @@
965 struct addressingdataelements_presentednumberunscreened divertingnr;
966 struct addressingdataelements_presentednumberunscreened originalcallednr;
967 struct rose_component *comp = NULL;
968 - unsigned char *vdata = sequence->data;
969 + unsigned char *vdata = data;
970 int res = 0;
971
972 - /* Data checks */
973 - if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
974 - pri_message(pri, "Invalid DivertingLegInformation2Type argument\n");
975 - return -1;
976 - }
977 -
978 - if (sequence->len == ASN1_LEN_INDEF) {
979 - len -= 4; /* For the 2 extra characters at the end
980 - * and two characters of header */
981 - } else
982 - len -= 2;
983 -
984 do {
985 /* diversionCounter stuff */
986 GET_COMPONENT(comp, i, vdata, len);
987 @@ -477,20 +493,18 @@
988
989 if(pri->debug & PRI_DEBUG_APDU)
990 pri_message(pri, " Redirection reason: %d, total diversions: %d\n", diversion_reason, diversion_counter);
991 - pri_message(NULL, "Length of message is %d\n", len);
992
993 for(; i < len; NEXT_COMPONENT(comp, i)) {
994 GET_COMPONENT(comp, i, vdata, len);
995 - switch(comp->type) {
996 - case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0):
997 + switch(comp->type & ASN1_TYPE_MASK) {
998 + case ASN1_TAG_0:
999 call->origredirectingreason = redirectingreason_for_q931(pri, comp->data[0]);
1000 if (pri->debug & PRI_DEBUG_APDU)
1001 pri_message(pri, " Received reason for original redirection %d\n", call->origredirectingreason);
1002 break;
1003 - case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1):
1004 + case ASN1_TAG_1: /* divertingnr: presentednumberunscreened */
1005 res = rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &divertingnr);
1006 /* TODO: Fix indefinite length form hacks */
1007 - ASN1_FIXUP_LEN(comp, res);
1008 comp->len = res;
1009 if (res < 0)
1010 return -1;
1011 @@ -499,43 +513,33 @@
1012 pri_message(pri, " ton = %d, pres = %d, npi = %d\n", divertingnr.ton, divertingnr.pres, divertingnr.npi);
1013 }
1014 break;
1015 - case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2):
1016 + case ASN1_TAG_2: /* originalCalledNr: PresentedNumberUnscreened */
1017 res = rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &originalcallednr);
1018 if (res < 0)
1019 return -1;
1020 - ASN1_FIXUP_LEN(comp, res);
1021 comp->len = res;
1022 if (pri->debug & PRI_DEBUG_APDU) {
1023 pri_message(pri, " Received originalcallednr '%s'\n", originalcallednr.partyaddress);
1024 pri_message(pri, " ton = %d, pres = %d, npi = %d\n", originalcallednr.ton, originalcallednr.pres, originalcallednr.npi);
1025 }
1026 break;
1027 - case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3):
1028 - res = asn1_name_decode(comp->data, comp->len, redirectingname, sizeof(redirectingname));
1029 - if (res < 0)
1030 - return -1;
1031 - ASN1_FIXUP_LEN(comp, res);
1032 - comp->len = res;
1033 + case ASN1_TAG_3:
1034 + comp->len = asn1_name_decode(comp->data, comp->len, redirectingname, sizeof(redirectingname));
1035 if (pri->debug & PRI_DEBUG_APDU)
1036 pri_message(pri, " Received RedirectingName '%s'\n", redirectingname);
1037 break;
1038 - case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4):
1039 - res = asn1_name_decode(comp->data, comp->len, origcalledname, sizeof(origcalledname));
1040 - if (res < 0)
1041 - return -1;
1042 - ASN1_FIXUP_LEN(comp, res);
1043 - comp->len = res;
1044 + case ASN1_TAG_4:
1045 + comp->len = asn1_name_decode(comp->data, comp->len, origcalledname, sizeof(origcalledname));
1046 if (pri->debug & PRI_DEBUG_APDU)
1047 pri_message(pri, " Received Originally Called Name '%s'\n", origcalledname);
1048 break;
1049 default:
1050 - if (comp->type == 0 && comp->len == 0) {
1051 - break; /* Found termination characters */
1052 - }
1053 pri_message(pri, "!! Invalid DivertingLegInformation2 component received 0x%X\n", comp->type);
1054 return -1;
1055 }
1056 }
1057 + if (i < len)
1058 + return -1; /* Aborted before */
1059
1060 if (divertingnr.pres >= 0) {
1061 call->redirectingplan = divertingnr.npi;
1062 @@ -548,15 +552,19 @@
1063 call->origcalledpres = originalcallednr.pres;
1064 libpri_copy_string(call->origcallednum, originalcallednr.partyaddress, sizeof(call->origcallednum));
1065 }
1066 - libpri_copy_string(call->redirectingname, redirectingname, sizeof(call->redirectingname));
1067 - libpri_copy_string(call->origcalledname, origcalledname, sizeof(call->origcalledname));
1068 + if (strlen(redirectingname) > 0) {
1069 + libpri_copy_string(call->redirectingname, redirectingname, sizeof(call->redirectingname));
1070 + }
1071 + if (strlen(origcalledname) > 0) {
1072 + libpri_copy_string(call->origcalledname, origcalledname, sizeof(call->origcalledname));
1073 + }
1074 return 0;
1075 }
1076 while (0);
1077
1078 return -1;
1079 }
1080 -
1081 +
1082 static int rose_diverting_leg_information2_encode(struct pri *pri, q931_call *call)
1083 {
1084 int i = 0, j, compsp = 0;
1085 @@ -694,6 +702,64 @@
1086 return 0;
1087 }
1088
1089 +/* Call deflection */
1090 +int add_call_deflection_facility_ie(struct pri *pri, q931_call *c, char *destination) {
1091 + int i = 0, j, compsp = 0;
1092 + struct rose_component *comp, *compstk[10];
1093 + unsigned char buffer[256];
1094 +
1095 + buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_ROSE);
1096 + /* invoke */
1097 + ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i);
1098 + ASN1_PUSH(compstk, compsp, comp);
1099 +
1100 + ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri));
1101 + ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, ROSE_CALLDEFLECTION);
1102 +
1103 + /* Argument sequence */
1104 + ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
1105 + ASN1_PUSH(compstk, compsp, comp);
1106 +
1107 + /* arg.Address */
1108 + ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
1109 + ASN1_PUSH(compstk, compsp, comp);
1110 +
1111 +#ifndef CD_UNLIKE_IN_CAPI
1112 + /* arg.address.PartyNumber */
1113 +
1114 +
1115 + j = asn1_string_encode((ASN1_CONTEXT_SPECIFIC|ASN1_TAG_0), &buffer[i], sizeof(buffer)-i, 20, destination, strlen(destination));
1116 + if (j<0) return -1;
1117 + i += j;
1118 +#else
1119 + /* using PublicPartyNumber instead */
1120 + ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE | ASN1_CONTEXT_SPECIFIC| ASN1_TAG_1), buffer, i);
1121 + ASN1_PUSH(compstk, compsp, comp);
1122 + /* ToN: unknown */
1123 + ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0);
1124 + j = asn1_string_encode(0x80, &buffer[i], sizeof(buffer)-i, 20, destination, strlen(destination));
1125 + if(j<0) return -1;
1126 + i += j;
1127 + /* close PublicPartyNumber */
1128 + ASN1_FIXUP(compstk, compsp, buffer, i);
1129 +#endif
1130 +
1131 + /* close Address */
1132 + ASN1_FIXUP(compstk, compsp, buffer, i);
1133 +
1134 + /* add boolean */
1135 + ASN1_ADD_BYTECOMP(comp, ASN1_BOOLEAN, buffer, i, 0);
1136 +
1137 + /* Fix length of stacked components */
1138 + while(compsp > 0) {
1139 + ASN1_FIXUP(compstk, compsp, buffer, i);
1140 + }
1141 + if (pri_call_apdu_queue(c, Q931_FACILITY, buffer, i, NULL, NULL))
1142 + return -1;
1143 +
1144 + return 0;
1145 +}
1146 +
1147 /* Sending callername information functions */
1148 static int add_callername_facility_ies(struct pri *pri, q931_call *c, int cpe)
1149 {
1150 @@ -936,7 +1002,7 @@
1151 CHECK_COMPONENT(comp, ASN1_ENUMERATED, "!! Invalid AOC Charging Request argument. Expected Enumerated (0x0A) but Received 0x%02X\n");
1152 ASN1_GET_INTEGER(comp, chargingcase);
1153 if (chargingcase >= 0 && chargingcase <= 2) {
1154 - if (pri->debug & PRI_DEBUG_APDU)
1155 +// if (pri->debug & PRI_DEBUG_APDU)
1156 pri_message(pri, "Channel %d/%d, Call %d - received AOC charging request - charging case: %i\n",
1157 call->ds1no, call->channelno, call->cr, chargingcase);
1158 } else {
1159 @@ -1054,7 +1120,7 @@
1160 return 0;
1161 }
1162
1163 -static int aoc_aoce_charging_unit_encode(struct pri *pri, q931_call *c, long chargedunits)
1164 +int aoc_aoce_charging_unit_encode(struct pri *pri, q931_call *c, long chargedunits, int msgtype)
1165 {
1166 /* sample data: [ 91 a1 12 02 02 3a 78 02 01 24 30 09 30 07 a1 05 30 03 02 01 01 ] */
1167 int i = 0, res = 0, compsp = 0;
1168 @@ -1108,18 +1174,20 @@
1169 dump_apdu (pri, buffer, i);
1170
1171 /* code below is untested */
1172 - res = pri_call_apdu_queue(c, Q931_FACILITY, buffer, i, NULL, NULL);
1173 + res = pri_call_apdu_queue(c, msgtype, buffer, i, NULL, NULL);
1174 if (res) {
1175 pri_message(pri, "Could not queue ADPU in facility message\n");
1176 return -1;
1177 }
1178
1179 - /* Remember that if we queue a facility IE for a facility message we
1180 - * have to explicitly send the facility message ourselves */
1181 - res = q931_facility(c->pri, c);
1182 - if (res) {
1183 + if (msgtype == Q931_FACILITY) {
1184 + /* Remember that if we queue a facility IE for a facility message we
1185 + * have to explicitly send the facility message ourselves */
1186 + res = q931_facility(c->pri, c);
1187 + if (res) {
1188 pri_message(pri, "Could not schedule facility message for call %d\n", c->cr);
1189 return -1;
1190 + }
1191 }
1192
1193 return 0;
1194 @@ -1152,13 +1220,15 @@
1195 NEXT_COMPONENT(comp, i);
1196
1197 /* No argument - return with error */
1198 - if (i >= len)
1199 + if ((i >= len) && (operation_tag != ROSE_EXPLICIT_CALL_TRANSFER))
1200 return -1;
1201
1202 - /* Arguement Tag */
1203 - GET_COMPONENT(comp, i, vdata, len);
1204 - if (!comp->type)
1205 - return -1;
1206 + if (operation_tag != ROSE_EXPLICIT_CALL_TRANSFER) {
1207 + /* Arguement Tag */
1208 + GET_COMPONENT(comp, i, vdata, len);
1209 + if (!comp->type)
1210 + return -1;
1211 + }
1212
1213 if (pri->debug & PRI_DEBUG_APDU)
1214 pri_message(pri, " [ Handling operation %d ]\n", operation_tag);
1215 @@ -1182,7 +1252,11 @@
1216 case ROSE_DIVERTING_LEG_INFORMATION2:
1217 if (pri->debug & PRI_DEBUG_APDU)
1218 pri_message(pri, " Handle DivertingLegInformation2\n");
1219 - return rose_diverting_leg_information2_decode(pri, call, comp, len-i);
1220 + if (comp->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */
1221 + pri_message(pri, "Invalid DivertingLegInformation2Type argument\n");
1222 + return -1;
1223 + }
1224 + return rose_diverting_leg_information2_decode(pri, call, comp->data, comp->len);
1225 case ROSE_AOC_NO_CHARGING_INFO_AVAILABLE:
1226 if (pri->debug & PRI_DEBUG_APDU) {
1227 pri_message(pri, "ROSE %i: AOC No Charging Info Available - not handled!", operation_tag);
1228 @@ -1210,6 +1284,7 @@
1229 }
1230 return -1;
1231 case ROSE_AOC_AOCD_CHARGING_UNIT:
1232 +// return aoc_aoce_charging_unit_decode(pri, call, (u_int8_t *)comp, comp->len + 2);
1233 if (pri->debug & PRI_DEBUG_APDU) {
1234 pri_message(pri, "ROSE %i: AOC-D Charging Unit - not handled!", operation_tag);
1235 dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
1236 @@ -1224,7 +1299,7 @@
1237 case ROSE_AOC_AOCE_CHARGING_UNIT:
1238 return aoc_aoce_charging_unit_decode(pri, call, (u_int8_t *)comp, comp->len + 2);
1239 if (0) { /* the following function is currently not used - just to make the compiler happy */
1240 - aoc_aoce_charging_unit_encode(pri, call, call->aoc_units); /* use this function to forward the aoc-e on a bridged channel */
1241 + aoc_aoce_charging_unit_encode(pri, call, call->aoc_units, 1); /* use this function to forward the aoc-e on a bridged channel */
1242 return 0;
1243 }
1244 case ROSE_AOC_IDENTIFICATION_OF_CHARGE:
1245 @@ -1233,6 +1308,22 @@
1246 dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
1247 }
1248 return -1;
1249 + case ROSE_CALLDEFLECTION:
1250 + call->facility = operation_tag;
1251 + return rose_cd_destination_decode(pri, call, (u_int8_t *)comp, comp->len + 2);
1252 + return -1;
1253 + case ROSE_EXPLICIT_CALL_TRANSFER:
1254 + call->facility = operation_tag;
1255 + if (pri->debug & PRI_DEBUG_APDU) {
1256 + pri_message(pri, "ROSE %i: received ECT execute!", operation_tag);
1257 + }
1258 + return 0;
1259 + case ROSE_MALICIOUS_CID:
1260 +// call->facility = operation_tag;
1261 +// if (pri->debug & PRI_DEBUG_APDU) {
1262 + pri_message(pri, "ROSE %i: received MALICIOUS CID!", operation_tag);
1263 + // }
1264 + return 0;
1265 default:
1266 if (pri->debug & PRI_DEBUG_APDU) {
1267 pri_message(pri, "!! Unable to handle ROSE operation %d", operation_tag);
1268 diff -urN libpri-1.2.3.orig/pri_facility.h libpri-1.2.3/pri_facility.h
1269 --- libpri-1.2.3.orig/pri_facility.h 2005-11-29 19:39:18.000000000 +0100
1270 +++ libpri-1.2.3/pri_facility.h 2006-04-15 21:35:05.000000000 +0200
1271 @@ -34,7 +34,7 @@
1272 /* Operation ID values */
1273 /* Q.952 ROSE operations (Diverting) */
1274 #define ROSE_DIVERTING_LEG_INFORMATION1 18
1275 -#define ROSE_DIVERTING_LEG_INFORMATION2 0x15
1276 +#define ROSE_DIVERTING_LEG_INFORMATION2 15
1277 #define ROSE_DIVERTING_LEG_INFORMATION3 19
1278 /* Q.956 ROSE operations (Advice Of Charge) */
1279 #define ROSE_AOC_NO_CHARGING_INFO_AVAILABLE 26
1280 @@ -48,11 +48,15 @@
1281 #define ROSE_AOC_IDENTIFICATION_OF_CHARGE 37
1282 /* Q.SIG operations */
1283 #define SS_CNID_CALLINGNAME 0
1284 -#define SS_DIVERTING_LEG_INFORMATION2 21
1285 +#define SS_DIVERTING_LEG_INFORMATION2 22
1286 #define SS_MWI_ACTIVATE 80
1287 #define SS_MWI_DEACTIVATE 81
1288 #define SS_MWI_INTERROGATE 82
1289
1290 +#define ROSE_CALLDEFLECTION 0x0D
1291 +#define ROSE_EXPLICIT_CALL_TRANSFER 0x06
1292 +#define ROSE_MALICIOUS_CID 0x31
1293 +
1294 /* ROSE definitions and data structures */
1295 #define INVOKE_IDENTIFIER 0x02
1296 #define INVOKE_LINKED_IDENTIFIER 0x80
1297 @@ -180,12 +184,6 @@
1298 (variable) = ((variable) << 8) | (component)->data[comp_idx]; \
1299 } while (0)
1300
1301 -#define ASN1_FIXUP_LEN(component, size) \
1302 - do { \
1303 - if ((component)->len == ASN1_LEN_INDEF) \
1304 - size += 2; \
1305 - } while (0)
1306 -
1307 #define ASN1_ADD_SIMPLE(component, comptype, ptr, idx) \
1308 do { \
1309 (component) = (struct rose_component *)&((ptr)[(idx)]); \
1310 @@ -260,4 +258,8 @@
1311 /* Adds the "standard" ADPUs to a call */
1312 extern int pri_call_add_standard_apdus(struct pri *pri, q931_call *call);
1313
1314 +extern int add_call_deflection_facility_ie(struct pri *pri, q931_call *c, char *destination);
1315 +
1316 +extern int aoc_aoce_charging_unit_encode(struct pri *pri, q931_call *c, long chargedunits, int send_facility_message);
1317 +
1318 #endif /* _PRI_FACILITY_H */
1319 diff -urN libpri-1.2.3.orig/pri_internal.h libpri-1.2.3/pri_internal.h
1320 --- libpri-1.2.3.orig/pri_internal.h 2005-11-29 19:39:18.000000000 +0100
1321 +++ libpri-1.2.3/pri_internal.h 2006-04-15 21:57:19.000000000 +0200
1322 @@ -5,6 +5,8 @@
1323 *
1324 * Copyright (C) 2001, Linux Support Services, Inc.
1325 * All Rights Reserved.
1326 + * Copyright (C) 2003-2006 Junghanns.NET GmbH
1327 + * Klaus-Peter Junghanns <kpj@junghanns.net>
1328 *
1329 * This program is free software; you can redistribute it and/or modify
1330 * it under the terms of the GNU General Public License as published by
1331 @@ -30,7 +32,10 @@
1332 struct pri_sched {
1333 struct timeval when;
1334 void (*callback)(void *data);
1335 + void (*callback2)(void *data, int);
1336 void *data;
1337 + char hasdata2;
1338 + int data2;
1339 };
1340
1341 struct q921_frame;
1342 @@ -38,8 +43,15 @@
1343 enum q931_mode;
1344
1345 /* No more than 128 scheduled events */
1346 +/* XXX is this sufficient for nfs ??? */
1347 #define MAX_SCHED 128
1348
1349 +/* this can be freely configured to support more devices .... ok, 63 would be max! */
1350 +#define Q921_MAX_TEIS 16
1351 +
1352 +/* dynamically allocated TEIs start here */
1353 +#define Q921_TEI_BASE 64
1354 +
1355 #define MAX_TIMERS 32
1356
1357 struct pri {
1358 @@ -51,6 +63,7 @@
1359 struct pri *master; /* Master channel if appropriate */
1360 struct pri_sched pri_sched[MAX_SCHED]; /* Scheduled events */
1361 int debug; /* Debug stuff */
1362 + int debugfd;
1363 int state; /* State of D-channel */
1364 int switchtype; /* Switch type */
1365 int nsf; /* Network-Specific Facility (if any) */
1366 @@ -62,25 +75,42 @@
1367 int protodisc;
1368
1369 /* Q.921 State */
1370 - int q921_state;
1371 - int window; /* Max window size */
1372 - int windowlen; /* Fullness of window */
1373 - int v_s; /* Next N(S) for transmission */
1374 - int v_a; /* Last acknowledged frame */
1375 - int v_r; /* Next frame expected to be received */
1376 - int v_na; /* What we've told our peer we've acknowledged */
1377 - int solicitfbit; /* Have we sent an I or S frame with the F-bit set? */
1378 - int retrans; /* Retransmissions */
1379 - int sentrej; /* Are we in reject state */
1380 -
1381 + int q921_state[Q921_MAX_TEIS];
1382 + char dchanup;
1383 +
1384 + /* TEI registry */
1385 + char q921_teis[Q921_MAX_TEIS];
1386 +
1387 + char q921_tei_check[Q921_MAX_TEIS];
1388 + unsigned short q921_tei_check_ri[Q921_MAX_TEIS];
1389 +
1390 + unsigned int ri;
1391 +
1392 + int busy[Q921_MAX_TEIS]; /* Peer is busy */
1393 +
1394 + int window[Q921_MAX_TEIS]; /* Max window size */
1395 + int windowlen[Q921_MAX_TEIS]; /* Fullness of window */
1396 + int v_s[Q921_MAX_TEIS]; /* Next N(S) for transmission */
1397 + int v_a[Q921_MAX_TEIS]; /* Last acknowledged frame */
1398 + int v_r[Q921_MAX_TEIS]; /* Next frame expected to be received */
1399 + int v_na[Q921_MAX_TEIS]; /* What we've told our peer we've acknowledged */
1400 + int solicitfbit[Q921_MAX_TEIS]; /* Have we sent an I or S frame with the F-bit set? */
1401 + int retrans[Q921_MAX_TEIS]; /* Retransmissions */
1402 + int sabme_retrans[Q921_MAX_TEIS]; /* Retransmissions */
1403 +
1404 + int sentrej[Q921_MAX_TEIS]; /* Are we in reject state */
1405 +
1406 + /* Various timers */
1407 + int sabme_timer[Q921_MAX_TEIS];
1408 + int t203_timer[Q921_MAX_TEIS];
1409 + int t202_timer[Q921_MAX_TEIS];
1410 +
1411 + int t201_timer[Q921_MAX_TEIS];
1412 + int t200_timer[Q921_MAX_TEIS];
1413 +
1414 +
1415 int cref; /* Next call reference value */
1416
1417 - int busy; /* Peer is busy */
1418 -
1419 - /* Various timers */
1420 - int sabme_timer; /* SABME retransmit */
1421 - int t203_timer; /* Max idle time */
1422 - int t200_timer; /* T-200 retransmission timer */
1423 /* All ISDN Timer values */
1424 int timers[MAX_TIMERS];
1425
1426 @@ -89,8 +119,8 @@
1427 int schedev;
1428 pri_event ev; /* Static event thingy */
1429
1430 - /* Q.921 Re-transmission queue */
1431 - struct q921_frame *txqueue;
1432 + /* Q.921 (Re)transmission queue */
1433 + struct q921_frame *txqueue[Q921_MAX_TEIS];
1434
1435 /* Q.931 calls */
1436 q931_call **callpool;
1437 @@ -109,6 +139,9 @@
1438
1439 unsigned char last_invoke; /* Last ROSE invoke ID */
1440 unsigned char sendfacility;
1441 +
1442 + int span; /* our fellow pri lives on this zaptel span */
1443 +
1444 };
1445
1446 struct pri_sr {
1447 @@ -118,6 +151,7 @@
1448 int nonisdn;
1449 char *caller;
1450 int callerplan;
1451 + int callerplanani;
1452 char *callername;
1453 int callerpres;
1454 char *called;
1455 @@ -130,6 +164,7 @@
1456 int redirectingreason;
1457 int justsignalling;
1458 char *useruserinfo;
1459 + char *llc;
1460 };
1461
1462 /* Internal switch types */
1463 @@ -167,8 +202,13 @@
1464
1465 int alive; /* Whether or not the call is alive */
1466 int acked; /* Whether setup has been acked or not */
1467 + int con_acked; /* Whether CONNECT has been CONNECT_ACKNOWLEDGEd or not */
1468 int sendhangupack; /* Whether or not to send a hangup ack */
1469 int proc; /* Whether we've sent a call proceeding / alerting */
1470 + int alert; /* Whether we've sent an alerting */
1471 +
1472 + int tei;
1473 + q921_call *phones;
1474
1475 int ri; /* Restart Indicator (Restart Indicator IE) */
1476
1477 @@ -202,15 +242,18 @@
1478 int callerplan;
1479 int callerplanani;
1480 int callerpres; /* Caller presentation */
1481 - char callerani[256]; /* Caller */
1482 - char callernum[256];
1483 + int callerplanuser;
1484 + int callerpresuser; /* Caller presentation */
1485 + char callernum[256]; /* Calling Number (network provided) */
1486 + char callerani[256]; /* Calling Number, (user provided) */
1487 +
1488 char callername[256];
1489
1490 - char digitbuf[64]; /* Buffer for digits that come in KEYPAD_FACILITY */
1491 + char digitbuf[64]; /* Buffer for digits that come in KEYPAD_FACILITY */
1492
1493 int ani2; /* ANI II */
1494
1495 - int calledplan;
1496 + int calledplan;
1497 int nonisdn;
1498 char callednum[256]; /* Called Number */
1499 int complete; /* no more digits coming */
1500 @@ -225,23 +268,36 @@
1501 char redirectingnum[256]; /* Number of redirecting party */
1502 char redirectingname[256]; /* Name of redirecting party */
1503
1504 + int t303timer;
1505 + int t303running;
1506 +
1507 /* Filled in cases of multiple diversions */
1508 int origcalledplan;
1509 int origcalledpres;
1510 - int origredirectingreason; /* Original reason for redirect (in cases of multiple redirects) */
1511 + int origredirectingreason; /* Original reason for redirect (in cases of multiple redirects) */
1512 char origcalledname[256]; /* Original name of person being called */
1513 - char origcallednum[256]; /* Orignal number of person being called */
1514 + char origcallednum[256]; /* Orignal number of person being called */
1515
1516 - int useruserprotocoldisc;
1517 + int useruserprotocoldisc;
1518 char useruserinfo[256];
1519 char callingsubaddr[256]; /* Calling parties sub address */
1520 +
1521 + char callid[10]; /* call identity for SUSPEND/RESUME */
1522 + char digits[256]; /* additional digits received via info msgs (cpn or keypad) */
1523 + char display[256]; /* display ie received in info msgs or for sending */
1524 +
1525 + /* euroisdn facility fun */
1526 + int facility; /* FACILTIY received */
1527 + int aoc;
1528
1529 long aoc_units; /* Advice of Charge Units */
1530
1531 + char llc[16]; /* low layer compatibility */
1532 struct apdu_event *apdus; /* APDU queue for call */
1533 };
1534
1535 extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);
1536 +extern int pri_schedule_event2(struct pri *pri, int ms, void (*function)(void *data, int data2), void *data, int data2);
1537
1538 extern pri_event *pri_schedule_run(struct pri *pri);
1539
1540 @@ -250,7 +306,7 @@
1541 extern pri_event *pri_mkerror(struct pri *pri, char *errstr);
1542
1543 extern void pri_message(struct pri *pri, char *fmt, ...);
1544 -
1545 +
1546 extern void pri_error(struct pri *pri, char *fmt, ...);
1547
1548 void libpri_copy_string(char *dst, const char *src, size_t size);
1549 diff -urN libpri-1.2.3.orig/pri_q921.h libpri-1.2.3/pri_q921.h
1550 --- libpri-1.2.3.orig/pri_q921.h 2005-11-29 19:39:18.000000000 +0100
1551 +++ libpri-1.2.3/pri_q921.h 2006-04-15 21:57:24.000000000 +0200
1552 @@ -5,6 +5,8 @@
1553 *
1554 * Copyright (C) 2001, Linux Support Services, Inc.
1555 * All Rights Reserved.
1556 + * Copyright (C) 2003-2006 Junghanns.NET GmbH
1557 + * Klaus-Peter Junghanns <kpj@junghanns.net>
1558 *
1559 * This program is free software; you can redistribute it and/or modify
1560 * it under the terms of the GNU General Public License as published by
1561 @@ -47,6 +49,13 @@
1562 #define Q921_FRAMETYPE_S 0x1
1563
1564 #define Q921_TEI_GROUP 127
1565 +#define Q921_TEI_ID_REQUEST 0x1
1566 +#define Q921_TEI_ID_ASSIGNED 0x2
1567 +#define Q921_TEI_ID_DENIED 0x3
1568 +#define Q921_TEI_ID_CHK_REQ 0x4
1569 +#define Q921_TEI_ID_CHK_RES 0x5
1570 +#define Q921_TEI_ID_REMOVE 0x6
1571 +#define Q921_TEI_ID_VERIFY 0x7
1572 #define Q921_TEI_GR303_EOC_PATH 0
1573 #define Q921_TEI_GR303_EOC_OPS 4
1574 #define Q921_TEI_GR303_TMC_SWITCHING 0
1575 @@ -164,12 +173,14 @@
1576 extern void q921_dump(struct pri *pri, q921_h *h, int len, int showraw, int txrx);
1577
1578 /* Bring up the D-channel */
1579 -extern void q921_start(struct pri *pri, int now);
1580 +extern void q921_start(struct pri *pri, int now, int tei);
1581
1582 -extern void q921_reset(struct pri *pri);
1583 +extern void q921_reset(struct pri *pri, int tei, int discard);
1584
1585 extern pri_event *q921_receive(struct pri *pri, q921_h *h, int len);
1586
1587 -extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr);
1588 +extern int q921_transmit_uframe(struct pri *pri, void *buf, int len, int cr, int tei);
1589 +
1590 +extern int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr, int tei);
1591
1592 #endif
1593 diff -urN libpri-1.2.3.orig/pri_q931.h libpri-1.2.3/pri_q931.h
1594 --- libpri-1.2.3.orig/pri_q931.h 2005-11-29 19:39:18.000000000 +0100
1595 +++ libpri-1.2.3/pri_q931.h 2006-04-15 21:57:29.000000000 +0200
1596 @@ -5,6 +5,8 @@
1597 *
1598 * Copyright (C) 2001, Linux Support Services, Inc.
1599 * All Rights Reserved.
1600 + * Copyright (C) 2003-2006 Junghanns.NET GmbH
1601 + * Klaus-Peter Junghanns <kpj@junghanns.net>
1602 *
1603 * This program is free software; you can redistribute it and/or modify
1604 * it under the terms of the GNU General Public License as published by
1605 @@ -190,6 +192,10 @@
1606 #define Q931_IE_CODESET(x) ((x) >> 8)
1607 #define Q931_IE_IE(x) ((x) & 0xff)
1608 #define Q931_FULL_IE(codeset, ie) (((codeset) << 8) | ((ie) & 0xff))
1609 +#define Q931_IE_MAX_LEN 257
1610 +
1611 +// BRI+
1612 +#define Q931_COLP 0x4c
1613
1614 #define Q931_DISPLAY 0x28
1615 #define Q931_IE_SEGMENTED_MSG 0x00
1616 @@ -218,6 +224,8 @@
1617 #define Q931_IE_USER_USER 0x7E
1618 #define Q931_IE_ESCAPE_FOR_EXT 0x7F
1619
1620 +#define Q931_IE_SPECIAL 0x02
1621 +
1622
1623 /* Call state stuff */
1624 #define Q931_CALL_STATE_NULL 0
1625 @@ -243,7 +251,7 @@
1626 /* EuroISDN */
1627 #define Q931_SENDING_COMPLETE 0xa1
1628
1629 -extern int q931_receive(struct pri *pri, q931_h *h, int len);
1630 +extern int q931_receive(struct pri *pri, q931_h *h, int len, int tei);
1631
1632 extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info);
1633
1634 @@ -257,6 +265,10 @@
1635
1636 extern int q931_information(struct pri *pri, q931_call *call, char digit);
1637
1638 +extern int q931_information_display(struct pri *pri, q931_call *call, char *display);
1639 +
1640 +extern int q931_add_display(struct pri *pri, q931_call *call, char *display);
1641 +
1642 extern int q931_connect(struct pri *pri, q931_call *call, int channel, int nonisdn);
1643
1644 extern int q931_release(struct pri *pri, q931_call *call, int cause);
1645 @@ -265,6 +277,10 @@
1646
1647 extern int q931_hangup(struct pri *pri, q931_call *call, int cause);
1648
1649 +extern int q921_hangup(struct pri *pri, q931_call *c, int tei);
1650 +
1651 +extern int q921_handle_hangup(struct pri *pri, q931_call *c, int tei);
1652 +
1653 extern int q931_restart(struct pri *pri, int channel);
1654
1655 extern int q931_facility(struct pri *pri, q931_call *call);
1656 @@ -279,5 +295,23 @@
1657 extern void q931_dump(struct pri *pri, q931_h *h, int len, int txrx);
1658
1659 extern void __q931_destroycall(struct pri *pri, q931_call *c);
1660 +
1661 +extern int q931_hold_acknowledge(struct pri *pri, q931_call *c);
1662 +
1663 +extern int q931_hold_reject(struct pri *pri, q931_call *c);
1664 +
1665 +extern int q931_retrieve_acknowledge(struct pri *pri, q931_call *c, int channel);
1666
1667 +extern int q931_retrieve_reject(struct pri *pri, q931_call *c);
1668 +
1669 +extern int q931_suspend_acknowledge(struct pri *pri, q931_call *c, char *display);
1670 +
1671 +extern int q931_suspend_reject(struct pri *pri, q931_call *c, char *display);
1672 +
1673 +extern int q931_resume_reject(struct pri *pri, q931_call *c, char *display);
1674 +
1675 +extern int q931_resume_acknowledge(struct pri *pri, q931_call *c, int channel, char *display);
1676 +
1677 +//extern int q931_facility(struct pri *pri, q931_call *c, int operation, char *arguments);
1678 +
1679 #endif
1680 diff -urN libpri-1.2.3.orig/pri_timers.h libpri-1.2.3/pri_timers.h
1681 --- libpri-1.2.3.orig/pri_timers.h 2005-11-29 19:39:18.000000000 +0100
1682 +++ libpri-1.2.3/pri_timers.h 2006-01-18 12:28:07.000000000 +0100
1683 @@ -27,17 +27,17 @@
1684
1685 /* -1 means we dont currently support the timer/counter */
1686 #define PRI_TIMERS_DEFAULT { 3, /* N200 */ \
1687 - -1, /* N201 */ \
1688 - -1, /* N202 */ \
1689 + 260, /* N201 */ \
1690 + 3, /* N202 */ \
1691 7, /* K */ \
1692 1000, /* T200 */ \
1693 - -1, /* T201 */ \
1694 - -1, /* T202 */ \
1695 + 2000, /* T201 */ \
1696 + 5000, /* T202 */ \
1697 10000, /* T203 */ \
1698 -1, /* T300 */ \
1699 -1, /* T301 */ \
1700 -1, /* T302 */ \
1701 - -1, /* T303 */ \
1702 + 4000, /* T303 */ \
1703 -1, /* T304 */ \
1704 30000, /* T305 */ \
1705 -1, /* T306 */ \
1706 diff -urN libpri-1.2.3.orig/pridump.c libpri-1.2.3/pridump.c
1707 --- libpri-1.2.3.orig/pridump.c 2005-11-29 19:39:18.000000000 +0100
1708 +++ libpri-1.2.3/pridump.c 2006-01-18 12:28:07.000000000 +0100
1709 @@ -1,9 +1,9 @@
1710 /*
1711 * libpri: An implementation of Primary Rate ISDN
1712 *
1713 - * Written by Mark Spencer <markster@digium.com>
1714 + * Written by Mark Spencer <markster@linux-support.net>
1715 *
1716 - * Copyright (C) 2001-2005, Digium
1717 + * Copyright (C) 2001, Linux Support Services, Inc.
1718 * All Rights Reserved.
1719 *
1720 * This program is free software; you can redistribute it and/or modify
1721 diff -urN libpri-1.2.3.orig/prisched.c libpri-1.2.3/prisched.c
1722 --- libpri-1.2.3.orig/prisched.c 2005-11-29 19:39:18.000000000 +0100
1723 +++ libpri-1.2.3/prisched.c 2006-04-15 21:57:42.000000000 +0200
1724 @@ -1,10 +1,12 @@
1725 /*
1726 * libpri: An implementation of Primary Rate ISDN
1727 *
1728 - * Written by Mark Spencer <markster@digium.com>
1729 + * Written by Mark Spencer <markster@linux-support.net>
1730 *
1731 - * Copyright (C) 2001-2005, Digium
1732 + * Copyright (C) 2001, Linux Support Services, Inc.
1733 * All Rights Reserved.
1734 + * Copyright (C) 2003-2006 Junghanns.NET GmbH
1735 + * Klaus-Peter Junghanns <kpj@junghanns.net>
1736 *
1737 * This program is free software; you can redistribute it and/or modify
1738 * it under the terms of the GNU General Public License as published by
1739 @@ -22,10 +24,9 @@
1740 *
1741 */
1742
1743 -#include <stdio.h>
1744 -
1745 #include "libpri.h"
1746 #include "pri_internal.h"
1747 +#include <stdio.h>
1748
1749
1750 static int maxsched = 0;
1751 @@ -36,7 +37,7 @@
1752 int x;
1753 struct timeval tv;
1754 for (x=1;x<MAX_SCHED;x++)
1755 - if (!pri->pri_sched[x].callback)
1756 + if ((!pri->pri_sched[x].callback2) && (!pri->pri_sched[x].callback))
1757 break;
1758 if (x == MAX_SCHED) {
1759 pri_error(pri, "No more room in scheduler\n");
1760 @@ -53,7 +54,39 @@
1761 }
1762 pri->pri_sched[x].when = tv;
1763 pri->pri_sched[x].callback = function;
1764 + pri->pri_sched[x].callback2 = NULL;
1765 pri->pri_sched[x].data = data;
1766 + pri->pri_sched[x].hasdata2 = 0;
1767 + pri->pri_sched[x].data2 = 0;
1768 + return x;
1769 +}
1770 +
1771 +int pri_schedule_event2(struct pri *pri, int ms, void (*function)(void *data, int data2), void *data, int data2)
1772 +{
1773 + int x;
1774 + struct timeval tv;
1775 + for (x=1;x<MAX_SCHED;x++)
1776 + if ((!pri->pri_sched[x].callback2) && (!pri->pri_sched[x].callback))
1777 + break;
1778 + if (x == MAX_SCHED) {
1779 + pri_error(pri, "No more room in scheduler\n");
1780 + return -1;
1781 + }
1782 + if (x > maxsched)
1783 + maxsched = x;
1784 + gettimeofday(&tv, NULL);
1785 + tv.tv_sec += ms / 1000;
1786 + tv.tv_usec += (ms % 1000) * 1000;
1787 + if (tv.tv_usec > 1000000) {
1788 + tv.tv_usec -= 1000000;
1789 + tv.tv_sec += 1;
1790 + }
1791 + pri->pri_sched[x].when = tv;
1792 + pri->pri_sched[x].callback = NULL;
1793 + pri->pri_sched[x].callback2 = function;
1794 + pri->pri_sched[x].data = data;
1795 + pri->pri_sched[x].hasdata2 = 1;
1796 + pri->pri_sched[x].data2 = data2;
1797 return x;
1798 }
1799
1800 @@ -65,7 +98,7 @@
1801 if (pri->subchannel)
1802 closest = pri_schedule_next(pri->subchannel);
1803 for (x=1;x<MAX_SCHED;x++) {
1804 - if (pri->pri_sched[x].callback &&
1805 + if ((pri->pri_sched[x].callback || pri->pri_sched[x].callback2) &&
1806 (!closest || (closest->tv_sec > pri->pri_sched[x].when.tv_sec) ||
1807 ((closest->tv_sec == pri->pri_sched[x].when.tv_sec) &&
1808 (closest->tv_usec > pri->pri_sched[x].when.tv_usec))))
1809 @@ -76,26 +109,38 @@
1810
1811 static pri_event *__pri_schedule_run(struct pri *pri, struct timeval *tv)
1812 {
1813 - int x;
1814 - void (*callback)(void *);
1815 - void *data;
1816 + int x;
1817 + void (*callback)(void *);
1818 + void (*callback2)(void *, int);
1819 + void *data;
1820 + int data2;
1821 pri_event *e;
1822 +
1823 if (pri->subchannel) {
1824 if ((e = __pri_schedule_run(pri->subchannel, tv))) {
1825 return e;
1826 }
1827 }
1828 for (x=1;x<MAX_SCHED;x++) {
1829 - if (pri->pri_sched[x].callback &&
1830 + if ((pri->pri_sched[x].callback || pri->pri_sched[x].callback2) &&
1831 ((pri->pri_sched[x].when.tv_sec < tv->tv_sec) ||
1832 ((pri->pri_sched[x].when.tv_sec == tv->tv_sec) &&
1833 (pri->pri_sched[x].when.tv_usec <= tv->tv_usec)))) {
1834 pri->schedev = 0;
1835 callback = pri->pri_sched[x].callback;
1836 + callback2 = pri->pri_sched[x].callback2;
1837 data = pri->pri_sched[x].data;
1838 + data2 = pri->pri_sched[x].data2;
1839 pri->pri_sched[x].callback = NULL;
1840 + pri->pri_sched[x].callback2 = NULL;
1841 pri->pri_sched[x].data = NULL;
1842 - callback(data);
1843 + pri->pri_sched[x].data2 = 0;
1844 + if (pri->pri_sched[x].hasdata2 == 1) {
1845 + pri->pri_sched[x].hasdata2 = 0;
1846 + callback2(data, data2);
1847 + } else {
1848 + callback(data);
1849 + }
1850 if (pri->schedev)
1851 return &pri->ev;
1852 }
1853 @@ -116,4 +161,6 @@
1854 if ((id >= MAX_SCHED) || (id < 0))
1855 pri_error(pri, "Asked to delete sched id %d???\n", id);
1856 pri->pri_sched[id].callback = NULL;
1857 + pri->pri_sched[id].callback2 = NULL;
1858 }
1859 +
1860 diff -urN libpri-1.2.3.orig/pritest.c libpri-1.2.3/pritest.c
1861 --- libpri-1.2.3.orig/pritest.c 2005-11-29 19:39:18.000000000 +0100
1862 +++ libpri-1.2.3/pritest.c 2006-01-18 12:28:07.000000000 +0100
1863 @@ -1,9 +1,9 @@
1864 /*
1865 * libpri: An implementation of Primary Rate ISDN
1866 *
1867 - * Written by Mark Spencer <markster@digium.com>
1868 + * Written by Mark Spencer <markster@linux-support.net>
1869 *
1870 - * Copyright (C) 2001-2005, Digium
1871 + * Copyright (C) 2001, Linux Support Services, Inc.
1872 * All Rights Reserved.
1873 *
1874 * This program is free software; you can redistribute it and/or modify
1875 @@ -51,8 +51,8 @@
1876 #define PRI_DEF_NODETYPE PRI_CPE
1877 #define PRI_DEF_SWITCHTYPE PRI_SWITCH_NI2
1878
1879 -#define MAX_CHAN 32
1880 -#define DCHANNEL_TIMESLOT 16
1881 +#define MAX_CHAN 3
1882 +#define DCHANNEL_TIMESLOT 3
1883
1884
1885 static int offset = 0;
1886 @@ -60,7 +60,7 @@
1887 static void do_channel(ZAP *z)
1888 {
1889 /* This is the part that runs on a given channel */
1890 - zap_playf(z, "raw.ulaw", 0);
1891 + zap_playf(z, "raw.alaw", 0);
1892 }
1893
1894 struct pri_chan {
1895 @@ -76,6 +76,14 @@
1896 return PRI_CPE;
1897 if (!strcasecmp(node, "network"))
1898 return PRI_NETWORK;
1899 + if (!strcasecmp(node, "bri_cpe_ptmp"))
1900 + return BRI_CPE_PTMP;
1901 + if (!strcasecmp(node, "bri_network_ptmp"))
1902 + return BRI_NETWORK_PTMP;
1903 + if (!strcasecmp(node, "bri_cpe"))
1904 + return BRI_CPE;
1905 + if (!strcasecmp(node, "bri_network"))
1906 + return BRI_NETWORK;
1907 return -1;
1908 }
1909
1910 @@ -285,6 +293,10 @@
1911 }
1912
1913 break;
1914 + case PRI_EVENT_HANGUP_REQ:
1915 + printf("-- Hanging up channel %d\n", e->hangup.channel);
1916 + hangup_channel(e->hangup.channel);
1917 + break;
1918 default:
1919 fprintf(stderr, "--!! Unknown PRI event %d\n", e->e);
1920 }
1921 diff -urN libpri-1.2.3.orig/q921.c libpri-1.2.3/q921.c
1922 --- libpri-1.2.3.orig/q921.c 2005-12-06 22:35:50.000000000 +0100
1923 +++ libpri-1.2.3/q921.c 2006-08-01 09:55:53.000000000 +0200
1924 @@ -1,10 +1,12 @@
1925 /*
1926 * libpri: An implementation of Primary Rate ISDN
1927 *
1928 - * Written by Mark Spencer <markster@digium.com>
1929 + * Written by Mark Spencer <markster@linux-support.net>
1930 *
1931 - * Copyright (C) 2001-2005, Digium
1932 + * Copyright (C) 2001, Linux Support Services, Inc.
1933 * All Rights Reserved.
1934 + * Copyright (C) 2003-2006 Junghanns.NET GmbH
1935 + * Klaus-Peter Junghanns <kpj@junghanns.net>
1936 *
1937 * This program is free software; you can redistribute it and/or modify
1938 * it under the terms of the GNU General Public License as published by
1939 @@ -21,7 +23,7 @@
1940 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
1941 *
1942 */
1943 -
1944 +
1945 #include <stdio.h>
1946 #include <string.h>
1947 #include <stdlib.h>
1948 @@ -50,19 +52,24 @@
1949 (hf).h.tei = (pri)->tei; \
1950 } while(0)
1951
1952 -static void reschedule_t203(struct pri *pri);
1953 +static void reschedule_t203(struct pri *pri, int tei);
1954 +static void q921_flush_txqueue(struct pri *pri, int tei, int devnull);
1955 +static void q921_send_teiverify(struct pri *pri,int tei);
1956
1957 -static void q921_discard_retransmissions(struct pri *pri)
1958 +static void q921_discard_retransmissions(struct pri *pri, int tei)
1959 {
1960 struct q921_frame *f, *p;
1961 - f = pri->txqueue;
1962 + int teio = tei - Q921_TEI_BASE;
1963 + if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
1964 +
1965 + f = pri->txqueue[teio];
1966 while(f) {
1967 - p = f;
1968 - f = f->next;
1969 - /* Free frame */
1970 - free(p);
1971 + p = f;
1972 + f = f->next;
1973 + /* Free frame */
1974 + free(p);
1975 }
1976 - pri->txqueue = NULL;
1977 + pri->txqueue[teio] = NULL;
1978 }
1979
1980 static int q921_transmit(struct pri *pri, q921_h *h, int len)
1981 @@ -88,11 +95,15 @@
1982 pri_error(pri, "Short write: %d/%d (%s)\n", res, len + 2, strerror(errno));
1983 return -1;
1984 }
1985 - reschedule_t203(pri);
1986 + if (pri->localtype == BRI_CPE_PTMP) {
1987 + reschedule_t203(pri, pri->tei);
1988 + } else if (h->h.tei != Q921_TEI_GROUP) {
1989 + reschedule_t203(pri, h->h.tei);
1990 + }
1991 return 0;
1992 }
1993
1994 -static void q921_send_ua(struct pri *pri, int pfbit)
1995 +static void q921_send_ua(struct pri *pri, int pfbit, int tei)
1996 {
1997 q921_h h;
1998 Q921_INIT(pri, h);
1999 @@ -100,6 +111,7 @@
2000 h.u.m2 = 0; /* M2 = 0 */
2001 h.u.p_f = pfbit; /* Final bit on */
2002 h.u.ft = Q921_FRAMETYPE_U;
2003 + h.h.tei = tei;
2004 switch(pri->localtype) {
2005 case PRI_NETWORK:
2006 h.h.c_r = 0;
2007 @@ -107,6 +119,19 @@
2008 case PRI_CPE:
2009 h.h.c_r = 1;
2010 break;
2011 + case BRI_NETWORK_PTMP:
2012 + h.h.c_r = 0;
2013 + break;
2014 + case BRI_CPE_PTMP:
2015 + h.h.tei = pri->tei;
2016 + h.h.c_r = 1;
2017 + break;
2018 + case BRI_NETWORK:
2019 + h.h.c_r = 0;
2020 + break;
2021 + case BRI_CPE:
2022 + h.h.c_r = 1;
2023 + break;
2024 default:
2025 pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype);
2026 return;
2027 @@ -116,18 +141,364 @@
2028 q921_transmit(pri, &h, 3);
2029 }
2030
2031 -static void q921_send_sabme_now(void *vpri);
2032 +/*
2033 +static void q921_send_disconnect(struct pri *pri, int pfbit, int tei) {
2034 + q921_h h;
2035 + Q921_INIT(pri, h);
2036 + h.u.m3 = 2;
2037 + h.u.m2 = 0;
2038 + h.u.p_f = pfbit;
2039 + h.u.ft = Q921_FRAMETYPE_U;
2040 + h.h.tei = tei;
2041 + switch(pri->localtype) {
2042 + case PRI_NETWORK:
2043 + h.h.c_r = 0;
2044 + break;
2045 + case PRI_CPE:
2046 + h.h.c_r = 1;
2047 + break;
2048 + case BRI_NETWORK_PTMP:
2049 + h.h.c_r = 0;
2050 + break;
2051 + case BRI_CPE_PTMP:
2052 + h.h.tei = pri->tei;
2053 + h.h.c_r = 1;
2054 + break;
2055 + case BRI_NETWORK:
2056 + h.h.c_r = 0;
2057 + break;
2058 + case BRI_CPE:
2059 + h.h.c_r = 1;
2060 + break;
2061 + default:
2062 + pri_error(pri, "Don't know how to disconnect on a type %d node\n", pri->localtype);
2063 + return;
2064 + }
2065 + if (pri->debug & PRI_DEBUG_Q921_STATE)
2066 + pri_message(pri, "Sending Disconnect\n");
2067 + q921_transmit(pri, &h, 3);
2068 + }
2069 +*/
2070
2071 -static void q921_send_sabme(void *vpri, int now)
2072 +static void q921_send_dm(struct pri *pri, int pfbit, int tei)
2073 +{
2074 + q921_h h;
2075 + Q921_INIT(pri, h);
2076 + h.u.m3 = 0; /* M3 = 0 */
2077 + h.u.m2 = 3; /* M2 = 3 */
2078 + h.u.p_f = pfbit; /* Final bit on */
2079 + h.u.ft = Q921_FRAMETYPE_U;
2080 + h.h.tei = tei;
2081 + switch(pri->localtype) {
2082 + case PRI_NETWORK:
2083 + h.h.c_r = 0;
2084 + break;
2085 + case PRI_CPE:
2086 + h.h.c_r = 1;
2087 + break;
2088 + case BRI_NETWORK_PTMP:
2089 + h.h.c_r = 0;
2090 + break;
2091 + case BRI_CPE_PTMP:
2092 + h.h.tei = pri->tei;
2093 + h.h.c_r = 1;
2094 + break;
2095 + case BRI_NETWORK:
2096 + h.h.c_r = 0;
2097 + break;
2098 + case BRI_CPE:
2099 + h.h.c_r = 1;
2100 + break;
2101 + default:
2102 + pri_error(pri, "Don't know how to DM on a type %d node\n", pri->localtype);
2103 + return;
2104 + }
2105 + if (pri->debug & PRI_DEBUG_Q921_STATE)
2106 + pri_message(pri, "Sending DM\n");
2107 + q921_transmit(pri, &h, 3);
2108 +}
2109 +
2110 +static void q921_send_teireq(void *vpri) {
2111 + struct pri *pri = vpri;
2112 + unsigned short ri=0x6464;
2113 + q921_u *f;
2114 + ri = rand();
2115 +
2116 + if (pri->localtype != BRI_CPE_PTMP) {
2117 + pri_error(pri, "TEI req for non-ptmp???\n");
2118 + return;
2119 + }
2120 + if (pri->t202_timer[0]) {
2121 + pri_schedule_del(pri, pri->t202_timer[0]);
2122 + pri->t202_timer[0] = 0;
2123 + }
2124 + if (pri->sabme_retrans[0]++ > (pri->timers[PRI_TIMER_N202])) {
2125 + /* delete txqueue */
2126 + q921_flush_txqueue(pri, 0, 1);
2127 + /* N202 retransmissions, activation of layer 2 failed, tell upper layer, start again */
2128 + pri->schedev = 1;
2129 + pri->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
2130 + pri->ev.gen.tei = 0;
2131 + pri->sabme_retrans[0] = 0;
2132 + q921_send_teiverify(pri, 127);
2133 +#ifdef RELAX_TRB
2134 + pri->t202_timer[0] = pri_schedule_event(pri, pri->timers[PRI_TIMER_T202] + 3000, q921_send_teireq, pri);
2135 +#endif
2136 + return;
2137 + }
2138 +
2139 + pri->t202_timer[0] = pri_schedule_event(pri, pri->timers[PRI_TIMER_T202], q921_send_teireq, pri);
2140 +
2141 + pri->ri = ri;
2142 + f = malloc(sizeof(q921_u) + 5 + 2);
2143 + memset(f,0x0,sizeof(q921_u) + 5 + 2);
2144 + if (f) {
2145 + f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
2146 + f->h.tei = Q921_TEI_GROUP;
2147 + f->h.c_r = 0;
2148 + f->h.ea1 = 0;
2149 + f->h.ea2 = 1;
2150 + f->m2 = 0;
2151 + f->m3 = 0;
2152 + f->ft = Q921_FRAMETYPE_U;
2153 + f->data[0] = 0xf;
2154 + f->data[1] = ri >> 8;
2155 + f->data[2] = ri & 0xff;
2156 + f->data[3] = Q921_TEI_ID_REQUEST;
2157 + f->data[4] = 0xff;
2158 + if (pri->debug & PRI_DEBUG_Q921_STATE)
2159 + pri_message(pri, "Sending TEI Request ri=%d\n",ri);
2160 + q921_transmit(pri,(q921_h *)&(f->h),8);
2161 + }
2162 +}
2163 +
2164 +static void q921_send_teiassign(struct pri *pri,int ri,int tei) {
2165 + q921_u *f;
2166 +
2167 + if (pri->localtype != BRI_NETWORK_PTMP) {
2168 + pri_error(pri, "TEI assign for non-ptmp???\n");
2169 + return;
2170 + }
2171 +
2172 + f = malloc(sizeof(q921_u) + 5 + 2);
2173 + memset(f,0x0,sizeof(q921_u) + 5 + 2);
2174 + if (f) {
2175 + f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
2176 + f->h.tei = Q921_TEI_GROUP;
2177 + f->h.c_r = 1;
2178 + f->h.ea1 = 0;
2179 + f->h.ea2 = 1;
2180 + f->m2 = 0;
2181 + f->m3 = 0;
2182 + f->ft = Q921_FRAMETYPE_U;
2183 + f->data[0] = 0xf;
2184 + f->data[1] = ri >> 8;
2185 + f->data[2] = ri & 0xff;
2186 + f->data[3] = Q921_TEI_ID_ASSIGNED;
2187 + f->data[4] = (tei << 1) | 0x1;
2188 + if (pri->debug & PRI_DEBUG_Q921_STATE)
2189 + pri_message(pri, "Sending TEI assign ri=%d tei=%d\n",ri,tei);
2190 + q921_transmit(pri,(q921_h *)&(f->h),8);
2191 + free(f);
2192 + } else {
2193 + pri_error(pri, "q921_send_teiassign: failed to malloc f!\n");
2194 + }
2195 +}
2196 +
2197 +static void q921_send_teichkresp(struct pri *pri,int tei) {
2198 + q921_u *f;
2199 + unsigned short ri=0x6464;
2200 + ri = rand();
2201 +
2202 + if (pri->localtype != BRI_CPE_PTMP) {
2203 + pri_error(pri, "TEI check response for non-ptmp???\n");
2204 + return;
2205 + }
2206 +
2207 + f = malloc(sizeof(q921_u) + 5 + 2);
2208 + memset(f,0x0,sizeof(q921_u) + 5 + 2);
2209 + if (f) {
2210 + f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
2211 + f->h.tei = Q921_TEI_GROUP;
2212 + f->h.c_r = 0; // command u->n
2213 + f->h.ea1 = 0;
2214 + f->h.ea2 = 1;
2215 + f->m2 = 0;
2216 + f->m3 = 0;
2217 + f->ft = Q921_FRAMETYPE_U;
2218 + f->data[0] = 0xf;
2219 + f->data[1] = ri >> 8;
2220 + f->data[2] = ri & 0xff;
2221 + f->data[3] = Q921_TEI_ID_CHK_RES;
2222 + f->data[4] = (tei << 1) | 0x1;
2223 + if (pri->debug & PRI_DEBUG_Q921_STATE)
2224 + pri_message(pri, "Sending TEI check resp ri=%d tei=%d\n",ri,tei);
2225 + q921_transmit(pri,(q921_h *)&(f->h),8);
2226 + free(f);
2227 + }
2228 +}
2229 +
2230 +static void q921_send_teichkreq(struct pri *pri,int tei) {
2231 + q921_u *f;
2232 + unsigned short ri=0x6464;
2233 + ri = rand();
2234 +
2235 + if (pri->localtype != BRI_NETWORK_PTMP) {
2236 + pri_error(pri, "TEI check response for non-ptmp???\n");
2237 + return;
2238 + }
2239 +
2240 + f = malloc(sizeof(q921_u) + 5 + 2);
2241 + memset(f,0x0,sizeof(q921_u) + 5 + 2);
2242 + if (f) {
2243 + f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
2244 + f->h.tei = Q921_TEI_GROUP;
2245 + f->h.c_r = 1; // command u->n
2246 + f->h.ea1 = 0;
2247 + f->h.ea2 = 1;
2248 + f->m2 = 0;
2249 + f->m3 = 0;
2250 + f->ft = Q921_FRAMETYPE_U;
2251 + f->data[0] = 0xf;
2252 + f->data[1] = 0;
2253 + f->data[2] = 0;
2254 + f->data[3] = Q921_TEI_ID_CHK_REQ;
2255 + f->data[4] = (tei << 1) | 0x1;
2256 + if (pri->debug & PRI_DEBUG_Q921_STATE)
2257 + pri_message(pri, "Sending TEI check request ri=%d tei=%d\n",ri,tei);
2258 + q921_transmit(pri,(q921_h *)&(f->h),8);
2259 + free(f);
2260 + }
2261 +}
2262 +
2263 +static void q921_send_teiverify(struct pri *pri,int tei) {
2264 + q921_u *f;
2265 +
2266 + if ((pri->localtype != BRI_CPE) && (pri->localtype != BRI_CPE_PTMP)) {
2267 + pri_error(pri, "TEI verify for non-ptmp???\n");
2268 + return;
2269 + }
2270 +
2271 + f = malloc(sizeof(q921_u) + 5 + 2);
2272 + memset(f,0x0,sizeof(q921_u) + 5 + 2);
2273 + if (f) {
2274 + f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
2275 + f->h.tei = Q921_TEI_GROUP;
2276 + f->h.c_r = 0; // command u->n
2277 + f->h.ea1 = 0;
2278 + f->h.ea2 = 1;
2279 + f->m2 = 0;
2280 + f->m3 = 0;
2281 + f->ft = Q921_FRAMETYPE_U;
2282 + f->data[0] = 0xf;
2283 + f->data[1] = 0;
2284 + f->data[2] = 0;
2285 + f->data[3] = Q921_TEI_ID_VERIFY;
2286 + f->data[4] = (tei << 1) | 0x1;
2287 + if (pri->debug & PRI_DEBUG_Q921_STATE)
2288 + pri_message(pri, "Sending TEI verify tei=%d\n", tei);
2289 + q921_transmit(pri,(q921_h *)&(f->h),8);
2290 + free(f);
2291 + }
2292 +}
2293 +
2294 + static void q921_send_teiremove(struct pri *pri, int tei) {
2295 + q921_u *f;
2296 + unsigned short ri=0x6464;
2297 + ri = rand();
2298 +
2299 + if (pri->localtype != BRI_NETWORK_PTMP) {
2300 + pri_error(pri, "TEI remove for non-ptmp???\n");
2301 + return;
2302 + }
2303 +
2304 + f = malloc(sizeof(q921_u) + 5 + 2);
2305 + memset(f,0x0,sizeof(q921_u) + 5 + 2);
2306 + if (f) {
2307 + f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
2308 + f->h.tei = Q921_TEI_GROUP;
2309 + f->h.c_r = 1;
2310 + f->h.ea1 = 0;
2311 + f->h.ea2 = 1;
2312 + f->m2 = 0;
2313 + f->m3 = 0;
2314 + f->ft = Q921_FRAMETYPE_U;
2315 + f->data[0] = 0xf;
2316 + f->data[1] = ri >> 8;
2317 + f->data[2] = ri & 0xff;
2318 + f->data[3] = Q921_TEI_ID_REMOVE;
2319 + f->data[4] = (tei << 1) | 0x1;
2320 + if (pri->debug & PRI_DEBUG_Q921_STATE)
2321 + pri_message(pri, "Sending TEI remove tei=%d\n",tei);
2322 + q921_transmit(pri,(q921_h *)&(f->h),8);
2323 + free(f);
2324 + }
2325 + }
2326 +
2327 + static void q921_send_teidenied(struct pri *pri, int ri, int tei) {
2328 + q921_u *f;
2329 +
2330 + if (pri->localtype != BRI_NETWORK_PTMP) {
2331 + pri_error(pri, "TEI ID denied for non-ptmp???\n");
2332 + return;
2333 + }
2334 +
2335 + f = malloc(sizeof(q921_u) + 5 + 2);
2336 + memset(f,0x0,sizeof(q921_u) + 5 + 2);
2337 + if (f) {
2338 + f->h.sapi = Q921_SAPI_LAYER2_MANAGEMENT;
2339 + f->h.tei = Q921_TEI_GROUP;
2340 + f->h.c_r = 1;
2341 + f->h.ea1 = 0;
2342 + f->h.ea2 = 1;
2343 + f->m2 = 0;
2344 + f->m3 = 0;
2345 + f->ft = Q921_FRAMETYPE_U;
2346 + f->data[0] = 0xf;
2347 + f->data[1] = ri >> 8;
2348 + f->data[2] = ri & 0xff;
2349 + f->data[3] = Q921_TEI_ID_DENIED;
2350 + f->data[4] = (tei << 1) | 0x1;
2351 + if (pri->debug & PRI_DEBUG_Q921_STATE)
2352 + pri_message(pri, "Sending TEI ID denied tei=%d\n",tei);
2353 + q921_transmit(pri,(q921_h *)&(f->h),8);
2354 + free(f);
2355 + }
2356 + }
2357 +
2358 +
2359 +static void q921_send_sabme_now(void *vpri, int tei);
2360 +
2361 +static void q921_send_sabme(void *vpri, int now, int tei)
2362 {
2363 struct pri *pri = vpri;
2364 q921_h h;
2365 - pri_schedule_del(pri, pri->sabme_timer);
2366 - pri->sabme_timer = 0;
2367 - pri->sabme_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], q921_send_sabme_now, pri);
2368 + int teio=tei - Q921_TEI_BASE;
2369 + if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
2370 +
2371 + if (pri->sabme_timer[teio]) {
2372 + pri_schedule_del(pri, pri->sabme_timer[teio]);
2373 + pri->sabme_timer[teio] = 0;
2374 + }
2375 + pri->sabme_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200], q921_send_sabme_now, pri, tei);
2376 if (!now)
2377 return;
2378 + if (pri->sabme_retrans[teio]++ > (pri->timers[PRI_TIMER_N202])) {
2379 + /* delete txqueue */
2380 + q921_flush_txqueue(pri, tei, 1);
2381 + /* N202 retransmissions, activation of layer 2 failed, tell upper layer, start again */
2382 + pri->schedev = 1;
2383 + pri->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
2384 + pri->ev.gen.tei = tei;
2385 + pri->sabme_retrans[teio] = 0;
2386 +#ifdef RELAX_TRB
2387 + pri->sabme_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200] + 3000, q921_send_sabme_now, pri, tei);
2388 +#endif
2389 + return;
2390 + }
2391 Q921_INIT(pri, h);
2392 + // XXX
2393 + h.h.tei = tei;
2394 h.u.m3 = 3; /* M3 = 3 */
2395 h.u.m2 = 3; /* M2 = 3 */
2396 h.u.p_f = 1; /* Poll bit set */
2397 @@ -139,25 +510,42 @@
2398 case PRI_CPE:
2399 h.h.c_r = 0;
2400 break;
2401 + case BRI_NETWORK_PTMP:
2402 + h.h.c_r = 1;
2403 + break;
2404 + case BRI_CPE_PTMP:
2405 + h.h.c_r = 0;
2406 + h.h.tei = pri->tei;
2407 + break;
2408 + case BRI_NETWORK:
2409 + h.h.c_r = 1;
2410 + break;
2411 + case BRI_CPE:
2412 + h.h.c_r = 0;
2413 + break;
2414 default:
2415 - pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype);
2416 + pri_error(pri, "Don't know how to send SABME on a type %d node\n", pri->localtype);
2417 return;
2418 }
2419 if (pri->debug & PRI_DEBUG_Q921_STATE)
2420 pri_message(pri, "Sending Set Asynchronous Balanced Mode Extended\n");
2421 q921_transmit(pri, &h, 3);
2422 - pri->q921_state = Q921_AWAITING_ESTABLISH;
2423 + pri->q921_state[teio] = Q921_AWAITING_ESTABLISH;
2424 }
2425
2426 -static void q921_send_sabme_now(void *vpri)
2427 +static void q921_send_sabme_now(void *vpri, int tei)
2428 {
2429 - q921_send_sabme(vpri, 1);
2430 + q921_send_sabme(vpri, 1, tei);
2431 }
2432
2433 -static int q921_ack_packet(struct pri *pri, int num)
2434 +
2435 +
2436 +static int q921_ack_packet(struct pri *pri, int num, int tei)
2437 {
2438 struct q921_frame *f, *prev = NULL;
2439 - f = pri->txqueue;
2440 + int teio=tei - Q921_TEI_BASE;
2441 + if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
2442 + f = pri->txqueue[teio];
2443 while(f) {
2444 if (f->h.n_s == num) {
2445 /* Cancel each packet as necessary */
2446 @@ -165,26 +553,26 @@
2447 if (prev)
2448 prev->next = f->next;
2449 else
2450 - pri->txqueue = f->next;
2451 + pri->txqueue[teio] = f->next;
2452 if (pri->debug & PRI_DEBUG_Q921_STATE)
2453 - pri_message(pri, "-- ACKing packet %d, new txqueue is %d (-1 means empty)\n", f->h.n_s, pri->txqueue ? pri->txqueue->h.n_s : -1);
2454 + pri_message(pri, "-- 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);
2455 /* Update v_a */
2456 - pri->v_a = num;
2457 + pri->v_a[teio] = num;
2458 free(f);
2459 /* Reset retransmission counter if we actually acked something */
2460 - pri->retrans = 0;
2461 + pri->retrans[teio] = 0;
2462 /* Decrement window size */
2463 - pri->windowlen--;
2464 + pri->windowlen[teio]--;
2465 /* Search for something to send */
2466 - f = pri->txqueue;
2467 + f = pri->txqueue[teio];
2468 while(f) {
2469 if (!f->transmitted) {
2470 /* Send it now... */
2471 if (pri->debug & PRI_DEBUG_Q921_STATE)
2472 pri_message(pri, "-- Finally transmitting %d, since window opened up\n", f->h.n_s);
2473 f->transmitted++;
2474 - pri->windowlen++;
2475 - f->h.n_r = pri->v_r;
2476 + pri->windowlen[teio]++;
2477 + f->h.n_r = pri->v_r[teio];
2478 q921_transmit(pri, (q921_h *)(&f->h), f->len);
2479 break;
2480 }
2481 @@ -198,77 +586,136 @@
2482 return 0;
2483 }
2484
2485 -static void t203_expire(void *);
2486 -static void t200_expire(void *);
2487 -static pri_event *q921_dchannel_down(struct pri *pri);
2488 +static void t203_expire(void *, int tei);
2489 +static void t200_expire(void *, int tei);
2490 +static pri_event *q921_dchannel_down(struct pri *pri, int tei);
2491 +
2492 +static void reschedule_t203(struct pri *pri, int tei)
2493 +{
2494 + int teio=tei - Q921_TEI_BASE;
2495 + if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
2496 + if (pri->t203_timer[teio]) {
2497 + pri_schedule_del(pri, pri->t203_timer[teio]);
2498 + pri->t203_timer[teio] = 0;
2499 + if (pri->q921_state[teio] != Q921_LINK_CONNECTION_RELEASED) {
2500 + if (pri->debug & PRI_DEBUG_Q921_STATE)
2501 + pri_message(pri, "-- Restarting T203 counter\n");
2502 + /* Nothing to transmit, start the T203 counter instead */
2503 + pri->t203_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri, tei);
2504 + }
2505 + }
2506 +}
2507
2508 -static void reschedule_t203(struct pri *pri)
2509 +static void q921_flush_txqueue(struct pri *pri, int tei, int devnull)
2510 {
2511 - if (pri->t203_timer) {
2512 - pri_schedule_del(pri, pri->t203_timer);
2513 - if (pri->debug & PRI_DEBUG_Q921_STATE)
2514 - pri_message(pri, "-- Restarting T203 counter\n");
2515 - /* Nothing to transmit, start the T203 counter instead */
2516 - pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
2517 + struct q921_frame *f, *tmp = NULL;
2518 + int teio=tei - Q921_TEI_BASE;
2519 + if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
2520 + f = pri->txqueue[teio];
2521 +
2522 + /* nothing to send */
2523 + if (!f) return;
2524 +
2525 + /* transmit all i-frames that were queued up while we were waiting for layer 2 to rise */
2526 + while(f) {
2527 + if (devnull) {
2528 + tmp = f;
2529 + f = f->next;
2530 + free(tmp);
2531 + tmp = NULL;
2532 + } else {
2533 + if (pri->localtype == BRI_CPE_PTMP) {
2534 + /* update TEI, it might have changed */
2535 + f->h.h.tei = pri->tei;
2536 + }
2537 + q921_transmit(pri, (q921_h *)&f->h, f->len);
2538 + f->transmitted++;
2539 + f = f->next;
2540 + }
2541 + }
2542 +
2543 + if (devnull) {
2544 + pri->txqueue[teio] = NULL;
2545 + pri->v_s[teio] = 0;
2546 + } else {
2547 + if (pri->t200_timer[teio]) {
2548 + pri_schedule_del(pri, pri->t200_timer[teio]);
2549 + pri->t200_timer[teio] = 0;
2550 + }
2551 + if (pri->t203_timer[teio]) {
2552 + pri_schedule_del(pri, pri->t203_timer[teio]);
2553 + pri->t203_timer[teio] = 0;
2554 + }
2555 + pri->t200_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri, tei);
2556 }
2557 }
2558
2559 -static pri_event *q921_ack_rx(struct pri *pri, int ack)
2560 +static pri_event *q921_ack_rx(struct pri *pri, int ack, int tei)
2561 {
2562 int x;
2563 int cnt=0;
2564 pri_event *ev;
2565 + int teio=tei - Q921_TEI_BASE;
2566 + if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
2567 /* Make sure the ACK was within our window */
2568 - for (x=pri->v_a; (x != pri->v_s) && (x != ack); Q921_INC(x));
2569 + for (x=pri->v_a[teio]; (x != pri->v_s[teio]) && (x != ack); Q921_INC(x));
2570 if (x != ack) {
2571 /* ACK was outside of our window --- ignore */
2572 - pri_error(pri, "ACK received for '%d' outside of window of '%d' to '%d', restarting\n", ack, pri->v_a, pri->v_s);
2573 - ev = q921_dchannel_down(pri);
2574 - q921_start(pri, 1);
2575 + pri_error(pri, "ACK received for '%d' outside of window of '%d' to '%d', restarting\n", ack, pri->v_a[teio], pri->v_s[teio]);
2576 + ev = q921_dchannel_down(pri, tei);
2577 + q921_start(pri, 1, tei);
2578 pri->schedev = 1;
2579 return ev;
2580 }
2581 /* Cancel each packet as necessary */
2582 if (pri->debug & PRI_DEBUG_Q921_STATE)
2583 - pri_message(pri, "-- ACKing all packets from %d to (but not including) %d\n", pri->v_a, ack);
2584 - for (x=pri->v_a; x != ack; Q921_INC(x))
2585 - cnt += q921_ack_packet(pri, x);
2586 - if (!pri->txqueue) {
2587 + pri_message(pri, "-- ACKing all packets from %d to (but not including) %d\n", pri->v_a[teio], ack);
2588 + for (x=pri->v_a[teio]; x != ack; Q921_INC(x))
2589 + cnt += q921_ack_packet(pri, x, tei);
2590 + if (!pri->txqueue[teio]) {
2591 + /* Something was ACK'd. Stop T200 counter */
2592 + if (pri->t200_timer[teio]) {
2593 + pri_schedule_del(pri, pri->t200_timer[teio]);
2594 + pri->t200_timer[teio] = 0;
2595 + }
2596 if (pri->debug & PRI_DEBUG_Q921_STATE)
2597 pri_message(pri, "-- Since there was nothing left, stopping T200 counter\n");
2598 - /* Something was ACK'd. Stop T200 counter */
2599 - pri_schedule_del(pri, pri->t200_timer);
2600 - pri->t200_timer = 0;
2601 }
2602 - if (pri->t203_timer) {
2603 + if (pri->t203_timer[teio]) {
2604 + pri_schedule_del(pri, pri->t203_timer[teio]);
2605 + pri->t203_timer[teio] = 0;
2606 if (pri->debug & PRI_DEBUG_Q921_STATE)
2607 pri_message(pri, "-- Stopping T203 counter since we got an ACK\n");
2608 - pri_schedule_del(pri, pri->t203_timer);
2609 - pri->t203_timer = 0;
2610 }
2611 - if (pri->txqueue) {
2612 + if (pri->txqueue[teio]) {
2613 /* Something left to transmit, Start the T200 counter again if we stopped it */
2614 + if (pri->t200_timer[teio]) {
2615 + pri_schedule_del(pri, pri->t200_timer[teio]);
2616 + pri->t200_timer[teio] = 0;
2617 + }
2618 if (pri->debug & PRI_DEBUG_Q921_STATE)
2619 - pri_message(pri, "-- Something left to transmit (%d), restarting T200 counter\n", pri->txqueue->h.n_s);
2620 - if (!pri->t200_timer)
2621 - pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
2622 + pri_message(pri, "-- Something left to transmit (%d), restarting T200 counter\n", pri->txqueue[teio]->h.n_s);
2623 + pri->t200_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri, tei);
2624 +
2625 } else {
2626 if (pri->debug & PRI_DEBUG_Q921_STATE)
2627 pri_message(pri, "-- Nothing left, starting T203 counter\n");
2628 /* Nothing to transmit, start the T203 counter instead */
2629 - pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
2630 + pri->t203_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri, tei);
2631 }
2632 return NULL;
2633 }
2634
2635 -static void q921_reject(struct pri *pri, int pf)
2636 +static void q921_reject(struct pri *pri, int pf, int tei)
2637 {
2638 q921_h h;
2639 + int teio=tei - Q921_TEI_BASE;
2640 + if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
2641 Q921_INIT(pri, h);
2642 h.s.x0 = 0; /* Always 0 */
2643 h.s.ss = 2; /* Reject */
2644 h.s.ft = 1; /* Frametype (01) */
2645 - h.s.n_r = pri->v_r; /* Where to start retransmission */
2646 + h.s.n_r = pri->v_r[teio]; /* Where to start retransmission */
2647 h.s.p_f = pf;
2648 switch(pri->localtype) {
2649 case PRI_NETWORK:
2650 @@ -277,23 +724,38 @@
2651 case PRI_CPE:
2652 h.h.c_r = 1;
2653 break;
2654 + case BRI_NETWORK_PTMP:
2655 + h.h.c_r = 0;
2656 + break;
2657 + case BRI_CPE_PTMP:
2658 + h.h.c_r = 1;
2659 + h.h.tei = tei;
2660 + break;
2661 + case BRI_NETWORK:
2662 + h.h.c_r = 0;
2663 + break;
2664 + case BRI_CPE:
2665 + h.h.c_r = 1;
2666 + break;
2667 default:
2668 - pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype);
2669 + pri_error(pri, "Don't know how to REJECT on a type %d node\n", pri->localtype);
2670 return;
2671 }
2672 if (pri->debug & PRI_DEBUG_Q921_STATE)
2673 - pri_message(pri, "Sending Reject (%d)\n", pri->v_r);
2674 - pri->sentrej = 1;
2675 + pri_message(pri, "Sending Reject (%d)\n", pri->v_r[teio]);
2676 + pri->sentrej[teio] = 1;
2677 q921_transmit(pri, &h, 4);
2678 }
2679
2680 -static void q921_rr(struct pri *pri, int pbit, int cmd) {
2681 +static void q921_rr(struct pri *pri, int pbit, int cmd, int tei) {
2682 q921_h h;
2683 + int teio=tei - Q921_TEI_BASE;
2684 + if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
2685 Q921_INIT(pri, h);
2686 h.s.x0 = 0; /* Always 0 */
2687 h.s.ss = 0; /* Receive Ready */
2688 h.s.ft = 1; /* Frametype (01) */
2689 - h.s.n_r = pri->v_r; /* N/R */
2690 + h.s.n_r = pri->v_r[teio]; /* N/R */
2691 h.s.p_f = pbit; /* Poll/Final set appropriately */
2692 switch(pri->localtype) {
2693 case PRI_NETWORK:
2694 @@ -308,81 +770,192 @@
2695 else
2696 h.h.c_r = 1;
2697 break;
2698 + case BRI_NETWORK_PTMP:
2699 + h.h.tei = tei;
2700 + if (cmd)
2701 + h.h.c_r = 1;
2702 + else
2703 + h.h.c_r = 0;
2704 + break;
2705 + case BRI_CPE_PTMP:
2706 + h.h.tei = tei;
2707 + if (cmd)
2708 + h.h.c_r = 0;
2709 + else
2710 + h.h.c_r = 1;
2711 + break;
2712 + case BRI_NETWORK:
2713 + if (cmd)
2714 + h.h.c_r = 1;
2715 + else
2716 + h.h.c_r = 0;
2717 + break;
2718 + case BRI_CPE:
2719 + if (cmd)
2720 + h.h.c_r = 0;
2721 + else
2722 + h.h.c_r = 1;
2723 + break;
2724 default:
2725 - pri_error(pri, "Don't know how to U/A on a type %d node\n", pri->localtype);
2726 + pri_error(pri, "Don't know how to RR on a type %d node\n", pri->localtype);
2727 return;
2728 }
2729 - pri->v_na = pri->v_r; /* Make a note that we've already acked this */
2730 + pri->v_na[teio] = pri->v_r[teio]; /* Make a note that we've already acked this */
2731 if (pri->debug & PRI_DEBUG_Q921_STATE)
2732 - pri_message(pri, "Sending Receiver Ready (%d)\n", pri->v_r);
2733 + pri_message(pri, "Sending Receiver Ready (%d)\n", pri->v_r[teio]);
2734 q921_transmit(pri, &h, 4);
2735 }
2736
2737 -static void t200_expire(void *vpri)
2738 +static void t200_expire(void *vpri, int tei)
2739 {
2740 struct pri *pri = vpri;
2741 - if (pri->txqueue) {
2742 + int teio=tei - Q921_TEI_BASE;
2743 + if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
2744 + if (pri->txqueue[teio]) {
2745 /* Retransmit first packet in the queue, setting the poll bit */
2746 if (pri->debug & PRI_DEBUG_Q921_STATE)
2747 pri_message(pri, "-- T200 counter expired, What to do...\n");
2748 - /* Force Poll bit */
2749 - pri->txqueue->h.p_f = 1;
2750 - /* Update nr */
2751 - pri->txqueue->h.n_r = pri->v_r;
2752 - pri->v_na = pri->v_r;
2753 - pri->solicitfbit = 1;
2754 - pri->retrans++;
2755 + if (pri->txqueue[teio]->transmitted) {
2756 + /* Force Poll bit, if this is a retransmission */
2757 + pri->txqueue[teio]->h.p_f = 1;
2758 + pri->solicitfbit[teio] = 1;
2759 + /* Update nr */
2760 + pri->txqueue[teio]->h.n_r = pri->v_r[teio];
2761 + pri->v_na[teio] = pri->v_r[teio];
2762 + pri->retrans[teio]++;
2763 + }
2764 /* Up to three retransmissions */
2765 - if (pri->retrans < pri->timers[PRI_TIMER_N200]) {
2766 + if ((pri->retrans[teio] + 1) <= pri->timers[PRI_TIMER_N200]) {
2767 /* Reschedule t200_timer */
2768 if (pri->debug & PRI_DEBUG_Q921_STATE)
2769 - pri_message(pri, "-- Retransmitting %d bytes\n", pri->txqueue->len);
2770 - if (pri->busy)
2771 - q921_rr(pri, 1, 1);
2772 - else {
2773 - if (!pri->txqueue->transmitted)
2774 + pri_message(pri, "-- Retransmitting %d bytes\n", pri->txqueue[teio]->len);
2775 + if (pri->busy[teio]) {
2776 + // pri_message(pri, "-- q921_rr(pri, 1, 1) \n", tei);
2777 + q921_rr(pri, 1, 1, tei);
2778 + } else {
2779 + if (!pri->txqueue[teio]->transmitted)
2780 pri_error(pri, "!! Not good - head of queue has not been transmitted yet\n");
2781 - q921_transmit(pri, (q921_h *)&pri->txqueue->h, pri->txqueue->len);
2782 + q921_transmit(pri, (q921_h *)&pri->txqueue[teio]->h, pri->txqueue[teio]->len);
2783 + //layer 3
2784 + pri->txqueue[teio]->transmitted++;
2785 }
2786 if (pri->debug & PRI_DEBUG_Q921_STATE)
2787 - pri_message(pri, "-- Rescheduling retransmission (%d)\n", pri->retrans);
2788 - pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
2789 + pri_message(pri, "-- Rescheduling retransmission (%d)\n", pri->retrans[teio]);
2790 + pri->t200_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri, tei);
2791 } else {
2792 if (pri->debug & PRI_DEBUG_Q921_STATE)
2793 pri_message(pri, "-- Timeout occured, restarting PRI\n");
2794 - pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
2795 - pri->t200_timer = 0;
2796 - q921_dchannel_down(pri);
2797 - q921_start(pri, 1);
2798 + pri->q921_state[teio] = Q921_LINK_CONNECTION_RELEASED;
2799 + pri->t200_timer[teio] = 0;
2800 + q921_dchannel_down(pri, tei);
2801 + q921_start(pri, 1, tei);
2802 pri->schedev = 1;
2803 }
2804 - } else if (pri->solicitfbit) {
2805 + } else if (pri->solicitfbit[teio]) {
2806 if (pri->debug & PRI_DEBUG_Q921_STATE)
2807 pri_message(pri, "-- Retrying poll with f-bit\n");
2808 - pri->retrans++;
2809 - if (pri->retrans < pri->timers[PRI_TIMER_N200]) {
2810 - pri->solicitfbit = 1;
2811 - q921_rr(pri, 1, 1);
2812 - pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
2813 + pri->retrans[teio]++;
2814 + if (pri->retrans[teio] < pri->timers[PRI_TIMER_N200]) {
2815 + pri->solicitfbit[teio] = 1;
2816 + q921_rr(pri, 1, 1, tei);
2817 + pri->t200_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri, tei);
2818 } else {
2819 if (pri->debug & PRI_DEBUG_Q921_STATE)
2820 pri_message(pri, "-- Timeout occured, restarting PRI\n");
2821 - pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
2822 - pri->t200_timer = 0;
2823 - q921_dchannel_down(pri);
2824 - q921_start(pri, 1);
2825 + pri->q921_state[teio] = Q921_LINK_CONNECTION_RELEASED;
2826 + pri->t200_timer[teio] = 0;
2827 + q921_dchannel_down(pri, tei);
2828 + q921_start(pri, 1, tei);
2829 pri->schedev = 1;
2830 }
2831 } else {
2832 pri_error(pri, "T200 counter expired, nothing to send...\n");
2833 - pri->t200_timer = 0;
2834 + pri->t200_timer[teio] = 0;
2835 + if (pri->busy[teio]) {
2836 + if ((pri->retrans[teio] + 1) <= pri->timers[PRI_TIMER_N200]) {
2837 + /* poll RR */
2838 + pri->t200_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri, tei);
2839 + pri->retrans[teio]++;
2840 + q921_rr(pri, 1, 1, tei);
2841 + } else {
2842 + q921_reset(pri, tei, 1);
2843 + q921_start(pri, 1, tei);
2844 + }
2845 + }
2846 }
2847 }
2848
2849 -int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr)
2850 +int q921_transmit_uframe(struct pri *pri, void *buf, int len, int cr, int tei)
2851 +{
2852 + q921_u *uf;
2853 + uf = malloc(sizeof(q921_u) + len + 2);
2854 + memset(uf,0,sizeof(q921_u) + len + 2);
2855 +
2856 + uf->h.sapi = 0;
2857 + uf->h.ea1 = 0;
2858 + uf->h.ea2 = 1;
2859 + uf->h.tei = tei;
2860 + uf->m3 = 0;
2861 + uf->m2 = 0;
2862 + uf->ft = Q921_FRAMETYPE_U;
2863 + switch(pri->localtype) {
2864 + case PRI_NETWORK:
2865 + uf->h.c_r = 1;
2866 + break;
2867 + case PRI_CPE:
2868 + uf->h.c_r = 0;
2869 + break;
2870 + case BRI_NETWORK_PTMP:
2871 + uf->h.c_r = 1;
2872 + break;
2873 + case BRI_CPE_PTMP:
2874 + uf->h.c_r = 0;
2875 + break;
2876 + case BRI_NETWORK:
2877 + uf->h.c_r = 1;
2878 + break;
2879 + case BRI_CPE:
2880 + uf->h.c_r = 0;
2881 + break;
2882 + default:
2883 + pri_error(pri, "Don't know how to send U frames on a type %d node\n", pri->localtype);
2884 + return -1;
2885 + }
2886 + memcpy(uf->data,buf,len);
2887 + q921_transmit(pri, (q921_h*)&(uf->h), 3+len);
2888 + free(uf);
2889 + return 0;
2890 +}
2891 +
2892 +
2893 +int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr, int tei)
2894 {
2895 q921_frame *f, *prev=NULL;
2896 - for (f=pri->txqueue; f; f = f->next) prev = f;
2897 + int teio=tei - Q921_TEI_BASE;
2898 + if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
2899 + if ((pri->q921_state[teio] == Q921_LINK_CONNECTION_RELEASED) && (!pri->sabme_timer[teio])) {
2900 + if (pri->localtype == BRI_CPE_PTMP) {
2901 + if (pri->tei > 0) {
2902 + /* p2p datalink is down */
2903 + pri->sabme_retrans[teio] = 0;
2904 + q921_send_sabme_now(pri, pri->tei);
2905 + if (pri->debug & PRI_DEBUG_Q921_STATE)
2906 + pri_message(pri, "Reactivating layer 2\n");
2907 + } else {
2908 + /* no tei */
2909 + if (pri->debug & PRI_DEBUG_Q921_STATE)
2910 + pri_message(pri, "reactivating layer 2, sending tei req\n");
2911 + q921_send_teireq(pri);
2912 + }
2913 + } else if ((pri->localtype == BRI_CPE) || (pri->localtype == BRI_NETWORK)) {
2914 + /* p2p datalink is down */
2915 + pri->sabme_retrans[teio] = 0;
2916 + q921_send_sabme_now(pri, pri->tei);
2917 + if (pri->debug & PRI_DEBUG_Q921_STATE)
2918 + pri_message(pri, "Reactivating layer 2\n");
2919 + }
2920 + }
2921 + for (f=pri->txqueue[teio]; f; f = f->next) prev = f;
2922 f = malloc(sizeof(q921_frame) + len + 2);
2923 if (f) {
2924 memset(f,0,sizeof(q921_frame) + len + 2);
2925 @@ -400,47 +973,80 @@
2926 else
2927 f->h.h.c_r = 1;
2928 break;
2929 + case BRI_NETWORK_PTMP:
2930 + f->h.h.tei = tei;
2931 + if (cr)
2932 + f->h.h.c_r = 1;
2933 + else
2934 + f->h.h.c_r = 0;
2935 + break;
2936 + case BRI_CPE_PTMP:
2937 + f->h.h.tei = pri->tei;
2938 + if (cr)
2939 + f->h.h.c_r = 0;
2940 + else
2941 + f->h.h.c_r = 1;
2942 + break;
2943 + case BRI_NETWORK:
2944 + if (cr)
2945 + f->h.h.c_r = 1;
2946 + else
2947 + f->h.h.c_r = 0;
2948 + break;
2949 + case BRI_CPE:
2950 + if (cr)
2951 + f->h.h.c_r = 0;
2952 + else
2953 + f->h.h.c_r = 1;
2954 + break;
2955 }
2956 f->next = NULL;
2957 f->transmitted = 0;
2958 f->len = len + 4;
2959 memcpy(f->h.data, buf, len);
2960 - f->h.n_s = pri->v_s;
2961 - f->h.n_r = pri->v_r;
2962 - pri->v_s++;
2963 - pri->v_na = pri->v_r;
2964 + f->h.n_s = pri->v_s[teio];
2965 + f->h.n_r = pri->v_r[teio];
2966 + pri->v_s[teio]++;
2967 + pri->v_na[teio] = pri->v_r[teio];
2968 f->h.p_f = 0;
2969 f->h.ft = 0;
2970 if (prev)
2971 prev->next = f;
2972 else
2973 - pri->txqueue = f;
2974 - /* Immediately transmit unless we're in a recovery state, or the window
2975 - size is too big */
2976 - if (!pri->retrans && !pri->busy) {
2977 - if (pri->windowlen < pri->window) {
2978 - pri->windowlen++;
2979 + pri->txqueue[teio] = f;
2980 +
2981 + if ((pri->q921_state[teio] != Q921_LINK_CONNECTION_ESTABLISHED) && ((pri->localtype == BRI_CPE_PTMP) || (pri->localtype == BRI_CPE) || (pri->localtype == BRI_NETWORK))){
2982 + /* no p2p datalink, yet. queue up the iframes... */
2983 + if (pri->debug & PRI_DEBUG_Q921_STATE)
2984 + pri_message(pri, "Layer 3 transmit waiting for layer 2\n");
2985 + } else {
2986 + /* Immediately transmit unless we're in a recovery state, or the window
2987 + size is too big */
2988 + if (!pri->retrans[teio] && !pri->busy[teio]) {
2989 + if (pri->windowlen[teio] < pri->window[teio]) {
2990 + pri->windowlen[teio]++;
2991 q921_transmit(pri, (q921_h *)(&f->h), f->len);
2992 f->transmitted++;
2993 } else {
2994 if (pri->debug & PRI_DEBUG_Q921_STATE)
2995 pri_message(pri, "Delaying transmission of %d, window is %d/%d long\n",
2996 - f->h.n_s, pri->windowlen, pri->window);
2997 + f->h.n_s, pri->windowlen[teio], pri->window[teio]);
2998 }
2999 - }
3000 - if (pri->t203_timer) {
3001 + }
3002 + if (pri->t203_timer[teio]) {
3003 + pri_schedule_del(pri, pri->t203_timer[teio]);
3004 + pri->t203_timer[teio] = 0;
3005 if (pri->debug & PRI_DEBUG_Q921_STATE)
3006 pri_message(pri, "Stopping T_203 timer\n");
3007 - pri_schedule_del(pri, pri->t203_timer);
3008 - pri->t203_timer = 0;
3009 - }
3010 - if (!pri->t200_timer) {
3011 + }
3012 + if (!pri->t200_timer[teio]) {
3013 if (pri->debug & PRI_DEBUG_Q921_STATE)
3014 pri_message(pri, "Starting T_200 timer\n");
3015 - pri->t200_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
3016 - } else
3017 + pri->t200_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri, tei);
3018 + } else
3019 if (pri->debug & PRI_DEBUG_Q921_STATE)
3020 - pri_message(pri, "T_200 timer already going (%d)\n", pri->t200_timer);
3021 + pri_message(pri, "T_200 timer already going (%d)\n", pri->t200_timer[teio]);
3022 + }
3023
3024 } else {
3025 pri_error(pri, "!! Out of memory for Q.921 transmit\n");
3026 @@ -449,49 +1055,86 @@
3027 return 0;
3028 }
3029
3030 -static void t203_expire(void *vpri)
3031 +static void t203_expire(void *vpri, int tei)
3032 {
3033 - struct pri *pri = vpri;
3034 - if (pri->q921_state == Q921_LINK_CONNECTION_ESTABLISHED) {
3035 - if (pri->debug & PRI_DEBUG_Q921_STATE)
3036 + struct pri *pri = vpri;
3037 + int teio=tei - Q921_TEI_BASE;
3038 + if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
3039 +
3040 + if (pri->q921_state[teio] == Q921_LINK_CONNECTION_ESTABLISHED) {
3041 + if (pri->debug & PRI_DEBUG_Q921_STATE)
3042 pri_message(pri, "T203 counter expired, sending RR and scheduling T203 again\n");
3043 - /* Solicit an F-bit in the other's RR */
3044 - pri->solicitfbit = 1;
3045 - pri->retrans = 0;
3046 - q921_rr(pri, 1, 1);
3047 - /* Start timer T200 to resend our RR if we don't get it */
3048 - pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri);
3049 + /* Solicit an F-bit in the other's RR */
3050 + pri->solicitfbit[teio] = 1;
3051 + pri->retrans[teio] = 0;
3052 + q921_rr(pri, 1, 1, tei);
3053 + /* Start timer T200 to resend our RR if we don't get it */
3054 + pri->t203_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri, tei);
3055 + } else {
3056 + if (pri->debug & PRI_DEBUG_Q921_STATE)
3057 + pri_message(pri, "T203 counter expired in weird state %d\n", pri->q921_state[teio]);
3058 + pri->t203_timer[teio] = 0;
3059 + }
3060 +}
3061 +
3062 +static void q921_start_tei(struct pri *pri, int tei);
3063 +
3064 +
3065 +static void t201_expire(void *vpri, int tei)
3066 +{
3067 + struct pri *pri = vpri;
3068 + int teio=tei - Q921_TEI_BASE;
3069 + int i = 0;
3070 + if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
3071 + if (tei == Q921_TEI_GROUP) {
3072 + for (i=0;i<Q921_MAX_TEIS;i++) {
3073 + if (pri->q921_tei_check[i] == 1) {
3074 + pri->q921_tei_check[i] = 0;
3075 + q921_start_tei(pri, Q921_TEI_BASE + i);
3076 + }
3077 + }
3078 } else {
3079 - if (pri->debug & PRI_DEBUG_Q921_STATE)
3080 - pri_message(pri, "T203 counter expired in weird state %d\n", pri->q921_state);
3081 - pri->t203_timer = 0;
3082 + if (pri->q921_tei_check[teio] == 1) {
3083 + pri->q921_tei_check[teio] = 0;
3084 + q921_start_tei(pri, tei);
3085 + }
3086 }
3087 + pri->t201_timer[teio] = 0;
3088 }
3089
3090 static pri_event *q921_handle_iframe(struct pri *pri, q921_i *i, int len)
3091 {
3092 int res;
3093 pri_event *ev;
3094 + int teio= i->h.tei - Q921_TEI_BASE;
3095 + if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
3096 +// pri_error(pri, "q921_handle_iframe: i->n_s %d pri->v_r[%d] %d \n", i->n_s, teio, pri->v_r[teio]);
3097 /* Make sure this is a valid packet */
3098 - if (i->n_s == pri->v_r) {
3099 + if (i->n_s == pri->v_r[teio]) {
3100 /* Increment next expected I-frame */
3101 - Q921_INC(pri->v_r);
3102 + Q921_INC(pri->v_r[teio]);
3103 /* Handle their ACK */
3104 - pri->sentrej = 0;
3105 - ev = q921_ack_rx(pri, i->n_r);
3106 + pri->sentrej[teio] = 0;
3107 + ev = q921_ack_rx(pri, i->n_r, i->h.tei);
3108 + if (ev) {
3109 + pri_error(pri, "q921_handle_iframe: ev = %d \n", ev->e);
3110 + }
3111 if (ev)
3112 return ev;
3113 if (i->p_f) {
3114 /* If the Poll/Final bit is set, immediate send the RR */
3115 - q921_rr(pri, 1, 0);
3116 - } else if (pri->busy) {
3117 - q921_rr(pri, 0, 0);
3118 + q921_rr(pri, 1, 0, i->h.tei);
3119 + } else if (pri->busy[teio]) {
3120 + q921_rr(pri, 0, 0, i->h.tei);
3121 + } else if (pri->t200_timer[teio] && pri->retrans[teio]) {
3122 + pri_error(pri, "q921_handle_iframe: sending RR \n");
3123 + q921_rr(pri, 0, 0, i->h.tei);
3124 }
3125 /* Receive Q.931 data */
3126 - res = q931_receive(pri, (q931_h *)i->data, len - 4);
3127 + res = q931_receive(pri, (q931_h *)i->data, len - 4, i->h.tei);
3128 /* Send an RR if one wasn't sent already */
3129 - if (pri->v_na != pri->v_r)
3130 - q921_rr(pri, 0, 0);
3131 + if (pri->v_na[teio] != pri->v_r[teio])
3132 + q921_rr(pri, 0, 0, i->h.tei);
3133 if (res == -1) {
3134 return NULL;
3135 }
3136 @@ -500,10 +1143,10 @@
3137 } else {
3138 /* If we haven't already sent a reject, send it now, otherwise
3139 we are obliged to RR */
3140 - if (!pri->sentrej)
3141 - q921_reject(pri, i->p_f);
3142 + if (!pri->sentrej[teio])
3143 + q921_reject(pri, i->p_f, i->h.tei);
3144 else if (i->p_f)
3145 - q921_rr(pri, 1, 0);
3146 + q921_rr(pri, 1, 0, i->h.tei);
3147 }
3148 return NULL;
3149 }
3150 @@ -641,75 +1284,158 @@
3151 };
3152 }
3153
3154 -static pri_event *q921_dchannel_up(struct pri *pri)
3155 +static void q921_tei_recovery(struct pri *pri, int tei) {
3156 + int i = 0;
3157 + int teio=tei - Q921_TEI_BASE;
3158 + if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
3159 + for (i=0;i<Q921_MAX_TEIS;i++) {
3160 + if ((i + Q921_TEI_BASE == tei) || (tei == Q921_TEI_GROUP)) {
3161 + pri->q921_tei_check[i] = 1;
3162 + }
3163 + }
3164 + q921_send_teichkreq(pri, tei);
3165 + if (!pri->t201_timer[teio]) {
3166 + pri->t201_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T201], t201_expire, pri, tei);
3167 + }
3168 +}
3169 +/*
3170 +static void q921_invoke_tei_recovery(void *vpri, int tei) {
3171 + struct pri *pri = vpri;
3172 + q921_tei_recovery(pri, tei);
3173 +}
3174 +*/
3175 +
3176 +static pri_event *q921_dchannel_up(struct pri *pri, int tei)
3177 {
3178 - /* Reset counters, etc */
3179 - q921_reset(pri);
3180 + // we treat this as MFE
3181 + int teio=tei - Q921_TEI_BASE;
3182 + if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
3183 +
3184 + if (((pri->localtype == BRI_CPE_PTMP) || (pri->localtype == BRI_CPE) || (pri->localtype == BRI_NETWORK)) && (pri->txqueue[teio])) {
3185 + /* Reset counters, etc */
3186 + q921_reset(pri, tei, 0);
3187 + } else {
3188 + /* Reset counters, discard frames, etc */
3189 + q921_reset(pri, tei, 1);
3190 + }
3191
3192 /* Stop any SABME retransmissions */
3193 - pri_schedule_del(pri, pri->sabme_timer);
3194 - pri->sabme_timer = 0;
3195 + if (pri->sabme_timer[teio]) {
3196 + pri_schedule_del(pri, pri->sabme_timer[teio]);
3197 + pri->sabme_timer[teio] = 0;
3198 + }
3199 +
3200 + if (pri->t202_timer[teio]) {
3201 + pri_schedule_del(pri, pri->t202_timer[teio]);
3202 + pri->t202_timer[teio] = 0;
3203 + }
3204 +
3205 +/* neonova test */
3206 + if (pri->t203_timer[teio]) {
3207 + pri_schedule_del(pri, pri->t203_timer[teio]);
3208 + pri->t203_timer[teio] = 0;
3209 + }
3210
3211 /* Reset any rejects */
3212 - pri->sentrej = 0;
3213 + pri->sentrej[teio] = 0;
3214
3215 /* Go into connection established state */
3216 - pri->q921_state = Q921_LINK_CONNECTION_ESTABLISHED;
3217 -
3218 - /* Start the T203 timer */
3219 - pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
3220 + pri->q921_state[teio] = Q921_LINK_CONNECTION_ESTABLISHED;
3221
3222 - /* Report event that D-Channel is now up */
3223 - pri->ev.gen.e = PRI_EVENT_DCHAN_UP;
3224 - return &pri->ev;
3225 + if (((pri->localtype == BRI_CPE_PTMP) || (pri->localtype == BRI_CPE) || (pri->localtype == BRI_NETWORK)) && (pri->txqueue[teio])) {
3226 + /* transmit queued iframes ans start T200 (handled by flush_txqueue) */
3227 + q921_flush_txqueue(pri, tei, 0);
3228 + /* dont upset upper layers if we reactivate layer 2 */
3229 + return NULL;
3230 + } else {
3231 + /* Start the T203 timer */
3232 + pri->t203_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri, tei);
3233 +
3234 + /* Report event that D-Channel is now up */
3235 + pri->ev.gen.e = PRI_EVENT_DCHAN_UP;
3236 + pri->ev.gen.tei = tei;
3237 + return &pri->ev;
3238 + }
3239 }
3240
3241 -static pri_event *q921_dchannel_down(struct pri *pri)
3242 +static pri_event *q921_dchannel_down(struct pri *pri, int tei)
3243 {
3244 + int teio=tei - Q921_TEI_BASE;
3245 + if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
3246 +
3247 + pri->q921_state[teio] = Q921_LINK_CONNECTION_RELEASED;
3248 +
3249 /* Reset counters, reset sabme timer etc */
3250 - q921_reset(pri);
3251 + if (pri->localtype == BRI_NETWORK_PTMP) {
3252 + if (pri->t203_timer[teio]) {
3253 + pri_schedule_del(pri, pri->t203_timer[teio]);
3254 + pri->t203_timer[teio] = 0;
3255 + if (pri->debug & PRI_DEBUG_Q921_STATE) {
3256 + pri_message(pri, "Stopping T_203 timer for TEI %d\n", tei);
3257 + }
3258 + }
3259 + }
3260 +
3261 + q921_reset(pri, tei, 1);
3262
3263 - /* Report event that D-Channel is now up */
3264 + /* Report event that D-Channel is now down */
3265 pri->ev.gen.e = PRI_EVENT_DCHAN_DOWN;
3266 + pri->ev.gen.tei = tei;
3267 return &pri->ev;
3268 }
3269
3270 -void q921_reset(struct pri *pri)
3271 +void q921_reset(struct pri *pri, int tei, int discard)
3272 {
3273 + int teio=tei - Q921_TEI_BASE;
3274 + if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
3275 /* Having gotten a SABME we MUST reset our entire state */
3276 - pri->v_s = 0;
3277 - pri->v_a = 0;
3278 - pri->v_r = 0;
3279 - pri->v_na = 0;
3280 - pri->window = pri->timers[PRI_TIMER_K];
3281 - pri->windowlen = 0;
3282 - pri_schedule_del(pri, pri->sabme_timer);
3283 - pri_schedule_del(pri, pri->t203_timer);
3284 - pri_schedule_del(pri, pri->t200_timer);
3285 - pri->sabme_timer = 0;
3286 - pri->t203_timer = 0;
3287 - pri->t200_timer = 0;
3288 - pri->busy = 0;
3289 - pri->solicitfbit = 0;
3290 - pri->q921_state = Q921_LINK_CONNECTION_RELEASED;
3291 - pri->retrans = 0;
3292 - pri->sentrej = 0;
3293 + if (discard) {
3294 + pri->v_s[teio] = 0;
3295 + }
3296 + pri->v_a[teio] = 0;
3297 + pri->v_r[teio] = 0;
3298 + pri->v_na[teio] = 0;
3299 + pri->window[teio] = pri->timers[PRI_TIMER_K];
3300 + pri->windowlen[teio] = 0;
3301 + pri_schedule_del(pri, pri->sabme_timer[teio]);
3302 + pri_schedule_del(pri, pri->t203_timer[teio]);
3303 + pri_schedule_del(pri, pri->t200_timer[teio]);
3304 + pri->sabme_timer[teio] = 0;
3305 + pri->t203_timer[teio] = 0;
3306 + pri->t200_timer[teio] = 0;
3307 + pri_schedule_del(pri, pri->t202_timer[teio]);
3308 + pri->t202_timer[teio] = 0;
3309 + pri_schedule_del(pri, pri->t201_timer[teio]);
3310 + pri->t201_timer[teio] = 0;
3311 + pri->busy[teio] = 0;
3312 + pri->solicitfbit[teio] = 0;
3313 + pri->q921_state[teio] = Q921_LINK_CONNECTION_RELEASED;
3314 + pri->retrans[teio] = 0;
3315 + pri->sabme_retrans[teio] = 0;
3316 + pri->sentrej[teio] = 0;
3317
3318 - /* Discard anything waiting to go out */
3319 - q921_discard_retransmissions(pri);
3320 + if (discard) {
3321 + /* Discard anything waiting to go out */
3322 + q921_discard_retransmissions(pri, tei);
3323 + }
3324 }
3325
3326 +
3327 static pri_event *__q921_receive_qualified(struct pri *pri, q921_h *h, int len)
3328 {
3329 q921_frame *f;
3330 pri_event *ev;
3331 int sendnow;
3332 + int tei;
3333 + int res=-1;
3334 + int teio=h->h.tei - Q921_TEI_BASE;
3335 + if (((teio < 0) || (teio > Q921_MAX_TEIS)) || (pri->localtype != BRI_NETWORK_PTMP)) { teio=0; }
3336
3337 switch(h->h.data[0] & Q921_FRAMETYPE_MASK) {
3338 case 0:
3339 case 2:
3340 - if (pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED) {
3341 - pri_error(pri, "!! Got I-frame while link state %d\n", pri->q921_state);
3342 + if (pri->q921_state[teio] != Q921_LINK_CONNECTION_ESTABLISHED) {
3343 + pri_error(pri, "!! Got I-frame while link state %d\n", pri->q921_state[teio]);
3344 return NULL;
3345 }
3346 /* Informational frame */
3347 @@ -720,8 +1446,10 @@
3348 return q921_handle_iframe(pri, &h->i, len);
3349 break;
3350 case 1:
3351 - if (pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED) {
3352 + if (pri->q921_state[teio] != Q921_LINK_CONNECTION_ESTABLISHED) {
3353 pri_error(pri, "!! Got S-frame while link down\n");
3354 + q921_send_dm(pri, 1, h->h.tei);
3355 + q921_reset(pri, h->h.tei, 1);
3356 return NULL;
3357 }
3358 if (len < 4) {
3359 @@ -731,80 +1459,128 @@
3360 switch(h->s.ss) {
3361 case 0:
3362 /* Receiver Ready */
3363 - pri->busy = 0;
3364 + pri->busy[teio] = 0;
3365 /* Acknowledge frames as necessary */
3366 - ev = q921_ack_rx(pri, h->s.n_r);
3367 + ev = q921_ack_rx(pri, h->s.n_r, h->h.tei);
3368 if (ev)
3369 return ev;
3370 if (h->s.p_f) {
3371 - /* If it's a p/f one then send back a RR in return with the p/f bit set */
3372 - if (pri->solicitfbit) {
3373 + /* If it's a p/f one then send back a RR in return with the p/f bit set */
3374 +// pri_error(pri, "-- h->s.pf %d pri->solicitfbit[teio] %d\n", h->s.p_f, pri->solicitfbit[teio]);
3375 + if (pri->solicitfbit[teio]) {
3376 if (pri->debug & PRI_DEBUG_Q921_STATE)
3377 pri_message(pri, "-- Got RR response to our frame\n");
3378 } else {
3379 - if (pri->debug & PRI_DEBUG_Q921_STATE)
3380 + if (pri->txqueue[teio]) {
3381 + q921_flush_txqueue(pri, pri->tei, 0);
3382 + } else {
3383 + if (pri->debug & PRI_DEBUG_Q921_STATE)
3384 pri_message(pri, "-- Unsolicited RR with P/F bit, responding\n");
3385 - q921_rr(pri, 1, 0);
3386 + q921_rr(pri, 1, 0, h->h.tei);
3387 + }
3388 }
3389 - pri->solicitfbit = 0;
3390 + pri->solicitfbit[teio] = 0;
3391 }
3392 break;
3393 case 1:
3394 /* Receiver not ready */
3395 if (pri->debug & PRI_DEBUG_Q921_STATE)
3396 pri_message(pri, "-- Got receiver not ready\n");
3397 - if(h->s.p_f) {
3398 - /* Send RR if poll bit set */
3399 - q921_rr(pri, h->s.p_f, 0);
3400 + if ((pri->localtype != PRI_NETWORK) && (pri->localtype != BRI_NETWORK) && (pri->localtype != BRI_NETWORK_PTMP)) {
3401 + if (h->s.p_f && h->s.h.c_r) {
3402 +// if (!pri->t200_timer[teio]) {
3403 + /* Send RR if poll bit set */
3404 + q921_rr(pri, h->s.p_f, 0, h->h.tei);
3405 +// }
3406 + }
3407 + } else {
3408 + if (h->s.p_f && (!h->s.h.c_r)) {
3409 +// if (!pri->t200_timer[teio]) {
3410 + /* Send RR if poll bit set */
3411 + q921_rr(pri, h->s.p_f, 0, h->h.tei);
3412 +// }
3413 + }
3414 + }
3415 + pri->busy[teio] = 1;
3416 + if (pri->t200_timer[teio]) {
3417 + pri_schedule_del(pri, pri->t200_timer[teio]);
3418 + pri->t200_timer[teio] = 0;
3419 }
3420 - pri->busy = 1;
3421 - break;
3422 + pri->t200_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T200], t200_expire, pri, h->h.tei);
3423 + break;
3424 case 2:
3425 /* Just retransmit */
3426 if (pri->debug & PRI_DEBUG_Q921_STATE)
3427 pri_message(pri, "-- Got reject requesting packet %d... Retransmitting.\n", h->s.n_r);
3428 - if (h->s.p_f) {
3429 - /* If it has the poll bit set, send an appropriate supervisory response */
3430 - q921_rr(pri, 1, 0);
3431 - }
3432 sendnow = 0;
3433 +// XXX
3434 + q921_ack_rx(pri, h->s.n_r, h->h.tei);
3435 + /* Reset t200 timer if it was somehow going */
3436 + if (pri->t200_timer[teio]) {
3437 + pri_schedule_del(pri, pri->t200_timer[teio]);
3438 + pri->t200_timer[teio] = 0;
3439 + }
3440 /* Resend the proper I-frame */
3441 - for(f=pri->txqueue;f;f=f->next) {
3442 + for(f=pri->txqueue[teio];f;f=f->next) {
3443 +// pri_error(pri, "!! frame n_s %d transmitted %d (searching for %d)!\n", f->h.n_s, f->transmitted, h->s.n_r);
3444 if ((sendnow || (f->h.n_s == h->s.n_r)) && f->transmitted) {
3445 /* Matches the request, or follows in our window, and has
3446 already been transmitted. */
3447 - sendnow = 1;
3448 - pri_error(pri, "!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n", h->s.n_r, f->h.n_s);
3449 - f->h.n_r = pri->v_r;
3450 - q921_transmit(pri, (q921_h *)(&f->h), f->len);
3451 +
3452 + /* multiframe established */
3453 + f->transmitted = 0;
3454 + f->h.n_r = pri->v_r[teio];
3455 +
3456 + if (pri->busy[teio]) {
3457 + pri->busy[teio] = 0;
3458 + sendnow = 0;
3459 + } else {
3460 + f->h.p_f = 0;
3461 + sendnow = 1;
3462 + pri_error(pri, "!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n", h->s.n_r, f->h.n_s);
3463 + q921_transmit(pri, (q921_h *)(&f->h), f->len);
3464 + f->transmitted++;
3465 + }
3466 }
3467 }
3468 if (!sendnow) {
3469 - if (pri->txqueue) {
3470 - /* This should never happen */
3471 - if (!h->s.p_f || h->s.n_r) {
3472 + if (pri->txqueue[teio]) {
3473 + if (h->s.p_f) {
3474 + q921_rr(pri, 1, 0, h->h.tei);
3475 + } else if (!h->s.p_f || h->s.n_r) {
3476 pri_error(pri, "!! Got reject for frame %d, but we only have others!\n", h->s.n_r);
3477 }
3478 } else {
3479 /* Hrm, we have nothing to send, but have been REJ'd. Reset v_a, v_s, etc */
3480 - pri_error(pri, "!! Got reject for frame %d, but we have nothing -- resetting!\n", h->s.n_r);
3481 - pri->v_a = h->s.n_r;
3482 - pri->v_s = h->s.n_r;
3483 - /* Reset t200 timer if it was somehow going */
3484 - if (pri->t200_timer) {
3485 - pri_schedule_del(pri, pri->t200_timer);
3486 - pri->t200_timer = 0;
3487 - }
3488 +/* pri_error(pri, "!! Got reject for frame %d, but we have nothing -- resetting!\n", h->s.n_r);
3489 + pri->v_a[teio] = h->s.n_r;
3490 + pri->v_s[teio] = h->s.n_r; */
3491 /* Reset and restart t203 timer */
3492 - if (pri->t203_timer)
3493 - pri_schedule_del(pri, pri->t203_timer);
3494 - pri->t203_timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri);
3495 + if (pri->t203_timer[teio])
3496 + pri_schedule_del(pri, pri->t203_timer[teio]);
3497 + pri->t203_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri, tei);
3498 + pri->solicitfbit[teio] = 0;
3499 }
3500 - }
3501 + } else {
3502 + if (h->s.p_f) {
3503 + /* If it has the poll bit set (and an iframe was retransmitted), send an appropriate supervisory response */
3504 +// q921_rr(pri, 1, 0, h->h.tei);
3505 + /* Reset t200 timer if it was somehow going */
3506 + if (pri->t200_timer[teio]) {
3507 + pri_schedule_del(pri, pri->t200_timer[teio]);
3508 + pri->t200_timer[teio] = 0;
3509 + }
3510 + /* Reset and restart t203 timer */
3511 + pri->solicitfbit[teio] = 0;
3512 + if (pri->t203_timer[teio])
3513 + pri_schedule_del(pri, pri->t203_timer[teio]);
3514 + pri->t203_timer[teio] = pri_schedule_event2(pri, pri->timers[PRI_TIMER_T203], t203_expire, pri, h->h.tei);
3515 + }
3516 + }
3517 break;
3518 default:
3519 pri_error(pri, "!! 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,
3520 - pri->v_s, pri->v_a);
3521 + pri->v_s[teio], pri->v_a[teio]);
3522 }
3523 break;
3524 case 3:
3525 @@ -821,8 +1597,16 @@
3526 if (pri->debug & PRI_DEBUG_Q921_STATE)
3527 pri_message(pri, "-- Got DM Mode from peer.\n");
3528 /* Disconnected mode, try again after T200 */
3529 - ev = q921_dchannel_down(pri);
3530 - q921_start(pri, 0);
3531 + ev = q921_dchannel_down(pri, h->h.tei);
3532 + if ((pri->localtype == BRI_CPE_PTMP) || (pri->localtype == BRI_CPE) || (pri->localtype == BRI_NETWORK)) {
3533 + /* release layer 2 */
3534 + // pri_error(pri, "got DM, restarting layer 2.\n");
3535 + // return NULL;
3536 + q921_start(pri, 0, h->h.tei);
3537 + }
3538 + if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)){
3539 + q921_start(pri, 0, h->h.tei);
3540 + }
3541 return ev;
3542
3543 } else {
3544 @@ -830,21 +1614,153 @@
3545 pri_message(pri, "-- Ignoring unsolicited DM with p/f set to 0\n");
3546 #if 0
3547 /* Requesting that we start */
3548 - q921_start(pri, 0);
3549 + q921_start(pri, 0, h->h.tei);
3550 #endif
3551 }
3552 break;
3553 - } else if (!h->u.m2) {
3554 - pri_message(pri, "XXX Unnumbered Information not implemented XXX\n");
3555 + } else if (h->u.m2 == 0) {
3556 + if (h->u.ft == 3) {
3557 + switch (h->u.data[0]) { /* Management Entity Identifier */
3558 + case 0x0f:
3559 + /* TEI Procedure */
3560 + switch (h->u.data[3]) {
3561 + case Q921_TEI_ID_VERIFY:
3562 + if (pri->localtype != BRI_NETWORK_PTMP)
3563 + break;
3564 + if (pri->debug & PRI_DEBUG_Q921_STATE)
3565 + pri_message(pri, "got TEI verify for TEI = %d\n",h->u.data[4] >> 1);
3566 + break;
3567 + case Q921_TEI_ID_ASSIGNED:
3568 + if (pri->localtype != BRI_CPE_PTMP)
3569 + break;
3570 + if (pri->tei == (h->u.data[4] >> 1)) {
3571 + // TEI already assgined, CHECK_TEI or REMOVE_TEI
3572 + pri_error(pri, "Double assgined TEI!\n");
3573 + }
3574 + if (pri->ri == ((unsigned short) (h->u.data[1] << 8) + h->u.data[2])) {
3575 + if (pri->t202_timer[0]) {
3576 + pri_schedule_del(pri, pri->t202_timer[0]);
3577 + pri->t202_timer[0] = 0;
3578 + }
3579 + pri->tei = h->u.data[4] >> 1;
3580 + pri->ri = 0;
3581 + if (pri->debug & PRI_DEBUG_Q921_STATE)
3582 + pri_message(pri, "received TEI assign TEI = %d ri=%d\n",pri->tei,(unsigned short) (h->u.data[1] << 8) + h->u.data[2]);
3583 + pri->sabme_retrans[teio] = 0;
3584 + q921_send_sabme_now(pri, pri->tei);
3585 + }
3586 + break;
3587 + case Q921_TEI_ID_REMOVE:
3588 + if (pri->localtype != BRI_CPE_PTMP)
3589 + break;
3590 + if (((h->u.data[4] >> 1) == Q921_TEI_GROUP) || (pri->tei == (h->u.data[4] >> 1))){
3591 + if (pri->debug & PRI_DEBUG_Q921_STATE)
3592 + pri_message(pri, "received TEI remove TEI = %d\n",pri->tei);
3593 + pri->tei = 0;
3594 + pri->ri = 0;
3595 + // get a new TEI
3596 + q921_reset(pri, 0, 1);
3597 + q921_send_teireq(pri);
3598 + }
3599 + break;
3600 + case Q921_TEI_ID_REQUEST:
3601 + if (pri->localtype != BRI_NETWORK_PTMP)
3602 + break;
3603 +
3604 + tei = h->u.data[4] >> 1;
3605 + if (tei != Q921_TEI_GROUP) {
3606 + pri_message(pri, "got TEI request for unavailable TEI..\n");
3607 + q921_send_teidenied(pri,((unsigned int)(h->u.data[1] << 8) + h->u.data[2]),h->u.data[4] >> 1);
3608 + break;
3609 + }
3610 +
3611 + for (tei=0;tei<Q921_MAX_TEIS;tei++) {
3612 + if (pri->q921_teis[tei] == 0) {
3613 + pri->q921_teis[tei] = 1;
3614 + break;
3615 + }
3616 + }
3617 + if (tei < Q921_MAX_TEIS) {
3618 + q921_send_teiassign(pri,((unsigned int)(h->u.data[1] << 8) + h->u.data[2]),tei + Q921_TEI_BASE);
3619 + } else {
3620 + pri_error(pri, "no TEI available. starting TEI recovery procedure. dont worry!\n");
3621 + q921_tei_recovery(pri, 127);
3622 +
3623 + }
3624 + break;
3625 + case Q921_TEI_ID_CHK_REQ:
3626 + if (pri->localtype != BRI_CPE_PTMP)
3627 + break;
3628 + 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)) {
3629 + pri_message(pri, "received TEI check request for TEI = %d\n",h->u.data[4] >> 1);
3630 + q921_send_teichkresp(pri, pri->tei);
3631 + }
3632 + break;
3633 + case Q921_TEI_ID_CHK_RES:
3634 + if (pri->localtype != BRI_NETWORK_PTMP)
3635 + break;
3636 + teio = (h->u.data[4] >> 1) - Q921_TEI_BASE;
3637 + if ((teio < 0) || (teio >= Q921_MAX_TEIS)) break;
3638 + if (pri->q921_tei_check[teio] == 1) {
3639 + pri->q921_tei_check_ri[teio] = (h->u.data[1] << 8) + h->u.data[2];
3640 + pri->q921_tei_check[teio] = 0;
3641 + } else {
3642 + // d a t
3643 + pri_error(pri, "double assgined tei for tei %d teio %d\n", h->u.data[4] >> 1, teio);
3644 + pri->q921_tei_check[teio] = 0;
3645 + q921_start_tei(pri, h->u.data[4] >> 1);
3646 + }
3647 + break;
3648 + default:
3649 + pri_message(pri, "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);
3650 + }
3651 + break;
3652 + case Q931_PROTOCOL_DISCRIMINATOR:
3653 + if ((pri->localtype == BRI_CPE_PTMP) || (pri->localtype == BRI_CPE)){
3654 + res = q931_receive(pri, (q931_h *)h->u.data, len-3, h->h.tei);
3655 + /* Send an RR if one wasn't sent already */
3656 + if (pri->v_na[teio] != pri->v_r[teio])
3657 + q921_rr(pri, 0, 0, pri->tei);
3658 + if (res == -1) {
3659 + return NULL;
3660 + }
3661 + if (res & Q931_RES_HAVEEVENT)
3662 + return &pri->ev;
3663 + }
3664 + break;
3665 + }
3666 + } else {
3667 + pri_message(pri, "XXX Unnumbered Information not implemented XXX\n");
3668 + }
3669 }
3670 break;
3671 case 2:
3672 if (pri->debug & PRI_DEBUG_Q921_STATE)
3673 pri_message(pri, "-- Got Disconnect from peer.\n");
3674 +#ifndef RELAX_TRB
3675 + if (pri->q921_state[teio] != Q921_LINK_CONNECTION_ESTABLISHED) {
3676 + q921_send_dm(pri, 1, h->h.tei);
3677 + return NULL;
3678 + }
3679 +#endif
3680 /* Acknowledge */
3681 - q921_send_ua(pri, h->u.p_f);
3682 - ev = q921_dchannel_down(pri);
3683 - q921_start(pri, 0);
3684 + q921_send_ua(pri, h->u.p_f, h->h.tei);
3685 + ev = q921_dchannel_down(pri, h->h.tei);
3686 + if ((pri->localtype == BRI_CPE_PTMP) || (pri->localtype == BRI_CPE) || (pri->localtype == BRI_NETWORK)) {
3687 +#ifndef LAYER2ALWAYSUP
3688 + /* release layer 2 */
3689 + return NULL;
3690 +#else
3691 + /* keep layer 2 up */
3692 + if (pri->t203_timer[teio])
3693 + pri_schedule_del(pri, pri->t203_timer[teio]);
3694 + pri->t203_timer[teio] = 0;
3695 + q921_send_sabme(pri, 1, pri->tei);
3696 +#endif
3697 + }
3698 + if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)){
3699 + q921_start(pri, 0, 0);
3700 + }
3701 return ev;
3702 case 3:
3703 if (h->u.m2 == 3) {
3704 @@ -866,17 +1782,28 @@
3705 }
3706 }
3707 /* Send Unnumbered Acknowledgement */
3708 - q921_send_ua(pri, h->u.p_f);
3709 - return q921_dchannel_up(pri);
3710 + q921_send_ua(pri, h->u.p_f, h->h.tei);
3711 + return q921_dchannel_up(pri, h->h.tei);
3712 } else if (h->u.m2 == 0) {
3713 /* It's a UA */
3714 - if (pri->q921_state == Q921_AWAITING_ESTABLISH) {
3715 + if (pri->q921_state[teio] == Q921_AWAITING_ESTABLISH) {
3716 if (pri->debug & PRI_DEBUG_Q921_STATE) {
3717 pri_message(pri, "-- Got UA from %s peer Link up.\n", h->h.c_r ? "cpe" : "network");
3718 }
3719 - return q921_dchannel_up(pri);
3720 - } else
3721 - pri_error(pri, "!! Got a UA, but i'm in state %d\n", pri->q921_state);
3722 + return q921_dchannel_up(pri, h->h.tei);
3723 + } else {
3724 + pri_error(pri, "!! Got a UA, but i'm in state %d\n", pri->q921_state[teio]);
3725 + if ((pri->localtype == BRI_CPE_PTMP) || (pri->localtype == BRI_CPE)) {
3726 + q921_reset(pri, h->h.tei, 1);
3727 + q921_send_teiverify(pri, h->h.tei);
3728 + } else {
3729 + /* send DM */
3730 + // q921_send_dm(pri, 1, h->h.tei);
3731 +#ifndef RELAX_TRB
3732 + q921_reset(pri, h->h.tei, 1);
3733 +#endif
3734 + }
3735 + }
3736 } else
3737 pri_error(pri, "!! Weird frame received (m3=3, m2 = %d)\n", h->u.m2);
3738 break;
3739 @@ -901,19 +1828,42 @@
3740 /* Discard FCS */
3741 len -= 2;
3742
3743 - if (!pri->master && pri->debug & PRI_DEBUG_Q921_DUMP)
3744 - q921_dump(pri, h, len, pri->debug & PRI_DEBUG_Q921_RAW, 0);
3745 -
3746 /* Check some reject conditions -- Start by rejecting improper ea's */
3747 if (h->h.ea1 || !(h->h.ea2))
3748 return NULL;
3749 + if ((pri->localtype == PRI_CPE) || (pri->localtype == PRI_NETWORK)) {
3750 + /* Check for broadcasts - not yet handled (for PRI) */
3751 + if (h->h.tei == Q921_TEI_GROUP) {
3752 + return NULL;
3753 + }
3754 + } else if ((pri->localtype == BRI_CPE) || (pri->localtype == BRI_CPE_PTMP)) {
3755 + if ((h->h.tei != pri->tei) && (h->h.tei != Q921_TEI_GROUP)) {
3756 + return NULL;
3757 + }
3758 + } else if (pri->localtype == BRI_NETWORK_PTMP) {
3759 + /* discard anything from a strange TEI (strange == not assigned by us or the broadcast tei) */
3760 + if (((h->h.tei < Q921_TEI_BASE) || (h->h.tei > Q921_TEI_BASE + Q921_MAX_TEIS)) && (h->h.tei != Q921_TEI_GROUP)) {
3761 + if (pri->debug & PRI_DEBUG_Q921_DUMP)
3762 + pri_message(pri, "Received a Q.921 message from strange/unassigned TEI %d.\n");
3763 + return NULL;
3764 + } else {
3765 + if ((pri->q921_teis[h->h.tei - Q921_TEI_BASE] != 1) && (h->h.tei != Q921_TEI_GROUP)) {
3766 + if (pri->debug & PRI_DEBUG_Q921_DUMP)
3767 + pri_message(pri, "Received a Q.921 message from unassigned TEI %d.. Sending DM and assigning.\n", h->h.tei);
3768 + // send DM
3769 + q921_send_dm(pri, 1, h->h.tei);
3770 + pri->q921_teis[h->h.tei - Q921_TEI_BASE] = 1;
3771 + }
3772 + }
3773 + }
3774 +
3775 + if (!pri->master && pri->debug & PRI_DEBUG_Q921_DUMP)
3776 + q921_dump(pri, h, len, pri->debug & PRI_DEBUG_Q921_RAW, 0);
3777
3778 - /* Check for broadcasts - not yet handled */
3779 - if (h->h.tei == Q921_TEI_GROUP)
3780 - return NULL;
3781
3782 + if (pri->localtype != BRI_NETWORK_PTMP) {
3783 /* Check for SAPIs we don't yet handle */
3784 - if ((h->h.sapi != pri->sapi) || (h->h.tei != pri->tei)) {
3785 + if (((h->h.sapi != pri->sapi) && (h->h.sapi != Q921_SAPI_LAYER2_MANAGEMENT)) || ((h->h.tei != pri->tei) && (h->h.tei != Q921_TEI_GROUP) )) {
3786 #ifdef PROCESS_SUBCHANNELS
3787 /* If it's not us, try any subchannels we have */
3788 if (pri->subchannel)
3789 @@ -921,10 +1871,16 @@
3790 else
3791 #endif
3792 return NULL;
3793 -
3794 + }
3795 }
3796 ev = __q921_receive_qualified(pri, h, len);
3797 - reschedule_t203(pri);
3798 +
3799 +// Q921_GROUP_TEI
3800 + if (pri->localtype == BRI_CPE_PTMP) {
3801 + reschedule_t203(pri, pri->tei);
3802 + } else {
3803 + reschedule_t203(pri, h->h.tei);
3804 + }
3805 return ev;
3806 }
3807
3808 @@ -938,14 +1894,58 @@
3809 return e;
3810 }
3811
3812 -void q921_start(struct pri *pri, int now)
3813 +static void q921_start_tei(struct pri *pri, int tei)
3814 {
3815 - if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED) {
3816 - pri_error(pri, "!! q921_start: Not in 'Link Connection Released' state\n");
3817 - return;
3818 + int teio=tei - Q921_TEI_BASE;
3819 + if (pri->localtype != BRI_NETWORK_PTMP) { return; }
3820 + if (((teio < 0) || (teio > Q921_MAX_TEIS))) { teio=0; }
3821 + pri->q921_teis[teio] = 0;
3822 + q921_send_teiremove(pri, tei);
3823 + q921_reset(pri,tei,1);
3824 +}
3825 +
3826 +void q921_start(struct pri *pri, int now, int tei)
3827 +{
3828 + int i=0;
3829 +/* if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED) {
3830 + pri_error(pri, "!! q921_start: Not in 'Link Connection Released' state\n");
3831 + return;
3832 + } */
3833 + /* Reset our interface */
3834 + if (pri->localtype != BRI_NETWORK_PTMP) {
3835 + q921_reset(pri,0,1);
3836 + }
3837 + /* Do the SABME XXX Maybe we should implement T_WAIT? XXX */
3838 + if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE) || (pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_CPE)) {
3839 + pri->sabme_retrans[0] = 0;
3840 + q921_send_sabme(pri, now, 0);
3841 + }
3842 +
3843 + if (pri->localtype == BRI_NETWORK_PTMP) {
3844 + if (tei == 0) {
3845 + // initial start or complete restart
3846 + q921_send_teiremove(pri, 127);
3847 + pri->dchanup = 0;
3848 + for (i=0;i<Q921_MAX_TEIS;i++) {
3849 + q921_start_tei(pri,Q921_TEI_BASE+i);
3850 + }
3851 + /* clean up those TEIs */
3852 +// pri_schedule_event2(pri, 10000, q921_invoke_tei_recovery, pri, 127 );
3853 + } else if ((tei >= Q921_TEI_BASE) && (tei < Q921_TEI_BASE + Q921_MAX_TEIS)){
3854 + // restart of a single p2p datalink
3855 + q921_start_tei(pri,tei);
3856 + }
3857 + }
3858 + if (pri->localtype == BRI_CPE_PTMP){
3859 + if (tei == 0) {
3860 +#ifdef RELAX_TRB
3861 + /* let's get a TEI */
3862 + q921_send_teireq(pri);
3863 +#endif
3864 + } else {
3865 + /* save the planet by recycling */
3866 + pri->sabme_retrans[0] = 0;
3867 + q921_send_sabme(pri, now, tei);
3868 + }
3869 }
3870 - /* Reset our interface */
3871 - q921_reset(pri);
3872 - /* Do the SABME XXX Maybe we should implement T_WAIT? XXX */
3873 - q921_send_sabme(pri, now);
3874 }
3875 diff -urN libpri-1.2.3.orig/q931.c libpri-1.2.3/q931.c
3876 --- libpri-1.2.3.orig/q931.c 2006-04-27 18:08:39.000000000 +0200
3877 +++ libpri-1.2.3/q931.c 2006-08-01 10:55:05.000000000 +0200
3878 @@ -1,10 +1,12 @@
3879 /*
3880 * libpri: An implementation of Primary Rate ISDN
3881 *
3882 - * Written by Mark Spencer <markster@digium.com>
3883 + * Written by Mark Spencer <markster@linux-support.net>
3884 *
3885 - * Copyright (C) 2001-2005, Digium
3886 + * Copyright (C) 2001, Linux Support Services, Inc.
3887 * All Rights Reserved.
3888 + * Copyright (C) 2003-2006 Junghanns.NET GmbH
3889 + * Klaus-Peter Junghanns <kpj@junghanns.net>
3890 *
3891 * This program is free software; you can redistribute it and/or modify
3892 * it under the terms of the GNU General Public License as published by
3893 @@ -21,7 +23,7 @@
3894 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
3895 *
3896 */
3897 -
3898 +
3899 #include "compat.h"
3900 #include "libpri.h"
3901 #include "pri_internal.h"
3902 @@ -31,6 +33,7 @@
3903
3904 #include <unistd.h>
3905 #include <stdlib.h>
3906 +#include <time.h>
3907 #include <string.h>
3908 #include <stdio.h>
3909 #include <limits.h>
3910 @@ -205,6 +208,14 @@
3911 #define LOC_INTERNATIONAL_NETWORK 0x7
3912 #define LOC_NETWORK_BEYOND_INTERWORKING 0xa
3913
3914 +struct q921_call {
3915 + int tei;
3916 + int proc;
3917 + int channel;
3918 + q921_call *next;
3919 +};
3920 +
3921 +
3922 static char *ie2str(int ie);
3923 static char *msg2str(int msg);
3924
3925 @@ -241,6 +252,7 @@
3926 static void call_init(struct q931_call *c)
3927 {
3928 memset(c, 0, sizeof(*c));
3929 + c->con_acked = 0;
3930 c->alive = 0;
3931 c->sendhangupack = 0;
3932 c->forceinvert = -1;
3933 @@ -253,8 +265,16 @@
3934 c->next = NULL;
3935 c->sentchannel = 0;
3936 c->newcall = 1;
3937 + c->t303timer = 0;
3938 + c->t303running = 0;
3939 + c->aoc = 0;
3940 + c->phones = NULL;
3941 c->ourcallstate = Q931_CALL_STATE_NULL;
3942 c->peercallstate = Q931_CALL_STATE_NULL;
3943 + c->llc[0] = '\0';
3944 + c->cause = -1;
3945 + c->causecode = -1;
3946 + c->causeloc = -1;
3947 }
3948
3949 static char *binary(int b, int len) {
3950 @@ -272,14 +292,17 @@
3951 {
3952 int x;
3953 int pos=0;
3954 -#ifdef NO_BRI_SUPPORT
3955 - if (!ie->data[0] & 0x20) {
3956 - pri_error(pri, "!! Not PRI type!?\n");
3957 - return -1;
3958 + if ((pri->localtype != PRI_CPE) && (pri->localtype != PRI_NETWORK)) {
3959 + // pri_error(pri, "!! BRI type %d!?\n",ie->data[0] & 0x03);
3960 + call->channelno = ie->data[0] & 0x03;
3961 + if (call->channelno == 3) {
3962 + call->channelno = -1; // any channel
3963 + }
3964 + return 0;
3965 }
3966 -#endif
3967 #ifndef NOAUTO_CHANNEL_SELECTION_SUPPORT
3968 - switch (ie->data[0] & 3) {
3969 + if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
3970 + switch (ie->data[0] & 3) {
3971 case 0:
3972 call->justsignalling = 1;
3973 break;
3974 @@ -288,6 +311,7 @@
3975 default:
3976 pri_error(pri, "!! Unexpected Channel selection %d\n", ie->data[0] & 3);
3977 return -1;
3978 + }
3979 }
3980 #endif
3981 if (ie->data[0] & 0x08)
3982 @@ -349,10 +373,16 @@
3983 }
3984
3985 /* Start with standard stuff */
3986 - if (pri->switchtype == PRI_SWITCH_GR303_TMC)
3987 + if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
3988 ie->data[pos] = 0x69;
3989 - else
3990 + } else {
3991 + if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
3992 ie->data[pos] = 0xa1;
3993 + } else {
3994 + // BRI
3995 + ie->data[pos] = 0x80;
3996 + }
3997 + }
3998 /* Add exclusive flag if necessary */
3999 if (call->chanflags & FLAG_EXCLUSIVE)
4000 ie->data[pos] |= 0x08;
4001 @@ -369,6 +399,7 @@
4002 } else
4003 pos++;
4004 if ((call->channelno > -1) || (call->slotmap != -1)) {
4005 + if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
4006 /* We'll have the octet 8.2 and 8.3's present */
4007 ie->data[pos++] = 0x83;
4008 if (call->channelno > -1) {
4009 @@ -384,11 +415,43 @@
4010 ie->data[pos++] = (call->slotmap & 0xff);
4011 return pos + 2;
4012 }
4013 - }
4014 + } else {
4015 + // BRI
4016 + // pri_error(pri, "channelno %d, ds1no %d data %d\n",call->channelno,call->ds1no,ie->data[pos-1]);
4017 + if (pri->localtype == BRI_CPE_PTMP) {
4018 + if (msgtype == Q931_SETUP) {
4019 + // network, you decide!
4020 + if (call->channelno > -1) {
4021 + // ie->data[pos-1] = 0x83;
4022 + ie->data[pos-1] = 0x80 | call->channelno;
4023 + }
4024 + } else {
4025 + if (call->channelno > -1) {
4026 + ie->data[pos-1] |= call->channelno;
4027 + }
4028 + }
4029 + } else {
4030 + if (call->channelno > -1) {
4031 + ie->data[pos-1] |= call->channelno;
4032 + }
4033 + }
4034 + return pos + 2;
4035 + }
4036 + } else {
4037 + if (pri->localtype == BRI_CPE) {
4038 + ie->data[pos++] = 0x80 | 3;
4039 + return pos + 2;
4040 + }
4041 + }
4042 +
4043 if (call->ds1no > 0) {
4044 /* We're done */
4045 return pos + 2;
4046 }
4047 + if (msgtype == Q931_RESTART_ACKNOWLEDGE) {
4048 + /* restart complete interface! */
4049 + return 0;
4050 + }
4051 pri_error(pri, "!! No channel map, no channel, and no ds1? What am I supposed to identify?\n");
4052 return -1;
4053 }
4054 @@ -734,9 +797,13 @@
4055 return code2str(pres, press, sizeof(press) / sizeof(press[0]));
4056 }
4057
4058 -static void q931_get_number(unsigned char *num, int maxlen, unsigned char *src, int len)
4059 +static void q931_get_number(char *num, int maxlen, unsigned char *src, int len)
4060 {
4061 - if ((len < 0) || (len > maxlen - 1)) {
4062 + if (len < 0) {
4063 + pri_error(NULL, "q931_get_number received invalid len = %d\n", len);
4064 + return;
4065 + }
4066 + if (len > maxlen - 1) {
4067 num[0] = 0;
4068 return;
4069 }
4070 @@ -746,50 +813,75 @@
4071
4072 static FUNC_DUMP(dump_called_party_number)
4073 {
4074 - unsigned char cnum[256];
4075 -
4076 - q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
4077 - pri_message(pri, "%c Called Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d) '%s' ]\n",
4078 - 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);
4079 + char cnum[256];
4080 + if (len >= 3) {
4081 + q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
4082 + pri_message(pri, "%c Called Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d) '%s' ]\n",
4083 + 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);
4084 + } else {
4085 + pri_error(pri, "Called Number (len=%2d) too short.\n", len);
4086 + }
4087 }
4088
4089 static FUNC_DUMP(dump_called_party_subaddr)
4090 {
4091 - unsigned char cnum[256];
4092 - q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
4093 - pri_message(pri, "%c Called Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
4094 - prefix, len, ie->data[0] >> 7,
4095 - subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
4096 - (ie->data[0] & 0x08) >> 3, cnum);
4097 + char cnum[256];
4098 + if (len >= 3) {
4099 + q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
4100 + pri_message(pri, "%c Called Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
4101 + prefix, len, ie->data[0] >> 7,
4102 + subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
4103 + (ie->data[0] & 0x08) >> 3, cnum);
4104 + } else {
4105 + pri_error(pri, "Called Party Subaddress (len=%2d) too short.\n", len);
4106 + }
4107 }
4108
4109 static FUNC_DUMP(dump_calling_party_number)
4110 {
4111 - unsigned char cnum[256];
4112 - if (ie->data[0] & 0x80)
4113 - q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
4114 - else
4115 - q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
4116 - pri_message(pri, "%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);
4117 - if (ie->data[0] & 0x80)
4118 - pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(0), 0, cnum);
4119 - else
4120 - pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum);
4121 + char cnum[256];
4122 + if ((ie->data[0] & 0x80) && (len >= 3)) {
4123 + q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
4124 + pri_message(pri, "%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);
4125 + pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(0), 0, cnum);
4126 + } else if (len >= 4) {
4127 + q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
4128 + pri_message(pri, "%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);
4129 + pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum);
4130 + } else {
4131 + pri_error(pri, "Calling Party Number (len=%2d) too short.\n", len);
4132 + }
4133 }
4134
4135 static FUNC_DUMP(dump_calling_party_subaddr)
4136 {
4137 - unsigned char cnum[256];
4138 - q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
4139 - pri_message(pri, "%c Calling Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
4140 - prefix, len, ie->data[0] >> 7,
4141 - subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
4142 - (ie->data[0] & 0x08) >> 3, cnum);
4143 + char cnum[256];
4144 + if (len >= 4) {
4145 + q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
4146 + pri_message(pri, "%c Calling Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
4147 + prefix, len, ie->data[0] >> 7,
4148 + subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
4149 + (ie->data[0] & 0x08) >> 3, cnum);
4150 + } else {
4151 + pri_error(pri, "Calling Party Subaddress (len=%2d) too short.\n", len);
4152 + }
4153 +}
4154 +
4155 +static FUNC_DUMP(dump_colp)
4156 +{
4157 + char cnum[256];
4158 + if (len >= 4) {
4159 + q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
4160 + pri_message(pri, "%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);
4161 + pri_message(pri, "%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum);
4162 + } else {
4163 + pri_error(pri, "COLP (len=%2d) too short.\n", len);
4164 + }
4165 }
4166
4167 static FUNC_DUMP(dump_redirecting_number)
4168 {
4169 - unsigned char cnum[256];
4170 + char cnum[256];
4171 int i = 0;
4172 /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
4173 walking through all bytes until one with ext bit (8) set to 1 */
4174 @@ -810,13 +902,17 @@
4175 }
4176 }
4177 while(!(ie->data[i++]& 0x80));
4178 - q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
4179 - pri_message(pri, " '%s' ]\n", cnum);
4180 + if ((ie->len - i) >= 0) {
4181 + q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
4182 + pri_message(pri, " '%s' ]\n", cnum);
4183 + } else {
4184 + pri_error(pri, "Redirecting Number (len=%2d) too short.\n", len);
4185 + }
4186 }
4187
4188 static FUNC_DUMP(dump_connected_number)
4189 {
4190 - unsigned char cnum[256];
4191 + char cnum[256];
4192 int i = 0;
4193 /* To follow Q.931 (4.5.1), we must search for start of octet 4 by
4194 walking through all bytes until one with ext bit (8) set to 1 */
4195 @@ -833,8 +929,12 @@
4196 }
4197 }
4198 while(!(ie->data[i++]& 0x80));
4199 - q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
4200 - pri_message(pri, " '%s' ]\n", cnum);
4201 + if ((ie->len - i) >= 0) {
4202 + q931_get_number(cnum, sizeof(cnum), ie->data + i, ie->len - i);
4203 + pri_message(pri, " '%s' ]\n", cnum);
4204 + } else {
4205 + pri_error(pri, "Connected Number (len=%2d) too short.\n", len);
4206 + }
4207 }
4208
4209
4210 @@ -858,7 +958,7 @@
4211 }
4212 }
4213 while(!(ie->data[i++] & 0x80));
4214 - q931_get_number((unsigned char *) call->redirectingnum, sizeof(call->redirectingnum), ie->data + i, ie->len - i);
4215 + q931_get_number(call->redirectingnum, sizeof(call->redirectingnum), ie->data + i, ie->len - i);
4216 return 0;
4217 }
4218
4219 @@ -866,7 +966,7 @@
4220 {
4221 if (order > 1)
4222 return 0;
4223 - if (call->redirectingnum && *call->redirectingnum) {
4224 + if (call->redirectingnum && strlen(call->redirectingnum)) {
4225 ie->data[0] = call->redirectingplan;
4226 ie->data[1] = call->redirectingpres;
4227 ie->data[2] = (call->redirectingreason & 0x0f) | 0x80;
4228 @@ -878,67 +978,90 @@
4229
4230 static FUNC_DUMP(dump_redirecting_subaddr)
4231 {
4232 - unsigned char cnum[256];
4233 - q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
4234 - pri_message(pri, "%c Redirecting Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
4235 - prefix, len, ie->data[0] >> 7,
4236 - subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
4237 - (ie->data[0] & 0x08) >> 3, cnum);
4238 + char cnum[256];
4239 + if (len >= 4) {
4240 + q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
4241 + pri_message(pri, "%c Redirecting Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
4242 + prefix, len, ie->data[0] >> 7,
4243 + subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
4244 + (ie->data[0] & 0x08) >> 3, cnum);
4245 + } else {
4246 + pri_error(pri, "Redirecting Subaddress (len=%2d) too short.\n", len);
4247 + }
4248 }
4249
4250 static FUNC_RECV(receive_calling_party_subaddr)
4251 {
4252 /* copy digits to call->callingsubaddr */
4253 - q931_get_number((unsigned char *) call->callingsubaddr, sizeof(call->callingsubaddr), ie->data + 1, len - 3);
4254 + if (len >= 4) {
4255 + q931_get_number(call->callingsubaddr, sizeof(call->callingsubaddr), ie->data + 1, len - 3);
4256 + } else {
4257 + pri_error(call->pri, "Calling Party Subaddress (len=%2d) too short.\n", len);
4258 + }
4259 return 0;
4260 }
4261
4262 static FUNC_RECV(receive_called_party_number)
4263 {
4264 - /* copy digits to call->callednum */
4265 - q931_get_number((unsigned char *) call->callednum, sizeof(call->callednum), ie->data + 1, len - 3);
4266 - call->calledplan = ie->data[0] & 0x7f;
4267 + /* copy digits to call->callednum or call->digits */
4268 + if (len >= 3) {
4269 + if (msgtype == Q931_INFORMATION) {
4270 + q931_get_number(call->digits, sizeof(call->digits), ie->data + 1, len - 3);
4271 + } else {
4272 + q931_get_number(call->callednum, sizeof(call->callednum), ie->data + 1, len - 3);
4273 + }
4274 + call->calledplan = ie->data[0] & 0x7f;
4275 + } else {
4276 + pri_error(call->pri, "Called Party Number (len=%2d) too short.\n", len);
4277 + }
4278 return 0;
4279 }
4280
4281 static FUNC_SEND(transmit_called_party_number)
4282 {
4283 ie->data[0] = 0x80 | call->calledplan;
4284 - if (*call->callednum)
4285 + if (strlen(call->callednum))
4286 memcpy(ie->data + 1, call->callednum, strlen(call->callednum));
4287 return strlen(call->callednum) + 3;
4288 }
4289
4290 static FUNC_RECV(receive_calling_party_number)
4291 {
4292 - u_int8_t *data;
4293 - size_t length;
4294 -
4295 - if (ie->data[0] & 0x80) {
4296 - data = ie->data + 1;
4297 - length = len - 3;
4298 - call->callerpres = 0; /* PI presentation allowed SI user-provided, not screened */
4299 - } else {
4300 - data = ie->data + 2;
4301 - length = len - 4;
4302 - call->callerpres = ie->data[1] & 0x7f;
4303 - }
4304 -
4305 - if (call->callerpres == PRES_ALLOWED_NETWORK_NUMBER ||
4306 - call->callerpres == PRES_PROHIB_NETWORK_NUMBER) {
4307 - q931_get_number((u_int8_t *)call->callerani, sizeof(call->callerani), data, length);
4308 - call->callerplanani = ie->data[0] & 0x7f;
4309 -
4310 - if (!*call->callernum) { /*Copy ANI to CallerID if CallerID is not already set */
4311 - libpri_copy_string(call->callernum, call->callerani, sizeof(call->callernum));
4312 - call->callerplan = call->callerplanani;
4313 - }
4314 -
4315 - } else {
4316 - q931_get_number((u_int8_t *)call->callernum, sizeof(call->callernum), data, length);
4317 - call->callerplan = ie->data[0] & 0x7f;
4318 - }
4319 +/// callerani!!
4320 + if (strlen(call->callernum)) {
4321 + call->callerplanuser = ie->data[0] & 0x7f;
4322 + } else {
4323 + call->callerplan = ie->data[0] & 0x7f;
4324 + }
4325
4326 + if (ie->data[0] & 0x80) {
4327 + if (len >= 3) {
4328 + if (strlen(call->callernum)) {
4329 + // got A NUM already (this is not 100% correct, but the network should do it this way to protect bad implementations
4330 + q931_get_number(call->callerani, sizeof(call->callerani), ie->data + 1, len - 3);
4331 + call->callerpresuser = 0; /* PI presentation allowed
4332 + SI user-provided, not screened */
4333 + } else {
4334 + q931_get_number(call->callernum, sizeof(call->callernum), ie->data + 1, len - 3);
4335 + call->callerpres = 0; /* PI presentation allowed
4336 + SI user-provided, not screened */
4337 + }
4338 + } else {
4339 + pri_error(call->pri, "Calling Party Number (len=%2d) too short.\n", len);
4340 + }
4341 + } else {
4342 + if (len >= 4) {
4343 + if (strlen(call->callernum)) {
4344 + q931_get_number(call->callerani, sizeof(call->callerani), ie->data + 2, len - 4);
4345 + call->callerpresuser = ie->data[1] & 0x7f;
4346 + } else {
4347 + q931_get_number(call->callernum, sizeof(call->callernum), ie->data + 2, len - 4);
4348 + call->callerpres = ie->data[1] & 0x7f;
4349 + }
4350 + } else {
4351 + pri_error(call->pri, "Calling Party Number (len=%2d) too short.\n", len);
4352 + }
4353 + }
4354 return 0;
4355 }
4356
4357 @@ -946,7 +1069,7 @@
4358 {
4359 ie->data[0] = call->callerplan;
4360 ie->data[1] = 0x80 | call->callerpres;
4361 - if (*call->callernum)
4362 + if (strlen(call->callernum))
4363 memcpy(ie->data + 2, call->callernum, strlen(call->callernum));
4364 return strlen(call->callernum) + 4;
4365 }
4366 @@ -964,11 +1087,89 @@
4367 static FUNC_RECV(receive_user_user)
4368 {
4369 call->useruserprotocoldisc = ie->data[0] & 0xff;
4370 - if (call->useruserprotocoldisc == 4) /* IA5 */
4371 - q931_get_number((unsigned char *) call->useruserinfo, sizeof(call->useruserinfo), ie->data + 1, len - 3);
4372 + if (call->useruserprotocoldisc == 4) { /* IA5 */
4373 + if (len >= 3) {
4374 + q931_get_number(call->useruserinfo, sizeof(call->useruserinfo), ie->data + 1, len - 3);
4375 + } else {
4376 + pri_error(call->pri, "User-User Information (len=%2d) too short.\n", len);
4377 + }
4378 + }
4379 return 0;
4380 }
4381
4382 +static FUNC_RECV(receive_call_identity)
4383 +{
4384 + if (len >= 2) {
4385 + q931_get_number(call->callid, sizeof(call->callid), ie->data, len - 2);
4386 + } else {
4387 + pri_error(call->pri, "Call Identity (len=%2d) too short.\n", len);
4388 + }
4389 + return 0;
4390 +}
4391 +
4392 +static FUNC_SEND(transmit_call_identity)
4393 +{
4394 + if (strlen(call->callid))
4395 + memcpy(ie->data , call->callid, strlen(call->callid));
4396 + return strlen(call->callednum) + 3;
4397 +}
4398 +
4399 +static FUNC_RECV(receive_high_layer_compat)
4400 +{
4401 + return 0;
4402 +}
4403 +
4404 +static FUNC_SEND(transmit_high_layer_compat)
4405 +{
4406 + if (call->transcapability != PRI_TRANS_CAP_RESTRICTED_DIGITAL && call->transcapability != PRI_TRANS_CAP_DIGITAL && call->transcapability != PRI_TRANS_CAP_DIGITAL_W_TONES) {
4407 + ie->data[0] = 0x91;
4408 + ie->data[1] = 0x81;
4409 + return 4;
4410 + }
4411 + return 0;
4412 +}
4413 +
4414 +static FUNC_DUMP(dump_high_layer_compat)
4415 +{
4416 + int x;
4417 + pri_message(pri, "%c High-layer compatibilty (len=%2d) [ ", prefix, len);
4418 + for (x=0;x<ie->len;x++)
4419 + pri_message(pri, "0x%02X ", ie->data[x]);
4420 + pri_message(pri, " ]\n");
4421 +}
4422 +
4423 +
4424 +static FUNC_RECV(receive_low_layer_compat)
4425 +{
4426 + if (len > 0) {
4427 + if (len > 16) {
4428 + pri_error(pri, "%d bytes LLC too long\n", len);
4429 + call->llc[0] = 0;
4430 + } else {
4431 + pri_error(pri, "copying %d bytes LLC \n", len);
4432 + call->llc[0] = len;
4433 + memcpy(call->llc+1, ie->data, len);
4434 + }
4435 + }
4436 + return 0;
4437 +}
4438 +
4439 +static FUNC_SEND(transmit_low_layer_compat)
4440 +{
4441 + if (call->llc[0] == 0) return 0;
4442 + memcpy(ie->data, call->llc + 1, call->llc[0]);
4443 + return call->llc[0] + 2;
4444 +}
4445 +
4446 +static FUNC_DUMP(dump_low_layer_compat)
4447 +{
4448 + int x;
4449 + pri_message(pri, "%c Low-layer compatibilty (len=%2d) [ ", prefix, len);
4450 + for (x=0;x<ie->len;x++)
4451 + pri_message(pri, "0x%02X ", ie->data[x]);
4452 + pri_message(pri, " ]\n");
4453 +}
4454 +
4455 static FUNC_SEND(transmit_user_user)
4456 {
4457 int datalen = strlen(call->useruserinfo);
4458 @@ -1050,22 +1251,41 @@
4459 data++;
4460 len--;
4461 }
4462 - q931_get_number((unsigned char *) call->callername, sizeof(call->callername), data, len - 2);
4463 + if (msgtype == Q931_SETUP) {
4464 + /* we treat display IEs in the SETUP msg as callername */
4465 + if (len >= 2) {
4466 + q931_get_number(call->callername, sizeof(call->callername), data, len - 2);
4467 + } else {
4468 + pri_error(call->pri, "Display (len=%2d) too short.\n", len);
4469 + }
4470 + } else {
4471 + /* in other msgs we will pass it as text to chan_zap */
4472 + if (len >= 2) {
4473 + q931_get_number(call->display, sizeof(call->display), data, len - 2);
4474 + } else {
4475 + pri_error(call->pri, "Display (len=%2d) too short.\n", len);
4476 + }
4477 + }
4478 return 0;
4479 }
4480
4481 static FUNC_SEND(transmit_display)
4482 {
4483 int i;
4484 - if ((pri->switchtype != PRI_SWITCH_NI1) && (pri->switchtype != PRI_SWITCH_QSIG)
4485 - && *call->callername) {
4486 + int cpe = pri->localtype == BRI_CPE || pri->localtype == BRI_CPE_PTMP || pri->localtype == PRI_CPE;
4487 + if ((pri->switchtype != PRI_SWITCH_NI1) && (pri->switchtype != PRI_SWITCH_QSIG) && strlen(call->callername) && !cpe) {
4488 i = 0;
4489 if(pri->switchtype != PRI_SWITCH_EUROISDN_E1) {
4490 ie->data[0] = 0xb1;
4491 ++i;
4492 }
4493 - memcpy(ie->data + i, call->callername, strlen(call->callername));
4494 - return 2 + i + strlen(call->callername);
4495 + if (msgtype == Q931_SETUP_ACKNOWLEDGE) {
4496 + memcpy(ie->data + i, call->display, strlen(call->display));
4497 + return 2 + i + strlen(call->display);
4498 + } else {
4499 + memcpy(ie->data + i, call->callername, strlen(call->callername));
4500 + return 2 + i + strlen(call->callername);
4501 + }
4502 }
4503 return 0;
4504 }
4505 @@ -1112,6 +1332,111 @@
4506 return 0;
4507 }
4508
4509 + #if 0
4510 + static FUNC_RECV(receive_facility_kpj)
4511 + {
4512 + unsigned char cpt_tag, cp_len, invoke_id_tag, invoke_id_len, operation_value_len, operation_value_tag;
4513 + unsigned char arg_len = 0;
4514 + unsigned char pos = 0;
4515 + short invoke_id = 0, operation_value = 0;
4516 + if ((ie->data[pos++] & 0x1F) == 0x11) {
4517 + /* service discriminator == supplementary services */
4518 + cpt_tag = ie->data[pos++] & 0x1F;
4519 + cp_len = ie->data[pos++];
4520 + switch (cpt_tag) {
4521 + case 1: /* invoke */
4522 + invoke_id_tag = ie->data[pos++];
4523 + if (invoke_id_tag != 0x02) {
4524 + // pri_error(call->pri, "invoke id tag != 0x02\n");
4525 + break;
4526 + }
4527 + invoke_id_len = ie->data[pos++]; // 4
4528 + while (invoke_id_len > 0) {
4529 + invoke_id = (invoke_id << 8) | (ie->data[pos++] & 0xFF);
4530 + invoke_id_len--;
4531 + }
4532 + operation_value_tag = ie->data[pos++];
4533 + if (operation_value_tag != 0x02) {
4534 + // pri_error(call->pri, "operation value tag != 0x02\n");
4535 + break;
4536 + }
4537 + operation_value_len = ie->data[pos++];
4538 + while (operation_value_len > 0) {
4539 + operation_value = (operation_value << 8) | (ie->data[pos++] & 0xFF);
4540 + operation_value_len--;
4541 + }
4542 + arg_len = ie->len - pos;
4543 + switch (operation_value) {
4544 + case 0x06: /* ECT execute */
4545 + call->facility = operation_value;
4546 + break;
4547 + case 0x0D: /* call deflection */
4548 + call->facility = operation_value;
4549 + /* dirty hack! */
4550 + arg_len -= 6;
4551 + if (arg_len > 0) {
4552 + pos += 6;
4553 + q931_get_number(call->redirectingnum, sizeof(call->redirectingnum), ie->data + pos, arg_len);
4554 + }
4555 + /* now retrieve the number */
4556 + break;
4557 + case 0x22: /* AOC-D */
4558 + break;
4559 + case 0x24: /* AOC-E */
4560 + break;
4561 + }
4562 + break;
4563 + case 2: /* return result */
4564 + break;
4565 + case 3: /* return error */
4566 + break;
4567 + case 4: /* reject */
4568 + break;
4569 + }
4570 + } else {
4571 + /* OLD DIRTY ULAW HACK */
4572 + if (ie->len < 14) {
4573 + pri_error(call->pri, "!! Facility message shorter than 14 bytes\n");
4574 + return 0;
4575 + }
4576 + if (ie->data[13] + 14 == ie->len) {
4577 + q931_get_number(call->callername, sizeof(call->callername) - 1, ie->data + 14, ie->len - 14);
4578 + }
4579 + call->facility = 0x0;
4580 + }
4581 + return 0;
4582 + }
4583 +
4584 + static FUNC_SEND(transmit_facility_kpj)
4585 + {
4586 + int i = 0;
4587 + return i;
4588 + if (call->aoc && (pri->switchtype == PRI_SWITCH_EUROISDN_E1) && ((pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_NETWORK_PTMP) || (pri->localtype == PRI_NETWORK))) {
4589 + ie->data[0] = 0x90; /* PP remote operations */
4590 + ie->data[i++] = 0x00; /* component tag */
4591 + ie->data[i++] = 0x02; /* invoke id tag */
4592 + ie->data[i++] = 0x02; /* invoke id len */
4593 + ie->data[i++] = 0x34; /* invoke id */
4594 + ie->data[i++] = 0x56; /* invoke id */
4595 + ie->data[i++] = 0x02; /* operation value tag */
4596 + ie->data[i++] = 0x01; /* operation value len */
4597 + switch (msgtype) {
4598 + case Q931_SETUP:
4599 + ie->data[i++] = 0x26; /* operation value AOC-S */
4600 + break;
4601 + case Q931_DISCONNECT:
4602 + ie->data[i++] = 0x24; /* operation value AOC-E */
4603 + break;
4604 + default:
4605 + ie->data[i++] = 0x22; /* operation value AOC-D */
4606 + break;
4607 + }
4608 + // ARGUMENTS!
4609 + }
4610 + // return 2 + i;
4611 + }
4612 +#endif
4613 +
4614 static FUNC_SEND(transmit_facility)
4615 {
4616 struct apdu_event *tmp;
4617 @@ -1138,6 +1463,182 @@
4618 return i + 2;
4619 }
4620
4621 +#if 0
4622 +static FUNC_SEND(transmit_facility)
4623 +{
4624 + int i = 0, j, first_i, compsp = 0;
4625 + struct rose_component *comp, *compstk[10];
4626 + unsigned char namelen = strlen(call->callername);
4627 +
4628 + if ((pri->switchtype == PRI_SWITCH_NI2) && (namelen > 15))
4629 + namelen = 15; /* According to GR-1367, for NI2 switches it can't be > 15 characters */
4630 + if ((namelen > 0) && ((pri->switchtype == PRI_SWITCH_QSIG) ||
4631 + ((pri->switchtype == PRI_SWITCH_NI2) && (pri->localtype == PRI_NETWORK)))) {
4632 + do {
4633 + first_i = i;
4634 + ie->data[i] = 0x80 | Q932_PROTOCOL_EXTENSIONS;
4635 + i++;
4636 + /* Interpretation component */
4637 + ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, ie->data, i, 0x00 /* Discard unrecognized invokes */);
4638 +
4639 + /* Invoke ID */
4640 + ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, ie->data, i);
4641 + ASN1_PUSH(compstk, compsp, comp);
4642 +
4643 + /* Invoke component contents */
4644 + /* Invoke ID */
4645 + ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, ie->data, i, ++pri->last_invoke);
4646 +
4647 + /* Operation Tag */
4648 + ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, ie->data, i, SS_CNID_CALLINGNAME);
4649 +
4650 + /* Arugement Tag */
4651 + j = asn1_string_encode(ROSE_NAME_PRESENTATION_ALLOWED_SIMPLE, &ie->data[i], len - i, 15, call->callername, namelen);
4652 + if (j < 0) {
4653 + i = first_i;
4654 + break;
4655 + }
4656 + i += j;
4657 +
4658 + /* Fix length of stacked components */
4659 + while(compsp > 0) {
4660 + ASN1_FIXUP(compstk, compsp, ie->data, i);
4661 + }
4662 + } while (0);
4663 + }
4664 + if (/*(pri->switchtype == PRI_SWITCH_EUROISDN_E1) &&*/ call->redirectingnum && strlen(call->redirectingnum)) {
4665 + if (!(first_i = i)) {
4666 + /* Add protocol information header */
4667 + ie->data[i++] = 0x80 | Q932_PROTOCOL_ROSE;
4668 + }
4669 +
4670 + /* ROSE invoke component */
4671 + ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, ie->data, i);
4672 + ASN1_PUSH(compstk, compsp, comp);
4673 +
4674 + /* ROSE invokeId component */
4675 + ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, ie->data, i, ++pri->last_invoke);
4676 +
4677 + /* ROSE operationId component */
4678 + ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, ie->data, i, ROSE_DIVERTING_LEG_INFORMATION2);
4679 +
4680 + /* ROSE ARGUMENT component */
4681 + ASN1_ADD_SIMPLE(comp, 0x30, ie->data, i);
4682 + ASN1_PUSH(compstk, compsp, comp);
4683 +
4684 + /* ROSE DivertingLegInformation2.diversionCounter component */
4685 + /* Always is 1 because other isn't available in the current design */
4686 + ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, ie->data, i, 1);
4687 +
4688 + /* ROSE DivertingLegInformation2.diversionReason component */
4689 + ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, ie->data, i, redirectingreason_from_q931(pri, call->redirectingreason));
4690 +
4691 + /* ROSE DivertingLegInformation2.divertingNr component */
4692 + ASN1_ADD_SIMPLE(comp, 0xA1, ie->data, i);
4693 + ASN1_PUSH(compstk, compsp, comp);
4694 +
4695 + /* Redirecting information always not screened */
4696 + switch(call->redirectingpres) {
4697 + case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
4698 + case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
4699 + if (call->redirectingnum && strlen(call->redirectingnum)) {
4700 + ASN1_ADD_SIMPLE(comp, 0xA0, ie->data, i);
4701 + ASN1_PUSH(compstk, compsp, comp);
4702 +
4703 + /* NPI of redirected number is not supported in the current design */
4704 + ASN1_ADD_SIMPLE(comp, 0xA1, ie->data, i);
4705 + ASN1_PUSH(compstk, compsp, comp);
4706 +
4707 + ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, ie->data, i, typeofnumber_from_q931(pri, call->redirectingplan >> 4));
4708 +
4709 + j = asn1_string_encode(ASN1_NUMERICSTRING, &ie->data[i], len - i, 20, call->redirectingnum, strlen(call->redirectingnum));
4710 + if (j < 0) {
4711 + i = first_i;
4712 + goto finish2;
4713 + }
4714 + i += j;
4715 + ASN1_FIXUP(compstk, compsp, ie->data, i);
4716 + ASN1_FIXUP(compstk, compsp, ie->data, i);
4717 + break;
4718 + }
4719 + /* fall through */
4720 + case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
4721 + case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
4722 + ASN1_ADD_SIMPLE(comp, 0x81, ie->data, i);
4723 + break;
4724 + /* Don't know how to handle this */
4725 + case PRES_ALLOWED_NETWORK_NUMBER:
4726 + case PRES_PROHIB_NETWORK_NUMBER:
4727 + case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
4728 + case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
4729 + ASN1_ADD_SIMPLE(comp, 0x81, ie->data, i);
4730 + break;
4731 + default:
4732 + pri_message(pri, "!! Undefined presentation value for redirecting number: %d\n", call->redirectingpres);
4733 + case PRES_NUMBER_NOT_AVAILABLE:
4734 + ASN1_ADD_SIMPLE(comp, 0x82, ie->data, i);
4735 + break;
4736 + }
4737 + ASN1_FIXUP(compstk, compsp, ie->data, i);
4738 +
4739 + /* ROSE DivertingLegInformation2.originalCalledNr component */
4740 + /* This information isn't supported by current design - duplicate divertingNr */
4741 + ASN1_ADD_SIMPLE(comp, 0xA2, ie->data, i);
4742 + ASN1_PUSH(compstk, compsp, comp);
4743 +
4744 + /* Redirecting information always not screened */
4745 + switch(call->redirectingpres) {
4746 + case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
4747 + case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
4748 + if (call->redirectingnum && strlen(call->redirectingnum)) {
4749 + ASN1_ADD_SIMPLE(comp, 0xA0, ie->data, i);
4750 + ASN1_PUSH(compstk, compsp, comp);
4751 +
4752 + ASN1_ADD_SIMPLE(comp, 0xA1, ie->data, i);
4753 + ASN1_PUSH(compstk, compsp, comp);
4754 +
4755 + ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, ie->data, i, typeofnumber_from_q931(pri, call->redirectingplan >> 4));
4756 +
4757 + j = asn1_string_encode(ASN1_NUMERICSTRING, &ie->data[i], len - i, 20, call->redirectingnum, strlen(call->redirectingnum));
4758 + if (j < 0) {
4759 + i = first_i;
4760 + goto finish2;
4761 + }
4762 + i += j;
4763 + ASN1_FIXUP(compstk, compsp, ie->data, i);
4764 + ASN1_FIXUP(compstk, compsp, ie->data, i);
4765 + break;
4766 + }
4767 + /* fall through */
4768 + case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
4769 + case PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
4770 + ASN1_ADD_SIMPLE(comp, 0x81, ie->data, i);
4771 + break;
4772 + /* Don't know how to handle this */
4773 + case PRES_ALLOWED_NETWORK_NUMBER:
4774 + case PRES_PROHIB_NETWORK_NUMBER:
4775 + case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
4776 + case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
4777 + ASN1_ADD_SIMPLE(comp, 0x81, ie->data, i);
4778 + break;
4779 + default:
4780 + pri_message(pri, "!! Undefined presentation value for redirecting number: %d\n", call->redirectingpres);
4781 + case PRES_NUMBER_NOT_AVAILABLE:
4782 + ASN1_ADD_SIMPLE(comp, 0x82, ie->data, i);
4783 + break;
4784 + }
4785 + ASN1_FIXUP(compstk, compsp, ie->data, i);
4786 +
4787 + /* Fix length of stacked components */
4788 + while(compsp > 0) {
4789 + ASN1_FIXUP(compstk, compsp, ie->data, i);
4790 + }
4791 + }
4792 +finish2:
4793 + return (i ? i+2 : 0);
4794 +}
4795 +#endif
4796 +
4797 static FUNC_RECV(receive_facility)
4798 {
4799 int i = 0;
4800 @@ -1346,6 +1847,7 @@
4801 pri_message(pri, " ]\n");
4802 }
4803
4804 +
4805 static FUNC_DUMP(dump_time_date)
4806 {
4807 pri_message(pri, "%c Time Date (len=%2d) [ ", prefix, len);
4808 @@ -1366,7 +1868,7 @@
4809
4810 static FUNC_DUMP(dump_keypad_facility)
4811 {
4812 - char tmp[64];
4813 + char tmp[64] = "";
4814
4815 if (ie->len == 0 || ie->len > sizeof(tmp))
4816 return;
4817 @@ -1377,28 +1879,49 @@
4818
4819 static FUNC_RECV(receive_keypad_facility)
4820 {
4821 - int mylen;
4822 + int mylen = 0;
4823
4824 if (ie->len == 0)
4825 return -1;
4826
4827 if (ie->len > (sizeof(call->digitbuf) - 1))
4828 - mylen = (sizeof(call->digitbuf) - 1);
4829 + mylen = sizeof(call->digitbuf) - 1;
4830 else
4831 mylen = ie->len;
4832
4833 - memcpy(call->digitbuf, ie->data, mylen);
4834 + strncpy(call->digitbuf, (char *) ie->data, mylen);
4835
4836 - call->digitbuf[mylen] = 0;
4837 + /* I must be really neurotic */
4838 + call->digitbuf[sizeof(call->digitbuf)-1] = '\0';
4839
4840 return 0;
4841 }
4842
4843 +static FUNC_RECV(receive_time_date)
4844 +{
4845 + return 0;
4846 +}
4847 +
4848 +static FUNC_SEND(transmit_time_date) {
4849 + time_t now;
4850 + struct tm *timedate;
4851 + time(&now);
4852 + timedate = localtime(&now);
4853 + ie->data[0] = timedate->tm_year - 100; // 1900+
4854 + ie->data[1] = timedate->tm_mon + 1;
4855 + ie->data[2] = timedate->tm_mday;
4856 + ie->data[3] = timedate->tm_hour;
4857 + ie->data[4] = timedate->tm_min;
4858 + return 7;
4859 +}
4860 +
4861 +
4862 +
4863 static FUNC_DUMP(dump_display)
4864 {
4865 int x, y;
4866 char *buf = malloc(len + 1);
4867 - char tmp[80];
4868 + char tmp[80]="";
4869 if (buf) {
4870 x=y=0;
4871 if ((x < ie->len) && (ie->data[x] & 0x80)) {
4872 @@ -1413,7 +1936,7 @@
4873 }
4874 }
4875
4876 -static void dump_ie_data(unsigned char *c, int len)
4877 +static void dump_ie_data(struct pri *pri, unsigned char *c, int len)
4878 {
4879 char tmp[1024] = "";
4880 int x=0;
4881 @@ -1423,7 +1946,7 @@
4882 ((*c >= 'a') && (*c <= 'z')) ||
4883 ((*c >= '0') && (*c <= '9'))) {
4884 if (!lastascii) {
4885 - if (*tmp) {
4886 + if (strlen(tmp)) {
4887 tmp[x++] = ',';
4888 tmp[x++] = ' ';
4889 }
4890 @@ -1435,7 +1958,7 @@
4891 if (lastascii) {
4892 tmp[x++] = '\'';
4893 }
4894 - if (*tmp) {
4895 + if (strlen(tmp)) {
4896 tmp[x++] = ',';
4897 tmp[x++] = ' ';
4898 }
4899 @@ -1448,14 +1971,14 @@
4900 }
4901 if (lastascii)
4902 tmp[x++] = '\'';
4903 - pri_message(NULL, tmp);
4904 + pri_message(pri, tmp);
4905 }
4906
4907 static FUNC_DUMP(dump_facility)
4908 {
4909 pri_message(pri, "%c Facility (len=%2d, codeset=%d) [ ", prefix, len, Q931_IE_CODESET(full_ie));
4910 - dump_ie_data(ie->data, ie->len);
4911 - pri_message(NULL, " ]\n");
4912 + dump_ie_data(pri, ie->data, ie->len);
4913 + pri_message(pri, " ]\n");
4914 }
4915
4916 static FUNC_DUMP(dump_network_spec_fac)
4917 @@ -1465,7 +1988,7 @@
4918 pri_message(pri, code2str(ie->data[1], facilities, sizeof(facilities) / sizeof(facilities[0])));
4919 }
4920 else
4921 - dump_ie_data(ie->data, ie->len);
4922 + dump_ie_data(pri, ie->data, ie->len);
4923 pri_message(pri, " ]\n");
4924 }
4925
4926 @@ -1932,8 +2455,8 @@
4927 { 1, Q931_REDIRECTING_SUBADDR, "Redirecting Subaddress", dump_redirecting_subaddr },
4928 { 0, Q931_TRANSIT_NET_SELECT, "Transit Network Selection" },
4929 { 1, Q931_RESTART_INDICATOR, "Restart Indicator", dump_restart_indicator, receive_restart_indicator, transmit_restart_indicator },
4930 - { 0, Q931_LOW_LAYER_COMPAT, "Low-layer Compatibility" },
4931 - { 0, Q931_HIGH_LAYER_COMPAT, "High-layer Compatibility" },
4932 + { 0, Q931_LOW_LAYER_COMPAT, "Low-layer Compatibility" , dump_low_layer_compat, receive_low_layer_compat, transmit_low_layer_compat },
4933 + { 1, Q931_HIGH_LAYER_COMPAT, "High-layer Compatibility" , dump_high_layer_compat, receive_high_layer_compat, transmit_high_layer_compat },
4934 { 1, Q931_PACKET_SIZE, "Packet Size" },
4935 { 1, Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility, transmit_facility },
4936 { 1, Q931_IE_REDIRECTION_NUMBER, "Redirection Number" },
4937 @@ -1942,11 +2465,11 @@
4938 { 1, Q931_IE_INFO_REQUEST, "Feature Request" },
4939 { 1, Q931_IE_FEATURE_IND, "Feature Indication" },
4940 { 1, Q931_IE_SEGMENTED_MSG, "Segmented Message" },
4941 - { 1, Q931_IE_CALL_IDENTITY, "Call Identity", dump_call_identity },
4942 + { 1, Q931_IE_CALL_IDENTITY, "Call Identity", dump_call_identity, receive_call_identity, transmit_call_identity },
4943 { 1, Q931_IE_ENDPOINT_ID, "Endpoint Identification" },
4944 { 1, Q931_IE_NOTIFY_IND, "Notification Indicator", dump_notify, receive_notify, transmit_notify },
4945 { 1, Q931_DISPLAY, "Display", dump_display, receive_display, transmit_display },
4946 - { 1, Q931_IE_TIME_DATE, "Date/Time", dump_time_date },
4947 + { 1, Q931_IE_TIME_DATE, "Date/Time", dump_time_date, receive_time_date, transmit_time_date },
4948 { 1, Q931_IE_KEYPAD_FACILITY, "Keypad Facility", dump_keypad_facility, receive_keypad_facility },
4949 { 0, Q931_IE_SIGNAL, "Signal", dump_signal },
4950 { 1, Q931_IE_SWITCHHOOK, "Switch-hook" },
4951 @@ -1954,6 +2477,7 @@
4952 { 1, Q931_IE_ESCAPE_FOR_EXT, "Escape for Extension" },
4953 { 1, Q931_IE_CALL_STATUS, "Call Status" },
4954 { 1, Q931_IE_CHANGE_STATUS, "Change Status" },
4955 + { 1, Q931_COLP, "Connect Line ID Presentation", dump_colp},
4956 { 1, Q931_IE_CONNECTED_ADDR, "Connected Number", dump_connected_number },
4957 { 1, Q931_IE_CONNECTED_NUM, "Connected Number", dump_connected_number },
4958 { 1, Q931_IE_ORIGINAL_CALLED_NUMBER, "Original Called Number", dump_redirecting_number, receive_redirecting_number, transmit_redirecting_number },
4959 @@ -2024,7 +2548,7 @@
4960 {
4961 if ((ie->ie & 0x80) != 0)
4962 return 1;
4963 - else
4964 + else
4965 return 2 + ie->len;
4966 }
4967
4968 @@ -2054,10 +2578,10 @@
4969 break;
4970 case 1:
4971 cr = h->crv[0];
4972 - if (cr & 0x80) {
4973 + /* if (cr & 0x80) {
4974 cr &= ~0x80;
4975 cr |= 0x8000;
4976 - }
4977 + } */
4978 break;
4979 default:
4980 pri_error(NULL, "Call Reference Length not supported: %d\n", h->crlen);
4981 @@ -2071,14 +2595,14 @@
4982 int full_ie = Q931_FULL_IE(codeset, ie->ie);
4983 int base_ie;
4984
4985 - pri_message(NULL, "%c [", prefix);
4986 - pri_message(NULL, "%02x", ie->ie);
4987 + pri_message(pri, "%c [", prefix);
4988 + pri_message(pri, "%02x", ie->ie);
4989 if (!(ie->ie & 0x80)) {
4990 - pri_message(NULL, " %02x", ielen(ie)-2);
4991 + pri_message(pri, " %02x", ielen(ie)-2);
4992 for (x = 0; x + 2 < ielen(ie); ++x)
4993 - pri_message(NULL, " %02x", ie->data[x]);
4994 + pri_message(pri, " %02x", ie->data[x]);
4995 }
4996 - pri_message(NULL, "]\n");
4997 + pri_message(pri, "]\n");
4998
4999 /* Special treatment for shifts */
5000 if((full_ie & 0xf0) == Q931_LOCKING_SHIFT)
5001 @@ -2098,14 +2622,46 @@
5002 pri_error(pri, "!! %c Unknown IE %d (len = %d)\n", prefix, base_ie, ielen(ie));
5003 }
5004
5005 -static q931_call *q931_getcall(struct pri *pri, int cr)
5006 +static q921_call *q921_getcall(struct pri *pri, struct q931_call *c, int tei)
5007 +{
5008 + q921_call *cur;
5009 + cur = c->phones;
5010 + while(cur) {
5011 + if (cur->tei == tei) {
5012 + return cur;
5013 + }
5014 + cur = cur->next;
5015 + }
5016 + /* No call exists, make a new one */
5017 + if (pri->debug & PRI_DEBUG_Q921_STATE)
5018 + pri_message(pri, "-- Making new q921 call for cref %d tei %d\n", c->cr, tei);
5019 + cur = malloc(sizeof(struct q921_call));
5020 + memset(cur, 0, sizeof(cur));
5021 + cur->tei = tei;
5022 + cur->proc = 0;
5023 + cur->channel = -1;
5024 + cur->next = c->phones;
5025 + c->phones = cur;
5026 + return cur;
5027 +}
5028 +
5029 +static q931_call *q931_getcall(struct pri *pri, int cr, int tei)
5030 {
5031 q931_call *cur, *prev;
5032 cur = *pri->callpool;
5033 prev = NULL;
5034 while(cur) {
5035 - if (cur->cr == cr)
5036 - return cur;
5037 + if ((pri->localtype == BRI_NETWORK_PTMP) && (tei >= 0)) {
5038 + // hmm...ok, we might be the 1st responding to the setup
5039 + // or it is really our call
5040 + if ((cur->cr == cr) && ((cur->tei == tei) || (cur->tei == 127)))
5041 + return cur;
5042 + // or we might not be the 1st responding, then we need to clone
5043 + // the call struct to hangup properly
5044 + } else {
5045 + if (cur->cr == cr)
5046 + return cur;
5047 + }
5048 prev = cur;
5049 cur = cur->next;
5050 }
5051 @@ -2118,6 +2674,7 @@
5052 /* Call reference */
5053 cur->cr = cr;
5054 cur->pri = pri;
5055 + cur->tei = tei;
5056 /* Append to end of list */
5057 if (prev)
5058 prev->next = cur;
5059 @@ -2133,24 +2690,42 @@
5060 do {
5061 cur = *pri->callpool;
5062 pri->cref++;
5063 - if (pri->cref > 32767)
5064 - pri->cref = 1;
5065 + if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
5066 + if (pri->cref > 32767)
5067 + pri->cref = 1;
5068 + } else {
5069 + // BRI
5070 + if (pri->cref > 255)
5071 + pri->cref = 1;
5072 + }
5073 while(cur) {
5074 - if (cur->cr == (0x8000 | pri->cref))
5075 - break;
5076 + if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
5077 + if (cur->cr == (0x8000 | pri->cref))
5078 + break;
5079 + } else {
5080 + // BRIs have only 1 bye cref
5081 + if (cur->cr == (0x80 | pri->cref))
5082 + break;
5083 + }
5084 cur = cur->next;
5085 }
5086 } while(cur);
5087 - return q931_getcall(pri, pri->cref | 0x8000);
5088 + if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
5089 + return q931_getcall(pri, pri->cref | 0x8000, 0);
5090 + } else {
5091 + // BRI
5092 + return q931_getcall(pri, pri->cref | 0x80, 0);
5093 + }
5094 }
5095
5096 -static void q931_destroy(struct pri *pri, int cr, q931_call *c)
5097 +static void q931_destroy(struct pri *pri, int cr, q931_call *c, int tei)
5098 {
5099 q931_call *cur, *prev;
5100 prev = NULL;
5101 cur = *pri->callpool;
5102 while(cur) {
5103 - if ((c && (cur == c)) || (!c && (cur->cr == cr))) {
5104 +// if ((c && (cur == c)) || (!c && (cur->cr == cr))) {
5105 + if ((c && (cur == c)) || (!c && ((cur->cr == cr) && ((pri->localtype != BRI_NETWORK_PTMP) || (cur->tei == tei))))) {
5106 if (prev)
5107 prev->next = cur->next;
5108 else
5109 @@ -2159,6 +2734,8 @@
5110 pri_message(pri, "NEW_HANGUP DEBUG: Destroying the call, ourstate %s, peerstate %s\n",callstate2str(cur->ourcallstate),callstate2str(cur->peercallstate));
5111 if (cur->retranstimer)
5112 pri_schedule_del(pri, cur->retranstimer);
5113 + if (cur->t303timer)
5114 + pri_schedule_del(pri, cur->t303timer);
5115 pri_call_apdu_queue_cleanup(cur);
5116 free(cur);
5117 return;
5118 @@ -2169,16 +2746,16 @@
5119 pri_error(pri, "Can't destroy call %d!\n", cr);
5120 }
5121
5122 -static void q931_destroycall(struct pri *pri, int cr)
5123 +static void q931_destroycall(struct pri *pri, int cr, int tei)
5124 {
5125 - return q931_destroy(pri, cr, NULL);
5126 + return q931_destroy(pri, cr, NULL, tei);
5127 }
5128
5129
5130 void __q931_destroycall(struct pri *pri, q931_call *c)
5131 {
5132 if (pri && c)
5133 - q931_destroy(pri,0, c);
5134 + q931_destroy(pri,0, c, c->tei);
5135 return;
5136 }
5137
5138 @@ -2290,6 +2867,10 @@
5139 {
5140 unsigned int x;
5141 int full_ie = Q931_FULL_IE(codeset, ie->ie);
5142 + if (ielen(ie) > Q931_IE_MAX_LEN) {
5143 + pri_error(pri, "!! Invalid IE length %d (len = %d)\n", full_ie, ielen(ie));
5144 + return -1;
5145 + }
5146 if (pri->debug & PRI_DEBUG_Q931_STATE)
5147 pri_message(pri, "-- Processing IE %d (cs%d, %s)\n", ie->ie, codeset, ie2str(full_ie));
5148 for (x=0;x<sizeof(ies) / sizeof(ies[0]);x++) {
5149 @@ -2307,21 +2888,36 @@
5150 return -1;
5151 }
5152
5153 -static void init_header(struct pri *pri, q931_call *call, unsigned char *buf, q931_h **hb, q931_mh **mhb, int *len)
5154 +static void init_header(struct pri *pri, q931_call *call, unsigned char *buf, q931_h **hb, q931_mh **mhb, int *len, int briflag)
5155 {
5156 /* Returns header and message header and modifies length in place */
5157 q931_h *h = (q931_h *)buf;
5158 - q931_mh * mh = (q931_mh *)(h->contents + 2);
5159 + q931_mh *mh;
5160 h->pd = pri->protodisc;
5161 h->x0 = 0; /* Reserved 0 */
5162 - h->crlen = 2; /* Two bytes of Call Reference. Invert the top bit to make it from our sense */
5163 - if (call->cr || call->forceinvert) {
5164 +
5165 + if (briflag == 1) {
5166 + mh = (q931_mh *)(h->contents + 1);
5167 + h->crlen = 1; /* One bytes of Call Reference. Invert the top bit to make it from our sense */
5168 + if (call->cr || call->forceinvert) {
5169 + h->crv[0] = (call->cr ^ 0x80);
5170 + } else {
5171 + /* Unless of course this has no call reference */
5172 + h->crv[0] = 0;
5173 + }
5174 + *len -= 4;
5175 + } else {
5176 + mh = (q931_mh *)(h->contents + 2);
5177 + h->crlen = 2; /* Two bytes of Call Reference. Invert the top bit to make it from our sense */
5178 + if (call->cr || call->forceinvert) {
5179 h->crv[0] = ((call->cr ^ 0x8000) & 0xff00) >> 8;
5180 h->crv[1] = (call->cr & 0xff);
5181 - } else {
5182 + } else {
5183 /* Unless of course this has no call reference */
5184 h->crv[0] = 0;
5185 h->crv[1] = 0;
5186 + }
5187 + *len -= 5;
5188 }
5189 if (pri->subchannel) {
5190 /* On GR-303, top bit is always 0 */
5191 @@ -2330,13 +2926,23 @@
5192 mh->f = 0;
5193 *hb = h;
5194 *mhb = mh;
5195 - *len -= 5;
5196 -
5197 }
5198
5199 -static int q931_xmit(struct pri *pri, q931_h *h, int len, int cr)
5200 +static int q931_xmit(struct pri *pri, q931_h *h, int len, int cr, int tei)
5201 {
5202 - q921_transmit_iframe(pri, h, len, cr);
5203 + q931_mh *mh;
5204 + if (pri->localtype == BRI_NETWORK_PTMP) {
5205 + mh = (q931_mh *)(h->contents + 1);
5206 + if (mh->msg == Q931_SETUP) {
5207 + q921_transmit_uframe(pri, h, len, cr, tei);
5208 + } else {
5209 + q921_transmit_iframe(pri, h, len, cr, tei);
5210 + }
5211 + } else if (pri->localtype == BRI_CPE_PTMP) {
5212 + q921_transmit_iframe(pri, h, len, cr, pri->tei);
5213 + } else {
5214 + q921_transmit_iframe(pri, h, len, cr, tei);
5215 + }
5216 /* The transmit operation might dump the q921 header, so logging the q931
5217 message body after the transmit puts the sections of the message in the
5218 right order in the log */
5219 @@ -2362,7 +2968,11 @@
5220
5221 memset(buf, 0, sizeof(buf));
5222 len = sizeof(buf);
5223 - init_header(pri, c, buf, &h, &mh, &len);
5224 + if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
5225 + init_header(pri, c, buf, &h, &mh, &len, 0);
5226 + } else {
5227 + init_header(pri, c, buf, &h, &mh, &len, 1);
5228 + }
5229 mh->msg = msgtype;
5230 x=0;
5231 codeset = 0;
5232 @@ -2397,11 +3007,34 @@
5233 }
5234 /* Invert the logic */
5235 len = sizeof(buf) - len;
5236 - q931_xmit(pri, h, len, 1);
5237 + if (pri->localtype == BRI_CPE_PTMP) {
5238 + q931_xmit(pri, h, len, 1, pri->tei);
5239 + } else {
5240 + q931_xmit(pri, h, len, 1, c->tei);
5241 + }
5242 c->acked = 1;
5243 return 0;
5244 }
5245
5246 +static int facility_ies[] = { Q931_IE_FACILITY, -1 };
5247 +
5248 +#if 0
5249 +int q931_facility_kpj(struct pri *pri, q931_call *c, int operation, char *arguments)
5250 +{
5251 + switch (operation) {
5252 + case 0x26: c->aoc = 1;
5253 + break;
5254 + case 0x24: c->aoc = 1;
5255 + break;
5256 + case 0x22: c->aoc = 1;
5257 + break;
5258 + default:
5259 + return -1;
5260 + }
5261 + return send_message(pri, c, Q931_FACILITY, facility_ies);
5262 +}
5263 +#endif
5264 +
5265 static int status_ies[] = { Q931_CAUSE, Q931_CALL_STATE, -1 };
5266
5267 static int q931_status(struct pri *pri, q931_call *c, int cause)
5268 @@ -2439,17 +3072,45 @@
5269 return send_message(pri, c, Q931_INFORMATION, information_ies);
5270 }
5271
5272 +static int information_display_ies[] = { Q931_DISPLAY, -1 };
5273 +
5274 +int q931_information_display(struct pri *pri, q931_call *c, char *display)
5275 +{
5276 + int res=0;
5277 + char temp[256];
5278 + if (!display) return -1;
5279 + strncpy(temp, c->callername, sizeof(temp));
5280 + strncpy(c->callername, display, sizeof(c->callername));
5281 + res = send_message(pri, c, Q931_INFORMATION, information_display_ies);
5282 + strncpy(c->callername, temp, sizeof(c->callername));
5283 + return res;
5284 +}
5285 +
5286 +int q931_add_display(struct pri *pri, q931_call *c, char *display)
5287 +{
5288 + strncpy(c->display, display, sizeof(c->display));
5289 + return 0;
5290 +}
5291 +
5292 +/* static int information_special_ies[] = { Q931_IE_SPECIAL, -1 };
5293 +static int q931_information_special(struct pri *pri, q931_call *c)
5294 +{
5295 + return send_message(pri, c, Q931_FACILITY, information_special_ies);
5296 +}
5297 +*/
5298 +
5299 +
5300 static int restart_ack_ies[] = { Q931_CHANNEL_IDENT, Q931_RESTART_INDICATOR, -1 };
5301
5302 static int restart_ack(struct pri *pri, q931_call *c)
5303 {
5304 c->ourcallstate = Q931_CALL_STATE_NULL;
5305 c->peercallstate = Q931_CALL_STATE_NULL;
5306 + c->chanflags &= ~FLAG_PREFERRED;
5307 + c->chanflags |= FLAG_EXCLUSIVE;
5308 return send_message(pri, c, Q931_RESTART_ACKNOWLEDGE, restart_ack_ies);
5309 }
5310
5311 -static int facility_ies[] = { Q931_IE_FACILITY, -1 };
5312 -
5313 int q931_facility(struct pri*pri, q931_call *c)
5314 {
5315 return send_message(pri, c, Q931_FACILITY, facility_ies);
5316 @@ -2463,7 +3124,6 @@
5317 if ((info > 0x2) || (info < 0x00))
5318 return 0;
5319 }
5320 -
5321 if (info >= 0)
5322 c->notify = info & 0x7F;
5323 else
5324 @@ -2506,6 +3166,8 @@
5325
5326 int q931_call_proceeding(struct pri *pri, q931_call *c, int channel, int info)
5327 {
5328 + // never send two PROCEEDINGs!
5329 + if (c->proc > 0) return 0;
5330 if (channel) {
5331 c->ds1no = (channel & 0xff00) >> 8;
5332 c->ds1explicit = (channel & 0x10000) >> 16;
5333 @@ -2532,8 +3194,12 @@
5334 static int alerting_ies[] = { -1 };
5335 #endif
5336
5337 +static int alerting_BRI_ies[] = { -1 };
5338 +
5339 int q931_alerting(struct pri *pri, q931_call *c, int channel, int info)
5340 {
5341 + // never send two ALERTINGs!
5342 + if (c->alert > 0) return 0;
5343 if (!c->proc)
5344 q931_call_proceeding(pri, c, channel, 0);
5345 if (info) {
5346 @@ -2544,14 +3210,130 @@
5347 c->progressmask = 0;
5348 c->ourcallstate = Q931_CALL_STATE_CALL_RECEIVED;
5349 c->peercallstate = Q931_CALL_STATE_CALL_DELIVERED;
5350 + c->alert = 1;
5351 c->alive = 1;
5352 - return send_message(pri, c, Q931_ALERTING, alerting_ies);
5353 + if ((pri->localtype == PRI_NETWORK) || (pri->localtype == PRI_CPE)) {
5354 + return send_message(pri, c, Q931_ALERTING, alerting_ies);
5355 + } else {
5356 + if ((pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_NETWORK_PTMP)) {
5357 + return send_message(pri, c, Q931_ALERTING, alerting_ies);
5358 + } else {
5359 + /* no PROGRESS_INDICATOR for BRI please */
5360 + return send_message(pri, c, Q931_ALERTING, alerting_BRI_ies);
5361 + }
5362 + }
5363 +}
5364 +
5365 +static int hold_acknowledge_ies[] = { -1 };
5366 +
5367 +int q931_hold_acknowledge(struct pri *pri, q931_call *c)
5368 +{
5369 + return send_message(pri, c, Q931_HOLD_ACKNOWLEDGE, hold_acknowledge_ies);
5370 +}
5371 +
5372 +static int hold_reject_ies[] = { Q931_CAUSE, -1 };
5373 +
5374 +int q931_hold_reject(struct pri *pri, q931_call *c)
5375 +{
5376 + c->cause = 12;
5377 + c->causecode = CODE_CCITT;
5378 + c->causeloc = LOC_PRIV_NET_LOCAL_USER;
5379 + return send_message(pri, c, Q931_HOLD_REJECT, hold_reject_ies);
5380 +}
5381 +
5382 +static int retrieve_acknowledge_ies[] = { Q931_CHANNEL_IDENT, -1 };
5383 +
5384 +int q931_retrieve_acknowledge(struct pri *pri, q931_call *c, int channel)
5385 +{
5386 + if (channel)
5387 + c->channelno = channel;
5388 + c->chanflags &= ~FLAG_PREFERRED;
5389 + c->chanflags |= FLAG_EXCLUSIVE;
5390 + return send_message(pri, c, Q931_RETRIEVE_ACKNOWLEDGE, retrieve_acknowledge_ies);
5391 +}
5392 +
5393 +static int retrieve_reject_ies[] = { -1 };
5394 +
5395 +int q931_retrieve_reject(struct pri *pri, q931_call *c)
5396 +{
5397 + return send_message(pri, c, Q931_RETRIEVE_REJECT, retrieve_reject_ies);
5398 }
5399
5400 -static int connect_ies[] = { Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, -1 };
5401 +static int suspend_acknowledge_ies[] = { Q931_DISPLAY, -1 };
5402 +
5403 +int q931_suspend_acknowledge(struct pri *pri, q931_call *c, char *display)
5404 +{
5405 + char tempcallername[256];
5406 + int res;
5407 + c->ourcallstate = Q931_CALL_STATE_NULL;
5408 + c->peercallstate = Q931_CALL_STATE_NULL;
5409 + strncpy(tempcallername,c->callername,sizeof(tempcallername));
5410 + strncpy(c->callername,display,sizeof(c->callername));
5411 + res = send_message(pri, c, Q931_SUSPEND_ACKNOWLEDGE, suspend_acknowledge_ies);
5412 + strncpy(c->callername,tempcallername,sizeof(c->callername));
5413 + __q931_destroycall(pri, c);
5414 + return res;
5415 +}
5416 +
5417 +static int suspend_reject_ies[] = { Q931_DISPLAY, Q931_CAUSE, -1 };
5418 +
5419 +int q931_suspend_reject(struct pri *pri, q931_call *c, char *display)
5420 +{
5421 + char tempcallername[256];
5422 + int res;
5423 + strncpy(tempcallername,c->callername,sizeof(tempcallername));
5424 + strncpy(c->callername,display,sizeof(c->callername));
5425 + c->cause = 12;
5426 + c->causecode = CODE_CCITT;
5427 + c->causeloc = LOC_PRIV_NET_LOCAL_USER;
5428 + res = send_message(pri, c, Q931_SUSPEND_REJECT, suspend_reject_ies);
5429 + strncpy(c->callername,tempcallername,sizeof(c->callername));
5430 + return res;
5431 +}
5432 +
5433 +static int resume_reject_ies[] = { Q931_CAUSE, Q931_DISPLAY, -1 };
5434 +
5435 +int q931_resume_reject(struct pri *pri, q931_call *c, char *display)
5436 +{
5437 + char tempcallername[256];
5438 + int res;
5439 + c->cause = 12;
5440 + c->causecode = CODE_CCITT;
5441 + c->causeloc = LOC_PRIV_NET_LOCAL_USER;
5442 + strncpy(tempcallername,c->callername,sizeof(tempcallername));
5443 + strncpy(c->callername,display,sizeof(c->callername));
5444 + res = send_message(pri, c, Q931_RESUME_REJECT, resume_reject_ies);
5445 + strncpy(c->callername,tempcallername,sizeof(c->callername));
5446 + return res;
5447 +}
5448 +
5449 +static int resume_acknowledge_ies[] = { Q931_CHANNEL_IDENT, Q931_DISPLAY, -1 };
5450 +
5451 +int q931_resume_acknowledge(struct pri *pri, q931_call *c, int channel, char *display)
5452 +{
5453 + char tempcallername[256];
5454 + int res;
5455 + if (channel)
5456 + c->channelno = channel;
5457 + c->chanflags &= ~FLAG_PREFERRED;
5458 + c->chanflags |= FLAG_EXCLUSIVE;
5459 + c->alive = 1;
5460 + c->ourcallstate = Q931_CALL_STATE_ACTIVE;
5461 + c->peercallstate = Q931_CALL_STATE_ACTIVE;
5462 + strncpy(tempcallername,c->callername,sizeof(tempcallername));
5463 + strncpy(c->callername,display,sizeof(c->callername));
5464 + res = send_message(pri, c, Q931_RESUME_ACKNOWLEDGE, resume_acknowledge_ies);
5465 + strncpy(c->callername,tempcallername,sizeof(c->callername));
5466 + return res;
5467 +}
5468 +
5469 +
5470 +static int connect_ies[] = { Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, Q931_DISPLAY, -1 };
5471 +static int connect_NET_ies[] = { Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, Q931_IE_TIME_DATE, -1 };
5472
5473 int q931_setup_ack(struct pri *pri, q931_call *c, int channel, int nonisdn)
5474 {
5475 + int network = pri->localtype == PRI_NETWORK || pri->localtype == BRI_NETWORK || pri->localtype == BRI_NETWORK_PTMP;
5476 if (channel) {
5477 c->ds1no = (channel & 0xff00) >> 8;
5478 c->ds1explicit = (channel & 0x10000) >> 16;
5479 @@ -2569,9 +3351,39 @@
5480 c->ourcallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
5481 c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;
5482 c->alive = 1;
5483 + if (network) {
5484 + c->progloc = LOC_PRIV_NET_LOCAL_USER;
5485 + c->progcode = CODE_CCITT;
5486 + c->progressmask = Q931_PROG_INBAND_AVAILABLE;
5487 + }
5488 return send_message(pri, c, Q931_SETUP_ACKNOWLEDGE, connect_ies);
5489 }
5490
5491 +static void pri_setup_response_timeout(void *data)
5492 +{
5493 + struct q931_call *c = data;
5494 + struct pri *pri = NULL;
5495 + if (!c) return;
5496 + pri = c->pri;
5497 + if (!pri) return;
5498 + c->alive = 1;
5499 + c->cause = PRI_CAUSE_NO_USER_RESPONSE;
5500 + if (pri->debug & PRI_DEBUG_Q931_STATE)
5501 + pri_message(pri, "No response to SETUP message\n");
5502 + pri->schedev = 1;
5503 + pri->ev.e = PRI_EVENT_HANGUP;
5504 + pri->ev.hangup.channel = c->channelno;
5505 + pri->ev.hangup.cref = c->cr;
5506 + pri->ev.hangup.aoc_units = -1;
5507 + if (c->cause == -1) {
5508 + pri->ev.hangup.cause = PRI_CAUSE_SWITCH_CONGESTION;
5509 + } else {
5510 + pri->ev.hangup.cause = c->cause;
5511 + }
5512 + pri->ev.hangup.call = c;
5513 + q931_hangup(pri, c, c->cause);
5514 +}
5515 +
5516 static void pri_connect_timeout(void *data)
5517 {
5518 struct q931_call *c = data;
5519 @@ -2624,6 +3436,7 @@
5520
5521 int q931_connect(struct pri *pri, q931_call *c, int channel, int nonisdn)
5522 {
5523 + int network = pri->localtype == PRI_NETWORK || pri->localtype == BRI_NETWORK || pri->localtype == BRI_NETWORK_PTMP;
5524 if (channel) {
5525 c->ds1no = (channel & 0xff00) >> 8;
5526 c->ds1explicit = (channel & 0x10000) >> 16;
5527 @@ -2638,22 +3451,37 @@
5528 c->progressmask = PRI_PROG_CALLED_NOT_ISDN;
5529 } else
5530 c->progressmask = 0;
5531 - c->ourcallstate = Q931_CALL_STATE_CONNECT_REQUEST;
5532 + if (network) {
5533 + /* WE decide when the call is up and active */
5534 + c->ourcallstate = Q931_CALL_STATE_ACTIVE;
5535 + } else {
5536 + c->ourcallstate = Q931_CALL_STATE_CONNECT_REQUEST;
5537 + }
5538 c->peercallstate = Q931_CALL_STATE_ACTIVE;
5539 c->alive = 1;
5540 + c->con_acked = 0;
5541 /* Setup timer */
5542 if (c->retranstimer)
5543 pri_schedule_del(pri, c->retranstimer);
5544 c->retranstimer = 0;
5545 - if ((pri->localtype == PRI_CPE) && (!pri->subchannel))
5546 + if (!network && (!pri->subchannel)) {
5547 + /* make sure that CPEs get a CONNECT_ACKNOWLEDGE */
5548 c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T313], pri_connect_timeout, c);
5549 - return send_message(pri, c, Q931_CONNECT, connect_ies);
5550 + }
5551 + if ((pri->localtype != PRI_CPE) && (pri->localtype != BRI_CPE) && (pri->localtype != BRI_CPE_PTMP)) {
5552 + // networks may send datetime
5553 + return send_message(pri, c, Q931_CONNECT, connect_NET_ies);
5554 + } else {
5555 + return send_message(pri, c, Q931_CONNECT, connect_ies);
5556 + }
5557 }
5558
5559 +static int release_aoce_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, Q931_IE_FACILITY, -1 };
5560 static int release_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, -1 };
5561
5562 int q931_release(struct pri *pri, q931_call *c, int cause)
5563 {
5564 + int network = pri->localtype == PRI_NETWORK || pri->localtype == BRI_NETWORK || pri->localtype == BRI_NETWORK_PTMP;
5565 c->ourcallstate = Q931_CALL_STATE_RELEASE_REQUEST;
5566 /* c->peercallstate stays the same */
5567 if (c->alive) {
5568 @@ -2669,7 +3497,14 @@
5569 } else {
5570 c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T308], pri_release_finaltimeout, c);
5571 }
5572 - return send_message(pri, c, Q931_RELEASE, release_ies);
5573 + if (network && (c->aoc_units > -1)) {
5574 + /* include FACILITY IE for AOC-E */
5575 + aoc_aoce_charging_unit_encode(pri, c , c->aoc_units, Q931_RELEASE);
5576 + c->aoc_units = -1;
5577 + return send_message(pri, c, Q931_RELEASE, release_aoce_ies);
5578 + } else {
5579 + return send_message(pri, c, Q931_RELEASE, release_ies);
5580 + }
5581 } else
5582 return send_message(pri, c, Q931_RELEASE_COMPLETE, release_ies); /* Yes, release_ies, not release_complete_ies */
5583 } else
5584 @@ -2681,7 +3516,7 @@
5585 int q931_restart(struct pri *pri, int channel)
5586 {
5587 struct q931_call *c;
5588 - c = q931_getcall(pri, 0 | 0x8000);
5589 + c = q931_getcall(pri, 0 | 0x8000, 0);
5590 if (!c)
5591 return -1;
5592 if (!channel)
5593 @@ -2698,10 +3533,12 @@
5594 return send_message(pri, c, Q931_RESTART, restart_ies);
5595 }
5596
5597 +static int disconnect_aoce_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, Q931_IE_FACILITY, -1 };
5598 static int disconnect_ies[] = { Q931_CAUSE, Q931_IE_USER_USER, -1 };
5599
5600 int q931_disconnect(struct pri *pri, q931_call *c, int cause)
5601 {
5602 + int network = pri->localtype == PRI_NETWORK || pri->localtype == BRI_NETWORK || pri->localtype == BRI_NETWORK_PTMP;
5603 c->ourcallstate = Q931_CALL_STATE_DISCONNECT_REQUEST;
5604 c->peercallstate = Q931_CALL_STATE_DISCONNECT_INDICATION;
5605 if (c->alive) {
5606 @@ -2713,14 +3550,27 @@
5607 if (c->retranstimer)
5608 pri_schedule_del(pri, c->retranstimer);
5609 c->retranstimer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T305], pri_disconnect_timeout, c);
5610 - return send_message(pri, c, Q931_DISCONNECT, disconnect_ies);
5611 + if (network && (c->aoc_units > -1)) {
5612 + /* include FACILITY IE for AOC-E */
5613 + aoc_aoce_charging_unit_encode(pri, c , c->aoc_units, Q931_DISCONNECT);
5614 + c->aoc_units = -1;
5615 + return send_message(pri, c, Q931_DISCONNECT, disconnect_aoce_ies);
5616 + } else {
5617 + return send_message(pri, c, Q931_DISCONNECT, disconnect_ies);
5618 + }
5619 } else
5620 return 0;
5621 }
5622
5623 +//static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_DISPLAY, Q931_PROGRESS_INDICATOR,
5624 +// Q931_IE_SIGNAL, Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_SENDING_COMPLETE, -1 };
5625 +
5626 static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, Q931_NETWORK_SPEC_FAC, Q931_DISPLAY, Q931_IE_USER_USER,
5627 Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_REDIRECTING_NUMBER, Q931_SENDING_COMPLETE, Q931_IE_ORIGINATING_LINE_INFO, Q931_IE_GENERIC_DIGITS, -1 };
5628
5629 +static int setup_bri_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_PROGRESS_INDICATOR, Q931_NETWORK_SPEC_FAC, Q931_DISPLAY, Q931_IE_USER_USER,
5630 + Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_REDIRECTING_NUMBER, Q931_SENDING_COMPLETE, Q931_IE_ORIGINATING_LINE_INFO, Q931_IE_GENERIC_DIGITS, Q931_HIGH_LAYER_COMPAT, Q931_LOW_LAYER_COMPAT, -1 };
5631 +
5632 static int gr303_setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, -1 };
5633
5634 static int cis_setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_IE_FACILITY, Q931_CALLED_PARTY_NUMBER, -1 };
5635 @@ -2728,7 +3578,12 @@
5636 int q931_setup(struct pri *pri, q931_call *c, struct pri_sr *req)
5637 {
5638 int res;
5639 -
5640 +
5641 + if (pri->localtype == BRI_NETWORK_PTMP) {
5642 + c->tei = 127;
5643 + } else {
5644 + c->tei = 0;
5645 + }
5646
5647 c->transcapability = req->transmode;
5648 c->transmoderate = TRANS_MODE_64_CIRCUIT;
5649 @@ -2753,6 +3608,7 @@
5650 c->chanflags = FLAG_EXCLUSIVE;
5651 else if (c->channelno)
5652 c->chanflags = FLAG_PREFERRED;
5653 + memcpy(c->llc, req->llc, sizeof(c->llc));
5654 if (req->caller) {
5655 libpri_copy_string(c->callernum, req->caller, sizeof(c->callernum));
5656 c->callerplan = req->callerplan;
5657 @@ -2812,14 +3668,19 @@
5658 res = send_message(pri, c, Q931_SETUP, gr303_setup_ies);
5659 else if (c->justsignalling)
5660 res = send_message(pri, c, Q931_SETUP, cis_setup_ies);
5661 + else if (pri->localtype == BRI_NETWORK || pri->localtype == BRI_NETWORK_PTMP)
5662 + res = send_message(pri, c, Q931_SETUP, setup_bri_ies);
5663 else
5664 res = send_message(pri, c, Q931_SETUP, setup_ies);
5665 +
5666 if (!res) {
5667 c->alive = 1;
5668 /* make sure we call PRI_EVENT_HANGUP_ACK once we send/receive RELEASE_COMPLETE */
5669 c->sendhangupack = 1;
5670 c->ourcallstate = Q931_CALL_STATE_CALL_INITIATED;
5671 c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;
5672 + c->t303timer = pri_schedule_event(pri, pri->timers[PRI_TIMER_T303], pri_setup_response_timeout, c);
5673 + c->t303running = 1;
5674 }
5675 return res;
5676
5677 @@ -2835,7 +3696,11 @@
5678 if (cause > -1) {
5679 c->cause = cause;
5680 c->causecode = CODE_CCITT;
5681 - c->causeloc = LOC_PRIV_NET_LOCAL_USER;
5682 + if ((pri->localtype == PRI_NETWORK) || (pri->localtype == BRI_NETWORK) || (pri->localtype == BRI_NETWORK_PTMP)) {
5683 + c->causeloc = LOC_PRIV_NET_LOCAL_USER;
5684 + } else {
5685 + c->causeloc = LOC_USER;
5686 + }
5687 /* release_ies has CAUSE in it */
5688 res = send_message(pri, c, Q931_RELEASE_COMPLETE, release_ies);
5689 } else
5690 @@ -2860,6 +3725,125 @@
5691 return 0;
5692 }
5693
5694 +/* here we cleanly hangup the phones that responded to our call but didnt get the call */
5695 +int q921_hangup(struct pri *pri, q931_call *c, int tei)
5696 +{
5697 + q921_call *cur,*prev;
5698 + int tc;
5699 + int ttei;
5700 + int res=0;
5701 +
5702 + if (!pri || !c)
5703 + return -1;
5704 +
5705 + if (pri->localtype != BRI_NETWORK_PTMP){
5706 + return 0;
5707 + }
5708 +// pri_error(pri, "q921_hangup(%d, %d)\n", c->cr, tei);
5709 +
5710 + if (tei == 127) {
5711 + tei = c->tei;
5712 + }
5713 +// pri_error(pri, "tei %d\n", tei);
5714 +
5715 + cur = c->phones;
5716 +
5717 + tc = c->cause;
5718 + ttei = c->tei;
5719 + while (cur) {
5720 + if (cur->tei != tei) {
5721 + c->cause = PRI_CAUSE_NORMAL_CLEARING;
5722 + c->tei = cur->tei;
5723 + if (pri->debug & PRI_DEBUG_Q921_STATE)
5724 + pri_message(pri, "sending RELEASE for TEI %d\n", cur->tei);
5725 + send_message(pri, c, Q931_RELEASE, release_ies);
5726 + }
5727 + prev = cur;
5728 + cur = cur->next;
5729 + if (prev) {
5730 + free(prev);
5731 + prev = NULL;
5732 + }
5733 + }
5734 + c->phones = NULL;
5735 + c->tei = ttei;
5736 + c->cause = tc;
5737 +
5738 + if (c->tei == 127) {
5739 + q931_destroycall(pri, c->cr, c->tei);
5740 + // make sure * frees the channel
5741 +/* pri_error(pri, "returning PRI_EVENT_HANGUP_ACK\n");
5742 + res = Q931_RES_HAVEEVENT;
5743 + pri->ev.hangup.channel = c->channelno;
5744 + pri->ev.e = PRI_EVENT_HANGUP_ACK; */
5745 + }
5746 + return res;
5747 +}
5748 +
5749 +/* here we handle release_completes from the phones
5750 + because some (elmeg) phones do not send a disconnect
5751 + message when the phone is busy */
5752 +int q921_handle_hangup(struct pri *pri, q931_call *c, int tei)
5753 +{
5754 + q921_call *cur,*match,*prev=NULL;
5755 + int left=0;
5756 + int res=0;
5757 +
5758 + if (!pri || !c)
5759 + return -1;
5760 +
5761 + if (pri->localtype != BRI_NETWORK_PTMP){
5762 + return 0;
5763 + }
5764 +
5765 + cur = c->phones;
5766 +
5767 + while (cur) {
5768 + if (cur->tei == tei) {
5769 + match = cur;
5770 + if (prev) {
5771 + prev->next = cur->next;
5772 + cur = prev;
5773 + } else {
5774 + c->phones = cur->next;
5775 + }
5776 + free(match);
5777 + }
5778 + prev = cur;
5779 + if (cur) cur = cur->next;
5780 + }
5781 +
5782 + cur = c->phones;
5783 +
5784 + while (cur) {
5785 + left++;
5786 + cur = cur->next;
5787 + }
5788 +
5789 + // if all phones have signalled busy AND the timer is not running anymore!
5790 +#ifdef FASTBUSYONBUSY
5791 + if ((c->cause == PRI_CAUSE_USER_BUSY) && (c->t303timer)) {
5792 + c->t303running = 0;
5793 + pri_schedule_del(pri, c->t303timer);
5794 + }
5795 +#endif
5796 +
5797 + if ((left==0) && (c->cause == PRI_CAUSE_USER_BUSY) && (c->t303running == 0)) {
5798 + // pri_error(pri, "q921_handle_hangup(%d, %d, %d)\n", c->cr, tei, c->tei);
5799 + // make sure * frees the channel
5800 + res = Q931_RES_HAVEEVENT;
5801 + pri->ev.hangup.cause = PRI_CAUSE_USER_BUSY;
5802 + pri->ev.hangup.channel = c->channelno | (c->ds1no << 8);
5803 + pri->ev.hangup.cref = c->cr;
5804 + pri->ev.hangup.call = c;
5805 + pri->ev.hangup.aoc_units = 0;
5806 + pri->ev.e = PRI_EVENT_HANGUP;
5807 + }
5808 + return res;
5809 + }
5810 +
5811 +
5812 +
5813 int q931_hangup(struct pri *pri, q931_call *c, int cause)
5814 {
5815 int disconnect = 1;
5816 @@ -2871,7 +3855,7 @@
5817 /* If mandatory IE was missing, insist upon that cause code */
5818 if (c->cause == PRI_CAUSE_MANDATORY_IE_MISSING)
5819 cause = c->cause;
5820 - if (cause == 34 || cause == 44 || cause == 82 || cause == 1 || cause == 81) {
5821 + if (cause == 34 || cause == 44 || cause == 82 || cause == 1 || cause == 81 || cause == 17) {
5822 /* We'll send RELEASE_COMPLETE with these causes */
5823 disconnect = 0;
5824 release_compl = 1;
5825 @@ -2885,7 +3869,7 @@
5826 case Q931_CALL_STATE_NULL:
5827 if (c->peercallstate == Q931_CALL_STATE_NULL)
5828 /* free the resources if we receive or send REL_COMPL */
5829 - q931_destroycall(pri, c->cr);
5830 + q931_destroycall(pri, c->cr, c->tei);
5831 else if (c->peercallstate == Q931_CALL_STATE_RELEASE_REQUEST)
5832 q931_release_complete(pri,c,cause);
5833 break;
5834 @@ -2911,6 +3895,11 @@
5835 /* received SETUP_ACKNOWLEDGE */
5836 /* send DISCONNECT in general */
5837 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) {
5838 + if (pri->localtype == BRI_NETWORK_PTMP) {
5839 + if (c->tei == 127) {
5840 + break;
5841 + }
5842 + }
5843 if (disconnect)
5844 q931_disconnect(pri,c,cause);
5845 else if (release_compl)
5846 @@ -2926,8 +3915,14 @@
5847 break;
5848 case Q931_CALL_STATE_DISCONNECT_INDICATION:
5849 /* received DISCONNECT */
5850 + if (pri->localtype == BRI_NETWORK_PTMP) {
5851 + if (c->tei == 127) {
5852 + break;
5853 + }
5854 + }
5855 if (c->peercallstate == Q931_CALL_STATE_DISCONNECT_REQUEST) {
5856 c->alive = 1;
5857 +// pri_error(pri, "sending release to %d\n", c->tei);
5858 q931_release(pri,c,cause);
5859 }
5860 break;
5861 @@ -2941,19 +3936,17 @@
5862 pri_error(pri, "q931_hangup shouldn't be called in this state, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate));
5863 break;
5864 default:
5865 - pri_error(pri, "We're not yet handling hanging up when our state is %d, contact support@digium.com, ourstate %s, peerstate %s\n",
5866 - c->ourcallstate,
5867 - callstate2str(c->ourcallstate),
5868 - callstate2str(c->peercallstate));
5869 + pri_error(pri, "We're not yet handling hanging up when our state is %d, contact support@digium.com, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate));
5870 return -1;
5871 }
5872 /* we did handle hangup properly at this point */
5873 return 0;
5874 }
5875
5876 -int q931_receive(struct pri *pri, q931_h *h, int len)
5877 +int q931_receive(struct pri *pri, q931_h *h, int len, int tei)
5878 {
5879 q931_mh *mh;
5880 + q921_call *l2c;
5881 q931_call *c;
5882 q931_ie *ie;
5883 unsigned int x;
5884 @@ -2965,6 +3958,7 @@
5885 int codeset, cur_codeset;
5886 int last_ie[8];
5887 struct apdu_event *cur = NULL;
5888 + int network = pri->localtype == PRI_NETWORK || pri->localtype == BRI_NETWORK || pri->localtype == BRI_NETWORK_PTMP;
5889
5890 memset(last_ie, 0, sizeof(last_ie));
5891 if (pri->debug & PRI_DEBUG_Q931_DUMP)
5892 @@ -2978,13 +3972,13 @@
5893 KLUDGE this by changing byte 4 from a 0xf (SERVICE)
5894 to a 0x7 (SERVICE ACKNOWLEDGE) */
5895 h->raw[h->crlen + 2] -= 0x8;
5896 - q931_xmit(pri, h, len, 1);
5897 + q931_xmit(pri, h, len, 1, tei);
5898 return 0;
5899 } else if (h->pd != pri->protodisc) {
5900 pri_error(pri, "Warning: unknown/inappropriate protocol discriminator received (%02x/%d)\n", h->pd, h->pd);
5901 return 0;
5902 }
5903 - c = q931_getcall(pri, q931_cr(h));
5904 + c = q931_getcall(pri, q931_cr(h), tei);
5905 if (!c) {
5906 pri_error(pri, "Unable to locate call %d\n", q931_cr(h));
5907 return -1;
5908 @@ -3007,6 +4001,7 @@
5909 case Q931_SETUP:
5910 if (pri->debug & PRI_DEBUG_Q931_STATE)
5911 pri_message(pri, "-- Processing Q.931 Call Setup\n");
5912 + c->tei = tei;
5913 c->channelno = -1;
5914 c->slotmap = -1;
5915 c->chanflags = 0;
5916 @@ -3027,28 +4022,44 @@
5917 c->callername[0] = '\0';
5918 c->callerani[0] = '\0';
5919 c->callerplanani = -1;
5920 - c->redirectingplan = -1;
5921 - c->redirectingpres = -1;
5922 - c->redirectingreason = -1;
5923 - c->origcalledplan = -1;
5924 - c->origcalledpres = -1;
5925 - c->origredirectingreason = -1;
5926 + c->redirectingplan = -1;
5927 + c->redirectingpres = -1;
5928 + c->redirectingreason = -1;
5929 + c->origcalledplan = -1;
5930 + c->origcalledpres = -1;
5931 + c->origredirectingreason = -1;
5932 c->redirectingnum[0] = '\0';
5933 c->origcallednum[0] = '\0';
5934 c->redirectingname[0] = '\0';
5935 c->origcalledname[0] = '\0';
5936 - c->useruserprotocoldisc = -1;
5937 + c->useruserprotocoldisc = -1;
5938 c->useruserinfo[0] = '\0';
5939 c->complete = 0;
5940 c->nonisdn = 0;
5941 c->aoc_units = -1;
5942 - /* Fall through */
5943 + c->digits[0] = '\0';
5944 + c->display[0] = '\0';
5945 + c->progress = -1;
5946 + c->progressmask = 0;
5947 + break;
5948 case Q931_CONNECT:
5949 + if (c->t303timer) {
5950 + c->t303running = 0;
5951 + pri_schedule_del(pri, c->t303timer);
5952 + }
5953 + c->useruserinfo[0] = '\0';
5954 + c->t303timer = 0;
5955 + c->progress = -1;
5956 + break;
5957 case Q931_ALERTING:
5958 case Q931_PROGRESS:
5959 - c->useruserinfo[0] = '\0';
5960 - c->cause = -1;
5961 + c->useruserinfo[0] = '\0';
5962 case Q931_CALL_PROCEEDING:
5963 + if (c->t303timer) {
5964 + c->t303running = 0;
5965 + pri_schedule_del(pri, c->t303timer);
5966 + }
5967 + c->t303timer = 0;
5968 c->progress = -1;
5969 c->progressmask = 0;
5970 break;
5971 @@ -3059,20 +4070,22 @@
5972 break;
5973 case Q931_RELEASE:
5974 case Q931_DISCONNECT:
5975 - c->cause = -1;
5976 - c->causecode = -1;
5977 - c->causeloc = -1;
5978 - c->aoc_units = -1;
5979 +// c->aoc_units = -1;
5980 + c->useruserinfo[0] = '\0';
5981 if (c->retranstimer)
5982 pri_schedule_del(pri, c->retranstimer);
5983 c->retranstimer = 0;
5984 - c->useruserinfo[0] = '\0';
5985 + if (c->t303timer) {
5986 + c->t303running = 0;
5987 + pri_schedule_del(pri, c->t303timer);
5988 + }
5989 + c->t303timer = 0;
5990 break;
5991 case Q931_RELEASE_COMPLETE:
5992 if (c->retranstimer)
5993 - pri_schedule_del(pri, c->retranstimer);
5994 + pri_schedule_del(pri, c->retranstimer);
5995 c->retranstimer = 0;
5996 - c->useruserinfo[0] = '\0';
5997 + c->useruserinfo[0] = '\0';
5998 case Q931_STATUS:
5999 c->cause = -1;
6000 c->causecode = -1;
6001 @@ -3089,22 +4102,32 @@
6002 case Q931_STATUS_ENQUIRY:
6003 break;
6004 case Q931_SETUP_ACKNOWLEDGE:
6005 + if (c->t303timer) {
6006 + c->t303running = 0;
6007 + pri_schedule_del(pri, c->t303timer);
6008 + }
6009 + c->t303timer = 0;
6010 break;
6011 case Q931_NOTIFY:
6012 break;
6013 + case Q931_HOLD:
6014 + break;
6015 + case Q931_RETRIEVE:
6016 + break;
6017 + case Q931_RESUME:
6018 + c->tei = tei;
6019 + break;
6020 + case Q931_SUSPEND:
6021 + break;
6022 case Q931_USER_INFORMATION:
6023 case Q931_SEGMENT:
6024 case Q931_CONGESTION_CONTROL:
6025 - case Q931_HOLD:
6026 case Q931_HOLD_ACKNOWLEDGE:
6027 case Q931_HOLD_REJECT:
6028 - case Q931_RETRIEVE:
6029 case Q931_RETRIEVE_ACKNOWLEDGE:
6030 case Q931_RETRIEVE_REJECT:
6031 - case Q931_RESUME:
6032 case Q931_RESUME_ACKNOWLEDGE:
6033 case Q931_RESUME_REJECT:
6034 - case Q931_SUSPEND:
6035 case Q931_SUSPEND_ACKNOWLEDGE:
6036 case Q931_SUSPEND_REJECT:
6037 pri_error(pri, "!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
6038 @@ -3113,7 +4136,7 @@
6039 pri_error(pri, "!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
6040 q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
6041 if (c->newcall)
6042 - q931_destroycall(pri,c->cr);
6043 + q931_destroycall(pri,c->cr,c->tei);
6044 return -1;
6045 }
6046 memset(mandies, 0, sizeof(mandies));
6047 @@ -3193,12 +4216,19 @@
6048 missingmand = 0;
6049 for (x=0;x<MAX_MAND_IES;x++) {
6050 if (mandies[x]) {
6051 - /* check if there is no channel identification when we're configured as network -> that's not an error */
6052 - if (((pri->localtype != PRI_NETWORK) || (mh->msg != Q931_SETUP) || (mandies[x] != Q931_CHANNEL_IDENT)) &&
6053 - ((mh->msg != Q931_PROGRESS) || (mandies[x] != Q931_PROGRESS_INDICATOR))) {
6054 - pri_error(pri, "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]));
6055 - missingmand++;
6056 + /* check if there is no channel identification when we're configured as network -> that's not an error */
6057 + if (network) {
6058 + if (((mh->msg == Q931_SETUP) && (mandies[x] == Q931_CHANNEL_IDENT)) ||
6059 + ((mh->msg == Q931_PROGRESS) && (mandies[x] == Q931_PROGRESS_INDICATOR))) {
6060 + /* according to ets 300 102-1 a progress indicator is mandatory, but so what? ;-) */
6061 + } else {
6062 + pri_error(pri, "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]));
6063 + missingmand++;
6064 }
6065 + } else {
6066 + pri_error(pri, "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]));
6067 + missingmand++;
6068 + }
6069 }
6070 }
6071
6072 @@ -3207,7 +4237,7 @@
6073 case Q931_RESTART:
6074 if (missingmand) {
6075 q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
6076 - q931_destroycall(pri, c->cr);
6077 + q931_destroycall(pri, c->cr, c->tei);
6078 break;
6079 }
6080 c->ourcallstate = Q931_CALL_STATE_RESTART;
6081 @@ -3225,6 +4255,7 @@
6082 }
6083 /* Must be new call */
6084 if (!c->newcall) {
6085 + pri_error(pri, "received SETUP message for call that is not a new call (retransmission). \n");
6086 break;
6087 }
6088 if (c->progressmask & PRI_PROG_CALLER_NOT_ISDN)
6089 @@ -3242,16 +4273,20 @@
6090 pri->ev.ring.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
6091 pri->ev.ring.callingpres = c->callerpres;
6092 pri->ev.ring.callingplan = c->callerplan;
6093 - pri->ev.ring.callingplanani = c->callerplanani;
6094 pri->ev.ring.callingplanrdnis = c->redirectingplan;
6095 pri->ev.ring.callingplanorigcalled = c->origcalledplan;
6096 pri->ev.ring.ani2 = c->ani2;
6097 libpri_copy_string(pri->ev.ring.callingani, c->callerani, sizeof(pri->ev.ring.callingani));
6098 + pri->ev.ring.callingplanani = c->callerplanani;
6099 libpri_copy_string(pri->ev.ring.callingnum, c->callernum, sizeof(pri->ev.ring.callingnum));
6100 libpri_copy_string(pri->ev.ring.callingname, c->callername, sizeof(pri->ev.ring.callingname));
6101 pri->ev.ring.calledplan = c->calledplan;
6102 libpri_copy_string(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr));
6103 - libpri_copy_string(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum));
6104 + if (!strlen(c->callednum) && strlen(c->digitbuf)) {
6105 + libpri_copy_string(pri->ev.ring.callednum, c->digitbuf, sizeof(pri->ev.ring.callednum));
6106 + } else {
6107 + libpri_copy_string(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum));
6108 + }
6109 libpri_copy_string(pri->ev.ring.origcalledname, c->origcalledname, sizeof(pri->ev.ring.origcalledname));
6110 libpri_copy_string(pri->ev.ring.origcallednum, c->origcallednum, sizeof(pri->ev.ring.origcallednum));
6111 libpri_copy_string(pri->ev.ring.redirectingnum, c->redirectingnum, sizeof(pri->ev.ring.redirectingnum));
6112 @@ -3261,11 +4296,13 @@
6113 pri->ev.ring.redirectingreason = c->redirectingreason;
6114 pri->ev.ring.origredirectingreason = c->origredirectingreason;
6115 pri->ev.ring.flexible = ! (c->chanflags & FLAG_EXCLUSIVE);
6116 - pri->ev.ring.cref = c->cr;
6117 + pri->ev.ring.tei = c->tei;
6118 pri->ev.ring.call = c;
6119 + pri->ev.ring.cref = c->cr;
6120 pri->ev.ring.layer1 = c->userl1;
6121 pri->ev.ring.complete = c->complete;
6122 pri->ev.ring.ctype = c->transcapability;
6123 + memcpy(pri->ev.ring.lowlayercompat, c->llc, sizeof(pri->ev.ring.lowlayercompat));
6124 pri->ev.ring.redirectingreason = c->redirectingreason;
6125 pri->ev.ring.progress = c->progress;
6126 pri->ev.ring.progressmask = c->progressmask;
6127 @@ -3275,6 +4312,9 @@
6128 q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
6129 break;
6130 }
6131 + if (pri->localtype == BRI_NETWORK_PTMP) {
6132 + l2c = q921_getcall(pri, c, tei);
6133 + }
6134 c->ourcallstate = Q931_CALL_STATE_CALL_DELIVERED;
6135 c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED;
6136 pri->ev.e = PRI_EVENT_RINGING;
6137 @@ -3295,17 +4335,24 @@
6138 q931_status(pri, c, PRI_CAUSE_WRONG_MESSAGE);
6139 break;
6140 }
6141 + /* TEI got the call */
6142 + c->tei = tei;
6143 c->ourcallstate = Q931_CALL_STATE_ACTIVE;
6144 c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST;
6145 pri->ev.e = PRI_EVENT_ANSWER;
6146 pri->ev.answer.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
6147 pri->ev.answer.cref = c->cr;
6148 pri->ev.answer.call = c;
6149 + pri->ev.answer.tei = c->tei;
6150 pri->ev.answer.progress = c->progress;
6151 pri->ev.answer.progressmask = c->progressmask;
6152 libpri_copy_string(pri->ev.answer.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo));
6153 c->useruserinfo[0] = '\0';
6154 q931_connect_acknowledge(pri, c);
6155 + if (pri->localtype == BRI_NETWORK_PTMP) {
6156 + /* Release all other TEIs */
6157 + q921_hangup(pri, c, tei);
6158 + }
6159 if (c->justsignalling) { /* Make sure WE release when we initiatie a signalling only connection */
6160 q931_release(pri, c, PRI_CAUSE_NORMAL_CLEARING);
6161 break;
6162 @@ -3313,23 +4360,43 @@
6163 return Q931_RES_HAVEEVENT;
6164 case Q931_FACILITY:
6165 if (c->newcall) {
6166 - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
6167 - break;
6168 - }
6169 - pri->ev.e = PRI_EVENT_FACNAME;
6170 - libpri_copy_string(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname));
6171 - libpri_copy_string(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingnum));
6172 - pri->ev.facname.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
6173 - pri->ev.facname.cref = c->cr;
6174 - pri->ev.facname.call = c;
6175 -#if 0
6176 - pri_message(pri, "Sending facility event (%s/%s)\n", pri->ev.facname.callingname, pri->ev.facname.callingnum);
6177 -#endif
6178 + if ((pri->localtype == PRI_CPE) || (pri->localtype == PRI_NETWORK)) {
6179 + q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
6180 + } else {
6181 + // BRI uses the dummy cref for sservices like ccnr
6182 + }
6183 + break;
6184 + }
6185 + if (c->facility > 0) {
6186 + pri->ev.e = PRI_EVENT_FACILITY;
6187 + pri->ev.facility.channel = c->channelno | (c->ds1no << 8);
6188 + pri->ev.facility.cref = c->cr;
6189 + pri->ev.facility.tei = c->tei;
6190 + pri->ev.facility.call = c;
6191 + switch (c->facility) {
6192 + case 0x06: /* ECT execute */
6193 + pri->ev.facility.operation = 0x06;
6194 + break;
6195 + case 0x0D: /* CD */
6196 + pri->ev.facility.operation = 0x0D;
6197 + libpri_copy_string(pri->ev.facility.forwardnum, c->redirectingnum, sizeof(pri->ev.facility.forwardnum));
6198 + break;
6199 + default:
6200 + pri->ev.facility.operation = c->facility;
6201 + }
6202 + } else {
6203 + pri->ev.e = PRI_EVENT_FACNAME;
6204 + libpri_copy_string(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname));
6205 + libpri_copy_string(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingname));
6206 + pri->ev.facname.channel = c->channelno | (c->ds1no << 8);
6207 + pri->ev.facname.cref = c->cr;
6208 + pri->ev.facname.call = c;
6209 + }
6210 return Q931_RES_HAVEEVENT;
6211 case Q931_PROGRESS:
6212 if (missingmand) {
6213 q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
6214 - q931_destroycall(pri, c->cr);
6215 + q931_destroycall(pri, c->cr, c->tei);
6216 break;
6217 }
6218 pri->ev.e = PRI_EVENT_PROGRESS;
6219 @@ -3347,6 +4414,11 @@
6220 q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE);
6221 break;
6222 }
6223 + if (pri->localtype == BRI_NETWORK_PTMP) {
6224 + l2c = q921_getcall(pri, c, tei);
6225 + l2c->proc = 1;
6226 + l2c->channel = c->channelno;
6227 + }
6228 pri->ev.proceeding.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
6229 if (mh->msg == Q931_CALL_PROCEEDING) {
6230 pri->ev.e = PRI_EVENT_PROCEEDING;
6231 @@ -3364,16 +4436,21 @@
6232 break;
6233 }
6234 if (c->ourcallstate != Q931_CALL_STATE_CONNECT_REQUEST) {
6235 + if ((c->ourcallstate == Q931_CALL_STATE_ACTIVE) && (c->con_acked == 0) && (network)) {
6236 + /* sending a CONNECT_ACKNOWLEDGE is optional for CPEs */
6237 + } else {
6238 q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE);
6239 - break;
6240 + }
6241 + break;
6242 }
6243 c->ourcallstate = Q931_CALL_STATE_ACTIVE;
6244 c->peercallstate = Q931_CALL_STATE_ACTIVE;
6245 + c->con_acked = 1;
6246 break;
6247 case Q931_STATUS:
6248 if (missingmand) {
6249 q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING);
6250 - q931_destroycall(pri, c->cr);
6251 + q931_destroycall(pri, c->cr, c->tei);
6252 break;
6253 }
6254 if (c->newcall) {
6255 @@ -3410,31 +4487,70 @@
6256 if (res)
6257 return res;
6258 }
6259 - break;
6260 + if (c->peercallstate != c->sugcallstate) {
6261 + pri_error(pri, "updating callstate, peercallstate %d to %d\n", c->peercallstate, c->sugcallstate);
6262 +// c->peercallstate = c->sugcallstate;
6263 + c->ourcallstate = c->sugcallstate;
6264 + if (c->sugcallstate != Q931_CALL_STATE_ACTIVE) {
6265 + /* pass hangup to upper layer! */
6266 + if (c->alive) {
6267 + pri->ev.e = PRI_EVENT_HANGUP;
6268 + res = Q931_RES_HAVEEVENT;
6269 + c->alive = 0;
6270 + } else if (c->sendhangupack) {
6271 + res = Q931_RES_HAVEEVENT;
6272 + pri->ev.e = PRI_EVENT_HANGUP_ACK;
6273 + q931_hangup(pri, c, c->cause);
6274 + } else {
6275 + q931_hangup(pri, c, c->cause);
6276 + res = 0;
6277 + if (res)
6278 + return res;
6279 + }
6280 + }
6281 + }
6282 + break;
6283 case Q931_RELEASE_COMPLETE:
6284 - c->ourcallstate = Q931_CALL_STATE_NULL;
6285 - c->peercallstate = Q931_CALL_STATE_NULL;
6286 - pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
6287 - pri->ev.hangup.cref = c->cr;
6288 - pri->ev.hangup.cause = c->cause;
6289 - pri->ev.hangup.call = c;
6290 - libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo));
6291 - c->useruserinfo[0] = '\0';
6292 - /* Free resources */
6293 - if (c->alive) {
6294 - pri->ev.e = PRI_EVENT_HANGUP;
6295 - res = Q931_RES_HAVEEVENT;
6296 - c->alive = 0;
6297 - } else if (c->sendhangupack) {
6298 - res = Q931_RES_HAVEEVENT;
6299 - pri->ev.e = PRI_EVENT_HANGUP_ACK;
6300 - pri_hangup(pri, c, c->cause);
6301 - } else
6302 - res = 0;
6303 - if (res)
6304 - return res;
6305 - else
6306 - q931_hangup(pri,c,c->cause);
6307 + if (pri->localtype != BRI_NETWORK_PTMP) {
6308 + /* only stop the T303 timer if WE are not a BRI PTMP network */
6309 + if (c->t303timer) {
6310 + c->t303running = 0;
6311 + pri_schedule_del(pri, c->t303timer);
6312 + c->t303timer = 0;
6313 + }
6314 + }
6315 +
6316 + if ((pri->localtype != BRI_NETWORK_PTMP) || (c->tei == tei)) {
6317 + c->ourcallstate = Q931_CALL_STATE_NULL;
6318 + c->peercallstate = Q931_CALL_STATE_NULL;
6319 + pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
6320 + pri->ev.hangup.cref = c->cr;
6321 + pri->ev.hangup.cause = c->cause;
6322 + pri->ev.hangup.call = c;
6323 + libpri_copy_string(pri->ev.hangup.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo));
6324 + c->useruserinfo[0] = '\0';
6325 + /* Free resources */
6326 + if (c->alive) {
6327 + pri->ev.e = PRI_EVENT_HANGUP;
6328 + res = Q931_RES_HAVEEVENT;
6329 + c->alive = 0;
6330 + } else if (c->sendhangupack) {
6331 + res = Q931_RES_HAVEEVENT;
6332 + pri->ev.e = PRI_EVENT_HANGUP_ACK;
6333 + pri_hangup(pri, c, c->cause, -1);
6334 + } else
6335 + res = 0;
6336 + if (res)
6337 + return res;
6338 + else
6339 + q931_hangup(pri,c,c->cause);
6340 + } else {
6341 + // BRI_NET_PTMP
6342 + // ignoring relase_complete
6343 + res = q921_handle_hangup(pri,c,tei);
6344 + if (res)
6345 + return res;
6346 + }
6347 break;
6348 case Q931_RELEASE:
6349 if (missingmand) {
6350 @@ -3450,6 +4566,7 @@
6351 pri->ev.e = PRI_EVENT_HANGUP;
6352 pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
6353 pri->ev.hangup.cref = c->cr;
6354 + pri->ev.hangup.tei = c->tei;
6355 pri->ev.hangup.cause = c->cause;
6356 pri->ev.hangup.call = c;
6357 pri->ev.hangup.aoc_units = c->aoc_units;
6358 @@ -3478,9 +4595,16 @@
6359 pri->ev.e = PRI_EVENT_HANGUP_REQ;
6360 pri->ev.hangup.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
6361 pri->ev.hangup.cref = c->cr;
6362 + pri->ev.hangup.tei = c->tei;
6363 pri->ev.hangup.cause = c->cause;
6364 pri->ev.hangup.call = c;
6365 pri->ev.hangup.aoc_units = c->aoc_units;
6366 + if (c->progressmask & PRI_PROG_INBAND_AVAILABLE) {
6367 + pri->ev.hangup.inband_progress = 1;
6368 + } else {
6369 + pri->ev.hangup.inband_progress = 0;
6370 + }
6371 + pri->ev.hangup.aoc_units = c->aoc_units;
6372 if (c->alive)
6373 return Q931_RES_HAVEEVENT;
6374 else
6375 @@ -3511,7 +4635,7 @@
6376 pri->ev.e = PRI_EVENT_INFO_RECEIVED;
6377 pri->ev.ring.call = c;
6378 pri->ev.ring.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
6379 - libpri_copy_string(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum));
6380 + libpri_copy_string(pri->ev.ring.callednum, c->digits, sizeof(pri->ev.ring.callednum) );
6381 libpri_copy_string(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr));
6382 pri->ev.ring.complete = c->complete; /* this covers IE 33 (Sending Complete) */
6383 return Q931_RES_HAVEEVENT;
6384 @@ -3531,7 +4655,6 @@
6385 pri->ev.e = PRI_EVENT_SETUP_ACK;
6386 pri->ev.setup_ack.channel = c->channelno | (c->ds1no << 8) | (c->ds1explicit << 16);
6387 pri->ev.setup_ack.call = c;
6388 -
6389 cur = c->apdus;
6390 while (cur) {
6391 if (!cur->sent && cur->message == Q931_FACILITY) {
6392 @@ -3547,19 +4670,53 @@
6393 pri->ev.notify.channel = c->channelno;
6394 pri->ev.notify.info = c->notify;
6395 return Q931_RES_HAVEEVENT;
6396 + case Q931_HOLD:
6397 + pri->ev.e = PRI_EVENT_HOLD_REQ;
6398 + pri->ev.hold_req.call = c;
6399 + pri->ev.hold_req.cref = c->cr;
6400 + pri->ev.hold_req.tei = c->tei;
6401 + pri->ev.hold_req.channel = c->channelno;
6402 + return Q931_RES_HAVEEVENT;
6403 + break;
6404 + case Q931_RETRIEVE:
6405 + pri->ev.e = PRI_EVENT_RETRIEVE_REQ;
6406 + pri->ev.retrieve_req.call = c;
6407 + pri->ev.retrieve_req.cref = c->cr;
6408 + pri->ev.retrieve_req.tei = c->tei;
6409 + pri->ev.retrieve_req.channel = c->channelno;
6410 + return Q931_RES_HAVEEVENT;
6411 + break;
6412 + case Q931_SUSPEND:
6413 + pri->ev.e = PRI_EVENT_SUSPEND_REQ;
6414 + pri->ev.suspend_req.call = c;
6415 + pri->ev.suspend_req.cref = c->cr;
6416 + pri->ev.suspend_req.tei = c->tei;
6417 + pri->ev.suspend_req.channel = c->channelno;
6418 + strncpy(pri->ev.suspend_req.callid, c->callid, sizeof(pri->ev.suspend_req.callid) - 1);
6419 + return Q931_RES_HAVEEVENT;
6420 + break;
6421 + case Q931_RESUME:
6422 + if (pri->localtype == BRI_NETWORK_PTMP) {
6423 + l2c = q921_getcall(pri, c, tei);
6424 + }
6425 + c->newcall = 0;
6426 + pri->ev.e = PRI_EVENT_RESUME_REQ;
6427 + pri->ev.resume_req.call = c;
6428 + pri->ev.resume_req.cref = c->cr;
6429 + pri->ev.resume_req.tei = c->tei;
6430 + pri->ev.resume_req.channel = c->channelno;
6431 + strncpy(pri->ev.resume_req.callid, c->callid, sizeof(pri->ev.resume_req.callid) - 1);
6432 + return Q931_RES_HAVEEVENT;
6433 + break;
6434 case Q931_USER_INFORMATION:
6435 case Q931_SEGMENT:
6436 case Q931_CONGESTION_CONTROL:
6437 - case Q931_HOLD:
6438 case Q931_HOLD_ACKNOWLEDGE:
6439 case Q931_HOLD_REJECT:
6440 - case Q931_RETRIEVE:
6441 case Q931_RETRIEVE_ACKNOWLEDGE:
6442 case Q931_RETRIEVE_REJECT:
6443 - case Q931_RESUME:
6444 case Q931_RESUME_ACKNOWLEDGE:
6445 case Q931_RESUME_REJECT:
6446 - case Q931_SUSPEND:
6447 case Q931_SUSPEND_ACKNOWLEDGE:
6448 case Q931_SUSPEND_REJECT:
6449 pri_error(pri, "!! Not yet handling post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
6450 @@ -3569,7 +4726,7 @@
6451 pri_error(pri, "!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
6452 q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST);
6453 if (c->newcall)
6454 - q931_destroycall(pri,c->cr);
6455 + q931_destroycall(pri,c->cr,c->tei);
6456 return -1;
6457 }
6458 return 0;