finish chan_misdn commit
[asterisk/asterisk.git] / channels / misdn / ie.c
1
2 /*
3  * Chan_Misdn -- Channel Driver for Asterisk
4  *
5  * Interface to mISDN
6  *
7  * Copyright (C) 2005, Christian Richter
8  *
9  * Christian Richter <crich@beronet.com>
10  *
11  * heaviliy patched from jollys ie.cpp, jolly gave me ALL
12  * rights for this code, i can even have my own copyright on it.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License
16  */
17
18 /*
19   the pointer of enc_ie_* always points to the IE itself
20   if qi is not NULL (TE-mode), offset is set
21 */
22
23 #include "isdn_lib.h"
24
25 #define CENTREX_FAC     0x88
26 #define CENTREX_ID      0xa1
27
28 #define MISDN_IE_DEBG 0
29
30 /* support stuff */
31 static void strnncpy(unsigned char *dest, unsigned char *src, int len, int dst_len)
32 {
33         if (len > dst_len-1)
34                 len = dst_len-1;
35         strncpy((char *)dest, (char *)src, len);
36         dest[len] = '\0';
37 }
38
39
40 /* IE_COMPLETE */
41 void enc_ie_complete(unsigned char **ntmode, msg_t *msg, int complete, int nt, struct misdn_bchannel *bc)
42 {
43         unsigned char *p;
44         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
45
46         if (complete<0 || complete>1)
47         {
48                 printf("%s: ERROR: complete(%d) is out of range.\n", __FUNCTION__, complete);
49                 return;
50         }
51
52         if (complete)
53                 if (MISDN_IE_DEBG) printf("    complete=%d\n", complete);
54
55         if (complete)
56         {
57                 p = msg_put(msg, 1);
58                 if (nt)
59                 {
60                         *ntmode = p;
61                 } else
62                         qi->sending_complete = p - (unsigned char *)qi - sizeof(Q931_info_t);
63                 p[0] = IE_COMPLETE;
64         }
65 }
66
67 void dec_ie_complete(unsigned char *p, Q931_info_t *qi, int *complete, int nt, struct misdn_bchannel *bc)
68 {
69         *complete = 0;
70         if (!nt)
71         {
72                 if (qi->sending_complete)
73                         *complete = 1;
74         } else
75                 if (p)
76                         *complete = 1;
77
78         if (*complete)
79                 if (MISDN_IE_DEBG) printf("    complete=%d\n", *complete);
80 }
81
82
83 /* IE_BEARER */
84 void enc_ie_bearer(unsigned char **ntmode, msg_t *msg, int coding, int capability, int mode, int rate, int multi, int user, int nt, struct misdn_bchannel *bc)
85 {
86         unsigned char *p;
87         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
88         int l;
89
90         if (coding<0 || coding>3)
91         {
92                 printf("%s: ERROR: coding(%d) is out of range.\n", __FUNCTION__, coding);
93                 return;
94         }
95         if (capability<0 || capability>31)
96         {
97                 printf("%s: ERROR: capability(%d) is out of range.\n", __FUNCTION__, capability);
98                 return;
99         }
100         if (mode<0 || mode>3)
101         {
102                 printf("%s: ERROR: mode(%d) is out of range.\n", __FUNCTION__, mode);
103                 return;
104         }
105         if (rate<0 || rate>31)
106         {
107                 printf("%s: ERROR: rate(%d) is out of range.\n", __FUNCTION__, rate);
108                 return;
109         }
110         if (multi>127)
111         {
112                 printf("%s: ERROR: multi(%d) is out of range.\n", __FUNCTION__, multi);
113                 return;
114         }
115         if (user>31)
116         {
117                 printf("%s: ERROR: user L1(%d) is out of range.\n", __FUNCTION__, rate);
118                 return;
119         }
120         if (rate!=24 && multi>=0)
121         {
122                 printf("%s: WARNING: multi(%d) is only possible if rate(%d) would be 24.\n", __FUNCTION__, multi, rate);
123                 multi = -1;
124         }
125
126         if (MISDN_IE_DEBG) printf("    coding=%d capability=%d mode=%d rate=%d multi=%d user=%d\n", coding, capability, mode, rate, multi, user);
127
128         l = 2 + (multi>=0) + (user>=0);
129         p = msg_put(msg, l+2);
130         if (nt)
131                 *ntmode = p+1;
132         else
133                 qi->bearer_capability = p - (unsigned char *)qi - sizeof(Q931_info_t);
134         p[0] = IE_BEARER;
135         p[1] = l;
136         p[2] = 0x80 + (coding<<5) + capability;
137         p[3] = 0x80 + (mode<<5) + rate;
138         if (multi >= 0)
139                 p[4] = 0x80 + multi;
140         if (user >= 0)
141                 p[4+(multi>=0)] = 0xa0 + user;
142 }
143
144 void dec_ie_bearer(unsigned char *p, Q931_info_t *qi, int *coding, int *capability, int *mode, int *rate, int *multi, int *user, 
145                    int *async, int *urate, int *stopbits, int *dbits, int *parity, int nt, struct misdn_bchannel *bc)
146 {
147         int octet;
148         *coding = -1;
149         *capability = -1;
150         *mode = -1;
151         *rate = -1;
152         *multi = -1;
153         *user = -1;
154         *async = -1;
155         *urate = -1;
156         *stopbits = -1;
157         *dbits = -1;
158         *parity = -1;
159
160         if (!nt)
161         {
162                 p = NULL;
163                 if (qi->llc)
164                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->llc + 1;
165                 else if (qi->bearer_capability)
166                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->bearer_capability + 1;
167         }
168         if (!p)
169                 return;
170         if (p[0] < 2)
171         {
172                 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
173                 return;
174         }
175
176         *coding = (p[1]&0x60) >> 5;
177         *capability = p[1] & 0x1f;
178         octet = 2;
179         if (!(p[1] & 0x80))
180                 octet++;
181
182         if (p[0] < octet)
183                 goto done;
184
185         *mode = (p[octet]&0x60) >> 5;
186         *rate = p[octet] & 0x1f;
187
188         octet++;
189
190         if (p[0] < octet)
191                 goto done;
192
193         if (*rate == 0x18) {
194                 /* Rate multiplier only present if 64Kb/s base rate */
195                 *multi = p[octet++] & 0x7f;
196         }
197
198         if (p[0] < octet)
199                 goto done;
200
201         /* Start L1 info */
202         if ((p[octet] & 0x60) == 0x20) {
203                 *user = p[octet] & 0x1f;
204
205                 if (p[0] <= octet)
206                         goto done;
207                 
208                 if (p[octet++] & 0x80)
209                         goto l2;
210
211                 *async = !!(p[octet] & 0x40);
212                 /* 0x20 is inband negotiation */
213                 *urate = p[octet] & 0x1f;
214
215                 if (p[0] <= octet)
216                         goto done;
217                 
218                 if (p[octet++] & 0x80)
219                         goto l2;
220
221                 /* Ignore next byte for now: Intermediate rate, NIC, flow control */
222
223                 if (p[0] <= octet)
224                         goto done;
225                 
226                 if (p[octet++] & 0x80)
227                         goto l2;
228
229                 /* And the next one. Header, multiframe, mode, assignor/ee, negotiation */
230
231                 if (p[0] <= octet)
232                         goto done;
233                 
234                 if (!p[octet++] & 0x80)
235                         goto l2;
236
237                 /* Wheee. V.110 speed information */
238
239                 *stopbits = (p[octet] & 0x60) >> 5;
240                 *dbits = (p[octet] & 0x18) >> 3; 
241                 *parity = p[octet] & 7;
242
243                 octet++;
244         }
245  l2: /* Nobody seems to want the rest so we don't bother (yet) */
246  done:          
247         if (MISDN_IE_DEBG) printf("    coding=%d capability=%d mode=%d rate=%d multi=%d user=%d async=%d urate=%d stopbits=%d dbits=%d parity=%d\n", *coding, *capability, *mode, *rate, *multi, *user, *async, *urate, *stopbits, *dbits, *parity);
248 }
249
250
251 /* IE_CALL_ID */
252 void enc_ie_call_id(unsigned char **ntmode, msg_t *msg, unsigned char *callid, int callid_len, int nt, struct misdn_bchannel *bc)
253 {
254         unsigned char *p;
255         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
256         int l;
257
258         char debug[25];
259         int i;
260
261         if (!callid || callid_len<=0)
262         {
263                 return;
264         }
265         if (callid_len>8)
266         {
267                 printf("%s: ERROR: callid_len(%d) is out of range.\n", __FUNCTION__, callid_len);
268                 return;
269         }
270
271         i = 0;
272         while(i < callid_len)
273         {
274                 if (MISDN_IE_DEBG) printf(debug+(i*3), " %02x", callid[i]);
275                 i++;
276         }
277                 
278         if (MISDN_IE_DEBG) printf("    callid%s\n", debug);
279
280         l = callid_len;
281         p = msg_put(msg, l+2);
282         if (nt)
283                 *ntmode = p+1;
284         else
285                 qi->call_id = p - (unsigned char *)qi - sizeof(Q931_info_t);
286         p[0] = IE_CALL_ID;
287         p[1] = l;
288         memcpy(p+2, callid, callid_len);
289 }
290
291 void dec_ie_call_id(unsigned char *p, Q931_info_t *qi, unsigned char *callid, int *callid_len, int nt, struct misdn_bchannel *bc)
292 {
293         char debug[25];
294         int i;
295
296         *callid_len = -1;
297
298         if (!nt)
299         {
300                 p = NULL;
301                 if (qi->call_id)
302                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->call_id + 1;
303         }
304         if (!p)
305                 return;
306         if (p[0] > 8)
307         {
308                 printf("%s: ERROR: IE too long (%d).\n", __FUNCTION__, p[0]);
309                 return;
310         }
311
312         *callid_len = p[0];
313         memcpy(callid, p+1, *callid_len);
314
315         i = 0;
316         while(i < *callid_len)
317         {
318                 if (MISDN_IE_DEBG) printf(debug+(i*3), " %02x", callid[i]);
319                 i++;
320         }
321                 
322         if (MISDN_IE_DEBG) printf("    callid%s\n", debug);
323 }
324
325
326 /* IE_CALLED_PN */
327 void enc_ie_called_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, unsigned char *number, int nt, struct misdn_bchannel *bc)
328 {
329         unsigned char *p;
330         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
331         int l;
332
333         if (type<0 || type>7)
334         {
335                 printf("%s: ERROR: type(%d) is out of range.\n", __FUNCTION__, type);
336                 return;
337         }
338         if (plan<0 || plan>15)
339         {
340                 printf("%s: ERROR: plan(%d) is out of range.\n", __FUNCTION__, plan);
341                 return;
342         }
343         if (!number[0])
344         {
345                 printf("%s: ERROR: number is not given.\n", __FUNCTION__);
346                 return;
347         }
348
349         if (MISDN_IE_DEBG) printf("    type=%d plan=%d number='%s'\n", type, plan, number);
350
351         l = 1+strlen((char *)number);
352         p = msg_put(msg, l+2);
353         if (nt)
354                 *ntmode = p+1;
355         else
356                 qi->called_nr = p - (unsigned char *)qi - sizeof(Q931_info_t);
357         p[0] = IE_CALLED_PN;
358         p[1] = l;
359         p[2] = 0x80 + (type<<4) + plan;
360         strncpy((char *)p+3, (char *)number, strlen((char *)number));
361 }
362
363 void dec_ie_called_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, unsigned char *number, int number_len, int nt, struct misdn_bchannel *bc)
364 {
365         *type = -1;
366         *plan = -1;
367         *number = '\0';
368
369         if (!nt)
370         {
371                 p = NULL;
372                 if (qi->called_nr)
373                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->called_nr + 1;
374         }
375         if (!p)
376                 return;
377         if (p[0] < 2)
378         {
379                 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
380                 return;
381         }
382
383         *type = (p[1]&0x70) >> 4;
384         *plan = p[1] & 0xf;
385         strnncpy(number, p+2, p[0]-1, number_len);
386
387         if (MISDN_IE_DEBG) printf("    type=%d plan=%d number='%s'\n", *type, *plan, number);
388 }
389
390
391 /* IE_CALLING_PN */
392 void enc_ie_calling_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, int present, int screen, unsigned char *number, int nt, struct misdn_bchannel *bc)
393 {
394         unsigned char *p;
395         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
396         int l;
397
398         if (type<0 || type>7)
399         {
400                 printf("%s: ERROR: type(%d) is out of range.\n", __FUNCTION__, type);
401                 return;
402         }
403         if (plan<0 || plan>15)
404         {
405                 printf("%s: ERROR: plan(%d) is out of range.\n", __FUNCTION__, plan);
406                 return;
407         }
408         if (present>3)
409         {
410                 printf("%s: ERROR: present(%d) is out of range.\n", __FUNCTION__, present);
411                 return;
412         }
413         if (present >= 0) if (screen<0 || screen>3)
414         {
415                 printf("%s: ERROR: screen(%d) is out of range.\n", __FUNCTION__, screen);
416                 return;
417         }
418
419         if (MISDN_IE_DEBG) printf("    type=%d plan=%d present=%d screen=%d number='%s'\n", type, plan, present, screen, number);
420
421         l = 1;
422         if (number) if (number[0])
423                 l += strlen((char *)number);
424         if (present >= 0)
425                 l += 1;
426         p = msg_put(msg, l+2);
427         if (nt)
428                 *ntmode = p+1;
429         else
430                 qi->calling_nr = p - (unsigned char *)qi - sizeof(Q931_info_t);
431         p[0] = IE_CALLING_PN;
432         p[1] = l;
433         if (present >= 0)
434         {
435                 p[2] = 0x00 + (type<<4) + plan;
436                 p[3] = 0x80 + (present<<5) + screen;
437                 if (number) if (number[0])
438                         strncpy((char *)p+4, (char *)number, strlen((char *)number));
439         } else
440         {
441                 p[2] = 0x80 + (type<<4) + plan;
442                 if (number) if (number[0])
443                         strncpy((char *)p+3, (char *)number, strlen((char *)number));
444         }
445 }
446
447 void dec_ie_calling_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, unsigned char *number, int number_len, int nt, struct misdn_bchannel *bc)
448 {
449         *type = -1;
450         *plan = -1;
451         *present = -1;
452         *screen = -1;
453         *number = '\0';
454
455         if (!nt)
456         {
457                 p = NULL;
458                 if (qi->calling_nr)
459                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->calling_nr + 1;
460         }
461         if (!p)
462                 return;
463         if (p[0] < 1)
464         {
465                 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
466                 return;
467         }
468
469         *type = (p[1]&0x70) >> 4;
470         *plan = p[1] & 0xf;
471         if (!(p[1] & 0x80))
472         {
473                 if (p[0] < 2)
474                 {
475                         printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
476                         return;
477                 }
478                 *present = (p[2]&0x60) >> 5;
479                 *screen = p[2] & 0x3;
480                 strnncpy(number, p+3, p[0]-2, number_len);
481         } else
482         {
483                 strnncpy(number, p+2, p[0]-1, number_len);
484                 /* SPECIAL workarround for IBT software bug */ 
485                 /* if (number[0]==0x80) */
486                 /*  strcpy((char *)number, (char *)number+1); */
487         }
488
489         if (MISDN_IE_DEBG) printf("    type=%d plan=%d present=%d screen=%d number='%s'\n", *type, *plan, *present, *screen, number);
490 }
491
492
493 /* IE_CONNECTED_PN */
494 void enc_ie_connected_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, int present, int screen, unsigned char *number, int nt, struct misdn_bchannel *bc)
495 {
496         unsigned char *p;
497         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
498         int l;
499
500         if (type<0 || type>7)
501         {
502                 printf("%s: ERROR: type(%d) is out of range.\n", __FUNCTION__, type);
503                 return;
504         }
505         if (plan<0 || plan>15)
506         {
507                 printf("%s: ERROR: plan(%d) is out of range.\n", __FUNCTION__, plan);
508                 return;
509         }
510         if (present>3)
511         {
512                 printf("%s: ERROR: present(%d) is out of range.\n", __FUNCTION__, present);
513                 return;
514         }
515         if (present >= 0) if (screen<0 || screen>3)
516         {
517                 printf("%s: ERROR: screen(%d) is out of range.\n", __FUNCTION__, screen);
518                 return;
519         }
520
521         if (MISDN_IE_DEBG) printf("    type=%d plan=%d present=%d screen=%d number='%s'\n", type, plan, present, screen, number);
522
523         l = 1;
524         if (number) if (number[0])
525                 l += strlen((char *)number);
526         if (present >= 0)
527                 l += 1;
528         p = msg_put(msg, l+2);
529         if (nt)
530                 *ntmode = p+1;
531         else
532                 qi->connected_nr = p - (unsigned char *)qi - sizeof(Q931_info_t);
533         p[0] = IE_CONNECT_PN;
534         p[1] = l;
535         if (present >= 0)
536         {
537                 p[2] = 0x00 + (type<<4) + plan;
538                 p[3] = 0x80 + (present<<5) + screen;
539                 if (number) if (number[0])
540                         strncpy((char *)p+4, (char *)number, strlen((char *)number));
541         } else
542         {
543                 p[2] = 0x80 + (type<<4) + plan;
544                 if (number) if (number[0])
545                         strncpy((char *)p+3, (char *)number, strlen((char *)number));
546         }
547 }
548
549 void dec_ie_connected_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, unsigned char *number, int number_len, int nt, struct misdn_bchannel *bc)
550 {
551         *type = -1;
552         *plan = -1;
553         *present = -1;
554         *screen = -1;
555         *number = '\0';
556
557         if (!nt)
558         {
559                 p = NULL;
560                 if (qi->connected_nr)
561                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->connected_nr + 1;
562         }
563         if (!p)
564                 return;
565         if (p[0] < 1)
566         {
567                 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
568                 return;
569         }
570
571         *type = (p[1]&0x70) >> 4;
572         *plan = p[1] & 0xf;
573         if (!(p[1] & 0x80))
574         {
575                 if (p[0] < 2)
576                 {
577                         printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
578                         return;
579                 }
580                 *present = (p[2]&0x60) >> 5;
581                 *screen = p[2] & 0x3;
582                 strnncpy(number, p+3, p[0]-2, number_len);
583         } else
584         {
585                 strnncpy(number, p+2, p[0]-1, number_len);
586         }
587
588         if (MISDN_IE_DEBG) printf("    type=%d plan=%d present=%d screen=%d number='%s'\n", *type, *plan, *present, *screen, number);
589 }
590
591
592 /* IE_CAUSE */
593 void enc_ie_cause(unsigned char **ntmode, msg_t *msg, int location, int cause, int nt, struct misdn_bchannel *bc)
594 {
595         unsigned char *p;
596         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
597         int l;
598
599         if (location<0 || location>7)
600         {
601                 printf("%s: ERROR: location(%d) is out of range.\n", __FUNCTION__, location);
602                 return;
603         }
604         if (cause<0 || cause>127)
605         {
606                 printf("%s: ERROR: cause(%d) is out of range.\n", __FUNCTION__, cause);
607                 return;
608         }
609
610         if (MISDN_IE_DEBG) printf("    location=%d cause=%d\n", location, cause);
611
612         l = 2;
613         p = msg_put(msg, l+2);
614         if (nt)
615                 *ntmode = p+1;
616         else
617                 qi->cause = p - (unsigned char *)qi - sizeof(Q931_info_t);
618         p[0] = IE_CAUSE;
619         p[1] = l;
620         p[2] = 0x80 + location;
621         p[3] = 0x80 + cause;
622 }
623 void enc_ie_cause_standalone(unsigned char **ntmode, msg_t *msg, int location, int cause, int nt, struct misdn_bchannel *bc)
624 {
625         unsigned char *p = msg_put(msg, 4);
626         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
627         if (ntmode)
628                 *ntmode = p+1;
629         else
630                 qi->cause = p - (unsigned char *)qi - sizeof(Q931_info_t);
631         p[0] = IE_CAUSE;
632         p[1] = 2;
633         p[2] = 0x80 + location;
634         p[3] = 0x80 + cause;
635 }
636
637
638 void dec_ie_cause(unsigned char *p, Q931_info_t *qi, int *location, int *cause, int nt, struct misdn_bchannel *bc)
639 {
640         *location = -1;
641         *cause = -1;
642
643         if (!nt)
644         {
645                 p = NULL;
646                 if (qi->cause)
647                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->cause + 1;
648         }
649         if (!p)
650                 return;
651         if (p[0] < 2)
652         {
653                 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
654                 return;
655         }
656
657         *location = p[1] & 0x0f;
658         *cause = p[2] & 0x7f;
659
660         if (MISDN_IE_DEBG) printf("    location=%d cause=%d\n", *location, *cause);
661 }
662
663
664 /* IE_CHANNEL_ID */
665 void enc_ie_channel_id(unsigned char **ntmode, msg_t *msg, int exclusive, int channel, int nt, struct misdn_bchannel *bc)
666 {
667         unsigned char *p;
668         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
669         int l;
670         int pri = bc->stack->pri;
671
672         if (exclusive<0 || exclusive>1)
673         {
674                 printf("%s: ERROR: exclusive(%d) is out of range.\n", __FUNCTION__, exclusive);
675                 return;
676         }
677         if ((channel<0 || channel>0xff)
678             || (!pri && (channel>2 && channel<0xff))
679             || (pri && (channel>31 && channel<0xff))
680             || (pri && channel==16))
681         {
682                 printf("%s: ERROR: channel(%d) is out of range.\n", __FUNCTION__, channel);
683                 return;
684         }
685
686         /* if (MISDN_IE_DEBG) printf("    exclusive=%d channel=%d\n", exclusive, channel); */
687         
688
689         if (!pri)
690         {
691                 /* BRI */
692                 l = 1;
693                 p = msg_put(msg, l+2);
694                 if (nt)
695                         *ntmode = p+1;
696                 else
697                         qi->channel_id = p - (unsigned char *)qi - sizeof(Q931_info_t);
698                 p[0] = IE_CHANNEL_ID;
699                 p[1] = l;
700                 if (channel == 0xff)
701                         channel = 3;
702                 p[2] = 0x80 + (exclusive<<3) + channel;
703                 /* printf("    exclusive=%d channel=%d\n", exclusive, channel); */
704         } else
705         {
706                 /* PRI */
707                 if (channel == 0) /* no channel */
708                         return; /* IE not present */
709 /*              if (MISDN_IE_DEBG) printf("channel = %d\n", channel); */
710                 if (channel == 0xff) /* any channel */
711                 {
712                         l = 1;
713                         p = msg_put(msg, l+2);
714                         if (nt)
715                                 *ntmode = p+1;
716                         else
717                                 qi->channel_id = p - (unsigned char *)qi - sizeof(Q931_info_t);
718                         p[0] = IE_CHANNEL_ID;
719                         p[1] = l;
720                         p[2] = 0x80 + 0x20 + 0x03;
721 /*                      if (MISDN_IE_DEBG) printf("%02x\n", p[2]); */
722                         return; /* end */
723                 }
724                 l = 3;
725                 p = msg_put(msg, l+2);
726                 if (nt)
727                         *ntmode = p+1;
728                 else
729                         qi->channel_id = p - (unsigned char *)qi - sizeof(Q931_info_t);
730                 p[0] = IE_CHANNEL_ID;
731                 p[1] = l;
732                 p[2] = 0x80 + 0x20 + (exclusive<<3) + 0x01;
733                 p[3] = 0x80 + 3; /* CCITT, Number, B-type */
734                 p[4] = 0x80 + channel;
735 /*              if (MISDN_IE_DEBG) printf("%02x %02x %02x\n", p[2], p[3], p[4]); */
736         }
737 }
738
739 void dec_ie_channel_id(unsigned char *p, Q931_info_t *qi, int *exclusive, int *channel, int nt, struct misdn_bchannel *bc)
740 {
741         int pri = bc->stack->pri;
742
743         *exclusive = -1;
744         *channel = -1;
745
746         if (!nt)
747         {
748                 p = NULL;
749                 if (qi->channel_id)
750                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->channel_id + 1;
751         }
752         if (!p)
753                 return;
754         if (p[0] < 1)
755         {
756                 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
757                 return;
758         }
759
760         if (p[1] & 0x40)
761         {
762                 printf("%s: ERROR: refering to channels of other interfaces is not supported.\n", __FUNCTION__);
763                 return;
764         }
765         if (p[1] & 0x04)
766         {
767                 printf("%s: ERROR: using d-channel is not supported.\n", __FUNCTION__);
768                 return;
769         }
770
771         *exclusive = (p[1]&0x08) >> 3;
772         if (!pri)
773         {
774                 /* BRI */
775                 if (p[1] & 0x20)
776                 {
777                         printf("%s: ERROR: extended channel ID with non PRI interface.\n", __FUNCTION__);
778                         return;
779                 }
780                 *channel = p[1] & 0x03;
781                 if (*channel == 3)
782                         *channel = 0xff;
783         } else
784         {
785                 /* PRI */
786                 if (p[0] < 1)
787                 {
788                         printf("%s: ERROR: IE too short for PRI (%d).\n", __FUNCTION__, p[0]);
789                         return;
790                 }
791                 if (!(p[1] & 0x20))
792                 {
793                         printf("%s: ERROR: basic channel ID with PRI interface.\n", __FUNCTION__);
794                         return;
795                 }
796                 if ((p[1]&0x03) == 0x00)
797                 {
798                         /* no channel */
799                         *channel = 0;
800                         return;
801                 }
802                 if ((p[1]&0x03) == 0x03)
803                 {
804                         /* any channel */
805                         *channel = 0xff;
806                         return;
807                 }
808                 if (p[0] < 3)
809                 {
810                         printf("%s: ERROR: IE too short for PRI with channel(%d).\n", __FUNCTION__, p[0]);
811                         return;
812                 }
813                 if (p[2] & 0x10)
814                 {
815                         printf("%s: ERROR: channel map not supported.\n", __FUNCTION__);
816                         return;
817                 }
818                 *channel = p[3] & 0x7f;
819                 if ( (*channel<1) | (*channel==16) | (*channel>31))
820                 {
821                         printf("%s: ERROR: PRI interface channel out of range (%d).\n", __FUNCTION__, *channel);
822                         return;
823                 }
824 /*              if (MISDN_IE_DEBG) printf("%02x %02x %02x\n", p[1], p[2], p[3]); */
825         }
826
827         if (MISDN_IE_DEBG) printf("    exclusive=%d channel=%d\n", *exclusive, *channel);
828 }
829
830
831 /* IE_DATE */
832 void enc_ie_date(unsigned char **ntmode, msg_t *msg, time_t ti, int nt, struct misdn_bchannel *bc)
833 {
834         unsigned char *p;
835         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
836         int l;
837
838         struct tm *tm;
839
840         tm = localtime(&ti);
841         if (!tm)
842         {
843                 printf("%s: ERROR: gettimeofday() returned NULL.\n", __FUNCTION__);
844                 return;
845         }
846
847         if (MISDN_IE_DEBG) printf("    year=%d month=%d day=%d hour=%d minute=%d\n", tm->tm_year%100, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min);
848
849         l = 5;
850         p = msg_put(msg, l+2);
851         if (nt)
852                 *ntmode = p+1;
853         else
854                 qi->date = p - (unsigned char *)qi - sizeof(Q931_info_t);
855         p[0] = IE_DATE;
856         p[1] = l;
857         p[2] = tm->tm_year % 100;
858         p[3] = tm->tm_mon + 1;
859         p[4] = tm->tm_mday;
860         p[5] = tm->tm_hour;
861         p[6] = tm->tm_min;
862 }
863
864
865 /* IE_DISPLAY */
866 void enc_ie_display(unsigned char **ntmode, msg_t *msg, unsigned char *display, int nt, struct misdn_bchannel *bc)
867 {
868         unsigned char *p;
869         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
870         int l;
871
872         if (!display[0])
873         {
874                 printf("%s: ERROR: display text not given.\n", __FUNCTION__);
875                 return;
876         }
877
878         if (strlen((char *)display) > 80)
879         {
880                 printf("%s: WARNING: display text too long (max 80 chars), cutting.\n", __FUNCTION__);
881                 display[80] = '\0';
882         }
883
884         /* if (MISDN_IE_DEBG) printf("    display='%s' (len=%d)\n", display, strlen((char *)display)); */
885
886         l = strlen((char *)display);
887         p = msg_put(msg, l+2);
888         if (nt)
889                 *ntmode = p+1;
890         else
891                 qi->display = p - (unsigned char *)qi - sizeof(Q931_info_t);
892         p[0] = IE_DISPLAY;
893         p[1] = l;
894         strncpy((char *)p+2, (char *)display, strlen((char *)display));
895 }
896
897 void dec_ie_display(unsigned char *p, Q931_info_t *qi, unsigned char *display, int display_len, int nt, struct misdn_bchannel *bc)
898 {
899         *display = '\0';
900
901         if (!nt)
902         {
903                 p = NULL;
904                 if (qi->display)
905                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->display + 1;
906         }
907         if (!p)
908                 return;
909         if (p[0] < 1)
910         {
911                 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
912                 return;
913         }
914
915         strnncpy(display, p+1, p[0], display_len);
916
917         if (MISDN_IE_DEBG) printf("    display='%s'\n", display);
918 }
919
920
921 /* IE_KEYPAD */
922 void enc_ie_keypad(unsigned char **ntmode, msg_t *msg, unsigned char *keypad, int nt, struct misdn_bchannel *bc)
923 {
924         unsigned char *p;
925         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
926         int l;
927
928         if (!keypad[0])
929         {
930                 printf("%s: ERROR: keypad info not given.\n", __FUNCTION__);
931                 return;
932         }
933
934         if (MISDN_IE_DEBG) printf("    keypad='%s'\n", keypad);
935
936         l = strlen((char *)keypad);
937         p = msg_put(msg, l+2);
938         if (nt)
939                 *ntmode = p+1;
940         else
941                 qi->keypad = p - (unsigned char *)qi - sizeof(Q931_info_t);
942         p[0] = IE_KEYPAD;
943         p[1] = l;
944         strncpy((char *)p+2, (char *)keypad, strlen((char *)keypad));
945 }
946
947 void dec_ie_keypad(unsigned char *p, Q931_info_t *qi, unsigned char *keypad, int keypad_len, int nt, struct misdn_bchannel *bc)
948 {
949         *keypad = '\0';
950
951         if (!nt)
952         {
953                 p = NULL;
954                 if (qi->keypad)
955                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->keypad + 1;
956         }
957         if (!p)
958                 return;
959         if (p[0] < 1)
960         {
961                 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
962                 return;
963         }
964
965         strnncpy(keypad, p+1, p[0], keypad_len);
966
967         if (MISDN_IE_DEBG) printf("    keypad='%s'\n", keypad);
968 }
969
970
971 /* IE_NOTIFY */
972 void enc_ie_notify(unsigned char **ntmode, msg_t *msg, int notify, int nt, struct misdn_bchannel *bc)
973 {
974         unsigned char *p;
975         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
976         int l;
977
978         if (notify<0 || notify>0x7f)
979         {
980                 printf("%s: ERROR: notify(%d) is out of range.\n", __FUNCTION__, notify);
981                 return;
982         }
983
984         if (MISDN_IE_DEBG) printf("    notify=%d\n", notify);
985
986         l = 1;
987         p = msg_put(msg, l+2);
988         if (nt)
989                 *ntmode = p+1;
990         else
991                 qi->notify = p - (unsigned char *)qi - sizeof(Q931_info_t);
992         p[0] = IE_NOTIFY;
993         p[1] = l;
994         p[2] = 0x80 + notify;
995 }
996
997 void dec_ie_notify(unsigned char *p, Q931_info_t *qi, int *notify, int nt, struct misdn_bchannel *bc)
998 {
999         *notify = -1;
1000
1001         if (!nt)
1002         {
1003                 p = NULL;
1004                 if (qi->notify)
1005                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->notify + 1;
1006         }
1007         if (!p)
1008                 return;
1009         if (p[0] < 1)
1010         {
1011                 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
1012                 return;
1013         }
1014
1015         *notify = p[1] & 0x7f;
1016
1017         if (MISDN_IE_DEBG) printf("    notify=%d\n", *notify);
1018 }
1019
1020
1021 /* IE_PROGRESS */
1022 void enc_ie_progress(unsigned char **ntmode, msg_t *msg, int coding, int location, int progress, int nt, struct misdn_bchannel *bc)
1023 {
1024         unsigned char *p;
1025         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
1026         int l;
1027
1028         if (coding<0 || coding>0x03)
1029         {
1030                 printf("%s: ERROR: coding(%d) is out of range.\n", __FUNCTION__, coding);
1031                 return;
1032         }
1033         if (location<0 || location>0x0f)
1034         {
1035                 printf("%s: ERROR: location(%d) is out of range.\n", __FUNCTION__, location);
1036                 return;
1037         }
1038         if (progress<0 || progress>0x7f)
1039         {
1040                 printf("%s: ERROR: progress(%d) is out of range.\n", __FUNCTION__, progress);
1041                 return;
1042         }
1043
1044         if (MISDN_IE_DEBG) printf("    coding=%d location=%d progress=%d\n", coding, location, progress);
1045
1046         l = 2;
1047         p = msg_put(msg, l+2);
1048         if (nt)
1049                 *ntmode = p+1;
1050         else
1051                 qi->progress = p - (unsigned char *)qi - sizeof(Q931_info_t);
1052         p[0] = IE_PROGRESS;
1053         p[1] = l;
1054         p[2] = 0x80 + (coding<<5) + location;
1055         p[3] = 0x80 + progress;
1056 }
1057
1058 void dec_ie_progress(unsigned char *p, Q931_info_t *qi, int *coding, int *location, int *progress, int nt, struct misdn_bchannel *bc)
1059 {
1060         *coding = -1;
1061         *location = -1;
1062         //*progress = -1;
1063         *progress = 0;
1064         
1065         if (!nt)
1066         {
1067                 p = NULL;
1068                 if (qi->progress)
1069                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->progress + 1;
1070         }
1071         if (!p)
1072                 return;
1073         if (p[0] < 1)
1074         {
1075                 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
1076                 return;
1077         }
1078
1079         *coding = (p[1]&0x60) >> 5;
1080         *location = p[1] & 0x0f;
1081         *progress = p[2] & 0x7f;
1082
1083         if (MISDN_IE_DEBG) printf("    coding=%d location=%d progress=%d\n", *coding, *location, *progress);
1084 }
1085
1086
1087 /* IE_REDIR_NR (redirecting = during MT_SETUP) */
1088 void enc_ie_redir_nr(unsigned char **ntmode, msg_t *msg, int type, int plan, int present, int screen, int reason, unsigned char *number, int nt, struct misdn_bchannel *bc)
1089 {
1090         unsigned char *p;
1091         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
1092         int l;
1093
1094         if (type<0 || type>7)
1095         {
1096                 printf("%s: ERROR: type(%d) is out of range.\n", __FUNCTION__, type);
1097                 return;
1098         }
1099         if (plan<0 || plan>15)
1100         {
1101                 printf("%s: ERROR: plan(%d) is out of range.\n", __FUNCTION__, plan);
1102                 return;
1103         }
1104         if (present > 3)
1105         {
1106                 printf("%s: ERROR: present(%d) is out of range.\n", __FUNCTION__, present);
1107                 return;
1108         }
1109         if (present >= 0) if (screen<0 || screen>3)
1110         {
1111                 printf("%s: ERROR: screen(%d) is out of range.\n", __FUNCTION__, screen);
1112                 return;
1113         }
1114         if (reason > 0x0f)
1115         {
1116                 printf("%s: ERROR: reason(%d) is out of range.\n", __FUNCTION__, reason);
1117                 return;
1118         }
1119
1120         if (MISDN_IE_DEBG) printf("    type=%d plan=%d present=%d screen=%d readon=%d number='%s'\n", type, plan, present, screen, reason, number);
1121
1122         l = 1;
1123         if (number)
1124                 l += strlen((char *)number);
1125         if (present >= 0)
1126         {
1127                 l += 1;
1128                 if (reason >= 0)
1129                         l += 1;
1130         }
1131         p = msg_put(msg, l+2);
1132         if (nt)
1133                 *ntmode = p+1;
1134         else
1135                 qi->redirect_nr = p - (unsigned char *)qi - sizeof(Q931_info_t);
1136         p[0] = IE_REDIR_NR;
1137         p[1] = l;
1138         if (present >= 0)
1139         {
1140                 if (reason >= 0)
1141                 {
1142                         p[2] = 0x00 + (type<<4) + plan;
1143                         p[3] = 0x00 + (present<<5) + screen;
1144                         p[4] = 0x80 + reason;
1145                         if (number)
1146                                 strncpy((char *)p+5, (char *)number, strlen((char *)number));
1147                 } else
1148                 {
1149                         p[2] = 0x00 + (type<<4) + plan;
1150                         p[3] = 0x80 + (present<<5) + screen;
1151                         if (number)
1152                                 strncpy((char *)p+4, (char *)number, strlen((char *)number));
1153                 }
1154         } else
1155         {
1156                 p[2] = 0x80 + (type<<4) + plan;
1157                 if (number) if (number[0])
1158                         strncpy((char *)p+3, (char *)number, strlen((char *)number));
1159         }
1160 }
1161
1162 void dec_ie_redir_nr(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, int *screen, int *reason, unsigned char *number, int number_len, int nt, struct misdn_bchannel *bc)
1163 {
1164         *type = -1;
1165         *plan = -1;
1166         *present = -1;
1167         *screen = -1;
1168         *reason = -1;
1169         *number = '\0';
1170
1171         if (!nt)
1172         {
1173                 p = NULL;
1174                 if (qi->redirect_nr)
1175                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->redirect_nr + 1;
1176         }
1177         if (!p)
1178                 return;
1179         if (p[0] < 1)
1180         {
1181                 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
1182                 return;
1183         }
1184
1185         *type = (p[1]&0x70) >> 4;
1186         *plan = p[1] & 0xf;
1187         if (!(p[1] & 0x80))
1188         {
1189                 *present = (p[2]&0x60) >> 5;
1190                 *screen = p[2] & 0x3;
1191                 if (!(p[2] & 0x80))
1192                 {
1193                         *reason = p[3] & 0x0f;
1194                         strnncpy(number, p+4, p[0]-3, number_len);
1195                 } else
1196                 {
1197                         strnncpy(number, p+3, p[0]-2, number_len);
1198                 }
1199         } else
1200         {
1201                 strnncpy(number, p+2, p[0]-1, number_len);
1202         }
1203
1204         if (MISDN_IE_DEBG) printf("    type=%d plan=%d present=%d screen=%d reason=%d number='%s'\n", *type, *plan, *present, *screen, *reason, number);
1205 }
1206
1207
1208 /* IE_REDIR_DN (redirection = during MT_NOTIFY) */
1209 void enc_ie_redir_dn(unsigned char **ntmode, msg_t *msg, int type, int plan, int present, unsigned char *number, int nt, struct misdn_bchannel *bc)
1210 {
1211         unsigned char *p;
1212 /*      Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN); */
1213         int l;
1214
1215         if (type<0 || type>7)
1216         {
1217                 printf("%s: ERROR: type(%d) is out of range.\n", __FUNCTION__, type);
1218                 return;
1219         }
1220         if (plan<0 || plan>15)
1221         {
1222                 printf("%s: ERROR: plan(%d) is out of range.\n", __FUNCTION__, plan);
1223                 return;
1224         }
1225         if (present > 3)
1226         {
1227                 printf("%s: ERROR: present(%d) is out of range.\n", __FUNCTION__, present);
1228                 return;
1229         }
1230
1231         if (MISDN_IE_DEBG) printf("    type=%d plan=%d present=%d number='%s'\n", type, plan, present, number);
1232
1233         l = 1;
1234         if (number)
1235                 l += strlen((char *)number);
1236         if (present >= 0)
1237                 l += 1;
1238         p = msg_put(msg, l+2);
1239         if (nt)
1240                 *ntmode = p+1;
1241         else
1242 /* #warning REINSERT redir_dn, when included in te-mode */
1243                 /*qi->redir_dn = p - (unsigned char *)qi - sizeof(Q931_info_t)*/;
1244         p[0] = IE_REDIR_DN;
1245         p[1] = l;
1246         if (present >= 0)
1247         {
1248                 p[2] = 0x00 + (type<<4) + plan;
1249                 p[3] = 0x80 + (present<<5);
1250                 if (number)
1251                         strncpy((char *)p+4, (char *)number, strlen((char *)number));
1252         } else
1253         {
1254                 p[2] = 0x80 + (type<<4) + plan;
1255                 if (number)
1256                         strncpy((char *)p+3, (char *)number, strlen((char *)number));
1257         }
1258 }
1259
1260 void dec_ie_redir_dn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, unsigned char *number, int number_len, int nt, struct misdn_bchannel *bc)
1261 {
1262         *type = -1;
1263         *plan = -1;
1264         *present = -1;
1265         *number = '\0';
1266
1267         if (!nt)
1268         {
1269                 p = NULL;
1270 /* #warning REINSERT redir_dn, when included in te-mode */
1271 /*              if (qi->redir_dn) */
1272 /*                      p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->redir_dn + 1; */
1273         }
1274         if (!p)
1275                 return;
1276         if (p[0] < 1)
1277         {
1278                 printf("%s: ERROR: IE too short (%d).\n", __FUNCTION__, p[0]);
1279                 return;
1280         }
1281
1282         *type = (p[1]&0x70) >> 4;
1283         *plan = p[1] & 0xf;
1284         if (!(p[1] & 0x80))
1285         {
1286                 *present = (p[2]&0x60) >> 5;
1287                 strnncpy(number, p+3, p[0]-2, number_len);
1288         } else
1289         {
1290                 strnncpy(number, p+2, p[0]-1, number_len);
1291         }
1292
1293         if (MISDN_IE_DEBG) printf("    type=%d plan=%d present=%d number='%s'\n", *type, *plan, *present, number);
1294 }
1295
1296
1297 /* IE_FACILITY */
1298 void enc_ie_facility(unsigned char **ntmode, msg_t *msg, unsigned char *facility, int facility_len, int nt, struct misdn_bchannel *bc)
1299 {
1300         unsigned char *p;
1301         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
1302         int l;
1303
1304         char debug[768];
1305         int i;
1306
1307         if (!facility || facility_len<=0)
1308         {
1309                 return;
1310         }
1311
1312         i = 0;
1313         while(i < facility_len)
1314         {
1315                 if (MISDN_IE_DEBG) printf(debug+(i*3), " %02x", facility[i]);
1316                 i++;
1317         }
1318                 
1319         if (MISDN_IE_DEBG) printf("    facility%s\n", debug);
1320
1321         l = facility_len;
1322         p = msg_put(msg, l+2);
1323         if (nt)
1324                 *ntmode = p+1;
1325         else
1326                 qi->facility = p - (unsigned char *)qi - sizeof(Q931_info_t);
1327         p[0] = IE_FACILITY;
1328         p[1] = l;
1329         memcpy(p+2, facility, facility_len);
1330 }
1331
1332 void dec_ie_facility(unsigned char *p, Q931_info_t *qi, unsigned char *facility, int *facility_len, int nt, struct misdn_bchannel *bc)
1333 {
1334         int i;
1335
1336         *facility_len = 0;
1337
1338         if (!nt)
1339         {
1340                 p = NULL;
1341                 if (qi->facility)
1342                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->facility + 1;
1343         }
1344         if (!p)
1345                 return;
1346
1347         *facility_len = p[0];
1348         memcpy(facility, p+1, *facility_len);
1349         
1350         i = 0;
1351         while(i < *facility_len)
1352         {
1353                 cb_log(3, bc->stack->port, " %02x", facility[i]);
1354                 i++;
1355         }
1356         cb_log(3, bc->stack->port, "    facility\n");
1357 }
1358
1359
1360 /* facility for siemens CENTEX (known parts implemented only) */
1361 void enc_facility_centrex(unsigned char **ntmode, msg_t *msg, unsigned char *cnip, int setup, int nt, struct misdn_bchannel *bc)
1362 {
1363         unsigned char centrex[256];
1364         int i = 0;
1365
1366         if (!cnip)
1367                 return;
1368
1369         /* centrex facility */
1370         centrex[i++] = CENTREX_FAC;
1371         centrex[i++] = CENTREX_ID;
1372
1373         /* cnip */
1374         if (strlen((char *)cnip) > 15)
1375         {
1376 /*              if (options.deb & DEBUG_PORT) */
1377                 if (MISDN_IE_DEBG) printf("%s: CNIP/CONP text too long (max 13 chars), cutting.\n", __FUNCTION__);
1378                 cnip[15] = '\0';
1379         }
1380         /*  dunno what the 8 bytes mean */
1381         if (setup)
1382         {
1383                 centrex[i++] = 0x17;
1384                 centrex[i++] = 0x02;
1385                 centrex[i++] = 0x02;
1386                 centrex[i++] = 0x44;
1387                 centrex[i++] = 0x18;
1388                 centrex[i++] = 0x02;
1389                 centrex[i++] = 0x01;
1390                 centrex[i++] = 0x09;
1391         } else
1392         {
1393                 centrex[i++] = 0x18;
1394                 centrex[i++] = 0x02;
1395                 centrex[i++] = 0x02;
1396                 centrex[i++] = 0x81;
1397                 centrex[i++] = 0x09;
1398                 centrex[i++] = 0x02;
1399                 centrex[i++] = 0x01;
1400                 centrex[i++] = 0x0a;
1401         }
1402
1403         centrex[i++] = 0x80;
1404         centrex[i++] = strlen((char *)cnip);
1405         strcpy((char *)(&centrex[i]), (char *)cnip);
1406         i += strlen((char *)cnip);
1407         if (MISDN_IE_DEBG) printf("    cnip='%s'\n", cnip);
1408
1409         /* encode facility */
1410         enc_ie_facility(ntmode, msg, centrex, i, nt , bc);
1411 }
1412
1413 void dec_facility_centrex(unsigned char *p, Q931_info_t *qi, unsigned char *cnip, int cnip_len, int nt, struct misdn_bchannel *bc)
1414 {
1415         unsigned char centrex[256];
1416         char debug[768];
1417         int facility_len = 0;
1418         int i = 0, j;
1419         *cnip = '\0';
1420
1421         dec_ie_facility(p, qi, centrex, &facility_len,  nt, bc);
1422         if (facility_len >= 2)
1423         {
1424                 if (centrex[i++] != CENTREX_FAC)
1425                         return;
1426                 if (centrex[i++] != CENTREX_ID)
1427                         return;
1428         }
1429
1430         /* loop sub IEs of facility */
1431         while(facility_len > i+1)
1432         {
1433                 if (centrex[i+1]+i+1 > facility_len)
1434                 {
1435                         printf("%s: ERROR: short read of centrex facility.\n", __FUNCTION__);
1436                         return;
1437                 }
1438                 switch(centrex[i])
1439                 {
1440                 case 0x80:
1441                         strnncpy(cnip, &centrex[i+2], centrex[i+1], cnip_len);
1442                         if (MISDN_IE_DEBG) printf("    CENTREX cnip='%s'\n", cnip);
1443                         break;
1444
1445                 default:
1446                         j = 0;
1447                         while(j < centrex[i+1])
1448                         {
1449                                 if (MISDN_IE_DEBG) printf(debug+(j*3), " %02x", centrex[i+1+j]);
1450                                 i++;
1451                         }
1452                         if (MISDN_IE_DEBG) printf("    CENTREX unknown=0x%2x len=%d%s\n", centrex[i], centrex[i+1], debug);
1453                 }
1454                 i += 1+centrex[i+1];
1455         }
1456 }
1457
1458
1459
1460
1461 /* facility for siemens CENTEX (known parts implemented only) */
1462 void enc_facility_calldeflect(unsigned char **ntmode, msg_t *msg, unsigned char *nr, int nt, struct misdn_bchannel *bc)
1463 {
1464         unsigned char fac[256];
1465         
1466         if (!nr)
1467                 return;
1468         
1469         /* calldeflect facility */
1470         
1471         /* cnip */
1472         if (strlen((char *)nr) > 15)
1473         {
1474 /*              if (options.deb & DEBUG_PORT) */
1475                 if (MISDN_IE_DEBG) printf("%s: NR text too long (max 13 chars), cutting.\n", __FUNCTION__);
1476                 nr[15] = '\0';
1477         }
1478         
1479         fac[0]=0; // len 
1480         fac[1]=0; //len 
1481         fac[2]=0x01; // Use D-Chan
1482         fac[3]=0; // Keypad len
1483         fac[4]=31;      // user user data? len = 31 = 29 + 2
1484         fac[5]=0x1c;    // magic?
1485         fac[6]=0x1d;    // strlen destination + 18 = 29
1486         fac[7]=0x91;    // ..
1487         fac[8]=0xA1;
1488         fac[9]=0x1A;    // strlen destination + 15 = 26
1489         fac[10]=0x02;
1490         fac[11]=0x01;
1491         fac[12]=0x70;
1492         fac[13]=0x02;
1493         fac[14]=0x01;
1494         fac[15]=0x0d;
1495         fac[16]=0x30;
1496         fac[17]=0x12;   // strlen destination + 7 = 18
1497         fac[18]=0x30;   // ...hm 0x30
1498         fac[19]=0x0d;   // strlen destination + 2       
1499         fac[20]=0x80;   // CLIP
1500         fac[21]=0x0b;   //  strlen destination 
1501         fac[22]=0x01;   //  destination start
1502         fac[23]=0x01;   //  
1503         fac[24]=0x01;   //  
1504         fac[25]=0x01;   //  
1505         fac[26]=0x01;   //  
1506         fac[27]=0x01;   //  
1507         fac[28]=0x01;   //  
1508         fac[29]=0x01;   //  
1509         fac[30]=0x01;   //  
1510         fac[31]=0x01;   //  
1511         fac[32]=0x01;   //  
1512         fac[33]=0x01;   // 0x1 = sending complete
1513         fac[34]=0x01;
1514         fac[35]=0x01;
1515                                    
1516         memcpy((unsigned char *)fac+22,nr,strlen(nr));
1517         fac[22+strlen( nr)]=0x01;       // fill with 0x01 if number is only 6 numbers (local call)
1518         fac[23+strlen(nr)]=0x01;
1519         fac[24+strlen(nr)]=0x01;
1520         fac[25+strlen(nr)]=0x01;
1521         fac[26+strlen(nr)]=0x01;
1522         
1523         fac[6]=18+strlen(nr);
1524         fac[9]=15+strlen(nr);
1525         fac[17]=7+strlen(nr);
1526         fac[19]=2+strlen(nr);
1527         fac[21]=strlen(nr);
1528         
1529         enc_ie_facility(ntmode, msg, &fac[4], 36-4, nt , bc);
1530 }
1531
1532
1533 /* IE_USERUSER */
1534 void enc_ie_useruser(unsigned char **ntmode, msg_t *msg, int protocol, unsigned char *user, int user_len, int nt, struct misdn_bchannel *bc)
1535 {
1536         unsigned char *p;
1537         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
1538         int l;
1539
1540         char debug[768];
1541         int i;
1542
1543         if (protocol<0 || protocol>127)
1544         {
1545                 printf("%s: ERROR: protocol(%d) is out of range.\n", __FUNCTION__, protocol);
1546                 return;
1547         }
1548         if (!user || user_len<=0)
1549         {
1550                 return;
1551         }
1552
1553         i = 0;
1554         while(i < user_len)
1555         {
1556                 if (MISDN_IE_DEBG) printf(debug+(i*3), " %02x", user[i]);
1557                 i++;
1558         }
1559                 
1560         if (MISDN_IE_DEBG) printf("    protocol=%d user-user%s\n", protocol, debug);
1561
1562         l = user_len;
1563         p = msg_put(msg, l+3);
1564         if (nt)
1565                 *ntmode = p+1;
1566         else
1567                 qi->useruser = p - (unsigned char *)qi - sizeof(Q931_info_t);
1568         p[0] = IE_USER_USER;
1569         p[1] = l;
1570         p[2] = 0x80 + protocol;
1571         memcpy(p+3, user, user_len);
1572 }
1573
1574 void dec_ie_useruser(unsigned char *p, Q931_info_t *qi, int *protocol, unsigned char *user, int *user_len, int nt, struct misdn_bchannel *bc)
1575 {
1576         char debug[768];
1577         int i;
1578
1579         *user_len = 0;
1580         *protocol = -1;
1581
1582         if (!nt)
1583         {
1584                 p = NULL;
1585                 if (qi->useruser)
1586                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->useruser + 1;
1587         }
1588         if (!p)
1589                 return;
1590
1591         *user_len = p[0]-1;
1592         if (p[0] < 1)
1593                 return;
1594         *protocol = p[1];
1595         memcpy(user, p+2, (*user_len<=128)?*(user_len):128); /* clip to 128 maximum */
1596
1597         i = 0;
1598         while(i < *user_len)
1599         {
1600                 if (MISDN_IE_DEBG) printf(debug+(i*3), " %02x", user[i]);
1601                 i++;
1602         }
1603         debug[i*3] = '\0';
1604                 
1605         if (MISDN_IE_DEBG) printf("    protocol=%d user-user%s\n", *protocol, debug);
1606 }
1607
1608