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