socket api work
[lcr.git] / ie.cpp
1
2 /*****************************************************************************\
3 **                                                                           **
4 ** PBX4Linux                                                                 **
5 **                                                                           **
6 **---------------------------------------------------------------------------**
7 ** Copyright: Andreas Eversberg                                              **
8 **                                                                           **
9 ** information elements encode and decode                                    **
10 **                                                                           **
11 \*****************************************************************************/ 
12
13 /*
14  the pointer of enc_ie_* always points to the IE itself
15  if qi is not NULL (TE-mode), offset is set
16 */
17
18 /* support stuff */
19 static void strnncpy(unsigned char *dest, unsigned char *src, int len, int dst_len)
20 {
21         if (len > dst_len-1)
22                 len = dst_len-1;
23         UNCPY((char *)dest, (char *)src, len);
24         dest[len] = '\0';
25 }
26
27
28 /* IE_COMPLETE */
29 #ifdef SOCKET_MISDN
30 void Pdss1::enc_ie_complete(struct l3_msg *l3m, int complete)
31 #else
32 void Pdss1::enc_ie_complete(unsigned char **ntmode, msg_t *msg, int complete)
33 #endif
34 {
35 #ifndef SOCKET_MISDN
36         unsigned char *p;
37         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
38 #endif
39
40         if (complete<0 || complete>1)
41         {
42                 PERROR("complete(%d) is out of range.\n", complete);
43                 return;
44         }
45
46         if (complete)
47         {
48                 add_trace("complete", NULL, NULL);
49 #ifndef SOCKET_MISDN
50                 p = msg_put(msg, 1);
51                 if (p_m_d_ntmode)
52                 {
53                         *ntmode = p;
54                 } else
55                         qi->sending_complete.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
56                 p[0] = IE_COMPLETE;
57 #else
58                 l3m->sending_complete++;
59 #endif
60         }
61 }
62
63 #ifdef SOCKET_MISDN
64 void Pdss1::dec_ie_complete(struct l3_msg *l3m, int *complete)
65 #else
66 void Pdss1::dec_ie_complete(unsigned char *p, Q931_info_t *qi, int *complete)
67 #endif
68 {
69         *complete = 0;
70 #ifndef SOCKET_MISDN
71         if (!p_m_d_ntmode)
72         {
73                 if (qi->sending_complete.off)
74                         *complete = 1;
75         } else
76 #else
77         unsigned char *p = l3m->sending_complete;
78 #endif
79         if (p)
80                 *complete = 1;
81
82         if (*complete)
83                 add_trace("complete", NULL, NULL);
84 }
85
86
87 /* IE_BEARER */
88 #ifdef SOCKET_MISDN
89 void Pdss1::enc_ie_bearer(struct l3_msg *l3m, int coding, int capability, int mode, int rate, int multi, int user)
90 #else
91 void Pdss1::enc_ie_bearer(unsigned char **ntmode, msg_t *msg, int coding, int capability, int mode, int rate, int multi, int user)
92 #endif
93 {
94 #ifdef SOCKET_MISDN
95         unsigned char p[256];
96 #else
97         unsigned char *p;
98         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
99 #endif
100         int l;
101
102         if (coding<0 || coding>3)
103         {
104                 PERROR("coding(%d) is out of range.\n", coding);
105                 return;
106         }
107         if (capability<0 || capability>31)
108         {
109                 PERROR("capability(%d) is out of range.\n", capability);
110                 return;
111         }
112         if (mode<0 || mode>3)
113         {
114                 PERROR("mode(%d) is out of range.\n", mode);
115                 return;
116         }
117         if (rate<0 || rate>31)
118         {
119                 PERROR("rate(%d) is out of range.\n", rate);
120                 return;
121         }
122         if (multi>127)
123         {
124                 PERROR("multi(%d) is out of range.\n", multi);
125                 return;
126         }
127         if (user>31)
128         {
129                 PERROR("user L1(%d) is out of range.\n", user);
130                 return;
131         }
132         if (rate!=24 && multi>=0)
133         {
134                 PERROR("multi(%d) is only possible if rate(%d) would be 24.\n", multi, rate);
135                 multi = -1;
136         }
137
138         add_trace("bearer", "coding", "%d", coding);
139         add_trace("bearer", "capability", "%d", capability);
140         add_trace("bearer", "mode", "%d", mode);
141         add_trace("bearer", "rate", "%d", rate);
142         add_trace("bearer", "multi", "%d", multi);
143         add_trace("bearer", "user", "%d", user);
144
145         l = 2 + (multi>=0) + (user>=0);
146 #ifndef SOCKET_MISDN
147         p = msg_put(msg, l+2);
148         if (p_m_d_ntmode)
149                 *ntmode = p+1;
150         else
151                 qi->bearer_capability.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
152 #endif
153         p[0] = IE_BEARER;
154         p[1] = l;
155         p[2] = 0x80 + (coding<<5) + capability;
156         p[3] = 0x80 + (mode<<5) + rate;
157         if (multi >= 0)
158                 p[4] = 0x80 + multi;
159         if (user >= 0)
160                 p[4+(multi>=0)] = 0xa0 + user;
161 #ifdef SOCKET_MISDN
162         add_layer3_ie(l3m, p[0], p[1], p+2);
163 #endif
164 }
165
166 #ifdef SOCKET_MISDN
167 void Pdss1::dec_ie_bearer(struct l3_msg *l3m, int *coding, int *capability, int *mode, int *rate, int *multi, int *user)
168 #else
169 void Pdss1::dec_ie_bearer(unsigned char *p, Q931_info_t *qi, int *coding, int *capability, int *mode, int *rate, int *multi, int *user)
170 #endif
171 {
172         *coding = -1;
173         *capability = -1;
174         *mode = -1;
175         *rate = -1;
176         *multi = -1;
177         *user = -1;
178
179 #ifndef SOCKET_MISDN
180         if (!p_m_d_ntmode)
181         {
182                 p = NULL;
183                 if (qi->bearer_capability.off)
184                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->bearer_capability.off + 1;
185         }
186 #else
187         unsigned char *p = l3m->bearer_capability;
188 #endif
189         if (!p)
190                 return;
191         if (p[0] < 2)
192         {
193                 add_trace("bearer", "error", "IE too short (len=%d)", p[0]);
194                 return;
195         }
196
197         *coding = (p[1]&0x60) >> 5;
198         *capability = p[1] & 0x1f;
199         if (p[0]>=2)
200         {
201                 *mode = (p[2]&0x60) >> 5;
202                 *rate = p[2] & 0x1f;
203         }
204         if (p[0]>=3 && *rate==0x18)
205         {
206                 *multi = p[3] & 0x7f;
207                 if (p[0]>=4)
208                         *user = p[4] & 0x1f;
209         } else
210         {
211                 if (p[0]>=3)
212                         *user = p[3] & 0x1f;
213         }
214
215         add_trace("bearer", "coding", "%d", *coding);
216         add_trace("bearer", "capability", "%d", *capability);
217         add_trace("bearer", "mode", "%d", *mode);
218         add_trace("bearer", "rate", "%d", *rate);
219         add_trace("bearer", "multi", "%d", *multi);
220         add_trace("bearer", "user", "%d", *user);
221 }
222
223
224 /* IE_HLC */
225 #ifdef SOCKET_MISDN
226 void Pdss1::enc_ie_hlc(struct l3_msg *l3m, int coding, int interpretation, int presentation, int hlc, int exthlc)
227 #else
228 void Pdss1::enc_ie_hlc(unsigned char **ntmode, msg_t *msg, int coding, int interpretation, int presentation, int hlc, int exthlc)
229 #endif
230 {
231 #ifdef SOCKET_MISDN
232         unsigned char p[256];
233 #else
234         unsigned char *p;
235         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
236 #endif
237         int l;
238
239         if (coding<0 || coding>3)
240         {
241                 PERROR("coding(%d) is out of range.\n", coding);
242                 return;
243         }
244         if (interpretation<0 || interpretation>7)
245         {
246                 PERROR("interpretation(%d) is out of range.\n", interpretation);
247                 return;
248         }
249         if (presentation<0 || presentation>3)
250         {
251                 PERROR("presentation(%d) is out of range.\n", presentation);
252                 return;
253         }
254         if (hlc<0 || hlc>127)
255         {
256                 PERROR("hlc(%d) is out of range.\n", hlc);
257                 return;
258         }
259         if (exthlc>127)
260         {
261                 PERROR("hlc(%d) is out of range.\n", exthlc);
262                 return;
263         }
264
265         add_trace("hlc", "coding", "%d", coding);
266         add_trace("hlc", "interpretation", "%d", interpretation);
267         add_trace("hlc", "presentation", "%d", presentation);
268         add_trace("hlc", "hlc", "%d", hlc);
269         if (exthlc >= 0)
270                 add_trace("hlc", "exthlc", "%d", exthlc);
271
272         l = 2 + (exthlc>=0);
273 #ifndef SOCKET_MISDN
274         p = msg_put(msg, l+2);
275         if (p_m_d_ntmode)
276                 *ntmode = p+1;
277         else
278                 qi->hlc.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
279 #endif
280         p[0] = IE_HLC;
281         p[1] = l;
282         p[2] = 0x80 + (coding<<5) + (interpretation<<2) + presentation;
283         if (exthlc >= 0)
284         {
285                 p[3] = hlc;
286                 p[4] = 0x80 + exthlc;
287         } else
288                 p[3] = 0x80 + hlc;
289 #ifdef SOCKET_MISDN
290         add_layer3_ie(l3m, p[0], p[1], p+2);
291 #endif
292 }
293
294 #ifdef SOCKET_MISDN
295 void Pdss1::dec_ie_hlc(struct l3_msg *l3m, int *coding, int *interpretation, int *presentation, int *hlc, int *exthlc)
296 #else
297 void Pdss1::dec_ie_hlc(unsigned char *p, Q931_info_t *qi, int *coding, int *interpretation, int *presentation, int *hlc, int *exthlc)
298 #endif
299 {
300         *coding = -1;
301         *interpretation = -1;
302         *presentation = -1;
303         *hlc = -1;
304         *exthlc = -1;
305
306 #ifndef SOCKET_MISDN
307         if (!p_m_d_ntmode)
308         {
309                 p = NULL;
310                 if (qi->hlc.off)
311                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->hlc.off + 1;
312         }
313 #else
314         unsigned char *p = l3m->hlc;
315 #endif
316         if (!p)
317                 return;
318         if (p[0] < 2)
319         {
320                 add_trace("hlc", "error", "IE too short (len=%d)", p[0]);
321                 return;
322         }
323
324         *coding = (p[1]&0x60) >> 5;
325         *interpretation = (p[1]&0x1c) >> 2;
326         *presentation = p[1] & 0x03;
327         *hlc = p[2] & 0x7f;
328         if (p[0]>=3)
329         {
330                 *exthlc = p[3] & 0x7f;
331         }
332
333         add_trace("hlc", "coding", "%d", *coding);
334         add_trace("hlc", "interpretation", "%d", *interpretation);
335         add_trace("hlc", "presentation", "%d", *presentation);
336         add_trace("hlc", "hlc", "%d", *hlc);
337         if (*exthlc >= 0)
338                 add_trace("hlc", "exthlc", "%d", *exthlc);
339 }
340
341
342 /* IE_CALL_ID */
343 #ifdef SOCKET_MISDN
344 void Pdss1::enc_ie_call_id(struct l3_msg *l3m, unsigned char *callid, int callid_len)
345 #else
346 void Pdss1::enc_ie_call_id(unsigned char **ntmode, msg_t *msg, unsigned char *callid, int callid_len)
347 #endif
348 {
349 #ifdef SOCKET_MISDN
350         unsigned char p[256];
351 #else
352         unsigned char *p;
353         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
354 #endif
355         int l;
356
357         char buffer[25];
358         int i;
359
360         if (!callid || callid_len<=0)
361         {
362                 return;
363         }
364         if (callid_len > 8)
365         {
366                 PERROR("callid_len(%d) is out of range.\n", callid_len);
367                 return;
368         }
369
370         i = 0;
371         while(i < callid_len)
372         {
373                 UPRINT(buffer+(i*3), " %02x", callid[i]);
374                 i++;
375         }
376                 
377         add_trace("callid", NULL, "%s", buffer[0]?buffer+1:"<none>");
378
379         l = callid_len;
380 #ifndef SOCKET_MISDN
381         p = msg_put(msg, l+2);
382         if (p_m_d_ntmode)
383                 *ntmode = p+1;
384         else
385                 qi->call_id.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
386 #endif
387         p[0] = IE_CALL_ID;
388         p[1] = l;
389         memcpy(p+2, callid, callid_len);
390 #ifdef SOCKET_MISDN
391         add_layer3_ie(l3m, p[0], p[1], p+2);
392 #endif
393 }
394
395 #ifdef SOCKET_MISDN
396 void Pdss1::dec_ie_call_id(struct l3_msg *l3m, unsigned char *callid, int *callid_len)
397 #else
398 void Pdss1::dec_ie_call_id(unsigned char *p, Q931_info_t *qi, unsigned char *callid, int *callid_len)
399 #endif
400 {
401         char buffer[25];
402         int i;
403
404         *callid_len = -1;
405
406 #ifndef SOCKET_MISDN
407         if (!p_m_d_ntmode)
408         {
409                 p = NULL;
410                 if (qi->call_id.off)
411                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->call_id.off + 1;
412         }
413 #else
414         unsigned char *p = l3m->call_id;
415 #endif
416         if (!p)
417                 return;
418         if (p[0] > 8)
419         {
420                 add_trace("callid", "error", "IE too long (len=%d)", p[0]);
421                 return;
422         }
423
424         *callid_len = p[0];
425         memcpy(callid, p+1, *callid_len);
426
427         i = 0;
428         while(i < *callid_len)
429         {
430                 UPRINT(buffer+(i*3), " %02x", callid[i]);
431                 i++;
432         }
433                 
434         add_trace("callid", NULL, "%s", buffer[0]?buffer+1:"<none>");
435 }
436
437
438 /* IE_CALLED_PN */
439 #ifdef SOCKET_MISDN
440 void Pdss1::enc_ie_called_pn(struct l3_msg *l3m, int type, int plan, unsigned char *number)
441 #else
442 void Pdss1::enc_ie_called_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, unsigned char *number)
443 #endif
444 {
445 #ifdef SOCKET_MISDN
446         unsigned char p[256];
447 #else
448         unsigned char *p;
449         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
450 #endif
451         int l;
452
453         if (type<0 || type>7)
454         {
455                 PERROR("type(%d) is out of range.\n", type);
456                 return;
457         }
458         if (plan<0 || plan>15)
459         {
460                 PERROR("plan(%d) is out of range.\n", plan);
461                 return;
462         }
463         if (!number[0])
464         {
465                 PERROR("number is not given.\n");
466                 return;
467         }
468
469         add_trace("called_pn", "type", "%d", type);
470         add_trace("called_pn", "plan", "%d", plan);
471         add_trace("called_pn", "number", "%s", number);
472
473         l = 1+strlen((char *)number);
474 #ifndef SOCKET_MISDN
475         p = msg_put(msg, l+2);
476         if (p_m_d_ntmode)
477                 *ntmode = p+1;
478         else
479                 qi->called_nr.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
480 #endif
481         p[0] = IE_CALLED_PN;
482         p[1] = l;
483         p[2] = 0x80 + (type<<4) + plan;
484         UNCPY((char *)p+3, (char *)number, strlen((char *)number));
485 #ifdef SOCKET_MISDN
486         add_layer3_ie(l3m, p[0], p[1], p+2);
487 #endif
488 }
489
490 #ifdef SOCKET_MISDN
491 void Pdss1::dec_ie_called_pn(struct l3_msg *l3m, int *type, int *plan, unsigned char *number, int number_len)
492 #else
493 void Pdss1::dec_ie_called_pn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, unsigned char *number, int number_len)
494 #endif
495 {
496         *type = -1;
497         *plan = -1;
498         *number = '\0';
499
500 #ifndef SOCKET_MISDN
501         if (!p_m_d_ntmode)
502         {
503                 p = NULL;
504                 if (qi->called_nr.off)
505                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->called_nr.off + 1;
506         }
507 #else
508         unsigned char *p = l3m->called_nr;
509 #endif
510         if (!p)
511                 return;
512         if (p[0] < 2)
513         {
514                 add_trace("called_pn", "error", "IE too short (len=%d)", p[0]);
515                 return;
516         }
517
518         *type = (p[1]&0x70) >> 4;
519         *plan = p[1] & 0xf;
520         strnncpy(number, p+2, p[0]-1, number_len);
521
522         add_trace("called_pn", "type", "%d", *type);
523         add_trace("called_pn", "plan", "%d", *plan);
524         add_trace("called_pn", "number", "%s", number);
525 }
526
527
528 /* IE_CALLING_PN */
529 #ifdef SOCKET_MISDN
530 void Pdss1::enc_ie_calling_pn(struct l3_msg *l3m, int type, int plan, int present, int screen, unsigned char *number)
531 #else
532 void Pdss1::enc_ie_calling_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, int present, int screen, unsigned char *number)
533 #endif
534 {
535 #ifdef SOCKET_MISDN
536         unsigned char p[256];
537 #else
538         unsigned char *p;
539         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
540 #endif
541         int l;
542
543         if (type<0 || type>7)
544         {
545                 PERROR("type(%d) is out of range.\n", type);
546                 return;
547         }
548         if (plan<0 || plan>15)
549         {
550                 PERROR("plan(%d) is out of range.\n", plan);
551                 return;
552         }
553         if (present>3)
554         {
555                 PERROR("present(%d) is out of range.\n", present);
556                 return;
557         }
558         if (present >= 0) if (screen<0 || screen>3)
559         {
560                 PERROR("screen(%d) is out of range.\n", screen);
561                 return;
562         }
563
564         add_trace("calling_pn", "type", "%d", type);
565         add_trace("calling_pn", "plan", "%d", plan);
566         add_trace("calling_pn", "present", "%d", present);
567         add_trace("calling_pn", "screen", "%d", screen);
568         add_trace("calling_pn", "number", "%s", number);
569
570         l = 1;
571         if (number) if (number[0])
572                 l += strlen((char *)number);
573         if (present >= 0)
574                 l += 1;
575 #ifndef SOCKET_MISDN
576         p = msg_put(msg, l+2);
577         if (p_m_d_ntmode)
578                 *ntmode = p+1;
579         else
580                 qi->calling_nr.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
581 #endif
582         p[0] = IE_CALLING_PN;
583         p[1] = l;
584         if (present >= 0)
585         {
586                 p[2] = 0x00 + (type<<4) + plan;
587                 p[3] = 0x80 + (present<<5) + screen;
588                 if (number) if (number[0])
589                         UNCPY((char *)p+4, (char *)number, strlen((char *)number));
590         } else
591         {
592                 p[2] = 0x80 + (type<<4) + plan;
593                 if (number) if (number[0])
594                         UNCPY((char *)p+3, (char *)number, strlen((char *)number));
595         }
596 #ifdef SOCKET_MISDN
597         add_layer3_ie(l3m, p[0], p[1], p+2);
598 #endif
599 }
600
601 #ifdef SOCKET_MISDN
602 void Pdss1::dec_ie_calling_pn(struct l3_msg *l3m, int *type, int *plan, int *present, int *screen, unsigned char *number, int number_len)
603 #else
604 void Pdss1::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)
605 #endif
606 {
607         *type = -1;
608         *plan = -1;
609         *present = -1;
610         *screen = -1;
611         *number = '\0';
612
613 #ifndef SOCKET_MISDN
614         if (!p_m_d_ntmode)
615         {
616                 p = NULL;
617                 if (qi->calling_nr.off)
618                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->calling_nr.off + 1;
619         }
620 #else
621         unsigned char *p = l3m->calling_nr;
622 #endif
623         if (!p)
624                 return;
625         if (p[0] < 1)
626         {
627                 add_trace("calling_pn", "error", "IE too short (len=%d)", p[0]);
628                 return;
629         }
630
631         *type = (p[1]&0x70) >> 4;
632         *plan = p[1] & 0xf;
633         if (!(p[1] & 0x80))
634         {
635                 if (p[0] < 2)
636                 {
637                         add_trace("calling_pn", "error", "IE too short (len=%d)", p[0]);
638                         return;
639                 }
640                 *present = (p[2]&0x60) >> 5;
641                 *screen = p[2] & 0x3;
642                 strnncpy(number, p+3, p[0]-2, number_len);
643         } else
644         {
645                 strnncpy(number, p+2, p[0]-1, number_len);
646         }
647
648         add_trace("calling_pn", "type", "%d", *type);
649         add_trace("calling_pn", "plan", "%d", *plan);
650         add_trace("calling_pn", "present", "%d", *present);
651         add_trace("calling_pn", "screen", "%d", *screen);
652         add_trace("calling_pn", "number", "%s", number);
653 }
654
655
656 /* IE_CONNECTED_PN */
657 #ifdef SOCKET_MISDN
658 void Pdss1::enc_ie_connected_pn(struct l3_msg *l3m, int type, int plan, int present, int screen, unsigned char *number)
659 #else
660 void Pdss1::enc_ie_connected_pn(unsigned char **ntmode, msg_t *msg, int type, int plan, int present, int screen, unsigned char *number)
661 #endif
662 {
663 #ifdef SOCKET_MISDN
664         unsigned char p[256];
665 #else
666         unsigned char *p;
667         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
668 #endif
669         int l;
670
671         if (type<0 || type>7)
672         {
673                 PERROR("type(%d) is out of range.\n", type);
674                 return;
675         }
676         if (plan<0 || plan>15)
677         {
678                 PERROR("plan(%d) is out of range.\n", plan);
679                 return;
680         }
681         if (present>3)
682         {
683                 PERROR("present(%d) is out of range.\n", present);
684                 return;
685         }
686         if (present >= 0) if (screen<0 || screen>3)
687         {
688                 PERROR("screen(%d) is out of range.\n", screen);
689                 return;
690         }
691
692         add_trace("connect_pn", "type", "%d", type);
693         add_trace("connect_pn", "plan", "%d", plan);
694         add_trace("connect_pn", "present", "%d", present);
695         add_trace("connect_pn", "screen", "%d", screen);
696         add_trace("connect_pn", "number", "%s", number);
697
698         l = 1;
699         if (number) if (number[0])
700                 l += strlen((char *)number);
701         if (present >= 0)
702                 l += 1;
703 #ifndef SOCKET_MISDN
704         p = msg_put(msg, l+2);
705         if (p_m_d_ntmode)
706                 *ntmode = p+1;
707         else
708                 qi->connected_nr.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
709 #endif
710         p[0] = IE_CONNECT_PN;
711         p[1] = l;
712         if (present >= 0)
713         {
714                 p[2] = 0x00 + (type<<4) + plan;
715                 p[3] = 0x80 + (present<<5) + screen;
716                 if (number) if (number[0])
717                         UNCPY((char *)p+4, (char *)number, strlen((char *)number));
718         } else
719         {
720                 p[2] = 0x80 + (type<<4) + plan;
721                 if (number) if (number[0])
722                         UNCPY((char *)p+3, (char *)number, strlen((char *)number));
723         }
724 #ifdef SOCKET_MISDN
725         add_layer3_ie(l3m, p[0], p[1], p+2);
726 #endif
727 }
728
729 #ifdef SOCKET_MISDN
730 void Pdss1::dec_ie_connected_pn(struct l3_msg *l3m, int *type, int *plan, int *present, int *screen, unsigned char *number, int number_len)
731 #else
732 void Pdss1::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)
733 #endif
734 {
735         *type = -1;
736         *plan = -1;
737         *present = -1;
738         *screen = -1;
739         *number = '\0';
740
741 #ifndef SOCKET_MISDN
742         if (!p_m_d_ntmode)
743         {
744                 p = NULL;
745                 if (qi->connected_nr.off)
746                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->connected_nr.off + 1;
747         }
748 #else
749         unsigned char *p = l3m->connected_nr;
750 #endif
751         if (!p)
752                 return;
753         if (p[0] < 1)
754         {
755                 add_trace("connect_pn", "error", "IE too short (len=%d)", p[0]);
756                 return;
757         }
758
759         *type = (p[1]&0x70) >> 4;
760         *plan = p[1] & 0xf;
761         if (!(p[1] & 0x80))
762         {
763                 if (p[0] < 2)
764                 {
765                         add_trace("connect_pn", "error", "IE too short (len=%d)", p[0]);
766                         return;
767                 }
768                 *present = (p[2]&0x60) >> 5;
769                 *screen = p[2] & 0x3;
770                 strnncpy(number, p+3, p[0]-2, number_len);
771         } else
772         {
773                 strnncpy(number, p+2, p[0]-1, number_len);
774         }
775
776         add_trace("connect_pn", "type", "%d", *type);
777         add_trace("connect_pn", "plan", "%d", *plan);
778         add_trace("connect_pn", "present", "%d", *present);
779         add_trace("connect_pn", "screen", "%d", *screen);
780         add_trace("connect_pn", "number", "%s", number);
781 }
782
783
784 /* IE_CAUSE */
785 #ifdef SOCKET_MISDN
786 void Pdss1::enc_ie_cause(struct l3_msg *l3m, int location, int cause)
787 #else
788 void Pdss1::enc_ie_cause(unsigned char **ntmode, msg_t *msg, int location, int cause)
789 #endif
790 {
791 #ifdef SOCKET_MISDN
792         unsigned char p[256];
793 #else
794         unsigned char *p;
795         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
796 #endif
797         int l;
798
799         if (location<0 || location>7)
800         {
801                 PERROR("location(%d) is out of range.\n", location);
802                 return;
803         }
804         if (cause<0 || cause>127)
805         {
806                 PERROR("cause(%d) is out of range.\n", cause);
807                 return;
808         }
809
810         add_trace("cause", "location", "%d", location);
811         add_trace("cause", "value", "%d", cause);
812
813         l = 2;
814 #ifndef SOCKET_MISDN
815         p = msg_put(msg, l+2);
816         if (p_m_d_ntmode)
817                 *ntmode = p+1;
818         else
819                 qi->cause.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
820 #endif
821         p[0] = IE_CAUSE;
822         p[1] = l;
823         p[2] = 0x80 + location;
824         p[3] = 0x80 + cause;
825 #ifdef SOCKET_MISDN
826         add_layer3_ie(l3m, p[0], p[1], p+2);
827 #endif
828 }
829 #ifdef SOCKET_MISDN
830 void enc_ie_cause_standalone(struct l3_msg *l3m, int location, int cause)
831 #else
832 void enc_ie_cause_standalone(unsigned char **ntmode, msg_t *msg, int location, int cause)
833 #endif
834 {
835 #ifdef SOCKET_MISDN
836         unsigned char p[256];
837 #else
838         unsigned char *p = msg_put(msg, 4);
839         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
840         if (ntmode)
841                 *ntmode = p+1;
842         else
843                 qi->cause.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
844 #endif
845         p[0] = IE_CAUSE;
846         p[1] = 2;
847         p[2] = 0x80 + location;
848         p[3] = 0x80 + cause;
849 #ifdef SOCKET_MISDN
850         add_layer3_ie(l3m, p[0], p[1], p+2);
851 #endif
852 }
853
854
855 #ifdef SOCKET_MISDN
856 void Pdss1::dec_ie_cause(struct l3_msg *l3m, int *location, int *cause)
857 #else
858 void Pdss1::dec_ie_cause(unsigned char *p, Q931_info_t *qi, int *location, int *cause)
859 #endif
860 {
861         *location = -1;
862         *cause = -1;
863
864 #ifndef SOCKET_MISDN
865         if (!p_m_d_ntmode)
866         {
867                 p = NULL;
868                 if (qi->cause.off)
869                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->cause.off + 1;
870         }
871 #else
872         unsigned char *p = l3m->cause;
873 #endif
874         if (!p)
875                 return;
876         if (p[0] < 2)
877         {
878                 add_trace("cause", "error", "IE too short (len=%d)", p[0]);
879                 return;
880         }
881
882         *location = p[1] & 0x0f;
883         *cause = p[2] & 0x7f;
884
885         add_trace("cause", "location", "%d", *location);
886         add_trace("cause", "value", "%d", *cause);
887 }
888
889
890 /* IE_CHANNEL_ID */
891 #ifdef SOCKET_MISDN
892 void Pdss1::enc_ie_channel_id(struct l3_msg *l3m, int exclusive, int channel)
893 #else
894 void Pdss1::enc_ie_channel_id(unsigned char **ntmode, msg_t *msg, int exclusive, int channel)
895 #endif
896 {
897 #ifdef SOCKET_MISDN
898         unsigned char p[256];
899 #else
900         unsigned char *p;
901         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
902 #endif
903         int l;
904         int pri = p_m_mISDNport->pri;
905
906         if (exclusive<0 || exclusive>1)
907         {
908                 PERROR("exclusive(%d) is out of range.\n", exclusive);
909                 return;
910         }
911         if ((channel<=0 && channel!=CHANNEL_NO && channel!=CHANNEL_ANY)
912          || (!pri && channel>2)
913          || (pri && channel>127)
914          || (pri && channel==16))
915         {
916                 PERROR("channel(%d) is out of range.\n", channel);
917                 return;
918         }
919
920         add_trace("channel_id", "exclusive", "%d", exclusive);
921         switch(channel)
922         {
923                 case CHANNEL_ANY:
924                 add_trace("channel_id", "channel", "any channel");
925                 break;
926                 case CHANNEL_NO:
927                 add_trace("channel_id", "channel", "no channel");
928                 break;
929                 default:
930                 add_trace("channel_id", "channel", "%d", channel);
931         }
932
933         if (!pri)
934         {
935                 /* BRI */
936                 l = 1;
937 #ifndef SOCKET_MISDN
938                 p = msg_put(msg, l+2);
939                 if (p_m_d_ntmode)
940                         *ntmode = p+1;
941                 else
942                         qi->channel_id.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
943 #endif
944                 p[0] = IE_CHANNEL_ID;
945                 p[1] = l;
946                 if (channel == CHANNEL_NO)
947                         channel = 0;
948                 else if (channel == CHANNEL_ANY)
949                         channel = 3;
950                 p[2] = 0x80 + (exclusive<<3) + channel;
951 #ifdef SOCKET_MISDN
952                 add_layer3_ie(l3m, p[0], p[1], p+2);
953 #endif
954         } else
955         {
956                 /* PRI */
957                 if (channel == CHANNEL_NO) /* no channel */
958                         return; /* IE not present */
959                 if (channel == CHANNEL_ANY) /* any channel */
960                 {
961                         l = 1;
962 #ifndef SOCKET_MISDN
963                         p = msg_put(msg, l+2);
964                         if (p_m_d_ntmode)
965                                 *ntmode = p+1;
966                         else
967                                 qi->channel_id.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
968 #endif
969                         p[0] = IE_CHANNEL_ID;
970                         p[1] = l;
971                         p[2] = 0x80 + 0x20 + 0x03;
972 #ifdef SOCKET_MISDN
973                         add_layer3_ie(l3m, p[0], p[1], p+2);
974 #endif
975                         return; /* end */
976                 }
977                 l = 3;
978 #ifndef SOCKET_MISDN
979                 p = msg_put(msg, l+2);
980                 if (p_m_d_ntmode)
981                         *ntmode = p+1;
982                 else
983                         qi->channel_id.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
984 #endif
985                 p[0] = IE_CHANNEL_ID;
986                 p[1] = l;
987                 p[2] = 0x80 + 0x20 + (exclusive<<3) + 0x01;
988                 p[3] = 0x80 + 3; /* CCITT, Number, B-type */
989                 p[4] = 0x80 + channel;
990 #ifdef SOCKET_MISDN
991                 add_layer3_ie(l3m, p[0], p[1], p+2);
992 #endif
993         }
994 }
995
996 #ifdef SOCKET_MISDN
997 void Pdss1::dec_ie_channel_id(struct l3_msg *l3m, int *exclusive, int *channel)
998 #else
999 void Pdss1::dec_ie_channel_id(unsigned char *p, Q931_info_t *qi, int *exclusive, int *channel)
1000 #endif
1001 {
1002         int pri = p_m_mISDNport->pri;
1003
1004         *exclusive = -1;
1005         *channel = -1;
1006
1007 #ifndef SOCKET_MISDN
1008         if (!p_m_d_ntmode)
1009         {
1010                 p = NULL;
1011                 if (qi->channel_id.off)
1012                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->channel_id.off + 1;
1013         }
1014 #else
1015         unsigned char *p = l3m->channel_id;
1016 #endif
1017         if (!p)
1018                 return;
1019         if (p[0] < 1)
1020         {
1021                 add_trace("channel_id", "error", "IE too short (len=%d)", p[0]);
1022                 return;
1023         }
1024
1025         if (p[1] & 0x40)
1026         {
1027                 add_trace("channel_id", "error", "refering to channels of other interfaces is not supported");
1028                 return;
1029         }
1030         if (p[1] & 0x04)
1031         {
1032                 add_trace("channel_id", "error", "using d-channel is not supported");
1033                 return;
1034         }
1035
1036         *exclusive = (p[1]&0x08) >> 3;
1037         if (!pri)
1038         {
1039                 /* BRI */
1040                 if (p[1] & 0x20)
1041                 {
1042                         add_trace("channel_id", "error", "extended channel ID with non PRI interface");
1043                         return;
1044                 }
1045                 *channel = p[1] & 0x03;
1046                 if (*channel == 3)
1047                         *channel = CHANNEL_ANY;
1048                 else if (*channel == 0)
1049                         *channel = CHANNEL_NO;
1050         } else
1051         {
1052                 /* PRI */
1053                 if (p[0] < 1)
1054                 {
1055
1056                         add_trace("channel_id", "error", "IE too short for PRI (len=%d)", p[0]);
1057                         return;
1058                 }
1059                 if (!(p[1] & 0x20))
1060                 {
1061                         add_trace("channel_id", "error", "basic channel ID with PRI interface");
1062                         return;
1063                 }
1064                 if ((p[1]&0x03) == 0x00)
1065                 {
1066                         /* no channel */
1067                         *channel = CHANNEL_NO;
1068                         return;
1069                 }
1070                 if ((p[1]&0x03) == 0x03)
1071                 {
1072                         /* any channel */
1073                         *channel = CHANNEL_ANY;
1074                         return;
1075                 }
1076                 if (p[0] < 3)
1077                 {
1078                         add_trace("channel_id", "error", "IE too short for PRI with channel (len=%d)", p[0]);
1079                         return;
1080                 }
1081                 if (p[2] & 0x10)
1082                 {
1083                         add_trace("channel_id", "error", "channel map not supported");
1084                         return;
1085                 }
1086                 *channel = p[3] & 0x7f;
1087                 if (*channel<1 | *channel==16)
1088                 {
1089                         add_trace("channel_id", "error", "PRI interface channel out of range (%d)", *channel);
1090                         return;
1091                 }
1092         }
1093
1094         add_trace("channel_id", "exclusive", "%d", *exclusive);
1095         switch(*channel)
1096         {
1097                 case CHANNEL_ANY:
1098                 add_trace("channel_id", "channel", "any channel");
1099                 break;
1100                 case CHANNEL_NO:
1101                 add_trace("channel_id", "channel", "no channel");
1102                 break;
1103                 default:
1104                 add_trace("channel_id", "channel", "%d", *channel);
1105         }
1106 }
1107
1108
1109 /* IE_DATE */
1110 #ifdef SOCKET_MISDN
1111 void Pdss1::enc_ie_date(struct l3_msg *l3m, time_t ti, int no_seconds)
1112 #else
1113 void Pdss1::enc_ie_date(unsigned char **ntmode, msg_t *msg, time_t ti, int no_seconds)
1114 #endif
1115 {
1116 #ifdef SOCKET_MISDN
1117         unsigned char p[256];
1118 #else
1119         unsigned char *p;
1120         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
1121 #endif
1122         int l;
1123
1124         struct tm *tm;
1125
1126         tm = localtime(&ti);
1127         if (!tm)
1128         {
1129                 PERROR("localtime() returned NULL.\n");
1130                 return;
1131         }
1132
1133         add_trace("date", "day", "%d.%d.%d", tm->tm_mday, tm->tm_mon+1, tm->tm_year%100);
1134         add_trace("date", "time", "%d:%d:%d", tm->tm_hour, tm->tm_min, tm->tm_sec);
1135
1136         l = 5 + (!no_seconds);
1137 #ifndef SOCKET_MISDN
1138         p = msg_put(msg, l+2);
1139         if (p_m_d_ntmode)
1140                 *ntmode = p+1;
1141         else
1142                 qi->date.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
1143 #endif
1144         p[0] = IE_DATE;
1145         p[1] = l;
1146         p[2] = tm->tm_year % 100;
1147         p[3] = tm->tm_mon + 1;
1148         p[4] = tm->tm_mday;
1149         p[5] = tm->tm_hour;
1150         p[6] = tm->tm_min;
1151         if (!no_seconds)
1152                 p[7] = tm->tm_sec;
1153 #ifdef SOCKET_MISDN
1154         add_layer3_ie(l3m, p[0], p[1], p+2);
1155 #endif
1156 }
1157
1158
1159 /* IE_DISPLAY */
1160 #ifdef SOCKET_MISDN
1161 void Pdss1::enc_ie_display(struct l3_msg *l3m, unsigned char *display)
1162 #else
1163 void Pdss1::enc_ie_display(unsigned char **ntmode, msg_t *msg, unsigned char *display)
1164 #endif
1165 {
1166 #ifdef SOCKET_MISDN
1167         unsigned char p[256];
1168 #else
1169         unsigned char *p;
1170         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
1171 #endif
1172         int l;
1173
1174         if (!display[0])
1175         {
1176                 PERROR("display text not given.\n");
1177                 return;
1178         }
1179
1180         if (strlen((char *)display) > 80)
1181         {
1182                 PERROR("display text too long (max 80 chars), cutting.\n");
1183                 display[80] = '\0';
1184         }
1185
1186         add_trace("display", NULL, "%s", display);
1187
1188         l = strlen((char *)display);
1189 #ifndef SOCKET_MISDN
1190         p = msg_put(msg, l+2);
1191         if (p_m_d_ntmode)
1192                 *ntmode = p+1;
1193         else
1194                 qi->display.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
1195 #endif
1196         p[0] = IE_DISPLAY;
1197         p[1] = l;
1198         UNCPY((char *)p+2, (char *)display, strlen((char *)display));
1199 #ifdef SOCKET_MISDN
1200         add_layer3_ie(l3m, p[0], p[1], p+2);
1201 #endif
1202 }
1203
1204 #ifdef SOCKET_MISDN
1205 void Pdss1::dec_ie_display(struct l3_msg *l3m, unsigned char *display, int display_len)
1206 #else
1207 void Pdss1::dec_ie_display(unsigned char *p, Q931_info_t *qi, unsigned char *display, int display_len)
1208 #endif
1209 {
1210         *display = '\0';
1211
1212 #ifndef SOCKET_MISDN
1213         if (!p_m_d_ntmode)
1214         {
1215                 p = NULL;
1216                 if (qi->display.off)
1217                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->display.off + 1;
1218         }
1219 #else
1220         unsigned char *p = l3m->display;
1221 #endif
1222         if (!p)
1223                 return;
1224         if (p[0] < 1)
1225         {
1226                 add_trace("display", "error", "IE too short (len=%d)", p[0]);
1227                 return;
1228         }
1229
1230         strnncpy(display, p+1, p[0], display_len);
1231
1232         add_trace("display", NULL, "%s", display);
1233 }
1234
1235
1236 /* IE_KEYPAD */
1237 #ifdef SOCKET_MISDN
1238 void Pdss1::enc_ie_keypad(struct l3_msg *l3m, unsigned char *keypad)
1239 #else
1240 void Pdss1::enc_ie_keypad(unsigned char **ntmode, msg_t *msg, unsigned char *keypad)
1241 #endif
1242 {
1243 #ifdef SOCKET_MISDN
1244         unsigned char p[256];
1245 #else
1246         unsigned char *p;
1247         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
1248 #endif
1249         int l;
1250
1251         if (!keypad[0])
1252         {
1253                 PERROR("keypad info not given.\n");
1254                 return;
1255         }
1256
1257         add_trace("keypad", NULL, "%s", keypad);
1258
1259         l = strlen((char *)keypad);
1260 #ifndef SOCKET_MISDN
1261         p = msg_put(msg, l+2);
1262         if (p_m_d_ntmode)
1263                 *ntmode = p+1;
1264         else
1265                 qi->keypad.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
1266 #endif
1267         p[0] = IE_KEYPAD;
1268         p[1] = l;
1269         UNCPY((char *)p+2, (char *)keypad, strlen((char *)keypad));
1270 #ifdef SOCKET_MISDN
1271         add_layer3_ie(l3m, p[0], p[1], p+2);
1272 #endif
1273 }
1274
1275 #ifdef SOCKET_MISDN
1276 void Pdss1::dec_ie_keypad(struct l3_msg *l3m, unsigned char *keypad, int keypad_len)
1277 #else
1278 void Pdss1::dec_ie_keypad(unsigned char *p, Q931_info_t *qi, unsigned char *keypad, int keypad_len)
1279 #endif
1280 {
1281         *keypad = '\0';
1282
1283 #ifndef SOCKET_MISDN
1284         if (!p_m_d_ntmode)
1285         {
1286                 p = NULL;
1287                 if (qi->keypad.off)
1288                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->keypad.off + 1;
1289         }
1290 #else
1291         unsigned char *p = l3m->keypad;
1292 #endif
1293         if (!p)
1294                 return;
1295         if (p[0] < 1)
1296         {
1297                 add_trace("keypad", "error", "IE too short (len=%d)", p[0]);
1298                 return;
1299         }
1300
1301         strnncpy(keypad, p+1, p[0], keypad_len);
1302
1303         add_trace("keypad", NULL, "%s", keypad);
1304 }
1305
1306
1307 /* IE_NOTIFY */
1308 #ifdef SOCKET_MISDN
1309 void Pdss1::enc_ie_notify(struct l3_msg *l3m, int notify)
1310 #else
1311 void Pdss1::enc_ie_notify(unsigned char **ntmode, msg_t *msg, int notify)
1312 #endif
1313 {
1314 #ifdef SOCKET_MISDN
1315         unsigned char p[256];
1316 #else
1317         unsigned char *p;
1318         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
1319 #endif
1320         int l;
1321
1322         if (notify<0 || notify>0x7f)
1323         {
1324                 PERROR("notify(%d) is out of range.\n", notify);
1325                 return;
1326         }
1327
1328         add_trace("notify", NULL, "%d", notify);
1329
1330         l = 1;
1331 #ifndef SOCKET_MISDN
1332         p = msg_put(msg, l+2);
1333         if (p_m_d_ntmode)
1334                 *ntmode = p+1;
1335         else
1336                 qi->notify.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
1337 #endif
1338         p[0] = IE_NOTIFY;
1339         p[1] = l;
1340         p[2] = 0x80 + notify;
1341 #ifdef SOCKET_MISDN
1342         add_layer3_ie(l3m, p[0], p[1], p+2);
1343 #endif
1344 }
1345
1346 #ifdef SOCKET_MISDN
1347 void Pdss1::dec_ie_notify(struct l3_msg *l3m, int *notify)
1348 #else
1349 void Pdss1::dec_ie_notify(unsigned char *p, Q931_info_t *qi, int *notify)
1350 #endif
1351 {
1352         *notify = -1;
1353
1354 #ifndef SOCKET_MISDN
1355         if (!p_m_d_ntmode)
1356         {
1357                 p = NULL;
1358                 if (qi->notify.off)
1359                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->notify.off + 1;
1360         }
1361 #else
1362         unsigned char *p = l3m->notify;
1363 #endif
1364         if (!p)
1365                 return;
1366         if (p[0] < 1)
1367         {
1368                 add_trace("notify", "error", "IE too short (len=%d)", p[0]);
1369                 return;
1370         }
1371
1372         *notify = p[1] & 0x7f;
1373
1374         add_trace("notify", NULL, "%d", *notify);
1375 }
1376
1377
1378 /* IE_PROGRESS */
1379 #ifdef SOCKET_MISDN
1380 void Pdss1::enc_ie_progress(struct l3_msg *l3m, int coding, int location, int progress)
1381 #else
1382 void Pdss1::enc_ie_progress(unsigned char **ntmode, msg_t *msg, int coding, int location, int progress)
1383 #endif
1384 {
1385 #ifdef SOCKET_MISDN
1386         unsigned char p[256];
1387 #else
1388         unsigned char *p;
1389         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
1390 #endif
1391         int l;
1392
1393         if (coding<0 || coding>0x03)
1394         {
1395                 PERROR("coding(%d) is out of range.\n", coding);
1396                 return;
1397         }
1398         if (location<0 || location>0x0f)
1399         {
1400                 PERROR("location(%d) is out of range.\n", location);
1401                 return;
1402         }
1403         if (progress<0 || progress>0x7f)
1404         {
1405                 PERROR("progress(%d) is out of range.\n", progress);
1406                 return;
1407         }
1408
1409         add_trace("progress", "codeing", "%d", coding);
1410         add_trace("progress", "location", "%d", location);
1411         add_trace("progress", "indicator", "%d", progress);
1412
1413         l = 2;
1414 #ifndef SOCKET_MISDN
1415         p = msg_put(msg, l+2);
1416         if (p_m_d_ntmode)
1417                 *ntmode = p+1;
1418         else
1419                 qi->progress.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
1420 #endif
1421         p[0] = IE_PROGRESS;
1422         p[1] = l;
1423         p[2] = 0x80 + (coding<<5) + location;
1424         p[3] = 0x80 + progress;
1425 #ifdef SOCKET_MISDN
1426         add_layer3_ie(l3m, p[0], p[1], p+2);
1427 #endif
1428 }
1429
1430 #ifdef SOCKET_MISDN
1431 void Pdss1::dec_ie_progress(struct l3_msg *l3m, int *coding, int *location, int *progress)
1432 #else
1433 void Pdss1::dec_ie_progress(unsigned char *p, Q931_info_t *qi, int *coding, int *location, int *progress)
1434 #endif
1435 {
1436         *coding = -1;
1437         *location = -1;
1438         *progress = -1;
1439
1440 #ifndef SOCKET_MISDN
1441         if (!p_m_d_ntmode)
1442         {
1443                 p = NULL;
1444                 if (qi->progress.off)
1445                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->progress.off + 1;
1446         }
1447 #else
1448         unsigned char *p = l3m->progress;
1449 #endif
1450         if (!p)
1451                 return;
1452         if (p[0] < 1)
1453         {
1454                 add_trace("progress", "error", "IE too short (len=%d)", p[0]);
1455                 return;
1456         }
1457
1458         *coding = (p[1]&0x60) >> 5;
1459         *location = p[1] & 0x0f;
1460         *progress = p[2] & 0x7f;
1461
1462         add_trace("progress", "codeing", "%d", *coding);
1463         add_trace("progress", "location", "%d", *location);
1464         add_trace("progress", "indicator", "%d", *progress);
1465 }
1466
1467
1468 /* IE_REDIR_NR (redirecting = during MT_SETUP) */
1469 #ifdef SOCKET_MISDN
1470 void Pdss1::enc_ie_redir_nr(struct l3_msg *l3m, int type, int plan, int present, int screen, int reason, unsigned char *number)
1471 #else
1472 void Pdss1::enc_ie_redir_nr(unsigned char **ntmode, msg_t *msg, int type, int plan, int present, int screen, int reason, unsigned char *number)
1473 #endif
1474 {
1475 #ifdef SOCKET_MISDN
1476         unsigned char p[256];
1477 #else
1478         unsigned char *p;
1479         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
1480 #endif
1481         int l;
1482
1483         if (type<0 || type>7)
1484         {
1485                 PERROR("type(%d) is out of range.\n", type);
1486                 return;
1487         }
1488         if (plan<0 || plan>15)
1489         {
1490                 PERROR("plan(%d) is out of range.\n", plan);
1491                 return;
1492         }
1493         if (present > 3)
1494         {
1495                 PERROR("present(%d) is out of range.\n", present);
1496                 return;
1497         }
1498         if (present >= 0) if (screen<0 || screen>3)
1499         {
1500                 PERROR("screen(%d) is out of range.\n", screen);
1501                 return;
1502         }
1503         if (reason > 0x0f)
1504         {
1505                 PERROR("reason(%d) is out of range.\n", reason);
1506                 return;
1507         }
1508
1509         add_trace("redir'ing", "type", "%d", type);
1510         add_trace("redir'ing", "plan", "%d", plan);
1511         add_trace("redir'ing", "present", "%d", present);
1512         add_trace("redir'ing", "screen", "%d", screen);
1513         add_trace("redir'ing", "reason", "%d", reason);
1514         add_trace("redir'ing", "number", "%s", number);
1515
1516         l = 1;
1517         if (number)
1518                 l += strlen((char *)number);
1519         if (present >= 0)
1520         {
1521                 l += 1;
1522                 if (reason >= 0)
1523                         l += 1;
1524         }
1525 #ifndef SOCKET_MISDN
1526         p = msg_put(msg, l+2);
1527         if (p_m_d_ntmode)
1528                 *ntmode = p+1;
1529         else
1530                 qi->redirect_nr.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
1531 #endif
1532         p[0] = IE_REDIR_NR;
1533         p[1] = l;
1534         if (present >= 0)
1535         {
1536                 if (reason >= 0)
1537                 {
1538                         p[2] = 0x00 + (type<<4) + plan;
1539                         p[3] = 0x00 + (present<<5) + screen;
1540                         p[4] = 0x80 + reason;
1541                         if (number)
1542                                 UNCPY((char *)p+5, (char *)number, strlen((char *)number));
1543                 } else
1544                 {
1545                         p[2] = 0x00 + (type<<4) + plan;
1546                         p[3] = 0x80 + (present<<5) + screen;
1547                         if (number)
1548                                 UNCPY((char *)p+4, (char *)number, strlen((char *)number));
1549                 }
1550         } else
1551         {
1552                 p[2] = 0x80 + (type<<4) + plan;
1553                 if (number) if (number[0])
1554                         UNCPY((char *)p+3, (char *)number, strlen((char *)number));
1555         }
1556 #ifdef SOCKET_MISDN
1557         add_layer3_ie(l3m, p[0], p[1], p+2);
1558 #endif
1559 }
1560
1561 #ifdef SOCKET_MISDN
1562 void Pdss1::dec_ie_redir_nr(struct l3_msg *l3m, int *type, int *plan, int *present, int *screen, int *reason, unsigned char *number, int number_len)
1563 #else
1564 void Pdss1::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)
1565 #endif
1566 {
1567         *type = -1;
1568         *plan = -1;
1569         *present = -1;
1570         *screen = -1;
1571         *reason = -1;
1572         *number = '\0';
1573
1574 #ifndef SOCKET_MISDN
1575         if (!p_m_d_ntmode)
1576         {
1577                 p = NULL;
1578                 if (qi->redirect_nr.off)
1579                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->redirect_nr.off + 1;
1580         }
1581 #else
1582         unsigned char *p = l3m->redirect_nr;
1583 #endif
1584         if (!p)
1585                 return;
1586         if (p[0] < 1)
1587         {
1588                 add_trace("redir'ing", "error", "IE too short (len=%d)", p[0]);
1589                 return;
1590         }
1591
1592         *type = (p[1]&0x70) >> 4;
1593         *plan = p[1] & 0xf;
1594         if (!(p[1] & 0x80))
1595         {
1596                 *present = (p[2]&0x60) >> 5;
1597                 *screen = p[2] & 0x3;
1598                 if (!(p[2] & 0x80))
1599                 {
1600                         *reason = p[3] & 0x0f;
1601                         strnncpy(number, p+4, p[0]-3, number_len);
1602                 } else
1603                 {
1604                         strnncpy(number, p+3, p[0]-2, number_len);
1605                 }
1606         } else
1607         {
1608                 strnncpy(number, p+2, p[0]-1, number_len);
1609         }
1610
1611         add_trace("redir'ing", "type", "%d", *type);
1612         add_trace("redir'ing", "plan", "%d", *plan);
1613         add_trace("redir'ing", "present", "%d", *present);
1614         add_trace("redir'ing", "screen", "%d", *screen);
1615         add_trace("redir'ing", "reason", "%d", *reason);
1616         add_trace("redir'ing", "number", "%s", number);
1617 }
1618
1619
1620 /* IE_REDIR_DN (redirection = during MT_NOTIFY) */
1621 #ifdef SOCKET_MISDN
1622 void Pdss1::enc_ie_redir_dn(struct l3_msg *l3m, int type, int plan, int present, unsigned char *number)
1623 #else
1624 void Pdss1::enc_ie_redir_dn(unsigned char **ntmode, msg_t *msg, int type, int plan, int present, unsigned char *number)
1625 #endif
1626 {
1627 #ifdef SOCKET_MISDN
1628         unsigned char p[256];
1629 #else
1630         unsigned char *p;
1631         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
1632 #endif
1633         int l;
1634
1635         if (type<0 || type>7)
1636         {
1637                 PERROR("type(%d) is out of range.\n", type);
1638                 return;
1639         }
1640         if (plan<0 || plan>15)
1641         {
1642                 PERROR("plan(%d) is out of range.\n", plan);
1643                 return;
1644         }
1645         if (present > 3)
1646         {
1647                 PERROR("present(%d) is out of range.\n", present);
1648                 return;
1649         }
1650
1651         add_trace("redir'tion", "type", "%d", type);
1652         add_trace("redir'tion", "plan", "%d", plan);
1653         add_trace("redir'tion", "present", "%d", present);
1654         add_trace("redir'tion", "number", "%s", number);
1655
1656         l = 1;
1657         if (number)
1658                 l += strlen((char *)number);
1659         if (present >= 0)
1660                 l += 1;
1661 #ifndef SOCKET_MISDN
1662         p = msg_put(msg, l+2);
1663         if (p_m_d_ntmode)
1664                 *ntmode = p+1;
1665         else
1666                 qi->redirect_dn.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
1667 #endif
1668         p[0] = IE_REDIR_DN;
1669         p[1] = l;
1670         if (present >= 0)
1671         {
1672                 p[2] = 0x00 + (type<<4) + plan;
1673                 p[3] = 0x80 + (present<<5);
1674                 if (number)
1675                         UNCPY((char *)p+4, (char *)number, strlen((char *)number));
1676         } else
1677         {
1678                 p[2] = 0x80 + (type<<4) + plan;
1679                 if (number)
1680                         UNCPY((char *)p+3, (char *)number, strlen((char *)number));
1681         }
1682 #ifdef SOCKET_MISDN
1683         add_layer3_ie(l3m, p[0], p[1], p+2);
1684 #endif
1685 }
1686
1687 #ifdef SOCKET_MISDN
1688 void Pdss1::dec_ie_redir_dn(struct l3_msg *l3m, int *type, int *plan, int *present, unsigned char *number, int number_len)
1689 #else
1690 void Pdss1::dec_ie_redir_dn(unsigned char *p, Q931_info_t *qi, int *type, int *plan, int *present, unsigned char *number, int number_len)
1691 #endif
1692 {
1693         *type = -1;
1694         *plan = -1;
1695         *present = -1;
1696         *number = '\0';
1697
1698 #ifndef SOCKET_MISDN
1699         if (!p_m_d_ntmode)
1700         {
1701                 p = NULL;
1702                 if (qi->redirect_dn.off)
1703                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->redirect_dn.off + 1;
1704         }
1705 #else
1706         unsigned char *p = l3m->redirect_dn;
1707 #endif
1708         if (!p)
1709                 return;
1710         if (p[0] < 1)
1711         {
1712                 add_trace("redir'tion", "error", "IE too short (len=%d)", p[0]);
1713                 return;
1714         }
1715
1716         *type = (p[1]&0x70) >> 4;
1717         *plan = p[1] & 0xf;
1718         if (!(p[1] & 0x80))
1719         {
1720                 *present = (p[2]&0x60) >> 5;
1721                 strnncpy(number, p+3, p[0]-2, number_len);
1722         } else
1723         {
1724                 strnncpy(number, p+2, p[0]-1, number_len);
1725         }
1726
1727         add_trace("redir'tion", "type", "%d", *type);
1728         add_trace("redir'tion", "plan", "%d", *plan);
1729         add_trace("redir'tion", "present", "%d", *present);
1730         add_trace("redir'tion", "number", "%s", number);
1731 }
1732
1733
1734 /* IE_FACILITY */
1735 #ifdef SOCKET_MISDN
1736 void Pdss1::enc_ie_facility(struct l3_msg *l3m, unsigned char *facility, int facility_len)
1737 #else
1738 void Pdss1::enc_ie_facility(unsigned char **ntmode, msg_t *msg, unsigned char *facility, int facility_len)
1739 #endif
1740 {
1741 #ifdef SOCKET_MISDN
1742         unsigned char p[256];
1743 #else
1744         unsigned char *p;
1745         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
1746 #endif
1747         int l;
1748
1749         char buffer[768];
1750         int i;
1751
1752         if (!facility || facility_len<=0)
1753         {
1754                 return;
1755         }
1756
1757         i = 0;
1758         while(i < facility_len)
1759         {
1760                 UPRINT(buffer+(i*3), " %02x", facility[i]);
1761                 i++;
1762         }
1763                 
1764         add_trace("facility", NULL, "%s", buffer+1);
1765
1766         l = facility_len;
1767 #ifndef SOCKET_MISDN
1768         p = msg_put(msg, l+2);
1769         if (p_m_d_ntmode)
1770                 *ntmode = p+1;
1771         else
1772                 qi->facility.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
1773 #endif
1774         p[0] = IE_FACILITY;
1775         p[1] = l;
1776         memcpy(p+2, facility, facility_len);
1777 #ifdef SOCKET_MISDN
1778         add_layer3_ie(l3m, p[0], p[1], p+2);
1779 #endif
1780 }
1781
1782 #ifdef SOCKET_MISDN
1783 void Pdss1::dec_ie_facility(struct l3_msg *l3m, unsigned char *facility, int *facility_len)
1784 #else
1785 void Pdss1::dec_ie_facility(unsigned char *p, Q931_info_t *qi, unsigned char *facility, int *facility_len)
1786 #endif
1787 {
1788         char debug[768];
1789         int i;
1790
1791         *facility_len = 0;
1792
1793 #ifndef SOCKET_MISDN
1794         if (!p_m_d_ntmode)
1795         {
1796                 p = NULL;
1797                 if (qi->facility.off)
1798                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->facility.off + 1;
1799         }
1800 #else
1801         unsigned char *p = l3m->facility;
1802 #endif
1803         if (!p)
1804                 return;
1805
1806         *facility_len = p[0];
1807         memcpy(facility, p+1, *facility_len);
1808
1809         i = 0;
1810         while(i < *facility_len)
1811         {
1812                 UPRINT(debug+(i*3), " %02x", facility[i]);
1813                 i++;
1814         }
1815         debug[i*3] = '\0';
1816                 
1817         add_trace("facility", NULL, "%s", debug[0]?debug+1:"<none>");
1818 }
1819
1820
1821 #ifdef SOCKET_MISDN
1822 void Pdss1::dec_facility_centrex(struct l3_msg *l3m, unsigned char *cnip, int cnip_len)
1823 #else
1824 void Pdss1::dec_facility_centrex(unsigned char *p, Q931_info_t *qi, unsigned char *cnip, int cnip_len)
1825 #endif
1826 {
1827         unsigned char centrex[256];
1828         char debug[768];
1829         int facility_len = 0;
1830         int i = 0, j;
1831         *cnip = '\0';
1832
1833 #ifdef SOCKET_MISDN
1834         dec_ie_facility(l3m, centrex, &facility_len);
1835 #else
1836         dec_ie_facility(p, qi, centrex, &facility_len);
1837 #endif
1838         if (facility_len >= 2)
1839         {
1840                 if (centrex[i++] != CENTREX_FAC)
1841                         return;
1842                 if (centrex[i++] != CENTREX_ID)
1843                         return;
1844         }
1845
1846         /* loop sub IEs of facility */
1847         while(facility_len > i+1)
1848         {
1849                 if (centrex[i+1]+i+1 > facility_len)
1850                 {
1851                         PERROR("short read of centrex facility.\n");
1852                         return;
1853                 }
1854                 switch(centrex[i])
1855                 {
1856                         case 0x80:
1857                         strnncpy(cnip, &centrex[i+2], centrex[i+1], cnip_len);
1858                         add_trace("facility", "cnip", "%s", cnip);
1859                         break;
1860
1861                         default:
1862                         j = 0;
1863                         while(j < centrex[i+1])
1864                         {
1865                                 UPRINT(debug+(j*3), " %02x", centrex[i+1+j]);
1866                                 i++;
1867                         }
1868                         add_trace("facility", "CENTREX", "unknown=0x%02x len=%d%s\n", centrex[i], centrex[i+1], debug);
1869                 }
1870                 i += 1+centrex[i+1];
1871         }
1872 }
1873
1874
1875 /* IE_USERUSER */
1876 #ifdef SOCKET_MISDN
1877 void Pdss1::enc_ie_useruser(struct l3_msg *l3m, int protocol, unsigned char *user, int user_len)
1878 #else
1879 void Pdss1::enc_ie_useruser(unsigned char **ntmode, msg_t *msg, int protocol, unsigned char *user, int user_len)
1880 #endif
1881 {
1882 #ifdef SOCKET_MISDN
1883         unsigned char p[256];
1884 #else
1885         unsigned char *p;
1886         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
1887 #endif
1888         int l;
1889
1890         char buffer[768];
1891         int i;
1892
1893         if (protocol<0 || protocol>127)
1894         {
1895                 PERROR("protocol(%d) is out of range.\n", protocol);
1896                 return;
1897         }
1898         if (!user || user_len<=0)
1899         {
1900                 return;
1901         }
1902
1903         i = 0;
1904         while(i < user_len)
1905         {
1906                 UPRINT(buffer+(i*3), " %02x", user[i]);
1907                 i++;
1908         }
1909                 
1910         add_trace("useruser", "protocol", "%d", protocol);
1911         add_trace("useruser", "value", "%s", buffer);
1912
1913         l = user_len;
1914 #ifndef SOCKET_MISDN
1915         p = msg_put(msg, l+3);
1916         if (p_m_d_ntmode)
1917                 *ntmode = p+1;
1918         else
1919                 qi->useruser.off = p - (unsigned char *)qi - sizeof(Q931_info_t);
1920 #endif
1921         p[0] = IE_USER_USER;
1922         p[1] = l;
1923         p[2] = 0x80 + protocol;
1924         memcpy(p+3, user, user_len);
1925 #ifdef SOCKET_MISDN
1926         add_layer3_ie(l3m, p[0], p[1], p+2);
1927 #endif
1928 }
1929
1930 #ifdef SOCKET_MISDN
1931 void Pdss1::dec_ie_useruser(struct l3_msg *l3m, int *protocol, unsigned char *user, int *user_len)
1932 #else
1933 void Pdss1::dec_ie_useruser(unsigned char *p, Q931_info_t *qi, int *protocol, unsigned char *user, int *user_len)
1934 #endif
1935 {
1936         char buffer[768];
1937         int i;
1938
1939         *user_len = 0;
1940         *protocol = -1;
1941
1942 #ifndef SOCKET_MISDN
1943         if (!p_m_d_ntmode)
1944         {
1945                 p = NULL;
1946                 if (qi->useruser.off)
1947                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->useruser.off + 1;
1948         }
1949 #else
1950         unsigned char *p = l3m->useruser;
1951 #endif
1952         if (!p)
1953                 return;
1954
1955         *user_len = p[0]-1;
1956         if (p[0] < 1)
1957                 return;
1958         *protocol = p[1];
1959         memcpy(user, p+2, (*user_len<=128)?*(user_len):128); /* clip to 128 maximum */
1960
1961         i = 0;
1962         while(i < *user_len)
1963         {
1964                 UPRINT(buffer+(i*3), " %02x", user[i]);
1965                 i++;
1966         }
1967         buffer[i*3] = '\0';
1968                 
1969         add_trace("useruser", "protocol", "%d", *protocol);
1970         add_trace("useruser", "value", "%s", buffer);
1971 }
1972
1973