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