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