2 * Copyright (c) 1997, 2001 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
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
25 *---------------------------------------------------------------------------
27 * q931.c - print Q.931 traces
28 * ---------------------------
32 * last edit-date: [Wed Oct 17 14:49:16 2001]
34 *---------------------------------------------------------------------------*/
38 /*---------------------------------------------------------------------------*
39 * decode Q.931 protocol
40 *---------------------------------------------------------------------------*/
42 decode_q931(char *pbuf, int n, int off, unsigned char *buf, int raw)
60 for (i = 0; i < n; i += 16)
62 sprintf((pbuf+strlen(pbuf)),"Dump:%.3d ", i+off);
63 for (j = 0; j < 16; j++)
65 sprintf((pbuf+strlen(pbuf)),"%02x ", buf[i + j]);
67 sprintf((pbuf+strlen(pbuf))," ");
68 sprintf((pbuf+strlen(pbuf))," ");
69 for (j = 0; j < 16 && i + j < n; j++)
70 if (isprint(buf[i + j]))
71 sprintf((pbuf+strlen(pbuf)),"%c", buf[i + j]);
73 sprintf((pbuf+strlen(pbuf)),".");
74 sprintf((pbuf+strlen(pbuf)),"\n");
80 sprintf((pbuf+strlen(pbuf)), "Q931: ");
82 /* protocol discriminator */
86 if(pd >= 0x00 && pd <= 0x07)
87 sprintf((pbuf+strlen(pbuf)), "pd=User-User (0x%02x)\n",pd);
89 sprintf((pbuf+strlen(pbuf)), "pd=Q.931/I.451, ");
90 else if(pd >= 0x10 && pd <= 0x3f)
91 sprintf((pbuf+strlen(pbuf)), "pd=Other Layer 3 or X.25 (0x%02x)\n",pd);
92 else if(pd >= 0x40 && pd <= 0x4f)
93 sprintf((pbuf+strlen(pbuf)), "pd=National Use (0x%02x)\n",pd);
94 else if(pd >= 0x50 && pd <= 0xfe)
95 sprintf((pbuf+strlen(pbuf)), "pd=Other Layer 3 or X.25 (0x%02x)\n",pd);
97 sprintf((pbuf+strlen(pbuf)), "pd=Reserved (0x%02x)\n",pd);
108 sprintf((pbuf+strlen(pbuf)), "cr=Dummy, ");
111 sprintf((pbuf+strlen(pbuf)), "cr=0x%02x %s, ", (buf[i+1] & 0x7f), (buf[i+1] & 0x80) ? "(from destination)" : "(from origination)");
114 sprintf((pbuf+strlen(pbuf)), "cr=0x%02x 0x%02x %s, ", (buf[i+1] & 0x7f), (buf[i+2] & 0x7f), (buf[i+1] & 0x80) ? "(org)" : "(dst)");
122 sprintf((pbuf+strlen(pbuf)), "message=");
126 /* escape to nationally specific message type */
129 sprintf((pbuf+strlen(pbuf)), "ESCAPE: ");
132 /* call establishment */
135 sprintf((pbuf+strlen(pbuf)), "ALERTING: ");
138 sprintf((pbuf+strlen(pbuf)), "CALL PROCEEDING: ");
141 sprintf((pbuf+strlen(pbuf)), "PROGRESS: ");
144 sprintf((pbuf+strlen(pbuf)), "SETUP: ");
147 sprintf((pbuf+strlen(pbuf)), "CONNECT: ");
150 sprintf((pbuf+strlen(pbuf)), "SETUP ACKNOWLEDGE: ");
153 sprintf((pbuf+strlen(pbuf)), "CONNECT ACKNOWLEDGE: ");
156 /* call information phase */
159 sprintf((pbuf+strlen(pbuf)), "USER INFORMATION: ");
162 sprintf((pbuf+strlen(pbuf)), "SUSPEND REJECT: ");
165 sprintf((pbuf+strlen(pbuf)), "RESUME REJECT: ");
168 sprintf((pbuf+strlen(pbuf)), "HOLD: ");
171 sprintf((pbuf+strlen(pbuf)), "SUSPEND: ");
174 sprintf((pbuf+strlen(pbuf)), "RESUME: ");
177 sprintf((pbuf+strlen(pbuf)), "HOLD ACKNOWLEDGE: ");
180 sprintf((pbuf+strlen(pbuf)), "SUSPEND ACKNOWLEDGE: ");
183 sprintf((pbuf+strlen(pbuf)), "RESUME ACKNOWLEDGE: ");
186 sprintf((pbuf+strlen(pbuf)), "HOLD REJECT (Q.932): ");
189 sprintf((pbuf+strlen(pbuf)), "RETRIEVE (Q.932): ");
192 sprintf((pbuf+strlen(pbuf)), "RETRIEVE ACKNOWLEDGE (Q.932): ");
195 sprintf((pbuf+strlen(pbuf)), "RETRIEVE REJECT (Q.932): ");
201 sprintf((pbuf+strlen(pbuf)), "DETACH: ");
204 sprintf((pbuf+strlen(pbuf)), "DISCONNECT: ");
207 sprintf((pbuf+strlen(pbuf)), "RESTART: ");
210 sprintf((pbuf+strlen(pbuf)), "DETACH ACKNOWLEDGE: ");
213 sprintf((pbuf+strlen(pbuf)), "RELEASE: ");
216 sprintf((pbuf+strlen(pbuf)), "RESTART ACKNOWLEDGE: ");
219 sprintf((pbuf+strlen(pbuf)), "RELEASE COMPLETE: ");
225 sprintf((pbuf+strlen(pbuf)), "SEGMENT: ");
228 sprintf((pbuf+strlen(pbuf)), "FACILITY (Q.932): ");
231 sprintf((pbuf+strlen(pbuf)), "REGISTER (Q.932): ");
234 sprintf((pbuf+strlen(pbuf)), "CANCEL ACKNOWLEDGE: ");
237 sprintf((pbuf+strlen(pbuf)), "FACILITY ACKNOWLEDGE: ");
240 sprintf((pbuf+strlen(pbuf)), "REGISTER ACKNOWLEDGE: ");
243 sprintf((pbuf+strlen(pbuf)), "NOTIFY: ");
246 sprintf((pbuf+strlen(pbuf)), "CANCEL REJECT: ");
249 sprintf((pbuf+strlen(pbuf)), "FACILITY REJECT: ");
252 sprintf((pbuf+strlen(pbuf)), "REGISTER REJECT: ");
255 sprintf((pbuf+strlen(pbuf)), "STATUS ENQIRY: ");
258 sprintf((pbuf+strlen(pbuf)), "CONGESTION CONTROL: ");
261 sprintf((pbuf+strlen(pbuf)), "INFORMATION: ");
264 sprintf((pbuf+strlen(pbuf)), "STATUS: ");
267 sprintf((pbuf+strlen(pbuf)), "UNDEFINED, TYPE=0x%02x, ", buf[i]);
271 /* other information elements */
277 sprintf((pbuf+strlen(pbuf)), "\n ");
281 /* single octett info element */
283 switch(buf[i] & 0x70)
285 case 0x00: /* reserved */
286 sprintf((pbuf+strlen(pbuf)), "[reserved single octett info]");
289 case 0x10: /* shift */
290 oldcodeset = codeset;
291 codeset = buf[i] & 0x07;
296 sprintf((pbuf+strlen(pbuf)), "[shift: codeset=%d lock=%d]", codeset, codelock);
299 case 0x20: /* more data */
301 sprintf((pbuf+strlen(pbuf)), "[sending complete]");
303 sprintf((pbuf+strlen(pbuf)), "[more data]");
306 case 0x30: /* congestion level */
307 sprintf((pbuf+strlen(pbuf)), "[congestion level=");
308 switch(buf[i] & 0x0f)
311 sprintf((pbuf+strlen(pbuf)), "rx-ready]");
314 sprintf((pbuf+strlen(pbuf)), "rx-not-ready]");
317 sprintf((pbuf+strlen(pbuf)), "reserved (0x%02x)]", buf[i] & 0x0f);
322 case 0x50: /* repeat ind */
323 sprintf((pbuf+strlen(pbuf)), "[repeat indicator]");
327 sprintf((pbuf+strlen(pbuf)), "[UNKNOWN SINGLE OCTET ELEMENT 0x%02x]", buf[i]);
336 /* variable length info element */
343 sprintf((pbuf+strlen(pbuf)), "[segmented message: ");
346 sprintf((pbuf+strlen(pbuf)), "[bearer capability: ");
347 i += p_q931bc(pbuf, &buf[i]);
351 sprintf((pbuf+strlen(pbuf)), "[cause: ");
352 i += p_q931cause(pbuf, &buf[i]);
356 sprintf((pbuf+strlen(pbuf)), "[connected address (old): ");
359 sprintf((pbuf+strlen(pbuf)), "[extended facility (Q.932: )");
362 sprintf((pbuf+strlen(pbuf)), "[call identity: ");
365 sprintf((pbuf+strlen(pbuf)), "[call state: ");
369 sprintf((pbuf+strlen(pbuf)), "Std=");
370 switch((buf[i] & 0x60) >> 5)
373 sprintf((pbuf+strlen(pbuf)), "CCITT");
376 sprintf((pbuf+strlen(pbuf)), "ISO/IEC");
379 sprintf((pbuf+strlen(pbuf)), "National");
382 sprintf((pbuf+strlen(pbuf)), "Special");
385 sprintf((pbuf+strlen(pbuf)), ", State=");
387 switch((buf[i] & 0x3f))
390 sprintf((pbuf+strlen(pbuf)), "Null");
393 sprintf((pbuf+strlen(pbuf)), "Call initiated");
396 sprintf((pbuf+strlen(pbuf)), "Overlap sending");
399 sprintf((pbuf+strlen(pbuf)), "Outgoing call proceeding");
402 sprintf((pbuf+strlen(pbuf)), "Call delivered");
405 sprintf((pbuf+strlen(pbuf)), "Call present");
408 sprintf((pbuf+strlen(pbuf)), "Call received");
411 sprintf((pbuf+strlen(pbuf)), "Connect request");
414 sprintf((pbuf+strlen(pbuf)), "Incoming call proceeding");
417 sprintf((pbuf+strlen(pbuf)), "Active");
420 sprintf((pbuf+strlen(pbuf)), "Disconnect request");
423 sprintf((pbuf+strlen(pbuf)), "Disconnect indication");
426 sprintf((pbuf+strlen(pbuf)), "Suspend request");
429 sprintf((pbuf+strlen(pbuf)), "Resume request");
432 sprintf((pbuf+strlen(pbuf)), "Release request");
435 sprintf((pbuf+strlen(pbuf)), "Call abort");
438 sprintf((pbuf+strlen(pbuf)), "Overlap receiving");
441 sprintf((pbuf+strlen(pbuf)), "Restart request");
444 sprintf((pbuf+strlen(pbuf)), "Restart");
447 sprintf((pbuf+strlen(pbuf)), "ERROR: undefined/reserved");
450 sprintf((pbuf+strlen(pbuf)), "]");
455 sprintf((pbuf+strlen(pbuf)), "[channel id: channel=");
459 switch(buf[i] & 0x03)
462 sprintf((pbuf+strlen(pbuf)), "no channel");
465 sprintf((pbuf+strlen(pbuf)), "B-1");
468 sprintf((pbuf+strlen(pbuf)), "B-2");
471 sprintf((pbuf+strlen(pbuf)), "any channel");
475 sprintf((pbuf+strlen(pbuf)), " (exclusive)]");
477 sprintf((pbuf+strlen(pbuf)), " (preferred)]");
482 sprintf((pbuf+strlen(pbuf)), "[data link connection id (Q.933): ");
485 i += q932_facility(pbuf, &buf[i]);
489 sprintf((pbuf+strlen(pbuf)), "[progress ind: ");
493 sprintf((pbuf+strlen(pbuf)), "Std=");
494 switch((buf[i] & 0x60) >> 5)
497 sprintf((pbuf+strlen(pbuf)), "CCITT");
500 sprintf((pbuf+strlen(pbuf)), "ISO/IEC");
503 sprintf((pbuf+strlen(pbuf)), "National");
506 sprintf((pbuf+strlen(pbuf)), "Local");
509 sprintf((pbuf+strlen(pbuf)), ", Loc=");
511 switch((buf[i] & 0x0f))
514 sprintf((pbuf+strlen(pbuf)), "User");
517 sprintf((pbuf+strlen(pbuf)), "Private network serving local user");
520 sprintf((pbuf+strlen(pbuf)), "Public network serving local user");
523 sprintf((pbuf+strlen(pbuf)), "Transit network");
526 sprintf((pbuf+strlen(pbuf)), "Public network serving remote user");
529 sprintf((pbuf+strlen(pbuf)), "Private network serving remote user");
532 sprintf((pbuf+strlen(pbuf)), "Network beyond interworking point");
535 sprintf((pbuf+strlen(pbuf)), "ERROR: undefined/reserved");
541 sprintf((pbuf+strlen(pbuf)), "\n Description: ");
543 switch((buf[i] & 0x7f))
546 sprintf((pbuf+strlen(pbuf)), "Call is not end-to-end ISDN");
549 sprintf((pbuf+strlen(pbuf)), "Destination address is non-ISDN");
552 sprintf((pbuf+strlen(pbuf)), "Origination address is non-ISDN");
555 sprintf((pbuf+strlen(pbuf)), "Call has returned to the ISDN");
558 sprintf((pbuf+strlen(pbuf)), "Interworking occured, Service change");
561 sprintf((pbuf+strlen(pbuf)), "In-band info or appropriate pattern now available");
564 sprintf((pbuf+strlen(pbuf)), "ERROR: undefined/reserved");
567 sprintf((pbuf+strlen(pbuf)), "]");
572 sprintf((pbuf+strlen(pbuf)), "[network specific facilities: ");
575 sprintf((pbuf+strlen(pbuf)), "[terminal capabilities: ");
578 sprintf((pbuf+strlen(pbuf)), "[notification indicator: ");
579 i += p_q931notification(pbuf, &buf[i]);
583 sprintf((pbuf+strlen(pbuf)), "[display: ");
587 for(j = 0; j < len; j++)
589 sprintf((pbuf+strlen(pbuf)),"%c", buf[j+i]);
591 sprintf((pbuf+strlen(pbuf)),"]");
596 sprintf((pbuf+strlen(pbuf)), "[date/time: ");
601 sprintf((pbuf+strlen(pbuf)),"%.2d.%.2d.%.2d",
602 buf[i+2], buf[i+1], buf[i]);
606 sprintf((pbuf+strlen(pbuf))," %.2d", buf[i+3]);
611 sprintf((pbuf+strlen(pbuf)),":%.2d", buf[i+4]);
616 sprintf((pbuf+strlen(pbuf)),":%.2d", buf[i+5]);
619 sprintf((pbuf+strlen(pbuf)),"]");
624 sprintf((pbuf+strlen(pbuf)), "[keypad: ");
628 for(j = 0; j < len; j++)
630 sprintf((pbuf+strlen(pbuf)),"%c", buf[j+i]);
632 sprintf((pbuf+strlen(pbuf)),"]");
637 sprintf((pbuf+strlen(pbuf)), "[keypad echo: ");
640 sprintf((pbuf+strlen(pbuf)), "[information req (Q.932): ");
643 sprintf((pbuf+strlen(pbuf)), "[signal: ");
646 sprintf((pbuf+strlen(pbuf)), "[switchhook: ");
649 sprintf((pbuf+strlen(pbuf)), "[feature activation (Q.932): ");
652 sprintf((pbuf+strlen(pbuf)), "[feature ind (Q.932): ");
655 sprintf((pbuf+strlen(pbuf)), "[service profile id (Q.932): ");
658 sprintf((pbuf+strlen(pbuf)), "[endpoint id (Q.932): ");
661 sprintf((pbuf+strlen(pbuf)), "[information rate: ");
664 sprintf((pbuf+strlen(pbuf)), "[precedence level (Q.955): ");
667 sprintf((pbuf+strlen(pbuf)), "[end-to-end transit delay: ");
670 sprintf((pbuf+strlen(pbuf)), "[transit delay detection and indication: ");
673 sprintf((pbuf+strlen(pbuf)), "[packet layer binary parameters: ");
676 sprintf((pbuf+strlen(pbuf)), "[packet layer window size: ");
679 sprintf((pbuf+strlen(pbuf)), "[packet size: ");
682 sprintf((pbuf+strlen(pbuf)), "[closed user group: ");
685 sprintf((pbuf+strlen(pbuf)), "[link layer core parameters (Q.933): ");
688 sprintf((pbuf+strlen(pbuf)), "[link layer protocol parameters (Q.933): ");
691 sprintf((pbuf+strlen(pbuf)), "[reverse charging information: ");
694 sprintf((pbuf+strlen(pbuf)), "[connected number (Q.951): ");
695 i += p_q931address(pbuf, &buf[i]);
701 sprintf((pbuf+strlen(pbuf)), "[connected subaddress (Q.951): ");
704 sprintf((pbuf+strlen(pbuf)), "[X.213 priority (Q.933): ");
707 sprintf((pbuf+strlen(pbuf)), "[report type (Q.933): ");
710 sprintf((pbuf+strlen(pbuf)), "[link integrity verification (Q.933): ");
713 sprintf((pbuf+strlen(pbuf)), "[PVC status (Q.933): ");
716 sprintf((pbuf+strlen(pbuf)), "[calling party number: ");
717 i += p_q931address(pbuf, &buf[i]);
721 sprintf((pbuf+strlen(pbuf)), "[calling party subaddress: ");
724 sprintf((pbuf+strlen(pbuf)), "[called party number: ");
725 i += p_q931address(pbuf, &buf[i]);
729 sprintf((pbuf+strlen(pbuf)), "[called party subaddress: ");
732 sprintf((pbuf+strlen(pbuf)), "[redirecting number: ");
733 i += p_q931redir(pbuf, &buf[i]);
737 sprintf((pbuf+strlen(pbuf)), "[redirection number: ");
738 i += p_q931redir(pbuf, &buf[i]);
742 sprintf((pbuf+strlen(pbuf)), "[transit network selection: ");
745 sprintf((pbuf+strlen(pbuf)), "[restart indicator: ");
748 sprintf((pbuf+strlen(pbuf)), "[low layer compatibility: ");
751 sprintf((pbuf+strlen(pbuf)), "[high layer compatibility:");
752 i += p_q931high_compat(pbuf, &buf[i]);
756 sprintf((pbuf+strlen(pbuf)), "[user-user: ");
757 i += p_q931user_user(pbuf, &buf[i]);
761 sprintf((pbuf+strlen(pbuf)), "[escape for extension: ");
764 sprintf((pbuf+strlen(pbuf)), "[UNKNOWN INFO-ELEMENT-ID=0x%02x: ", buf[i]);
770 sprintf((pbuf+strlen(pbuf)), "[UNKNOWN CODESET=%d, IE=0x%02x: ", codeset, buf[i]);
773 i++; /* index -> length */
777 sprintf((pbuf+strlen(pbuf)), "LEN=0x%02x, DATA=", len);
779 i++; /* index -> 1st param */
781 for(j = 0; j < len; j++)
783 sprintf((pbuf+strlen(pbuf)),"0x%02x ", buf[j+i]);
786 sprintf((pbuf+strlen(pbuf)),"]");
792 if(!codelock && (codeset != oldcodeset))
793 codeset = oldcodeset;
796 sprintf((pbuf+strlen(pbuf)),"\n");