modules: pull in most of FreeBSD's module linker changes
[dragonfly.git] / usr.sbin / i4b / isdndecode / layer3.c
blobde16adbc69a1cf8e734ba72b17a8d9554859c6b3
1 /*
2 * Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
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.
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.
25 *---------------------------------------------------------------------------
27 * layer3.c - decode and print layer 3 (Q.931) information
28 * -------------------------------------------------------
30 * $Id: layer3.c,v 1.9 2000/02/21 15:17:17 hm Exp $
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 $
35 * last edit-date: [Mon Feb 21 15:54:58 2000]
37 *---------------------------------------------------------------------------*/
39 #include "decode.h"
41 char *mttab[] = {
43 /* 0x00 */ /* call establishment group */
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",
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)",
80 /* 0x20 */
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)",
99 /* 0x30 */
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)",
118 /* 0x40 */
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)",
137 /* 0x50 */
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)",
156 /* 0x60 */
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)",
175 /* 0x70 */
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)",
195 #define MTTAB_MAX 0x7f
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);
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 }
273 /*---------------------------------------------------------------------------*
274 * decode Q.931 protocol
275 *---------------------------------------------------------------------------*/
276 void
277 layer3(char *pbuf, int n, int off, unsigned char *buf)
279 char buffer[256];
280 int codeset = 0;
281 int codelock = 0;
282 int oldcodeset = 0;
284 int pd;
285 int len;
286 int j;
287 int i;
289 if(n <= 0)
290 return;
292 *pbuf = '\0';
294 i = 0;
296 /* protocol discriminator */
298 pd = buf[i];
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);
313 sprintline(3, (pbuf+strlen(pbuf)), off+i, pd, 0xff, "Protocol discriminator = %s", buffer);
314 i++;
316 if(pd != 0x08)
318 for (; i < n;i++)
319 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0xff, "-");
320 return;
323 /* call reference */
325 len = buf[i] & 0x0f;
327 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0xf0, "Call Reference");
329 switch(len)
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;
349 i++;
351 /* message type */
353 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x80, "Message type extension = %d", buf[i] & 0x80 ? 1 : 0);
355 if(buf[i] <= MTTAB_MAX)
356 strcpy(buffer, mttab[buf[i]]);
357 else
358 sprintf(buffer, "unknown (0x%02x)", buf[i]);
360 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x7f, "Message type = %s", buffer);
361 i++;
363 /* information elements */
365 for (; i < n;)
367 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x80, "%s Information element", buf[i] & 0x80 ? "Single octet" : "Variable length");
369 if(buf[i] & 0x80)
371 /* single octett info element type 1 */
373 if((buf[i] & 0x70) == 0x00)
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");
379 else if((buf[i] & 0x70) == 0x10)
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");
385 switch(buf[i] & 0x07)
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;
408 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x07, "%s", buffer);
409 break;
411 else if((buf[i] & 0x70) == 0x30)
413 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x70, "Congestion Level");
414 switch(buf[i] & 0x0f)
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;
426 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x0f, "Congestion Level = ", buffer);
427 break;
429 else if((buf[i] & 0x70) == 0x50)
431 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x70, "Repeat Indicator");
432 switch(buf[i] & 0x0f)
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;
441 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x0f, "Repeat indication = ", buffer);
442 break;
445 /* single octett info element type 2 */
447 else if((buf[i] & 0x7f) == 0x20)
449 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x7f, "More data");
451 else if((buf[i] & 0x7f) == 0x21)
453 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x7f, "Sending complete");
455 else
457 sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0xff, "UNKNOWN single octet IE = 0x%02x", buf[i]);
459 i++; /* next */
461 else
463 if(codeset == 0)
465 struct ie *iep = &ietab[0];
467 for(;;)
469 if((iep->code == buf[i]) ||
470 (iep->code == 0xff))
471 break;
472 iep++;
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]);
478 if(iep->func == f_null)
481 else
483 i += (iep->func)(pbuf, &buf[i], off+i);
484 goto next;
487 else
489 sprintf((pbuf+strlen(pbuf)), "UNKNOWN CODESET=%d, IE=0x%02x", codeset, buf[i]);
492 i++; /* index -> length */
494 len = buf[i];
496 sprintf((pbuf+strlen(pbuf)), "LEN=0x%02x, DATA=", len);
498 i++; /* index -> 1st param */
500 for(j = 0; j < len; j++)
502 sprintf((pbuf+strlen(pbuf)),"0x%02x ", buf[j+i]);
505 sprintf((pbuf+strlen(pbuf)),"]");
507 i += len;
509 next:
511 if(!codelock && (codeset != oldcodeset))
512 codeset = oldcodeset;
515 /* sprintf((pbuf+strlen(pbuf)),"\n"); */
518 /* EOF */