1/*
2 * Copyright (c) 1997, 2000 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 *	q931.c - print Q.931 traces
28 *	---------------------------
29 *
30 *	$Id: q931.c,v 1.3 2003/10/06 09:43:28 itojun Exp $
31 *
32 * $FreeBSD$
33 *
34 *      last edit-date: [Mon Feb 14 14:51:13 2000]
35 *
36 *---------------------------------------------------------------------------*/
37
38#include "trace.h"
39
40/*---------------------------------------------------------------------------*
41 *	decode Q.931 protocol
42 *---------------------------------------------------------------------------*/
43void
44decode_q931(char *pbuf, int n, int off, unsigned char *buf, int raw)
45{
46	int codeset = 0;
47	int codelock = 0;
48	int oldcodeset = 0;
49
50	int pd;
51	int len;
52	int j;
53	int i;
54
55	if (n <= 0)
56		return;
57
58	*pbuf = '\0';
59
60	if (raw)
61	{
62		for (i = 0; i < n; i += 16)
63		{
64			sprintf((pbuf+strlen(pbuf)),"Dump:%.3d  ", i+off);
65			for (j = 0; j < 16; j++)
66				if (i + j < n)
67					sprintf((pbuf+strlen(pbuf)),"%02x ", buf[i + j]);
68				else
69					sprintf((pbuf+strlen(pbuf)),"   ");
70			sprintf((pbuf+strlen(pbuf)),"      ");
71			for (j = 0; j < 16 && i + j < n; j++)
72				if (isprint(buf[i + j]))
73					sprintf((pbuf+strlen(pbuf)),"%c", buf[i + j]);
74				else
75					sprintf((pbuf+strlen(pbuf)),".");
76			sprintf((pbuf+strlen(pbuf)),"\n");
77		}
78	}
79
80	i = 0;
81
82	sprintf((pbuf+strlen(pbuf)), "Q931: ");
83
84	/* protocol discriminator */
85
86	pd = buf[i];
87
88	if (pd >= 0x00 && pd <= 0x07)
89		sprintf((pbuf+strlen(pbuf)), "pd=User-User (0x%02x)\n",pd);
90	else if (pd == 0x08)
91		sprintf((pbuf+strlen(pbuf)), "pd=Q.931/I.451, ");
92	else if (pd >= 0x10 && pd <= 0x3f)
93		sprintf((pbuf+strlen(pbuf)), "pd=Other Layer 3 or X.25 (0x%02x)\n",pd);
94	else if (pd >= 0x40 && pd <= 0x4f)
95		sprintf((pbuf+strlen(pbuf)), "pd=National Use (0x%02x)\n",pd);
96	else if (pd >= 0x50 && pd <= 0xfe)
97		sprintf((pbuf+strlen(pbuf)), "pd=Other Layer 3 or X.25 (0x%02x)\n",pd);
98	else
99		sprintf((pbuf+strlen(pbuf)), "pd=Reserved (0x%02x)\n",pd);
100
101	/* call reference */
102
103	i++;
104
105	len = buf[i] & 0x0f;
106
107	switch (len)
108	{
109	case 0:
110		sprintf((pbuf+strlen(pbuf)), "cr=Dummy, ");
111		break;
112	case 1:
113		sprintf((pbuf+strlen(pbuf)), "cr=0x%02x %s, ", (buf[i+1] & 0x7f), (buf[i+1] & 0x80) ? "(from destination)" : "(from origination)");
114		break;
115	case 2:
116		sprintf((pbuf+strlen(pbuf)), "cr=0x%02x 0x%02x %s, ", (buf[i+1] & 0x7f), (buf[i+2] & 0x7f), (buf[i+1] & 0x80) ? "(org)" : "(dst)");
117		break;
118	}
119
120	i += (len+1);
121
122	/* message type */
123
124	sprintf((pbuf+strlen(pbuf)), "message=");
125
126	switch (buf[i])
127	{
128	/* escape to nationally specific message type */
129
130	case 0x00:
131		sprintf((pbuf+strlen(pbuf)), "ESCAPE: ");
132		break;
133
134	/* call establishment */
135
136	case 0x01:
137		sprintf((pbuf+strlen(pbuf)), "ALERTING: ");
138		break;
139	case 0x02:
140		sprintf((pbuf+strlen(pbuf)), "CALL PROCEEDING: ");
141		break;
142	case 0x03:
143		sprintf((pbuf+strlen(pbuf)), "PROGRESS: ");
144		break;
145	case 0x05:
146		sprintf((pbuf+strlen(pbuf)), "SETUP: ");
147		break;
148	case 0x07:
149		sprintf((pbuf+strlen(pbuf)), "CONNECT: ");
150		break;
151	case 0x0d:
152		sprintf((pbuf+strlen(pbuf)), "SETUP ACKNOWLEDGE: ");
153		break;
154	case 0x0f:
155		sprintf((pbuf+strlen(pbuf)), "CONNECT ACKNOWLEDGE: ");
156		break;
157
158	/* call information phase */
159
160	case 0x20:
161		sprintf((pbuf+strlen(pbuf)), "USER INFORMATION: ");
162		break;
163	case 0x21:
164		sprintf((pbuf+strlen(pbuf)), "SUSPEND REJECT: ");
165		break;
166	case 0x22:
167		sprintf((pbuf+strlen(pbuf)), "RESUME REJECT: ");
168		break;
169	case 0x24:
170		sprintf((pbuf+strlen(pbuf)), "HOLD: ");
171		break;
172	case 0x25:
173		sprintf((pbuf+strlen(pbuf)), "SUSPEND: ");
174		break;
175	case 0x26:
176		sprintf((pbuf+strlen(pbuf)), "RESUME: ");
177		break;
178	case 0x28:
179		sprintf((pbuf+strlen(pbuf)), "HOLD ACKNOWLEDGE: ");
180		break;
181	case 0x2d:
182		sprintf((pbuf+strlen(pbuf)), "SUSPEND ACKNOWLEDGE: ");
183		break;
184	case 0x2e:
185		sprintf((pbuf+strlen(pbuf)), "RESUME ACKNOWLEDGE: ");
186		break;
187	case 0x30:
188		sprintf((pbuf+strlen(pbuf)), "HOLD REJECT (Q.932): ");
189		break;
190	case 0x31:
191		sprintf((pbuf+strlen(pbuf)), "RETRIEVE (Q.932): ");
192		break;
193	case 0x32:
194		sprintf((pbuf+strlen(pbuf)), "RETRIEVE ACKNOWLEDGE (Q.932): ");
195		break;
196	case 0x37:
197		sprintf((pbuf+strlen(pbuf)), "RETRIEVE REJECT (Q.932): ");
198		break;
199
200	/* call clearing */
201
202	case 0x40:
203		sprintf((pbuf+strlen(pbuf)), "DETACH: ");
204		break;
205	case 0x45:
206		sprintf((pbuf+strlen(pbuf)), "DISCONNECT: ");
207		break;
208	case 0x46:
209		sprintf((pbuf+strlen(pbuf)), "RESTART: ");
210		break;
211	case 0x48:
212		sprintf((pbuf+strlen(pbuf)), "DETACH ACKNOWLEDGE: ");
213		break;
214	case 0x4d:
215		sprintf((pbuf+strlen(pbuf)), "RELEASE: ");
216		break;
217	case 0x4e:
218		sprintf((pbuf+strlen(pbuf)), "RESTART ACKNOWLEDGE: ");
219		break;
220	case 0x5a:
221		sprintf((pbuf+strlen(pbuf)), "RELEASE COMPLETE: ");
222		break;
223
224	/* misc messages */
225
226	case 0x60:
227		sprintf((pbuf+strlen(pbuf)), "SEGMENT: ");
228		break;
229	case 0x62:
230		sprintf((pbuf+strlen(pbuf)), "FACILITY (Q.932): ");
231		break;
232	case 0x64:
233		sprintf((pbuf+strlen(pbuf)), "REGISTER (Q.932): ");
234		break;
235	case 0x68:
236		sprintf((pbuf+strlen(pbuf)), "CANCEL ACKNOWLEDGE: ");
237		break;
238	case 0x6a:
239		sprintf((pbuf+strlen(pbuf)), "FACILITY ACKNOWLEDGE: ");
240		break;
241	case 0x6c:
242		sprintf((pbuf+strlen(pbuf)), "REGISTER ACKNOWLEDGE: ");
243		break;
244	case 0x6e:
245		sprintf((pbuf+strlen(pbuf)), "NOTIFY: ");
246		break;
247	case 0x70:
248		sprintf((pbuf+strlen(pbuf)), "CANCEL REJECT: ");
249		break;
250	case 0x72:
251		sprintf((pbuf+strlen(pbuf)), "FACILITY REJECT: ");
252		break;
253	case 0x74:
254		sprintf((pbuf+strlen(pbuf)), "REGISTER REJECT: ");
255		break;
256	case 0x75:
257		sprintf((pbuf+strlen(pbuf)), "STATUS ENQIRY: ");
258		break;
259	case 0x79:
260		sprintf((pbuf+strlen(pbuf)), "CONGESTION CONTROL: ");
261		break;
262	case 0x7b:
263		sprintf((pbuf+strlen(pbuf)), "INFORMATION: ");
264		break;
265	case 0x7d:
266		sprintf((pbuf+strlen(pbuf)), "STATUS: ");
267		break;
268	default:
269		sprintf((pbuf+strlen(pbuf)), "UNDEFINED, TYPE=0x%02x, ", buf[i]);
270		break;
271	}
272
273	/* other information elements */
274
275	i++;
276
277	for (; i < n;)
278	{
279		sprintf((pbuf+strlen(pbuf)), "\n     ");
280
281		if (buf[i] & 0x80)
282		{
283			/* single octett info element */
284
285			switch (buf[i] & 0x70)
286			{
287			case 0x00:	/* reserved */
288				sprintf((pbuf+strlen(pbuf)), "[reserved single octett info]");
289				break;
290
291			case 0x10:	/* shift */
292				oldcodeset = codeset;
293				codeset = buf[i] & 0x07;
294				if (buf[i] & 0x08)
295					codelock = 0;
296				else
297					codelock = 1;
298				sprintf((pbuf+strlen(pbuf)), "[shift: codeset=%d lock=%d]", codeset, codelock);
299				break;
300
301			case 0x20:	/* more data */
302				if (buf[i] & 0x01)
303					sprintf((pbuf+strlen(pbuf)), "[sending complete]");
304				else
305					sprintf((pbuf+strlen(pbuf)), "[more data]");
306				break;
307
308			case 0x30:	/* congestion level */
309				sprintf((pbuf+strlen(pbuf)), "[congestion level=");
310				switch (buf[i] & 0x0f)
311				{
312				case 0x00:
313					sprintf((pbuf+strlen(pbuf)), "rx-ready]");
314					break;
315				case 0x0f:
316					sprintf((pbuf+strlen(pbuf)), "rx-not-ready]");
317					break;
318				default:
319					sprintf((pbuf+strlen(pbuf)), "reserved (0x%02x)]", buf[i] & 0x0f);
320					break;
321				}
322				break;
323
324			case 0x50:	/* repeat ind */
325				sprintf((pbuf+strlen(pbuf)), "[repeat indicator]");
326				break;
327
328			default:
329				sprintf((pbuf+strlen(pbuf)), "[UNKNOWN SINGLE OCTET ELEMENT 0x%02x]", buf[i]);
330				break;
331			}
332
333			i++;	/* next */
334
335		}
336		else
337		{
338			/* variable length info element */
339
340			if (codeset == 0)
341			{
342				switch (buf[i])
343				{
344				case 0x00:
345					sprintf((pbuf+strlen(pbuf)), "[segmented message: ");
346					break;
347				case 0x04:
348					sprintf((pbuf+strlen(pbuf)), "[bearer capability: ");
349					i += p_q931bc(pbuf, &buf[i]);
350					goto next;
351					break;
352				case 0x08:
353					sprintf((pbuf+strlen(pbuf)), "[cause: ");
354					i += p_q931cause(pbuf, &buf[i]);
355					goto next;
356					break;
357				case 0x0c:
358					sprintf((pbuf+strlen(pbuf)), "[connected address (old): ");
359					break;
360				case 0x0d:
361					sprintf((pbuf+strlen(pbuf)), "[extended facility (Q.932: )");
362					break;
363				case 0x10:
364					sprintf((pbuf+strlen(pbuf)), "[call identity: ");
365					break;
366				case 0x14:
367					sprintf((pbuf+strlen(pbuf)), "[call state: ");
368					i++;
369					len = buf[i];
370					i++;
371					sprintf((pbuf+strlen(pbuf)), "Std=");
372					switch ((buf[i] & 0x60) >> 5)
373					{
374					case 0:
375						sprintf((pbuf+strlen(pbuf)), "CCITT");
376						break;
377					case 1:
378						sprintf((pbuf+strlen(pbuf)), "ISO/IEC");
379						break;
380					case 2:
381						sprintf((pbuf+strlen(pbuf)), "National");
382						break;
383					case 3:
384						sprintf((pbuf+strlen(pbuf)), "Special");
385						break;
386					}
387					sprintf((pbuf+strlen(pbuf)), ", State=");
388
389					switch ((buf[i] & 0x3f))
390					{
391					case 0:
392						sprintf((pbuf+strlen(pbuf)), "Null");
393						break;
394					case 1:
395						sprintf((pbuf+strlen(pbuf)), "Call initiated");
396						break;
397					case 2:
398						sprintf((pbuf+strlen(pbuf)), "Overlap sending");
399						break;
400					case 3:
401						sprintf((pbuf+strlen(pbuf)), "Outgoing call proceeding");
402						break;
403					case 4:
404						sprintf((pbuf+strlen(pbuf)), "Call delivered");
405						break;
406					case 6:
407						sprintf((pbuf+strlen(pbuf)), "Call present");
408						break;
409					case 7:
410						sprintf((pbuf+strlen(pbuf)), "Call received");
411						break;
412					case 8:
413						sprintf((pbuf+strlen(pbuf)), "Connect request");
414						break;
415					case 9:
416						sprintf((pbuf+strlen(pbuf)), "Incoming call proceeding");
417						break;
418					case 10:
419						sprintf((pbuf+strlen(pbuf)), "Active");
420						break;
421					case 11:
422						sprintf((pbuf+strlen(pbuf)), "Disconnect request");
423						break;
424					case 12:
425						sprintf((pbuf+strlen(pbuf)), "Disconnect indication");
426						break;
427					case 15:
428						sprintf((pbuf+strlen(pbuf)), "Suspend request");
429						break;
430					case 17:
431						sprintf((pbuf+strlen(pbuf)), "Resume request");
432						break;
433					case 19:
434						sprintf((pbuf+strlen(pbuf)), "Release request");
435						break;
436					case 22:
437						sprintf((pbuf+strlen(pbuf)), "Call abort");
438						break;
439					case 25:
440						sprintf((pbuf+strlen(pbuf)), "Overlap receiving");
441						break;
442					case 0x3d:
443						sprintf((pbuf+strlen(pbuf)), "Restart request");
444						break;
445					case 0x3e:
446						sprintf((pbuf+strlen(pbuf)), "Restart");
447						break;
448					default:
449						sprintf((pbuf+strlen(pbuf)), "ERROR: undefined/reserved");
450						break;
451					}
452					sprintf((pbuf+strlen(pbuf)), "]");
453					i++;
454					goto next;
455					break;
456				case 0x18:
457					sprintf((pbuf+strlen(pbuf)), "[channel id: channel=");
458					i++;
459					len = buf[i];
460					i++;
461					switch (buf[i] & 0x03)
462					{
463					case 0:
464						sprintf((pbuf+strlen(pbuf)), "no channel");
465						break;
466					case 1:
467						sprintf((pbuf+strlen(pbuf)), "B-1");
468						break;
469					case 2:
470						sprintf((pbuf+strlen(pbuf)), "B-2");
471						break;
472					case 3:
473						sprintf((pbuf+strlen(pbuf)), "any channel");
474						break;
475					}
476					if (buf[i] & 0x08)
477						sprintf((pbuf+strlen(pbuf)), " (exclusive)]");
478					else
479						sprintf((pbuf+strlen(pbuf)), " (preferred)]");
480					i++;
481					goto next;
482					break;
483				case 0x19:
484					sprintf((pbuf+strlen(pbuf)), "[data link connection id (Q.933): ");
485					break;
486				case 0x1c:
487					i += q932_facility(pbuf, &buf[i]);
488					goto next;
489					break;
490				case 0x1e:
491					sprintf((pbuf+strlen(pbuf)), "[progress ind: ");
492					i++;
493					len = buf[i];
494					i++;
495					sprintf((pbuf+strlen(pbuf)), "Std=");
496					switch ((buf[i] & 0x60) >> 5)
497					{
498					case 0:
499						sprintf((pbuf+strlen(pbuf)), "CCITT");
500						break;
501					case 1:
502						sprintf((pbuf+strlen(pbuf)), "ISO/IEC");
503						break;
504					case 2:
505						sprintf((pbuf+strlen(pbuf)), "National");
506						break;
507					case 3:
508						sprintf((pbuf+strlen(pbuf)), "Local");
509						break;
510					}
511					sprintf((pbuf+strlen(pbuf)), ", Loc=");
512
513					switch ((buf[i] & 0x0f))
514					{
515					case 0:
516						sprintf((pbuf+strlen(pbuf)), "User");
517						break;
518					case 1:
519						sprintf((pbuf+strlen(pbuf)), "Private network serving local user");
520						break;
521					case 2:
522						sprintf((pbuf+strlen(pbuf)), "Public network serving local user");
523						break;
524					case 3:
525						sprintf((pbuf+strlen(pbuf)), "Transit network");
526						break;
527					case 4:
528						sprintf((pbuf+strlen(pbuf)), "Public network serving remote user");
529						break;
530					case 5:
531						sprintf((pbuf+strlen(pbuf)), "Private network serving remote user");
532						break;
533					case 6:
534						sprintf((pbuf+strlen(pbuf)), "Network beyond interworking point");
535						break;
536					default:
537						sprintf((pbuf+strlen(pbuf)), "ERROR: undefined/reserved");
538						break;
539					}
540
541					i++;
542
543					sprintf((pbuf+strlen(pbuf)), "\n          Description: ");
544
545					switch ((buf[i] & 0x7f))
546					{
547					case 1:
548						sprintf((pbuf+strlen(pbuf)), "Call is not end-to-end ISDN");
549						break;
550					case 2:
551						sprintf((pbuf+strlen(pbuf)), "Destination address is non-ISDN");
552						break;
553					case 3:
554						sprintf((pbuf+strlen(pbuf)), "Origination address is non-ISDN");
555						break;
556					case 4:
557						sprintf((pbuf+strlen(pbuf)), "Call has returned to the ISDN");
558						break;
559					case 5:
560						sprintf((pbuf+strlen(pbuf)), "Interworking occurred, Service change");
561						break;
562					case 8:
563						sprintf((pbuf+strlen(pbuf)), "In-band info or appropriate pattern now available");
564						break;
565					default:
566						sprintf((pbuf+strlen(pbuf)), "ERROR: undefined/reserved");
567						break;
568					}
569					sprintf((pbuf+strlen(pbuf)), "]");
570					i++;
571					goto next;
572					break;
573				case 0x20:
574					sprintf((pbuf+strlen(pbuf)), "[network specific facilities: ");
575					break;
576				case 0x24:
577					sprintf((pbuf+strlen(pbuf)), "[terminal capabilities: ");
578					break;
579				case 0x27:
580					sprintf((pbuf+strlen(pbuf)), "[notification indicator: ");
581					i += p_q931notification(pbuf, &buf[i]);
582					goto next;
583					break;
584				case 0x28:
585					sprintf((pbuf+strlen(pbuf)), "[display: ");
586					i++;
587					len = buf[i];
588					i++;
589					for (j = 0; j < len; j++)
590					{
591						sprintf((pbuf+strlen(pbuf)),"%c", buf[j+i]);
592					}
593					sprintf((pbuf+strlen(pbuf)),"]");
594					i += j;
595					goto next;
596					break;
597				case 0x29:
598					sprintf((pbuf+strlen(pbuf)), "[date/time: ");
599					i++;
600					len = buf[i];
601					i++;
602					j = 0;
603					sprintf((pbuf+strlen(pbuf)),"%.2d.%.2d.%.2d",
604						buf[i+2], buf[i+1], buf[i]);
605					j+=3;
606					if (j < len)
607					{
608						sprintf((pbuf+strlen(pbuf))," %.2d", buf[i+3]);
609						j++;
610					}
611					if (j < len)
612					{
613						sprintf((pbuf+strlen(pbuf)),":%.2d", buf[i+4]);
614						j++;
615					}
616					if (j < len)
617					{
618						sprintf((pbuf+strlen(pbuf)),":%.2d", buf[i+5]);
619						j++;
620					}
621					sprintf((pbuf+strlen(pbuf)),"]");
622					i += len;
623					goto next;
624					break;
625				case 0x2c:
626					sprintf((pbuf+strlen(pbuf)), "[keypad: ");
627					break;
628				case 0x30:
629					sprintf((pbuf+strlen(pbuf)), "[keypad echo: ");
630					break;
631				case 0x32:
632					sprintf((pbuf+strlen(pbuf)), "[information req (Q.932): ");
633					break;
634				case 0x34:
635					sprintf((pbuf+strlen(pbuf)), "[signal: ");
636					break;
637				case 0x36:
638					sprintf((pbuf+strlen(pbuf)), "[switchhook: ");
639					break;
640				case 0x38:
641					sprintf((pbuf+strlen(pbuf)), "[feature activation (Q.932): ");
642					break;
643				case 0x39:
644					sprintf((pbuf+strlen(pbuf)), "[feature ind (Q.932): ");
645					break;
646				case 0x3a:
647					sprintf((pbuf+strlen(pbuf)), "[service profile id (Q.932): ");
648					break;
649				case 0x3b:
650					sprintf((pbuf+strlen(pbuf)), "[endpoint id (Q.932): ");
651					break;
652				case 0x40:
653					sprintf((pbuf+strlen(pbuf)), "[information rate: ");
654					break;
655				case 0x41:
656					sprintf((pbuf+strlen(pbuf)), "[precedence level (Q.955): ");
657					break;
658				case 0x42:
659					sprintf((pbuf+strlen(pbuf)), "[end-to-end transit delay: ");
660					break;
661				case 0x43:
662					sprintf((pbuf+strlen(pbuf)), "[transit delay detection and indication: ");
663					break;
664				case 0x44:
665					sprintf((pbuf+strlen(pbuf)), "[packet layer binary parameters: ");
666					break;
667				case 0x45:
668					sprintf((pbuf+strlen(pbuf)), "[packet layer window size: ");
669					break;
670				case 0x46:
671					sprintf((pbuf+strlen(pbuf)), "[packet size: ");
672					break;
673				case 0x47:
674					sprintf((pbuf+strlen(pbuf)), "[closed user group: ");
675					break;
676				case 0x48:
677					sprintf((pbuf+strlen(pbuf)), "[link layer core parameters (Q.933): ");
678					break;
679				case 0x49:
680					sprintf((pbuf+strlen(pbuf)), "[link layer protocol parameters (Q.933): ");
681					break;
682				case 0x4a:
683					sprintf((pbuf+strlen(pbuf)), "[reverse charging information: ");
684					break;
685				case 0x4c:
686					sprintf((pbuf+strlen(pbuf)), "[connected number (Q.951): ");
687					i += p_q931address(pbuf, &buf[i]);
688					goto next;
689					break;
690
691					break;
692				case 0x4d:
693					sprintf((pbuf+strlen(pbuf)), "[connected subaddress (Q.951): ");
694					break;
695				case 0x50:
696					sprintf((pbuf+strlen(pbuf)), "[X.213 priority (Q.933): ");
697					break;
698				case 0x51:
699					sprintf((pbuf+strlen(pbuf)), "[report type (Q.933): ");
700					break;
701				case 0x53:
702					sprintf((pbuf+strlen(pbuf)), "[link integrity verification (Q.933): ");
703					break;
704				case 0x57:
705					sprintf((pbuf+strlen(pbuf)), "[PVC status (Q.933): ");
706					break;
707				case 0x6c:
708					sprintf((pbuf+strlen(pbuf)), "[calling party number: ");
709					i += p_q931address(pbuf, &buf[i]);
710					goto next;
711					break;
712				case 0x6d:
713					sprintf((pbuf+strlen(pbuf)), "[calling party subaddress: ");
714					break;
715				case 0x70:
716					sprintf((pbuf+strlen(pbuf)), "[called party number: ");
717					i += p_q931address(pbuf, &buf[i]);
718					goto next;
719					break;
720				case 0x71:
721					sprintf((pbuf+strlen(pbuf)), "[called party subaddress: ");
722					break;
723				case 0x74:
724					sprintf((pbuf+strlen(pbuf)), "[redirecting number: ");
725					i += p_q931redir(pbuf, &buf[i]);
726					goto next;
727					break;
728				case 0x76:
729					sprintf((pbuf+strlen(pbuf)), "[redirection number: ");
730					i += p_q931redir(pbuf, &buf[i]);
731					goto next;
732					break;
733				case 0x78:
734					sprintf((pbuf+strlen(pbuf)), "[transit network selection: ");
735					break;
736				case 0x79:
737					sprintf((pbuf+strlen(pbuf)), "[restart indicator: ");
738					break;
739				case 0x7c:
740					sprintf((pbuf+strlen(pbuf)), "[low layer compatibility: ");
741					break;
742				case 0x7d:
743					sprintf((pbuf+strlen(pbuf)), "[high layer compatibility:");
744					i += p_q931high_compat(pbuf, &buf[i]);
745					goto next;
746					break;
747				case 0x7e:
748					sprintf((pbuf+strlen(pbuf)), "[user-user: ");
749					i += p_q931user_user(pbuf, &buf[i]);
750					goto next;
751					break;
752				case 0x7f:
753					sprintf((pbuf+strlen(pbuf)), "[escape for extension: ");
754					break;
755				default:
756					sprintf((pbuf+strlen(pbuf)), "[UNKNOWN INFO-ELEMENT-ID=0x%02x: ", buf[i]);
757					break;
758				}
759			}
760			else
761			{
762				sprintf((pbuf+strlen(pbuf)), "[UNKNOWN CODESET=%d, IE=0x%02x: ", codeset, buf[i]);
763			}
764
765			i++;	/* index -> length */
766
767			len = buf[i];
768
769			sprintf((pbuf+strlen(pbuf)), "LEN=0x%02x, DATA=", len);
770
771			i++;	/* index -> 1st param */
772
773			for (j = 0; j < len; j++)
774			{
775				sprintf((pbuf+strlen(pbuf)),"0x%02x ", buf[j+i]);
776			}
777
778			sprintf((pbuf+strlen(pbuf)),"]");
779
780			i += len;
781
782next:
783
784			if (!codelock && (codeset != oldcodeset))
785				codeset = oldcodeset;
786		}
787	}
788	sprintf((pbuf+strlen(pbuf)),"\n");
789}
790
791/* EOF */
792
793