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