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