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