Fix lot of warnings
[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 void Pdss1::enc_ie_complete(struct l3_msg *l3m, int complete)
30 {
31
32         if (complete<0 || complete>1)
33         {
34                 PERROR("complete(%d) is out of range.\n", complete);
35                 return;
36         }
37
38         if (complete)
39         {
40                 add_trace("complete", NULL, NULL);
41                 l3m->sending_complete++;
42         }
43 }
44
45 void Pdss1::dec_ie_complete(struct l3_msg *l3m, int *complete)
46 {
47         *complete = 0;
48         // special case: p is not a pointer, it's a value
49         unsigned char p = l3m->sending_complete;
50         if (p)
51                 *complete = 1;
52
53         if (*complete)
54                 add_trace("complete", NULL, NULL);
55 }
56
57
58 /* IE_BEARER */
59 void Pdss1::enc_ie_bearer(struct l3_msg *l3m, int coding, int capability, int mode, int rate, int multi, int user)
60 {
61         unsigned char p[256];
62         int l;
63
64         if (coding<0 || coding>3)
65         {
66                 PERROR("coding(%d) is out of range.\n", coding);
67                 return;
68         }
69         if (capability<0 || capability>31)
70         {
71                 PERROR("capability(%d) is out of range.\n", capability);
72                 return;
73         }
74         if (mode<0 || mode>3)
75         {
76                 PERROR("mode(%d) is out of range.\n", mode);
77                 return;
78         }
79         if (rate<0 || rate>31)
80         {
81                 PERROR("rate(%d) is out of range.\n", rate);
82                 return;
83         }
84         if (multi>127)
85         {
86                 PERROR("multi(%d) is out of range.\n", multi);
87                 return;
88         }
89         if (user>31)
90         {
91                 PERROR("user L1(%d) is out of range.\n", user);
92                 return;
93         }
94         if (rate!=24 && multi>=0)
95         {
96                 PERROR("multi(%d) is only possible if rate(%d) would be 24.\n", multi, rate);
97                 multi = -1;
98         }
99
100         add_trace("bearer", "coding", "%d", coding);
101         add_trace("bearer", "capability", "%d", capability);
102         add_trace("bearer", "mode", "%d", mode);
103         add_trace("bearer", "rate", "%d", rate);
104         add_trace("bearer", "multi", "%d", multi);
105         add_trace("bearer", "user", "%d", user);
106
107         l = 2 + (multi>=0) + (user>=0);
108         p[0] = IE_BEARER;
109         p[1] = l;
110         p[2] = 0x80 + (coding<<5) + capability;
111         p[3] = 0x80 + (mode<<5) + rate;
112         if (multi >= 0)
113                 p[4] = 0x80 + multi;
114         if (user >= 0)
115                 p[4+(multi>=0)] = 0xa0 + user;
116         add_layer3_ie(l3m, p[0], p[1], p+2);
117 }
118
119 void Pdss1::dec_ie_bearer(struct l3_msg *l3m, int *coding, int *capability, int *mode, int *rate, int *multi, int *user)
120 {
121         *coding = -1;
122         *capability = -1;
123         *mode = -1;
124         *rate = -1;
125         *multi = -1;
126         *user = -1;
127
128         unsigned char *p = l3m->bearer_capability;
129         if (!p)
130                 return;
131         if (p[0] < 2)
132         {
133                 add_trace("bearer", "error", "IE too short (len=%d)", p[0]);
134                 return;
135         }
136
137         *coding = (p[1]&0x60) >> 5;
138         *capability = p[1] & 0x1f;
139         if (p[0]>=2)
140         {
141                 *mode = (p[2]&0x60) >> 5;
142                 *rate = p[2] & 0x1f;
143         }
144         if (p[0]>=3 && *rate==0x18)
145         {
146                 *multi = p[3] & 0x7f;
147                 if (p[0]>=4)
148                         *user = p[4] & 0x1f;
149         } else
150         {
151                 if (p[0]>=3)
152                         *user = p[3] & 0x1f;
153         }
154
155         add_trace("bearer", "coding", "%d", *coding);
156         add_trace("bearer", "capability", "%d", *capability);
157         add_trace("bearer", "mode", "%d", *mode);
158         add_trace("bearer", "rate", "%d", *rate);
159         add_trace("bearer", "multi", "%d", *multi);
160         add_trace("bearer", "user", "%d", *user);
161 }
162
163
164 /* IE_HLC */
165 void Pdss1::enc_ie_hlc(struct l3_msg *l3m, int coding, int interpretation, int presentation, int hlc, int exthlc)
166 {
167         unsigned char p[256];
168         int l;
169
170         if (coding<0 || coding>3)
171         {
172                 PERROR("coding(%d) is out of range.\n", coding);
173                 return;
174         }
175         if (interpretation<0 || interpretation>7)
176         {
177                 PERROR("interpretation(%d) is out of range.\n", interpretation);
178                 return;
179         }
180         if (presentation<0 || presentation>3)
181         {
182                 PERROR("presentation(%d) is out of range.\n", presentation);
183                 return;
184         }
185         if (hlc<0 || hlc>127)
186         {
187                 PERROR("hlc(%d) is out of range.\n", hlc);
188                 return;
189         }
190         if (exthlc>127)
191         {
192                 PERROR("hlc(%d) is out of range.\n", exthlc);
193                 return;
194         }
195
196         add_trace("hlc", "coding", "%d", coding);
197         add_trace("hlc", "interpretation", "%d", interpretation);
198         add_trace("hlc", "presentation", "%d", presentation);
199         add_trace("hlc", "hlc", "%d", hlc);
200         if (exthlc >= 0)
201                 add_trace("hlc", "exthlc", "%d", exthlc);
202
203         l = 2 + (exthlc>=0);
204         p[0] = IE_HLC;
205         p[1] = l;
206         p[2] = 0x80 + (coding<<5) + (interpretation<<2) + presentation;
207         if (exthlc >= 0)
208         {
209                 p[3] = hlc;
210                 p[4] = 0x80 + exthlc;
211         } else
212                 p[3] = 0x80 + hlc;
213         add_layer3_ie(l3m, p[0], p[1], p+2);
214 }
215
216 void Pdss1::dec_ie_hlc(struct l3_msg *l3m, int *coding, int *interpretation, int *presentation, int *hlc, int *exthlc)
217 {
218         *coding = -1;
219         *interpretation = -1;
220         *presentation = -1;
221         *hlc = -1;
222         *exthlc = -1;
223
224         unsigned char *p = l3m->hlc;
225         if (!p)
226                 return;
227         if (p[0] < 2)
228         {
229                 add_trace("hlc", "error", "IE too short (len=%d)", p[0]);
230                 return;
231         }
232
233         *coding = (p[1]&0x60) >> 5;
234         *interpretation = (p[1]&0x1c) >> 2;
235         *presentation = p[1] & 0x03;
236         *hlc = p[2] & 0x7f;
237         if (p[0]>=3)
238         {
239                 *exthlc = p[3] & 0x7f;
240         }
241
242         add_trace("hlc", "coding", "%d", *coding);
243         add_trace("hlc", "interpretation", "%d", *interpretation);
244         add_trace("hlc", "presentation", "%d", *presentation);
245         add_trace("hlc", "hlc", "%d", *hlc);
246         if (*exthlc >= 0)
247                 add_trace("hlc", "exthlc", "%d", *exthlc);
248 }
249
250
251 /* IE_CALL_ID */
252 void Pdss1::enc_ie_call_id(struct l3_msg *l3m, unsigned char *callid, int callid_len)
253 {
254         unsigned char p[256];
255         int l;
256
257         char buffer[25];
258         int i;
259
260         if (!callid || callid_len<=0)
261         {
262                 return;
263         }
264         if (callid_len > 8)
265         {
266                 PERROR("callid_len(%d) is out of range.\n", callid_len);
267                 return;
268         }
269
270         i = 0;
271         while(i < callid_len)
272         {
273                 UPRINT(buffer+(i*3), " %02x", callid[i]);
274                 i++;
275         }
276                 
277         add_trace("callid", NULL, "%s", buffer[0]?buffer+1:"<none>");
278
279         l = callid_len;
280         p[0] = IE_CALL_ID;
281         p[1] = l;
282         memcpy(p+2, callid, callid_len);
283         add_layer3_ie(l3m, p[0], p[1], p+2);
284 }
285
286 void Pdss1::dec_ie_call_id(struct l3_msg *l3m, unsigned char *callid, int *callid_len)
287 {
288         char buffer[25];
289         int i;
290
291         *callid_len = -1;
292
293         unsigned char *p = l3m->call_id;
294         if (!p)
295                 return;
296         if (p[0] > 8)
297         {
298                 add_trace("callid", "error", "IE too long (len=%d)", p[0]);
299                 return;
300         }
301
302         *callid_len = p[0];
303         memcpy(callid, p+1, *callid_len);
304
305         i = 0;
306         while(i < *callid_len)
307         {
308                 UPRINT(buffer+(i*3), " %02x", callid[i]);
309                 i++;
310         }
311                 
312         add_trace("callid", NULL, "%s", buffer[0]?buffer+1:"<none>");
313 }
314
315
316 /* IE_CALLED_PN */
317 void Pdss1::enc_ie_called_pn(struct l3_msg *l3m, int type, int plan, unsigned char *number)
318 {
319         unsigned char p[256];
320         int l;
321
322         if (type<0 || type>7)
323         {
324                 PERROR("type(%d) is out of range.\n", type);
325                 return;
326         }
327         if (plan<0 || plan>15)
328         {
329                 PERROR("plan(%d) is out of range.\n", plan);
330                 return;
331         }
332         if (!number[0])
333         {
334                 PERROR("number is not given.\n");
335                 return;
336         }
337
338         add_trace("called_pn", "type", "%d", type);
339         add_trace("called_pn", "plan", "%d", plan);
340         add_trace("called_pn", "number", "%s", number);
341
342         l = 1+strlen((char *)number);
343         p[0] = IE_CALLED_PN;
344         p[1] = l;
345         p[2] = 0x80 + (type<<4) + plan;
346         UNCPY((char *)p+3, (char *)number, strlen((char *)number));
347         add_layer3_ie(l3m, p[0], p[1], p+2);
348 }
349
350 void Pdss1::dec_ie_called_pn(struct l3_msg *l3m, int *type, int *plan, unsigned char *number, int number_len)
351 {
352         *type = -1;
353         *plan = -1;
354         *number = '\0';
355
356         unsigned char *p = l3m->called_nr;
357         if (!p)
358                 return;
359         if (p[0] < 2)
360         {
361                 add_trace("called_pn", "error", "IE too short (len=%d)", p[0]);
362                 return;
363         }
364
365         *type = (p[1]&0x70) >> 4;
366         *plan = p[1] & 0xf;
367         strnncpy(number, p+2, p[0]-1, number_len);
368
369         add_trace("called_pn", "type", "%d", *type);
370         add_trace("called_pn", "plan", "%d", *plan);
371         add_trace("called_pn", "number", "%s", number);
372 }
373
374
375 /* IE_CALLING_PN */
376 void Pdss1::enc_ie_calling_pn(struct l3_msg *l3m, int type, int plan, int present, int screen, unsigned char *number)
377 {
378         unsigned char p[256];
379         int l;
380
381         if (type<0 || type>7)
382         {
383                 PERROR("type(%d) is out of range.\n", type);
384                 return;
385         }
386         if (plan<0 || plan>15)
387         {
388                 PERROR("plan(%d) is out of range.\n", plan);
389                 return;
390         }
391         if (present>3)
392         {
393                 PERROR("present(%d) is out of range.\n", present);
394                 return;
395         }
396         if (present >= 0) if (screen<0 || screen>3)
397         {
398                 PERROR("screen(%d) is out of range.\n", screen);
399                 return;
400         }
401
402         add_trace("calling_pn", "type", "%d", type);
403         add_trace("calling_pn", "plan", "%d", plan);
404         add_trace("calling_pn", "present", "%d", present);
405         add_trace("calling_pn", "screen", "%d", screen);
406         add_trace("calling_pn", "number", "%s", number);
407
408         l = 1;
409         if (number) if (number[0])
410                 l += strlen((char *)number);
411         if (present >= 0)
412                 l += 1;
413         p[0] = IE_CALLING_PN;
414         p[1] = l;
415         if (present >= 0)
416         {
417                 p[2] = 0x00 + (type<<4) + plan;
418                 p[3] = 0x80 + (present<<5) + screen;
419                 if (number) if (number[0])
420                         UNCPY((char *)p+4, (char *)number, strlen((char *)number));
421         } else
422         {
423                 p[2] = 0x80 + (type<<4) + plan;
424                 if (number) if (number[0])
425                         UNCPY((char *)p+3, (char *)number, strlen((char *)number));
426         }
427         add_layer3_ie(l3m, p[0], p[1], p+2);
428 }
429
430 void Pdss1::dec_ie_calling_pn(struct l3_msg *l3m, int *type, int *plan, int *present, int *screen, unsigned char *number, int number_len)
431 {
432         *type = -1;
433         *plan = -1;
434         *present = -1;
435         *screen = -1;
436         *number = '\0';
437
438         unsigned char *p = l3m->calling_nr;
439         if (!p)
440                 return;
441         if (p[0] < 1)
442         {
443                 add_trace("calling_pn", "error", "IE too short (len=%d)", p[0]);
444                 return;
445         }
446
447         *type = (p[1]&0x70) >> 4;
448         *plan = p[1] & 0xf;
449         if (!(p[1] & 0x80))
450         {
451                 if (p[0] < 2)
452                 {
453                         add_trace("calling_pn", "error", "IE too short (len=%d)", p[0]);
454                         return;
455                 }
456                 *present = (p[2]&0x60) >> 5;
457                 *screen = p[2] & 0x3;
458                 strnncpy(number, p+3, p[0]-2, number_len);
459         } else
460         {
461                 strnncpy(number, p+2, p[0]-1, number_len);
462         }
463
464         add_trace("calling_pn", "type", "%d", *type);
465         add_trace("calling_pn", "plan", "%d", *plan);
466         add_trace("calling_pn", "present", "%d", *present);
467         add_trace("calling_pn", "screen", "%d", *screen);
468         add_trace("calling_pn", "number", "%s", number);
469 }
470
471
472 /* IE_CONNECTED_PN */
473 void Pdss1::enc_ie_connected_pn(struct l3_msg *l3m, int type, int plan, int present, int screen, unsigned char *number)
474 {
475         unsigned char p[256];
476         int l;
477
478         if (type<0 || type>7)
479         {
480                 PERROR("type(%d) is out of range.\n", type);
481                 return;
482         }
483         if (plan<0 || plan>15)
484         {
485                 PERROR("plan(%d) is out of range.\n", plan);
486                 return;
487         }
488         if (present>3)
489         {
490                 PERROR("present(%d) is out of range.\n", present);
491                 return;
492         }
493         if (present >= 0) if (screen<0 || screen>3)
494         {
495                 PERROR("screen(%d) is out of range.\n", screen);
496                 return;
497         }
498
499         add_trace("connect_pn", "type", "%d", type);
500         add_trace("connect_pn", "plan", "%d", plan);
501         add_trace("connect_pn", "present", "%d", present);
502         add_trace("connect_pn", "screen", "%d", screen);
503         add_trace("connect_pn", "number", "%s", number);
504
505         l = 1;
506         if (number) if (number[0])
507                 l += strlen((char *)number);
508         if (present >= 0)
509                 l += 1;
510         p[0] = IE_CONNECT_PN;
511         p[1] = l;
512         if (present >= 0)
513         {
514                 p[2] = 0x00 + (type<<4) + plan;
515                 p[3] = 0x80 + (present<<5) + screen;
516                 if (number) if (number[0])
517                         UNCPY((char *)p+4, (char *)number, strlen((char *)number));
518         } else
519         {
520                 p[2] = 0x80 + (type<<4) + plan;
521                 if (number) if (number[0])
522                         UNCPY((char *)p+3, (char *)number, strlen((char *)number));
523         }
524         add_layer3_ie(l3m, p[0], p[1], p+2);
525 }
526
527 void Pdss1::dec_ie_connected_pn(struct l3_msg *l3m, int *type, int *plan, int *present, int *screen, unsigned char *number, int number_len)
528 {
529         *type = -1;
530         *plan = -1;
531         *present = -1;
532         *screen = -1;
533         *number = '\0';
534
535         unsigned char *p = l3m->connected_nr;
536         if (!p)
537                 return;
538         if (p[0] < 1)
539         {
540                 add_trace("connect_pn", "error", "IE too short (len=%d)", p[0]);
541                 return;
542         }
543
544         *type = (p[1]&0x70) >> 4;
545         *plan = p[1] & 0xf;
546         if (!(p[1] & 0x80))
547         {
548                 if (p[0] < 2)
549                 {
550                         add_trace("connect_pn", "error", "IE too short (len=%d)", p[0]);
551                         return;
552                 }
553                 *present = (p[2]&0x60) >> 5;
554                 *screen = p[2] & 0x3;
555                 strnncpy(number, p+3, p[0]-2, number_len);
556         } else
557         {
558                 strnncpy(number, p+2, p[0]-1, number_len);
559         }
560
561         add_trace("connect_pn", "type", "%d", *type);
562         add_trace("connect_pn", "plan", "%d", *plan);
563         add_trace("connect_pn", "present", "%d", *present);
564         add_trace("connect_pn", "screen", "%d", *screen);
565         add_trace("connect_pn", "number", "%s", number);
566 }
567
568
569 /* IE_CAUSE */
570 void Pdss1::enc_ie_cause(struct l3_msg *l3m, int location, int cause)
571 {
572         unsigned char p[256];
573         int l;
574
575         if (location<0 || location>7)
576         {
577                 PERROR("location(%d) is out of range.\n", location);
578                 return;
579         }
580         if (cause<0 || cause>127)
581         {
582                 PERROR("cause(%d) is out of range.\n", cause);
583                 return;
584         }
585
586         add_trace("cause", "location", "%d", location);
587         add_trace("cause", "value", "%d", cause);
588
589         l = 2;
590         p[0] = IE_CAUSE;
591         p[1] = l;
592         p[2] = 0x80 + location;
593         p[3] = 0x80 + cause;
594         add_layer3_ie(l3m, p[0], p[1], p+2);
595 }
596 void enc_ie_cause_standalone(struct l3_msg *l3m, int location, int cause)
597 {
598         unsigned char p[256];
599         p[0] = IE_CAUSE;
600         p[1] = 2;
601         p[2] = 0x80 + location;
602         p[3] = 0x80 + cause;
603         add_layer3_ie(l3m, p[0], p[1], p+2);
604 }
605
606
607 void Pdss1::dec_ie_cause(struct l3_msg *l3m, int *location, int *cause)
608 {
609         *location = -1;
610         *cause = -1;
611
612         unsigned char *p = l3m->cause;
613         if (!p)
614                 return;
615         if (p[0] < 2)
616         {
617                 add_trace("cause", "error", "IE too short (len=%d)", p[0]);
618                 return;
619         }
620
621         *location = p[1] & 0x0f;
622         *cause = p[2] & 0x7f;
623
624         add_trace("cause", "location", "%d", *location);
625         add_trace("cause", "value", "%d", *cause);
626 }
627
628
629 /* IE_CHANNEL_ID */
630 void Pdss1::enc_ie_channel_id(struct l3_msg *l3m, int exclusive, int channel)
631 {
632         unsigned char p[256];
633         int l;
634         int pri = p_m_mISDNport->pri;
635
636         if (exclusive<0 || exclusive>1)
637         {
638                 PERROR("exclusive(%d) is out of range.\n", exclusive);
639                 return;
640         }
641         if ((channel<=0 && channel!=CHANNEL_NO && channel!=CHANNEL_ANY)
642          || (!pri && channel>2)
643          || (pri && channel>127)
644          || (pri && channel==16))
645         {
646                 PERROR("channel(%d) is out of range.\n", channel);
647                 return;
648         }
649
650         add_trace("channel_id", "exclusive", "%d", exclusive);
651         switch(channel)
652         {
653                 case CHANNEL_ANY:
654                 add_trace("channel_id", "channel", "any channel");
655                 break;
656                 case CHANNEL_NO:
657                 add_trace("channel_id", "channel", "no channel");
658                 break;
659                 default:
660                 add_trace("channel_id", "channel", "%d", channel);
661         }
662
663         if (!pri)
664         {
665                 /* BRI */
666                 l = 1;
667                 p[0] = IE_CHANNEL_ID;
668                 p[1] = l;
669                 if (channel == CHANNEL_NO)
670                         channel = 0;
671                 else if (channel == CHANNEL_ANY)
672                         channel = 3;
673                 p[2] = 0x80 + (exclusive<<3) + channel;
674                 add_layer3_ie(l3m, p[0], p[1], p+2);
675         } else
676         {
677                 /* PRI */
678                 if (channel == CHANNEL_NO) /* no channel */
679                         return; /* IE not present */
680                 if (channel == CHANNEL_ANY) /* any channel */
681                 {
682                         l = 1;
683                         p[0] = IE_CHANNEL_ID;
684                         p[1] = l;
685                         p[2] = 0x80 + 0x20 + 0x03;
686                         add_layer3_ie(l3m, p[0], p[1], p+2);
687                         return; /* end */
688                 }
689                 l = 3;
690                 p[0] = IE_CHANNEL_ID;
691                 p[1] = l;
692                 p[2] = 0x80 + 0x20 + (exclusive<<3) + 0x01;
693                 p[3] = 0x80 + 3; /* CCITT, Number, B-type */
694                 p[4] = 0x80 + channel;
695                 add_layer3_ie(l3m, p[0], p[1], p+2);
696         }
697 }
698
699 void Pdss1::dec_ie_channel_id(struct l3_msg *l3m, int *exclusive, int *channel)
700 {
701         int pri = p_m_mISDNport->pri;
702
703         *exclusive = -1;
704         *channel = -1;
705
706         unsigned char *p = l3m->channel_id;
707         if (!p)
708                 return;
709         if (p[0] < 1)
710         {
711                 add_trace("channel_id", "error", "IE too short (len=%d)", p[0]);
712                 return;
713         }
714
715         if (p[1] & 0x40)
716         {
717                 add_trace("channel_id", "error", "refering to channels of other interfaces is not supported");
718                 return;
719         }
720         if (p[1] & 0x04)
721         {
722                 add_trace("channel_id", "error", "using d-channel is not supported");
723                 return;
724         }
725
726         *exclusive = (p[1]&0x08) >> 3;
727         if (!pri)
728         {
729                 /* BRI */
730                 if (p[1] & 0x20)
731                 {
732                         add_trace("channel_id", "error", "extended channel ID with non PRI interface");
733                         return;
734                 }
735                 *channel = p[1] & 0x03;
736                 if (*channel == 3)
737                         *channel = CHANNEL_ANY;
738                 else if (*channel == 0)
739                         *channel = CHANNEL_NO;
740         } else
741         {
742                 /* PRI */
743                 if (p[0] < 1)
744                 {
745
746                         add_trace("channel_id", "error", "IE too short for PRI (len=%d)", p[0]);
747                         return;
748                 }
749                 if (!(p[1] & 0x20))
750                 {
751                         add_trace("channel_id", "error", "basic channel ID with PRI interface");
752                         return;
753                 }
754                 if ((p[1]&0x03) == 0x00)
755                 {
756                         /* no channel */
757                         *channel = CHANNEL_NO;
758                         return;
759                 }
760                 if ((p[1]&0x03) == 0x03)
761                 {
762                         /* any channel */
763                         *channel = CHANNEL_ANY;
764                         return;
765                 }
766                 if (p[0] < 3)
767                 {
768                         add_trace("channel_id", "error", "IE too short for PRI with channel (len=%d)", p[0]);
769                         return;
770                 }
771                 if (p[2] & 0x10)
772                 {
773                         add_trace("channel_id", "error", "channel map not supported");
774                         return;
775                 }
776                 *channel = p[3] & 0x7f;
777                 if ((*channel<1) || (*channel==16))
778                 {
779                         add_trace("channel_id", "error", "PRI interface channel out of range (%d)", *channel);
780                         return;
781                 }
782         }
783
784         add_trace("channel_id", "exclusive", "%d", *exclusive);
785         switch(*channel)
786         {
787                 case CHANNEL_ANY:
788                 add_trace("channel_id", "channel", "any channel");
789                 break;
790                 case CHANNEL_NO:
791                 add_trace("channel_id", "channel", "no channel");
792                 break;
793                 default:
794                 add_trace("channel_id", "channel", "%d", *channel);
795         }
796 }
797
798
799 /* IE_DATE */
800 void Pdss1::enc_ie_date(struct l3_msg *l3m, time_t ti, int no_seconds)
801 {
802         unsigned char p[256];
803         int l;
804
805         struct tm *tm;
806
807         tm = localtime(&ti);
808         if (!tm)
809         {
810                 PERROR("localtime() returned NULL.\n");
811                 return;
812         }
813
814         add_trace("date", "day", "%d.%d.%d", tm->tm_mday, tm->tm_mon+1, tm->tm_year%100);
815         add_trace("date", "time", "%d:%d:%d", tm->tm_hour, tm->tm_min, tm->tm_sec);
816
817         l = 5 + (!no_seconds);
818         p[0] = IE_DATE;
819         p[1] = l;
820         p[2] = tm->tm_year % 100;
821         p[3] = tm->tm_mon + 1;
822         p[4] = tm->tm_mday;
823         p[5] = tm->tm_hour;
824         p[6] = tm->tm_min;
825         if (!no_seconds)
826                 p[7] = tm->tm_sec;
827         add_layer3_ie(l3m, p[0], p[1], p+2);
828 }
829
830
831 /* IE_DISPLAY */
832 void Pdss1::enc_ie_display(struct l3_msg *l3m, unsigned char *display)
833 {
834         unsigned char p[256];
835         int l;
836
837         if (!display[0])
838         {
839                 PERROR("display text not given.\n");
840                 return;
841         }
842
843         if (strlen((char *)display) > 80)
844         {
845                 PERROR("display text too long (max 80 chars), cutting.\n");
846                 display[80] = '\0';
847         }
848
849         add_trace("display", NULL, "%s", display);
850
851         l = strlen((char *)display);
852         p[0] = IE_DISPLAY;
853         p[1] = l;
854         UNCPY((char *)p+2, (char *)display, strlen((char *)display));
855         add_layer3_ie(l3m, p[0], p[1], p+2);
856 }
857
858 void Pdss1::dec_ie_display(struct l3_msg *l3m, unsigned char *display, int display_len)
859 {
860         *display = '\0';
861
862         unsigned char *p = l3m->display;
863         if (!p)
864                 return;
865         if (p[0] < 1)
866         {
867                 add_trace("display", "error", "IE too short (len=%d)", p[0]);
868                 return;
869         }
870
871         strnncpy(display, p+1, p[0], display_len);
872
873         add_trace("display", NULL, "%s", display);
874 }
875
876
877 /* IE_KEYPAD */
878 void Pdss1::enc_ie_keypad(struct l3_msg *l3m, unsigned char *keypad)
879 {
880         unsigned char p[256];
881         int l;
882
883         if (!keypad[0])
884         {
885                 PERROR("keypad info not given.\n");
886                 return;
887         }
888
889         add_trace("keypad", NULL, "%s", keypad);
890
891         l = strlen((char *)keypad);
892         p[0] = IE_KEYPAD;
893         p[1] = l;
894         UNCPY((char *)p+2, (char *)keypad, strlen((char *)keypad));
895         add_layer3_ie(l3m, p[0], p[1], p+2);
896 }
897
898 void Pdss1::dec_ie_keypad(struct l3_msg *l3m, unsigned char *keypad, int keypad_len)
899 {
900         *keypad = '\0';
901
902         unsigned char *p = l3m->keypad;
903         if (!p)
904                 return;
905         if (p[0] < 1)
906         {
907                 add_trace("keypad", "error", "IE too short (len=%d)", p[0]);
908                 return;
909         }
910
911         strnncpy(keypad, p+1, p[0], keypad_len);
912
913         add_trace("keypad", NULL, "%s", keypad);
914 }
915
916
917 /* IE_NOTIFY */
918 void Pdss1::enc_ie_notify(struct l3_msg *l3m, int notify)
919 {
920         unsigned char p[256];
921         int l;
922
923         if (notify<0 || notify>0x7f)
924         {
925                 PERROR("notify(%d) is out of range.\n", notify);
926                 return;
927         }
928
929         add_trace("notify", NULL, "%d", notify);
930
931         l = 1;
932         p[0] = IE_NOTIFY;
933         p[1] = l;
934         p[2] = 0x80 + notify;
935         add_layer3_ie(l3m, p[0], p[1], p+2);
936 }
937
938 void Pdss1::dec_ie_notify(struct l3_msg *l3m, int *notify)
939 {
940         *notify = -1;
941
942         unsigned char *p = l3m->notify;
943         if (!p)
944                 return;
945         if (p[0] < 1)
946         {
947                 add_trace("notify", "error", "IE too short (len=%d)", p[0]);
948                 return;
949         }
950
951         *notify = p[1] & 0x7f;
952
953         add_trace("notify", NULL, "%d", *notify);
954 }
955
956
957 /* IE_PROGRESS */
958 void Pdss1::enc_ie_progress(struct l3_msg *l3m, int coding, int location, int progress)
959 {
960         unsigned char p[256];
961         int l;
962
963         if (coding<0 || coding>0x03)
964         {
965                 PERROR("coding(%d) is out of range.\n", coding);
966                 return;
967         }
968         if (location<0 || location>0x0f)
969         {
970                 PERROR("location(%d) is out of range.\n", location);
971                 return;
972         }
973         if (progress<0 || progress>0x7f)
974         {
975                 PERROR("progress(%d) is out of range.\n", progress);
976                 return;
977         }
978
979         add_trace("progress", "codeing", "%d", coding);
980         add_trace("progress", "location", "%d", location);
981         add_trace("progress", "indicator", "%d", progress);
982
983         l = 2;
984         p[0] = IE_PROGRESS;
985         p[1] = l;
986         p[2] = 0x80 + (coding<<5) + location;
987         p[3] = 0x80 + progress;
988         add_layer3_ie(l3m, p[0], p[1], p+2);
989 }
990
991 void Pdss1::dec_ie_progress(struct l3_msg *l3m, int *coding, int *location, int *progress)
992 {
993         *coding = -1;
994         *location = -1;
995         *progress = -1;
996
997         unsigned char *p = l3m->progress;
998         if (!p)
999                 return;
1000         if (p[0] < 1)
1001         {
1002                 add_trace("progress", "error", "IE too short (len=%d)", p[0]);
1003                 return;
1004         }
1005
1006         *coding = (p[1]&0x60) >> 5;
1007         *location = p[1] & 0x0f;
1008         *progress = p[2] & 0x7f;
1009
1010         add_trace("progress", "codeing", "%d", *coding);
1011         add_trace("progress", "location", "%d", *location);
1012         add_trace("progress", "indicator", "%d", *progress);
1013 }
1014
1015
1016 /* IE_REDIR_NR (redirecting = during MT_SETUP) */
1017 void Pdss1::enc_ie_redir_nr(struct l3_msg *l3m, int type, int plan, int present, int screen, int reason, unsigned char *number)
1018 {
1019         unsigned char p[256];
1020         int l;
1021
1022         if (type<0 || type>7)
1023         {
1024                 PERROR("type(%d) is out of range.\n", type);
1025                 return;
1026         }
1027         if (plan<0 || plan>15)
1028         {
1029                 PERROR("plan(%d) is out of range.\n", plan);
1030                 return;
1031         }
1032         if (present > 3)
1033         {
1034                 PERROR("present(%d) is out of range.\n", present);
1035                 return;
1036         }
1037         if (present >= 0) if (screen<0 || screen>3)
1038         {
1039                 PERROR("screen(%d) is out of range.\n", screen);
1040                 return;
1041         }
1042         if (reason > 0x0f)
1043         {
1044                 PERROR("reason(%d) is out of range.\n", reason);
1045                 return;
1046         }
1047
1048         add_trace("redir'ing", "type", "%d", type);
1049         add_trace("redir'ing", "plan", "%d", plan);
1050         add_trace("redir'ing", "present", "%d", present);
1051         add_trace("redir'ing", "screen", "%d", screen);
1052         add_trace("redir'ing", "reason", "%d", reason);
1053         add_trace("redir'ing", "number", "%s", number);
1054
1055         l = 1;
1056         if (number)
1057                 l += strlen((char *)number);
1058         if (present >= 0)
1059         {
1060                 l += 1;
1061                 if (reason >= 0)
1062                         l += 1;
1063         }
1064         p[0] = IE_REDIR_NR;
1065         p[1] = l;
1066         if (present >= 0)
1067         {
1068                 if (reason >= 0)
1069                 {
1070                         p[2] = 0x00 + (type<<4) + plan;
1071                         p[3] = 0x00 + (present<<5) + screen;
1072                         p[4] = 0x80 + reason;
1073                         if (number)
1074                                 UNCPY((char *)p+5, (char *)number, strlen((char *)number));
1075                 } else
1076                 {
1077                         p[2] = 0x00 + (type<<4) + plan;
1078                         p[3] = 0x80 + (present<<5) + screen;
1079                         if (number)
1080                                 UNCPY((char *)p+4, (char *)number, strlen((char *)number));
1081                 }
1082         } else
1083         {
1084                 p[2] = 0x80 + (type<<4) + plan;
1085                 if (number) if (number[0])
1086                         UNCPY((char *)p+3, (char *)number, strlen((char *)number));
1087         }
1088         add_layer3_ie(l3m, p[0], p[1], p+2);
1089 }
1090
1091 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)
1092 {
1093         *type = -1;
1094         *plan = -1;
1095         *present = -1;
1096         *screen = -1;
1097         *reason = -1;
1098         *number = '\0';
1099
1100         unsigned char *p = l3m->redirect_nr;
1101         if (!p)
1102                 return;
1103         if (p[0] < 1)
1104         {
1105                 add_trace("redir'ing", "error", "IE too short (len=%d)", p[0]);
1106                 return;
1107         }
1108
1109         *type = (p[1]&0x70) >> 4;
1110         *plan = p[1] & 0xf;
1111         if (!(p[1] & 0x80))
1112         {
1113                 *present = (p[2]&0x60) >> 5;
1114                 *screen = p[2] & 0x3;
1115                 if (!(p[2] & 0x80))
1116                 {
1117                         *reason = p[3] & 0x0f;
1118                         strnncpy(number, p+4, p[0]-3, number_len);
1119                 } else
1120                 {
1121                         strnncpy(number, p+3, p[0]-2, number_len);
1122                 }
1123         } else
1124         {
1125                 strnncpy(number, p+2, p[0]-1, number_len);
1126         }
1127
1128         add_trace("redir'ing", "type", "%d", *type);
1129         add_trace("redir'ing", "plan", "%d", *plan);
1130         add_trace("redir'ing", "present", "%d", *present);
1131         add_trace("redir'ing", "screen", "%d", *screen);
1132         add_trace("redir'ing", "reason", "%d", *reason);
1133         add_trace("redir'ing", "number", "%s", number);
1134 }
1135
1136
1137 /* IE_REDIR_DN (redirection = during MT_NOTIFY) */
1138 void Pdss1::enc_ie_redir_dn(struct l3_msg *l3m, int type, int plan, int present, unsigned char *number)
1139 {
1140         unsigned char p[256];
1141         int l;
1142
1143         if (type<0 || type>7)
1144         {
1145                 PERROR("type(%d) is out of range.\n", type);
1146                 return;
1147         }
1148         if (plan<0 || plan>15)
1149         {
1150                 PERROR("plan(%d) is out of range.\n", plan);
1151                 return;
1152         }
1153         if (present > 3)
1154         {
1155                 PERROR("present(%d) is out of range.\n", present);
1156                 return;
1157         }
1158
1159         add_trace("redir'tion", "type", "%d", type);
1160         add_trace("redir'tion", "plan", "%d", plan);
1161         add_trace("redir'tion", "present", "%d", present);
1162         add_trace("redir'tion", "number", "%s", number);
1163
1164         l = 1;
1165         if (number)
1166                 l += strlen((char *)number);
1167         if (present >= 0)
1168                 l += 1;
1169         p[0] = IE_REDIR_DN;
1170         p[1] = l;
1171         if (present >= 0)
1172         {
1173                 p[2] = 0x00 + (type<<4) + plan;
1174                 p[3] = 0x80 + (present<<5);
1175                 if (number)
1176                         UNCPY((char *)p+4, (char *)number, strlen((char *)number));
1177         } else
1178         {
1179                 p[2] = 0x80 + (type<<4) + plan;
1180                 if (number)
1181                         UNCPY((char *)p+3, (char *)number, strlen((char *)number));
1182         }
1183         add_layer3_ie(l3m, p[0], p[1], p+2);
1184 }
1185
1186 void Pdss1::dec_ie_redir_dn(struct l3_msg *l3m, int *type, int *plan, int *present, unsigned char *number, int number_len)
1187 {
1188         *type = -1;
1189         *plan = -1;
1190         *present = -1;
1191         *number = '\0';
1192
1193         unsigned char *p = l3m->redirect_dn;
1194         if (!p)
1195                 return;
1196         if (p[0] < 1)
1197         {
1198                 add_trace("redir'tion", "error", "IE too short (len=%d)", p[0]);
1199                 return;
1200         }
1201
1202         *type = (p[1]&0x70) >> 4;
1203         *plan = p[1] & 0xf;
1204         if (!(p[1] & 0x80))
1205         {
1206                 *present = (p[2]&0x60) >> 5;
1207                 strnncpy(number, p+3, p[0]-2, number_len);
1208         } else
1209         {
1210                 strnncpy(number, p+2, p[0]-1, number_len);
1211         }
1212
1213         add_trace("redir'tion", "type", "%d", *type);
1214         add_trace("redir'tion", "plan", "%d", *plan);
1215         add_trace("redir'tion", "present", "%d", *present);
1216         add_trace("redir'tion", "number", "%s", number);
1217 }
1218
1219
1220 /* IE_FACILITY */
1221 void Pdss1::enc_ie_facility(struct l3_msg *l3m, unsigned char *facility, int facility_len)
1222 {
1223         unsigned char p[256];
1224         int l;
1225
1226         char buffer[768];
1227         int i;
1228
1229         if (!facility || facility_len<=0)
1230         {
1231                 return;
1232         }
1233
1234         i = 0;
1235         while(i < facility_len)
1236         {
1237                 UPRINT(buffer+(i*3), " %02x", facility[i]);
1238                 i++;
1239         }
1240                 
1241         add_trace("facility", NULL, "%s", buffer+1);
1242
1243         l = facility_len;
1244         p[0] = IE_FACILITY;
1245         p[1] = l;
1246         memcpy(p+2, facility, facility_len);
1247         add_layer3_ie(l3m, p[0], p[1], p+2);
1248 }
1249
1250 void Pdss1::dec_ie_facility(struct l3_msg *l3m, unsigned char *facility, int *facility_len)
1251 {
1252         char debug[768];
1253         int i;
1254
1255         *facility_len = 0;
1256
1257         unsigned char *p = l3m->facility;
1258         if (!p)
1259                 return;
1260
1261         *facility_len = p[0];
1262         memcpy(facility, p+1, *facility_len);
1263
1264         i = 0;
1265         while(i < *facility_len)
1266         {
1267                 UPRINT(debug+(i*3), " %02x", facility[i]);
1268                 i++;
1269         }
1270         debug[i*3] = '\0';
1271                 
1272         add_trace("facility", NULL, "%s", debug[0]?debug+1:"<none>");
1273 }
1274
1275
1276 void Pdss1::dec_facility_centrex(struct l3_msg *l3m, unsigned char *cnip, int cnip_len)
1277 {
1278         unsigned char centrex[256];
1279         char debug[768];
1280         int facility_len = 0;
1281         int i = 0, j;
1282         *cnip = '\0';
1283
1284         dec_ie_facility(l3m, centrex, &facility_len);
1285         if (facility_len >= 2)
1286         {
1287                 if (centrex[i++] != CENTREX_FAC)
1288                         return;
1289                 if (centrex[i++] != CENTREX_ID)
1290                         return;
1291         }
1292
1293         /* loop sub IEs of facility */
1294         while(facility_len > i+1)
1295         {
1296                 if (centrex[i+1]+i+1 > facility_len)
1297                 {
1298                         PERROR("short read of centrex facility.\n");
1299                         return;
1300                 }
1301                 switch(centrex[i])
1302                 {
1303                         case 0x80:
1304                         strnncpy(cnip, &centrex[i+2], centrex[i+1], cnip_len);
1305                         add_trace("facility", "cnip", "%s", cnip);
1306                         break;
1307
1308                         default:
1309                         j = 0;
1310                         while(j < centrex[i+1])
1311                         {
1312                                 UPRINT(debug+(j*3), " %02x", centrex[i+1+j]);
1313                                 i++;
1314                         }
1315                         add_trace("facility", "CENTREX", "unknown=0x%02x len=%d%s\n", centrex[i], centrex[i+1], debug);
1316                 }
1317                 i += 1+centrex[i+1];
1318         }
1319 }
1320
1321
1322 /* IE_USERUSER */
1323 void Pdss1::enc_ie_useruser(struct l3_msg *l3m, int protocol, unsigned char *user, int user_len)
1324 {
1325         unsigned char p[256];
1326         int l;
1327
1328         char buffer[768];
1329         int i;
1330
1331         if (protocol<0 || protocol>127)
1332         {
1333                 PERROR("protocol(%d) is out of range.\n", protocol);
1334                 return;
1335         }
1336         if (!user || user_len<=0)
1337         {
1338                 return;
1339         }
1340
1341         i = 0;
1342         while(i < user_len)
1343         {
1344                 UPRINT(buffer+(i*3), " %02x", user[i]);
1345                 i++;
1346         }
1347                 
1348         add_trace("useruser", "protocol", "%d", protocol);
1349         add_trace("useruser", "value", "%s", buffer);
1350
1351         l = user_len;
1352         p[0] = IE_USER_USER;
1353         p[1] = l;
1354         p[2] = 0x80 + protocol;
1355         memcpy(p+3, user, user_len);
1356         add_layer3_ie(l3m, p[0], p[1], p+2);
1357 }
1358
1359 void Pdss1::dec_ie_useruser(struct l3_msg *l3m, int *protocol, unsigned char *user, int *user_len)
1360 {
1361         char buffer[768];
1362         int i;
1363
1364         *user_len = 0;
1365         *protocol = -1;
1366
1367         unsigned char *p = l3m->useruser;
1368         if (!p)
1369                 return;
1370
1371         *user_len = p[0]-1;
1372         if (p[0] < 1)
1373                 return;
1374         *protocol = p[1];
1375         memcpy(user, p+2, (*user_len<=128)?*(user_len):128); /* clip to 128 maximum */
1376
1377         i = 0;
1378         while(i < *user_len)
1379         {
1380                 UPRINT(buffer+(i*3), " %02x", user[i]);
1381                 i++;
1382         }
1383         buffer[i*3] = '\0';
1384                 
1385         add_trace("useruser", "protocol", "%d", *protocol);
1386         add_trace("useruser", "value", "%s", buffer);
1387 }
1388
1389