]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - usr.sbin/i4b/isdndecode/layer3.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / usr.sbin / i4b / isdndecode / layer3.c
1 /*
2  * Copyright (c) 1997, 2002 Hellmuth Michaelis. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  *---------------------------------------------------------------------------
26  *
27  *      layer3.c - decode and print layer 3 (Q.931) information
28  *      -------------------------------------------------------
29  *
30  * $FreeBSD$
31  *
32  *      last edit-date: [Tue Mar 26 14:39:02 2002]
33  *
34  *---------------------------------------------------------------------------*/
35
36 #include "decode.h"
37
38 char *mttab[] = {
39
40 /* 0x00 */                      /* call establishment group */
41
42         "ESCAPE",
43         "ALERTING",
44         "CALL PROCEEDING",
45         "PROGRESS",
46         "undefined (0x04)",
47         "SETUP",
48         "undefined (0x06)",
49         "CONNECT",
50         "undefined (0x08)",
51         "undefined (0x09)",
52         "undefined (0x0a)",
53         "undefined (0x0b)",
54         "undefined (0x0c)",
55         "SETUP ACKNOWLEDGE",
56         "undefined (0x0e)",
57         "CONNECT ACKNOWLEDGE",
58
59 /* 0x10 */
60         "undefined (0x10)",
61         "undefined (0x11)",
62         "undefined (0x12)",
63         "undefined (0x13)",
64         "undefined (0x14)",
65         "undefined (0x15)",
66         "undefined (0x16)",
67         "undefined (0x17)",
68         "undefined (0x18)",
69         "undefined (0x19)",
70         "undefined (0x1a)",
71         "undefined (0x1b)",
72         "undefined (0x1c)",
73         "undefined (0x1d)",
74         "undefined (0x1e)",
75         "undefined (0x1f)",
76
77 /* 0x20 */      
78                 
79         "USER INFORMATION",             /* call information phase */
80         "SUSPEND REJECT",
81         "RESUME REJECT",
82         "undefined (0x23)",
83         "HOLD",
84         "SUSPEND",
85         "RESUME",
86         "undefined (0x27)",
87         "HOLD ACKNOWLEDGE",
88         "undefined (0x29)",
89         "undefined (0x2a)",
90         "undefined (0x2b)",
91         "undefined (0x2c)",
92         "SUSPEND ACKNOWLEDGE",
93         "RESUME ACKNOWLEDGE",
94         "undefined (0x2f)",
95
96 /* 0x30 */
97
98         "HOLD REJECT",
99         "RETRIEVE",
100         "undefined (0x32)",     
101         "RETRIEVE ACKNOWLEDGE",
102         "undefined (0x34)",
103         "undefined (0x35)",
104         "undefined (0x36)",
105         "RETRIEVE REJECT",
106         "undefined (0x38)",
107         "undefined (0x39)",
108         "undefined (0x3a)",
109         "undefined (0x3b)",
110         "undefined (0x3c)",
111         "undefined (0x3d)",
112         "undefined (0x3e)",
113         "undefined (0x3f)",
114
115 /* 0x40 */      
116         
117         "DETACH",                       /* call clearing */
118         "undefined (0x41)",
119         "undefined (0x42)",
120         "undefined (0x43)",
121         "undefined (0x44)",
122         "DISCONNECT",
123         "RESTART",
124         "undefined (0x47)",
125         "DETACH ACKNOWLEDGE",
126         "undefined (0x49)",
127         "undefined (0x4a)",
128         "undefined (0x4b)",
129         "undefined (0x4c)",
130         "RELEASE",
131         "RESTART ACKNOWLEDGE",
132         "undefined (0x4f)",
133
134 /* 0x50 */
135
136         "undefined (0x50)",
137         "undefined (0x51)",
138         "undefined (0x52)",
139         "undefined (0x53)",
140         "undefined (0x54)",
141         "undefined (0x55)",
142         "undefined (0x56)",
143         "undefined (0x57)",
144         "undefined (0x58)",
145         "undefined (0x59)",
146         "RELEASE COMPLETE",
147         "undefined (0x5b)",
148         "undefined (0x5c)",
149         "undefined (0x5d)",
150         "undefined (0x5e)",
151         "undefined (0x5f)",
152
153 /* 0x60 */      
154
155         "SEGMENT",                      /* misc messages */
156         "undefined (0x61)",
157         "FACILITY",
158         "undefined (0x63)",
159         "REGISTER",
160         "undefined (0x65)",
161         "undefined (0x66)",
162         "undefined (0x67)",
163         "CANCEL ACKNOWLEDGE",
164         "undefined (0x69)",
165         "FACILITY ACKNOWLEDGE",
166         "undefined (0x6b)",
167         "REGISTER ACKNOWLEDGE",
168         "undefined (0x6d)",
169         "NOTIFY",
170         "undefined (0x6f)",
171
172 /* 0x70 */
173
174         "CANCEL REJECT",
175         "undefined (0x71)",
176         "FACILITY REJECT",
177         "undefined (0x73)",
178         "REGISTER REJECT",
179         "STATUS ENQIRY",
180         "undefined (0x76)",
181         "undefined (0x77)",
182         "undefined (0x78)",
183         "CONGESTION CONTROL",
184         "undefined (0x7a)",
185         "INFORMATION",
186         "undefined (0x7c)",
187         "STATUS",
188         "undefined (0x7e)",
189         "undefined (0x7f)",
190 };
191
192 #define MTTAB_MAX 0x7f
193
194 extern int f_null(char *pbuf, unsigned char *buf, int off);
195 extern int f_bc(char *pbuf, unsigned char *buf, int off);
196 extern int f_cause(char *pbuf, unsigned char *buf, int off);
197 extern int f_cstat(char *pbuf, unsigned char *buf, int off);
198 extern int f_chid(char *pbuf, unsigned char *buf, int off);
199 extern int f_fac(char *pbuf, unsigned char *buf, int off);
200 extern int f_progi(char *pbuf, unsigned char *buf, int off);
201 extern int f_displ(char *pbuf, unsigned char *buf, int off);
202 extern int f_date(char *pbuf, unsigned char *buf, int off);
203 extern int f_cnu(char *pbuf, unsigned char *buf, int off);
204 extern int f_cgpn(char *pbuf, unsigned char *buf, int off);
205 extern int f_cdpn(char *pbuf, unsigned char *buf, int off);
206 extern int f_hlc(char *pbuf, unsigned char *buf, int off);
207 extern int f_uu(char *pbuf, unsigned char *buf, int off);
208
209 struct ie {
210         unsigned char code;     /* information element identifier code */
211         char *name;             /* ie name */
212         int (*func) (char *pbuf, unsigned char *buf, int off); /* decode function */
213 } ietab[] = {
214         { 0x00, "segmented message",            f_null },
215         { 0x04, "bearer capability",            f_bc },
216         { 0x08, "cause",                        f_cause },
217         { 0x0c, "connected address",            f_null },
218         { 0x0d, "extended facility",            f_null },
219         { 0x10, "call identity",                f_null },
220         { 0x14, "call state",                   f_cstat },
221         { 0x18, "channel id",                   f_chid },
222         { 0x19, "data link connection id",      f_null },
223         { 0x1c, "facility",                     f_fac },
224         { 0x1e, "progress indicator",           f_progi },
225         { 0x20, "network specific facilities",  f_null },
226         { 0x24, "terminal capabilities",        f_null },
227         { 0x27, "notification indicator",       f_null },
228         { 0x28, "display",                      f_displ },
229         { 0x29, "date/time",                    f_date },
230         { 0x2c, "keypad",                       f_null },
231         { 0x30, "keypad echo",                  f_null },
232         { 0x32, "information request",          f_null },
233         { 0x34, "signal",                       f_null },
234         { 0x36, "switchhook",                   f_null },
235         { 0x38, "feature activation",           f_null },
236         { 0x39, "feature indication",           f_null },
237         { 0x3a, "service profile id",           f_null },
238         { 0x3b, "endpoint identifier",          f_null },
239         { 0x40, "information rate",             f_null },
240         { 0x41, "precedence level",             f_null },
241         { 0x42, "end-to-end transit delay",     f_null },
242         { 0x43, "transit delay detection",      f_null },
243         { 0x44, "packet layer binary parms",    f_null },
244         { 0x45, "packet layer window size",     f_null },
245         { 0x46, "packet size",                  f_null },
246         { 0x47, "closed user group",            f_null },
247         { 0x48, "link layer core parameters",   f_null },
248         { 0x49, "link layer protocol parms",    f_null },
249         { 0x4a, "reverse charging information", f_null },
250         { 0x4c, "connected number",             f_cnu },
251         { 0x4d, "connected subaddress",         f_null },
252         { 0x50, "X.213 priority",               f_null },
253         { 0x51, "report type",                  f_null },
254         { 0x53, "link integrity verification",  f_null },
255         { 0x57, "PVC status",                   f_null },
256         { 0x6c, "calling party number",         f_cnu },
257         { 0x6d, "calling party subaddress",     f_null },
258         { 0x70, "called party number",          f_cnu },
259         { 0x71, "called party subaddress",      f_null },
260         { 0x74, "redirecting number",           f_null },
261         { 0x78, "transit network selection",    f_null },
262         { 0x79, "restart indicator",            f_null },
263         { 0x7c, "low layer compatibility",      f_null },
264         { 0x7d, "high layer compatibility",     f_hlc },
265         { 0x7e, "user-user",                    f_uu },
266         { 0x7f, "escape for extension",         f_null },
267         { 0xff, "unknown information element",  f_null }        
268 };
269
270 /*---------------------------------------------------------------------------*
271  *      decode Q.931 protocol
272  *---------------------------------------------------------------------------*/
273 void
274 layer3(char *pbuf, int n, int off, unsigned char *buf)
275 {
276         char buffer[256];
277         int codeset = 0;
278         int codelock = 0;
279         int oldcodeset = 0;
280         
281         int pd;
282         int len;
283         int j;
284         int i;
285
286         if(n <= 0)
287                 return;
288
289         *pbuf = '\0';
290         
291         i = 0;
292                 
293         /* protocol discriminator */
294
295         pd = buf[i];
296
297         if(pd >= 0x00 && pd <= 0x07)
298                 sprintf(buffer, "User-User IE (0x%02x)",pd);
299         else if(pd == 0x08)
300                 sprintf(buffer, "Q.931/I.451");
301         else if(pd >= 0x10 && pd <= 0x3f)
302                 sprintf(buffer, "Other Layer 3 or X.25 (0x%02x)",pd);
303         else if(pd >= 0x40 && pd <= 0x4f)
304                 sprintf(buffer, "National Use (0x%02x)",pd);
305         else if(pd >= 0x50 && pd <= 0xfe)
306                 sprintf(buffer, "Other Layer 3 or X.25 (0x%02x)",pd);
307         else
308                 sprintf(buffer, "Reserved (0x%02x)",pd);
309
310         sprintline(3, (pbuf+strlen(pbuf)), off+i, pd, 0xff, "Protocol discriminator = %s", buffer);
311         i++;
312
313         if(pd != 0x08)
314         {
315                 for (; i < n;i++)
316                         sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0xff, "-");
317                 return;
318         }
319         
320         /* call reference */
321
322         len = buf[i] & 0x0f;
323         
324         sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0xf0, "Call Reference");
325
326         switch(len)
327         {
328                 case 0:
329                         sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x0f, "Length of Call Reference = 0 (Dummy CR)");
330                         break;
331                 case 1:
332                         sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x0f, "Length of Call Reference = 1");
333                         i++;
334                         sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x80, "Call Reference sent %s origination side", (buf[i] & 0x80) ? "to" : "from");
335                         sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x7f, "Call Reference = %d = 0x%02x", (buf[i] & 0x7f), (buf[i] & 0x7f));
336                         break;
337                 case 2:
338                         sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x0f, "Length of Call Reference = 2");
339                         i++;
340                         sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x80, "Call Reference sent %s origination side", (buf[i] & 0x80) ? "to" : "from");
341                         sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x7f, "Call reference = %d = %02x", (buf[i] & 0x7f), (buf[i] & 0x7f));
342                         i++;
343                         sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0xff, "Call reference = %d = %02x", (buf[i]), (buf[i]));
344                         break;
345         }
346         i++;    
347
348         /* message type */      
349
350         sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x80, "Message type extension = %d", buf[i] & 0x80 ? 1 : 0);
351
352         if(buf[i] <= MTTAB_MAX)
353                 strcpy(buffer, mttab[buf[i]]);
354         else
355                 sprintf(buffer, "unknown (0x%02x)", buf[i]);
356
357         sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x7f, "Message type = %s", buffer);
358         i++;
359         
360         /* information elements */
361         
362         for (; i < n;)
363         {
364                 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x80, "%s Information element", buf[i] & 0x80 ? "Single octet" : "Variable length");
365
366                 if(buf[i] & 0x80)
367                 {
368                         /* single octett info element type 1 */
369
370                         if((buf[i] & 0x70) == 0x00)
371                         {
372                                 strcpy(buffer, "Reserved");
373                                 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x70, "Reserved");
374                                 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x0f, "Reserved, content of IE");
375                         }
376                         else if((buf[i] & 0x70) == 0x10)
377                         {
378                                 strcpy(buffer, "Shift");
379                                 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x70, "Shift");
380                                 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x08, "%s shift", buf[i] & 0x08 ? "Non-locking" : "Locking");
381
382                                         switch(buf[i] & 0x07)
383                                         {
384                                                 case 0:
385                                                         strcpy(buffer, "Not applicable");
386                                                         break;
387                                                 case 1:
388                                                 case 2:
389                                                 case 3:
390                                                         sprintf(buffer, "Reserved (%d)", buf[i] & 0x07);
391                                                         break;
392                                                 case 4:
393                                                         strcpy(buffer, "Codeset 4 (ISO/IEC)");
394                                                         break;
395                                                 case 5:
396                                                         strcpy(buffer, "Codeset 5 (National use)");
397                                                         break;
398                                                 case 6:
399                                                         strcpy(buffer, "Codeset 6 (Local network specific)");
400                                                         break;
401                                                 case 7:
402                                                         strcpy(buffer, "Codeset 7 (User specific)");
403                                                         break;
404                                         }
405                                         sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x07, "%s", buffer);
406                                         break;
407                         }
408                         else if((buf[i] & 0x70) == 0x30)
409                         {
410                                 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x70, "Congestion Level");
411                                 switch(buf[i] & 0x0f)
412                                 {
413                                         case 0x00:
414                                                 strcpy(buffer, "receiver ready");
415                                                 break;
416                                         case 0x0f:
417                                                 strcpy(buffer, "receiver not ready");
418                                                 break;
419                                         default:
420                                                 sprintf(buffer, "reserved (0x%02x)", buf[i] & 0x0f);
421                                                 break;
422                                 }
423                                 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x0f, "Congestion Level = ", buffer);
424                                 break;
425                         }
426                         else if((buf[i] & 0x70) == 0x50)
427                         {
428                                 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x70, "Repeat Indicator");
429                                 switch(buf[i] & 0x0f)
430                                 {
431                                         case 0x02:
432                                                 strcpy(buffer, "Prioritized list for selecting one possibility");
433                                                 break;
434                                         default:
435                                                 sprintf(buffer, "reserved (0x%02x)", buf[i] & 0x0f);
436                                                 break;
437                                 }
438                                 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x0f, "Repeat indication = ", buffer);
439                                 break;
440                         }
441                         
442                         /* single octett info element type 2 */
443
444                         else if((buf[i] & 0x7f) == 0x20)
445                         {
446                                 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x7f, "More data");
447                         }
448                         else if((buf[i] & 0x7f) == 0x21)
449                         {
450                                 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x7f, "Sending complete");
451                         }
452                         else
453                         {
454                                 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0xff, "UNKNOWN single octet IE = 0x%02x", buf[i]);
455                         }
456                         i++;    /* next */
457                 }
458                 else
459                 {
460                         if(codeset == 0)
461                         {
462                                 struct ie *iep = &ietab[0];
463
464                                 for(;;)
465                                 {
466                                         if((iep->code == buf[i]) ||
467                                            (iep->code == 0xff))
468                                                 break;
469                                         iep++;
470                                 }
471
472                                 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x7f, "IE = %s", iep->name);
473                                 sprintline(3, pbuf+strlen(pbuf), off+i+1, buf[i+1], 0xff, "IE Length = %d", buf[i+1]);
474                                 
475                                 if(iep->func == f_null)
476                                 {
477                                 }
478                                 else
479                                 {
480                                         i += (iep->func)(pbuf, &buf[i], off+i);
481                                         goto next;
482                                 }
483                         }
484                         else
485                         {
486                                 sprintf((pbuf+strlen(pbuf)), "UNKNOWN CODESET=%d, IE=0x%02x", codeset, buf[i]);
487                         }
488
489                         i++;    /* index -> length */
490
491                         len = buf[i];
492
493                         sprintf((pbuf+strlen(pbuf)), "LEN=0x%02x, DATA=", len);                 
494
495                         i++;    /* index -> 1st param */
496
497                         for(j = 0; j < len; j++)
498                         {
499                                 sprintf((pbuf+strlen(pbuf)),"0x%02x ", buf[j+i]);
500                         }
501         
502                         sprintf((pbuf+strlen(pbuf)),"]\n");
503
504                         i += len;
505
506 next:
507
508                         if(!codelock && (codeset != oldcodeset))
509                                 codeset = oldcodeset;
510                 }
511         }
512 /*      sprintf((pbuf+strlen(pbuf)),"\n"); */
513 }
514
515 /* EOF */
516