1 /* $Id: q931.c,v 1.12.2.3 2004/01/13 14:31:26 keil Exp $
2 *
3 * code to decode ITU Q.931 call control messages
4 *
5 * Author Jan den Ouden
6 * Copyright by Jan den Ouden
7 *
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
10 *
11 * Changelog:
12 *
13 * Pauline Middelink general improvements
14 * Beat Doebeli cause texts, display information element
15 * Karsten Keil cause texts, display information element for 1TR6
16 *
17 */
18
19
20 #include "hisax.h"
21 #include "l3_1tr6.h"
22
23 void
iecpy(u_char * dest,u_char * iestart,int ieoffset)24 iecpy(u_char *dest, u_char *iestart, int ieoffset)
25 {
26 u_char *p;
27 int l;
28
29 p = iestart + ieoffset + 2;
30 l = iestart[1] - ieoffset;
31 while (l--)
32 *dest++ = *p++;
33 *dest++ = '\0';
34 }
35
36 /*
37 * According to Table 4-2/Q.931
38 */
39 static
40 struct MessageType {
41 u_char nr;
42 char *descr;
43 } mtlist[] = {
44
45 {
46 0x1, "ALERTING"
47 },
48 {
49 0x2, "CALL PROCEEDING"
50 },
51 {
52 0x7, "CONNECT"
53 },
54 {
55 0xf, "CONNECT ACKNOWLEDGE"
56 },
57 {
58 0x3, "PROGRESS"
59 },
60 {
61 0x5, "SETUP"
62 },
63 {
64 0xd, "SETUP ACKNOWLEDGE"
65 },
66 {
67 0x24, "HOLD"
68 },
69 {
70 0x28, "HOLD ACKNOWLEDGE"
71 },
72 {
73 0x30, "HOLD REJECT"
74 },
75 {
76 0x31, "RETRIEVE"
77 },
78 {
79 0x33, "RETRIEVE ACKNOWLEDGE"
80 },
81 {
82 0x37, "RETRIEVE REJECT"
83 },
84 {
85 0x26, "RESUME"
86 },
87 {
88 0x2e, "RESUME ACKNOWLEDGE"
89 },
90 {
91 0x22, "RESUME REJECT"
92 },
93 {
94 0x25, "SUSPEND"
95 },
96 {
97 0x2d, "SUSPEND ACKNOWLEDGE"
98 },
99 {
100 0x21, "SUSPEND REJECT"
101 },
102 {
103 0x20, "USER INFORMATION"
104 },
105 {
106 0x45, "DISCONNECT"
107 },
108 {
109 0x4d, "RELEASE"
110 },
111 {
112 0x5a, "RELEASE COMPLETE"
113 },
114 {
115 0x46, "RESTART"
116 },
117 {
118 0x4e, "RESTART ACKNOWLEDGE"
119 },
120 {
121 0x60, "SEGMENT"
122 },
123 {
124 0x79, "CONGESTION CONTROL"
125 },
126 {
127 0x7b, "INFORMATION"
128 },
129 {
130 0x62, "FACILITY"
131 },
132 {
133 0x6e, "NOTIFY"
134 },
135 {
136 0x7d, "STATUS"
137 },
138 {
139 0x75, "STATUS ENQUIRY"
140 }
141 };
142
143 #define MTSIZE ARRAY_SIZE(mtlist)
144
145 static
146 struct MessageType mt_n0[] =
147 {
148 {MT_N0_REG_IND, "REGister INDication"},
149 {MT_N0_CANC_IND, "CANCel INDication"},
150 {MT_N0_FAC_STA, "FACility STAtus"},
151 {MT_N0_STA_ACK, "STAtus ACKnowledge"},
152 {MT_N0_STA_REJ, "STAtus REJect"},
153 {MT_N0_FAC_INF, "FACility INFormation"},
154 {MT_N0_INF_ACK, "INFormation ACKnowledge"},
155 {MT_N0_INF_REJ, "INFormation REJect"},
156 {MT_N0_CLOSE, "CLOSE"},
157 {MT_N0_CLO_ACK, "CLOse ACKnowledge"}
158 };
159
160 #define MT_N0_LEN ARRAY_SIZE(mt_n0)
161
162 static
163 struct MessageType mt_n1[] =
164 {
165 {MT_N1_ESC, "ESCape"},
166 {MT_N1_ALERT, "ALERT"},
167 {MT_N1_CALL_SENT, "CALL SENT"},
168 {MT_N1_CONN, "CONNect"},
169 {MT_N1_CONN_ACK, "CONNect ACKnowledge"},
170 {MT_N1_SETUP, "SETUP"},
171 {MT_N1_SETUP_ACK, "SETUP ACKnowledge"},
172 {MT_N1_RES, "RESume"},
173 {MT_N1_RES_ACK, "RESume ACKnowledge"},
174 {MT_N1_RES_REJ, "RESume REJect"},
175 {MT_N1_SUSP, "SUSPend"},
176 {MT_N1_SUSP_ACK, "SUSPend ACKnowledge"},
177 {MT_N1_SUSP_REJ, "SUSPend REJect"},
178 {MT_N1_USER_INFO, "USER INFO"},
179 {MT_N1_DET, "DETach"},
180 {MT_N1_DISC, "DISConnect"},
181 {MT_N1_REL, "RELease"},
182 {MT_N1_REL_ACK, "RELease ACKnowledge"},
183 {MT_N1_CANC_ACK, "CANCel ACKnowledge"},
184 {MT_N1_CANC_REJ, "CANCel REJect"},
185 {MT_N1_CON_CON, "CONgestion CONtrol"},
186 {MT_N1_FAC, "FACility"},
187 {MT_N1_FAC_ACK, "FACility ACKnowledge"},
188 {MT_N1_FAC_CAN, "FACility CANcel"},
189 {MT_N1_FAC_REG, "FACility REGister"},
190 {MT_N1_FAC_REJ, "FACility REJect"},
191 {MT_N1_INFO, "INFOrmation"},
192 {MT_N1_REG_ACK, "REGister ACKnowledge"},
193 {MT_N1_REG_REJ, "REGister REJect"},
194 {MT_N1_STAT, "STATus"}
195 };
196
197 #define MT_N1_LEN ARRAY_SIZE(mt_n1)
198
199
200 static int
prbits(char * dest,u_char b,int start,int len)201 prbits(char *dest, u_char b, int start, int len)
202 {
203 char *dp = dest;
204
205 b = b << (8 - start);
206 while (len--) {
207 if (b & 0x80)
208 *dp++ = '1';
209 else
210 *dp++ = '0';
211 b = b << 1;
212 }
213 return (dp - dest);
214 }
215
216 static
217 u_char *
skipext(u_char * p)218 skipext(u_char *p)
219 {
220 while (!(*p++ & 0x80));
221 return (p);
222 }
223
224 /*
225 * Cause Values According to Q.850
226 * edescr: English description
227 * ddescr: German description used by Swissnet II (Swiss Telecom
228 * not yet written...
229 */
230
231 static
232 struct CauseValue {
233 u_char nr;
234 char *edescr;
235 char *ddescr;
236 } cvlist[] = {
237
238 {
239 0x01, "Unallocated (unassigned) number", "Nummer nicht zugeteilt"
240 },
241 {
242 0x02, "No route to specified transit network", ""
243 },
244 {
245 0x03, "No route to destination", ""
246 },
247 {
248 0x04, "Send special information tone", ""
249 },
250 {
251 0x05, "Misdialled trunk prefix", ""
252 },
253 {
254 0x06, "Channel unacceptable", "Kanal nicht akzeptierbar"
255 },
256 {
257 0x07, "Channel awarded and being delivered in an established channel", ""
258 },
259 {
260 0x08, "Preemption", ""
261 },
262 {
263 0x09, "Preemption - circuit reserved for reuse", ""
264 },
265 {
266 0x10, "Normal call clearing", "Normale Ausloesung"
267 },
268 {
269 0x11, "User busy", "TNB besetzt"
270 },
271 {
272 0x12, "No user responding", ""
273 },
274 {
275 0x13, "No answer from user (user alerted)", ""
276 },
277 {
278 0x14, "Subscriber absent", ""
279 },
280 {
281 0x15, "Call rejected", ""
282 },
283 {
284 0x16, "Number changed", ""
285 },
286 {
287 0x1a, "non-selected user clearing", ""
288 },
289 {
290 0x1b, "Destination out of order", ""
291 },
292 {
293 0x1c, "Invalid number format (address incomplete)", ""
294 },
295 {
296 0x1d, "Facility rejected", ""
297 },
298 {
299 0x1e, "Response to Status enquiry", ""
300 },
301 {
302 0x1f, "Normal, unspecified", ""
303 },
304 {
305 0x22, "No circuit/channel available", ""
306 },
307 {
308 0x26, "Network out of order", ""
309 },
310 {
311 0x27, "Permanent frame mode connection out-of-service", ""
312 },
313 {
314 0x28, "Permanent frame mode connection operational", ""
315 },
316 {
317 0x29, "Temporary failure", ""
318 },
319 {
320 0x2a, "Switching equipment congestion", ""
321 },
322 {
323 0x2b, "Access information discarded", ""
324 },
325 {
326 0x2c, "Requested circuit/channel not available", ""
327 },
328 {
329 0x2e, "Precedence call blocked", ""
330 },
331 {
332 0x2f, "Resource unavailable, unspecified", ""
333 },
334 {
335 0x31, "Quality of service unavailable", ""
336 },
337 {
338 0x32, "Requested facility not subscribed", ""
339 },
340 {
341 0x35, "Outgoing calls barred within CUG", ""
342 },
343 {
344 0x37, "Incoming calls barred within CUG", ""
345 },
346 {
347 0x39, "Bearer capability not authorized", ""
348 },
349 {
350 0x3a, "Bearer capability not presently available", ""
351 },
352 {
353 0x3e, "Inconsistency in designated outgoing access information and subscriber class ", " "
354 },
355 {
356 0x3f, "Service or option not available, unspecified", ""
357 },
358 {
359 0x41, "Bearer capability not implemented", ""
360 },
361 {
362 0x42, "Channel type not implemented", ""
363 },
364 {
365 0x43, "Requested facility not implemented", ""
366 },
367 {
368 0x44, "Only restricted digital information bearer capability is available", ""
369 },
370 {
371 0x4f, "Service or option not implemented", ""
372 },
373 {
374 0x51, "Invalid call reference value", ""
375 },
376 {
377 0x52, "Identified channel does not exist", ""
378 },
379 {
380 0x53, "A suspended call exists, but this call identity does not", ""
381 },
382 {
383 0x54, "Call identity in use", ""
384 },
385 {
386 0x55, "No call suspended", ""
387 },
388 {
389 0x56, "Call having the requested call identity has been cleared", ""
390 },
391 {
392 0x57, "User not member of CUG", ""
393 },
394 {
395 0x58, "Incompatible destination", ""
396 },
397 {
398 0x5a, "Non-existent CUG", ""
399 },
400 {
401 0x5b, "Invalid transit network selection", ""
402 },
403 {
404 0x5f, "Invalid message, unspecified", ""
405 },
406 {
407 0x60, "Mandatory information element is missing", ""
408 },
409 {
410 0x61, "Message type non-existent or not implemented", ""
411 },
412 {
413 0x62, "Message not compatible with call state or message type non-existent or not implemented ", " "
414 },
415 {
416 0x63, "Information element/parameter non-existent or not implemented", ""
417 },
418 {
419 0x64, "Invalid information element contents", ""
420 },
421 {
422 0x65, "Message not compatible with call state", ""
423 },
424 {
425 0x66, "Recovery on timer expiry", ""
426 },
427 {
428 0x67, "Parameter non-existent or not implemented - passed on", ""
429 },
430 {
431 0x6e, "Message with unrecognized parameter discarded", ""
432 },
433 {
434 0x6f, "Protocol error, unspecified", ""
435 },
436 {
437 0x7f, "Interworking, unspecified", ""
438 },
439 };
440
441 #define CVSIZE ARRAY_SIZE(cvlist)
442
443 static
444 int
prcause(char * dest,u_char * p)445 prcause(char *dest, u_char *p)
446 {
447 u_char *end;
448 char *dp = dest;
449 int i, cause;
450
451 end = p + p[1] + 1;
452 p += 2;
453 dp += sprintf(dp, " coding ");
454 dp += prbits(dp, *p, 7, 2);
455 dp += sprintf(dp, " location ");
456 dp += prbits(dp, *p, 4, 4);
457 *dp++ = '\n';
458 p = skipext(p);
459
460 cause = 0x7f & *p++;
461
462 /* locate cause value */
463 for (i = 0; i < CVSIZE; i++)
464 if (cvlist[i].nr == cause)
465 break;
466
467 /* display cause value if it exists */
468 if (i == CVSIZE)
469 dp += sprintf(dp, "Unknown cause type %x!\n", cause);
470 else
471 dp += sprintf(dp, " cause value %x : %s \n", cause, cvlist[i].edescr);
472
473 while (!0) {
474 if (p > end)
475 break;
476 dp += sprintf(dp, " diag attribute %d ", *p++ & 0x7f);
477 dp += sprintf(dp, " rej %d ", *p & 0x7f);
478 if (*p & 0x80) {
479 *dp++ = '\n';
480 break;
481 } else
482 dp += sprintf(dp, " av %d\n", (*++p) & 0x7f);
483 }
484 return (dp - dest);
485
486 }
487
488 static
489 struct MessageType cause_1tr6[] =
490 {
491 {CAUSE_InvCRef, "Invalid Call Reference"},
492 {CAUSE_BearerNotImpl, "Bearer Service Not Implemented"},
493 {CAUSE_CIDunknown, "Caller Identity unknown"},
494 {CAUSE_CIDinUse, "Caller Identity in Use"},
495 {CAUSE_NoChans, "No Channels available"},
496 {CAUSE_FacNotImpl, "Facility Not Implemented"},
497 {CAUSE_FacNotSubscr, "Facility Not Subscribed"},
498 {CAUSE_OutgoingBarred, "Outgoing calls barred"},
499 {CAUSE_UserAccessBusy, "User Access Busy"},
500 {CAUSE_NegativeGBG, "Negative GBG"},
501 {CAUSE_UnknownGBG, "Unknown GBG"},
502 {CAUSE_NoSPVknown, "No SPV known"},
503 {CAUSE_DestNotObtain, "Destination not obtainable"},
504 {CAUSE_NumberChanged, "Number changed"},
505 {CAUSE_OutOfOrder, "Out Of Order"},
506 {CAUSE_NoUserResponse, "No User Response"},
507 {CAUSE_UserBusy, "User Busy"},
508 {CAUSE_IncomingBarred, "Incoming Barred"},
509 {CAUSE_CallRejected, "Call Rejected"},
510 {CAUSE_NetworkCongestion, "Network Congestion"},
511 {CAUSE_RemoteUser, "Remote User initiated"},
512 {CAUSE_LocalProcErr, "Local Procedure Error"},
513 {CAUSE_RemoteProcErr, "Remote Procedure Error"},
514 {CAUSE_RemoteUserSuspend, "Remote User Suspend"},
515 {CAUSE_RemoteUserResumed, "Remote User Resumed"},
516 {CAUSE_UserInfoDiscarded, "User Info Discarded"}
517 };
518
519 static int cause_1tr6_len = ARRAY_SIZE(cause_1tr6);
520
521 static int
prcause_1tr6(char * dest,u_char * p)522 prcause_1tr6(char *dest, u_char *p)
523 {
524 char *dp = dest;
525 int i, cause;
526
527 p++;
528 if (0 == *p) {
529 dp += sprintf(dp, " OK (cause length=0)\n");
530 return (dp - dest);
531 } else if (*p > 1) {
532 dp += sprintf(dp, " coding ");
533 dp += prbits(dp, p[2], 7, 2);
534 dp += sprintf(dp, " location ");
535 dp += prbits(dp, p[2], 4, 4);
536 *dp++ = '\n';
537 }
538 p++;
539 cause = 0x7f & *p;
540
541 /* locate cause value */
542 for (i = 0; i < cause_1tr6_len; i++)
543 if (cause_1tr6[i].nr == cause)
544 break;
545
546 /* display cause value if it exists */
547 if (i == cause_1tr6_len)
548 dp += sprintf(dp, "Unknown cause type %x!\n", cause);
549 else
550 dp += sprintf(dp, " cause value %x : %s \n", cause, cause_1tr6[i].descr);
551
552 return (dp - dest);
553
554 }
555
556 static int
prchident(char * dest,u_char * p)557 prchident(char *dest, u_char *p)
558 {
559 char *dp = dest;
560
561 p += 2;
562 dp += sprintf(dp, " octet 3 ");
563 dp += prbits(dp, *p, 8, 8);
564 *dp++ = '\n';
565 return (dp - dest);
566 }
567
568 static int
prcalled(char * dest,u_char * p)569 prcalled(char *dest, u_char *p)
570 {
571 int l;
572 char *dp = dest;
573
574 p++;
575 l = *p++ - 1;
576 dp += sprintf(dp, " octet 3 ");
577 dp += prbits(dp, *p++, 8, 8);
578 *dp++ = '\n';
579 dp += sprintf(dp, " number digits ");
580 while (l--)
581 *dp++ = *p++;
582 *dp++ = '\n';
583 return (dp - dest);
584 }
585 static int
prcalling(char * dest,u_char * p)586 prcalling(char *dest, u_char *p)
587 {
588 int l;
589 char *dp = dest;
590
591 p++;
592 l = *p++ - 1;
593 dp += sprintf(dp, " octet 3 ");
594 dp += prbits(dp, *p, 8, 8);
595 *dp++ = '\n';
596 if (!(*p & 0x80)) {
597 dp += sprintf(dp, " octet 3a ");
598 dp += prbits(dp, *++p, 8, 8);
599 *dp++ = '\n';
600 l--;
601 };
602 p++;
603
604 dp += sprintf(dp, " number digits ");
605 while (l--)
606 *dp++ = *p++;
607 *dp++ = '\n';
608 return (dp - dest);
609 }
610
611 static
612 int
prbearer(char * dest,u_char * p)613 prbearer(char *dest, u_char *p)
614 {
615 char *dp = dest, ch;
616
617 p += 2;
618 dp += sprintf(dp, " octet 3 ");
619 dp += prbits(dp, *p++, 8, 8);
620 *dp++ = '\n';
621 dp += sprintf(dp, " octet 4 ");
622 dp += prbits(dp, *p, 8, 8);
623 *dp++ = '\n';
624 if ((*p++ & 0x1f) == 0x18) {
625 dp += sprintf(dp, " octet 4.1 ");
626 dp += prbits(dp, *p++, 8, 8);
627 *dp++ = '\n';
628 }
629 /* check for user information layer 1 */
630 if ((*p & 0x60) == 0x20) {
631 ch = ' ';
632 do {
633 dp += sprintf(dp, " octet 5%c ", ch);
634 dp += prbits(dp, *p, 8, 8);
635 *dp++ = '\n';
636 if (ch == ' ')
637 ch = 'a';
638 else
639 ch++;
640 }
641 while (!(*p++ & 0x80));
642 }
643 /* check for user information layer 2 */
644 if ((*p & 0x60) == 0x40) {
645 dp += sprintf(dp, " octet 6 ");
646 dp += prbits(dp, *p++, 8, 8);
647 *dp++ = '\n';
648 }
649 /* check for user information layer 3 */
650 if ((*p & 0x60) == 0x60) {
651 dp += sprintf(dp, " octet 7 ");
652 dp += prbits(dp, *p++, 8, 8);
653 *dp++ = '\n';
654 }
655 return (dp - dest);
656 }
657
658
659 static
660 int
prbearer_ni1(char * dest,u_char * p)661 prbearer_ni1(char *dest, u_char *p)
662 {
663 char *dp = dest;
664 u_char len;
665
666 p++;
667 len = *p++;
668 dp += sprintf(dp, " octet 3 ");
669 dp += prbits(dp, *p, 8, 8);
670 switch (*p++) {
671 case 0x80:
672 dp += sprintf(dp, " Speech");
673 break;
674 case 0x88:
675 dp += sprintf(dp, " Unrestricted digital information");
676 break;
677 case 0x90:
678 dp += sprintf(dp, " 3.1 kHz audio");
679 break;
680 default:
681 dp += sprintf(dp, " Unknown information-transfer capability");
682 }
683 *dp++ = '\n';
684 dp += sprintf(dp, " octet 4 ");
685 dp += prbits(dp, *p, 8, 8);
686 switch (*p++) {
687 case 0x90:
688 dp += sprintf(dp, " 64 kbps, circuit mode");
689 break;
690 case 0xc0:
691 dp += sprintf(dp, " Packet mode");
692 break;
693 default:
694 dp += sprintf(dp, " Unknown transfer mode");
695 }
696 *dp++ = '\n';
697 if (len > 2) {
698 dp += sprintf(dp, " octet 5 ");
699 dp += prbits(dp, *p, 8, 8);
700 switch (*p++) {
701 case 0x21:
702 dp += sprintf(dp, " Rate adaption\n");
703 dp += sprintf(dp, " octet 5a ");
704 dp += prbits(dp, *p, 8, 8);
705 break;
706 case 0xa2:
707 dp += sprintf(dp, " u-law");
708 break;
709 default:
710 dp += sprintf(dp, " Unknown UI layer 1 protocol");
711 }
712 *dp++ = '\n';
713 }
714 return (dp - dest);
715 }
716
717 static int
general(char * dest,u_char * p)718 general(char *dest, u_char *p)
719 {
720 char *dp = dest;
721 char ch = ' ';
722 int l, octet = 3;
723
724 p++;
725 l = *p++;
726 /* Iterate over all octets in the information element */
727 while (l--) {
728 dp += sprintf(dp, " octet %d%c ", octet, ch);
729 dp += prbits(dp, *p++, 8, 8);
730 *dp++ = '\n';
731
732 /* last octet in group? */
733 if (*p & 0x80) {
734 octet++;
735 ch = ' ';
736 } else if (ch == ' ')
737 ch = 'a';
738 else
739 ch++;
740 }
741 return (dp - dest);
742 }
743
744 static int
general_ni1(char * dest,u_char * p)745 general_ni1(char *dest, u_char *p)
746 {
747 char *dp = dest;
748 char ch = ' ';
749 int l, octet = 3;
750
751 p++;
752 l = *p++;
753 /* Iterate over all octets in the information element */
754 while (l--) {
755 dp += sprintf(dp, " octet %d%c ", octet, ch);
756 dp += prbits(dp, *p, 8, 8);
757 *dp++ = '\n';
758
759 /* last octet in group? */
760 if (*p++ & 0x80) {
761 octet++;
762 ch = ' ';
763 } else if (ch == ' ')
764 ch = 'a';
765 else
766 ch++;
767 }
768 return (dp - dest);
769 }
770
771 static int
prcharge(char * dest,u_char * p)772 prcharge(char *dest, u_char *p)
773 {
774 char *dp = dest;
775 int l;
776
777 p++;
778 l = *p++ - 1;
779 dp += sprintf(dp, " GEA ");
780 dp += prbits(dp, *p++, 8, 8);
781 dp += sprintf(dp, " Anzahl: ");
782 /* Iterate over all octets in the * information element */
783 while (l--)
784 *dp++ = *p++;
785 *dp++ = '\n';
786 return (dp - dest);
787 }
788 static int
prtext(char * dest,u_char * p)789 prtext(char *dest, u_char *p)
790 {
791 char *dp = dest;
792 int l;
793
794 p++;
795 l = *p++;
796 dp += sprintf(dp, " ");
797 /* Iterate over all octets in the * information element */
798 while (l--)
799 *dp++ = *p++;
800 *dp++ = '\n';
801 return (dp - dest);
802 }
803
804 static int
prfeatureind(char * dest,u_char * p)805 prfeatureind(char *dest, u_char *p)
806 {
807 char *dp = dest;
808
809 p += 2; /* skip id, len */
810 dp += sprintf(dp, " octet 3 ");
811 dp += prbits(dp, *p, 8, 8);
812 *dp++ = '\n';
813 if (!(*p++ & 0x80)) {
814 dp += sprintf(dp, " octet 4 ");
815 dp += prbits(dp, *p++, 8, 8);
816 *dp++ = '\n';
817 }
818 dp += sprintf(dp, " Status: ");
819 switch (*p) {
820 case 0:
821 dp += sprintf(dp, "Idle");
822 break;
823 case 1:
824 dp += sprintf(dp, "Active");
825 break;
826 case 2:
827 dp += sprintf(dp, "Prompt");
828 break;
829 case 3:
830 dp += sprintf(dp, "Pending");
831 break;
832 default:
833 dp += sprintf(dp, "(Reserved)");
834 break;
835 }
836 *dp++ = '\n';
837 return (dp - dest);
838 }
839
840 static
841 struct DTag { /* Display tags */
842 u_char nr;
843 char *descr;
844 } dtaglist[] = {
845 { 0x82, "Continuation" },
846 { 0x83, "Called address" },
847 { 0x84, "Cause" },
848 { 0x85, "Progress indicator" },
849 { 0x86, "Notification indicator" },
850 { 0x87, "Prompt" },
851 { 0x88, "Accumlated digits" },
852 { 0x89, "Status" },
853 { 0x8a, "Inband" },
854 { 0x8b, "Calling address" },
855 { 0x8c, "Reason" },
856 { 0x8d, "Calling party name" },
857 { 0x8e, "Called party name" },
858 { 0x8f, "Original called name" },
859 { 0x90, "Redirecting name" },
860 { 0x91, "Connected name" },
861 { 0x92, "Originating restrictions" },
862 { 0x93, "Date & time of day" },
863 { 0x94, "Call Appearance ID" },
864 { 0x95, "Feature address" },
865 { 0x96, "Redirection name" },
866 { 0x9e, "Text" },
867 };
868 #define DTAGSIZE ARRAY_SIZE(dtaglist)
869
870 static int
disptext_ni1(char * dest,u_char * p)871 disptext_ni1(char *dest, u_char *p)
872 {
873 char *dp = dest;
874 int l, tag, len, i;
875
876 p++;
877 l = *p++ - 1;
878 if (*p++ != 0x80) {
879 dp += sprintf(dp, " Unknown display type\n");
880 return (dp - dest);
881 }
882 /* Iterate over all tag,length,text fields */
883 while (l > 0) {
884 tag = *p++;
885 len = *p++;
886 l -= len + 2;
887 /* Don't space or skip */
888 if ((tag == 0x80) || (tag == 0x81)) p++;
889 else {
890 for (i = 0; i < DTAGSIZE; i++)
891 if (tag == dtaglist[i].nr)
892 break;
893
894 /* When not found, give appropriate msg */
895 if (i != DTAGSIZE) {
896 dp += sprintf(dp, " %s: ", dtaglist[i].descr);
897 while (len--)
898 *dp++ = *p++;
899 } else {
900 dp += sprintf(dp, " (unknown display tag %2x): ", tag);
901 while (len--)
902 *dp++ = *p++;
903 }
904 dp += sprintf(dp, "\n");
905 }
906 }
907 return (dp - dest);
908 }
909 static int
display(char * dest,u_char * p)910 display(char *dest, u_char *p)
911 {
912 char *dp = dest;
913 char ch = ' ';
914 int l, octet = 3;
915
916 p++;
917 l = *p++;
918 /* Iterate over all octets in the * display-information element */
919 dp += sprintf(dp, " \"");
920 while (l--) {
921 dp += sprintf(dp, "%c", *p++);
922
923 /* last octet in group? */
924 if (*p & 0x80) {
925 octet++;
926 ch = ' ';
927 } else if (ch == ' ')
928 ch = 'a';
929
930 else
931 ch++;
932 }
933 *dp++ = '\"';
934 *dp++ = '\n';
935 return (dp - dest);
936 }
937
938 static int
prfacility(char * dest,u_char * p)939 prfacility(char *dest, u_char *p)
940 {
941 char *dp = dest;
942 int l, l2;
943
944 p++;
945 l = *p++;
946 dp += sprintf(dp, " octet 3 ");
947 dp += prbits(dp, *p++, 8, 8);
948 dp += sprintf(dp, "\n");
949 l -= 1;
950
951 while (l > 0) {
952 dp += sprintf(dp, " octet 4 ");
953 dp += prbits(dp, *p++, 8, 8);
954 dp += sprintf(dp, "\n");
955 dp += sprintf(dp, " octet 5 %d\n", l2 = *p++ & 0x7f);
956 l -= 2;
957 dp += sprintf(dp, " contents ");
958 while (l2--) {
959 dp += sprintf(dp, "%2x ", *p++);
960 l--;
961 }
962 dp += sprintf(dp, "\n");
963 }
964
965 return (dp - dest);
966 }
967
968 static
969 struct InformationElement {
970 u_char nr;
971 char *descr;
972 int (*f) (char *, u_char *);
973 } ielist[] = {
974
975 {
976 0x00, "Segmented message", general
977 },
978 {
979 0x04, "Bearer capability", prbearer
980 },
981 {
982 0x08, "Cause", prcause
983 },
984 {
985 0x10, "Call identity", general
986 },
987 {
988 0x14, "Call state", general
989 },
990 {
991 0x18, "Channel identification", prchident
992 },
993 {
994 0x1c, "Facility", prfacility
995 },
996 {
997 0x1e, "Progress indicator", general
998 },
999 {
1000 0x20, "Network-specific facilities", general
1001 },
1002 {
1003 0x27, "Notification indicator", general
1004 },
1005 {
1006 0x28, "Display", display
1007 },
1008 {
1009 0x29, "Date/Time", general
1010 },
1011 {
1012 0x2c, "Keypad facility", general
1013 },
1014 {
1015 0x34, "Signal", general
1016 },
1017 {
1018 0x40, "Information rate", general
1019 },
1020 {
1021 0x42, "End-to-end delay", general
1022 },
1023 {
1024 0x43, "Transit delay selection and indication", general
1025 },
1026 {
1027 0x44, "Packet layer binary parameters", general
1028 },
1029 {
1030 0x45, "Packet layer window size", general
1031 },
1032 {
1033 0x46, "Packet size", general
1034 },
1035 {
1036 0x47, "Closed user group", general
1037 },
1038 {
1039 0x4a, "Reverse charge indication", general
1040 },
1041 {
1042 0x6c, "Calling party number", prcalling
1043 },
1044 {
1045 0x6d, "Calling party subaddress", general
1046 },
1047 {
1048 0x70, "Called party number", prcalled
1049 },
1050 {
1051 0x71, "Called party subaddress", general
1052 },
1053 {
1054 0x74, "Redirecting number", general
1055 },
1056 {
1057 0x78, "Transit network selection", general
1058 },
1059 {
1060 0x79, "Restart indicator", general
1061 },
1062 {
1063 0x7c, "Low layer compatibility", general
1064 },
1065 {
1066 0x7d, "High layer compatibility", general
1067 },
1068 {
1069 0x7e, "User-user", general
1070 },
1071 {
1072 0x7f, "Escape for extension", general
1073 },
1074 };
1075
1076
1077 #define IESIZE ARRAY_SIZE(ielist)
1078
1079 static
1080 struct InformationElement ielist_ni1[] = {
1081 { 0x04, "Bearer Capability", prbearer_ni1 },
1082 { 0x08, "Cause", prcause },
1083 { 0x14, "Call State", general_ni1 },
1084 { 0x18, "Channel Identification", prchident },
1085 { 0x1e, "Progress Indicator", general_ni1 },
1086 { 0x27, "Notification Indicator", general_ni1 },
1087 { 0x2c, "Keypad Facility", prtext },
1088 { 0x32, "Information Request", general_ni1 },
1089 { 0x34, "Signal", general_ni1 },
1090 { 0x38, "Feature Activation", general_ni1 },
1091 { 0x39, "Feature Indication", prfeatureind },
1092 { 0x3a, "Service Profile Identification (SPID)", prtext },
1093 { 0x3b, "Endpoint Identifier", general_ni1 },
1094 { 0x6c, "Calling Party Number", prcalling },
1095 { 0x6d, "Calling Party Subaddress", general_ni1 },
1096 { 0x70, "Called Party Number", prcalled },
1097 { 0x71, "Called Party Subaddress", general_ni1 },
1098 { 0x74, "Redirecting Number", general_ni1 },
1099 { 0x78, "Transit Network Selection", general_ni1 },
1100 { 0x7c, "Low Layer Compatibility", general_ni1 },
1101 { 0x7d, "High Layer Compatibility", general_ni1 },
1102 };
1103
1104
1105 #define IESIZE_NI1 ARRAY_SIZE(ielist_ni1)
1106
1107 static
1108 struct InformationElement ielist_ni1_cs5[] = {
1109 { 0x1d, "Operator system access", general_ni1 },
1110 { 0x2a, "Display text", disptext_ni1 },
1111 };
1112
1113 #define IESIZE_NI1_CS5 ARRAY_SIZE(ielist_ni1_cs5)
1114
1115 static
1116 struct InformationElement ielist_ni1_cs6[] = {
1117 { 0x7b, "Call appearance", general_ni1 },
1118 };
1119
1120 #define IESIZE_NI1_CS6 ARRAY_SIZE(ielist_ni1_cs6)
1121
1122 static struct InformationElement we_0[] =
1123 {
1124 {WE0_cause, "Cause", prcause_1tr6},
1125 {WE0_connAddr, "Connecting Address", prcalled},
1126 {WE0_callID, "Call IDentity", general},
1127 {WE0_chanID, "Channel IDentity", general},
1128 {WE0_netSpecFac, "Network Specific Facility", general},
1129 {WE0_display, "Display", general},
1130 {WE0_keypad, "Keypad", general},
1131 {WE0_origAddr, "Origination Address", prcalled},
1132 {WE0_destAddr, "Destination Address", prcalled},
1133 {WE0_userInfo, "User Info", general}
1134 };
1135
1136 #define WE_0_LEN ARRAY_SIZE(we_0)
1137
1138 static struct InformationElement we_6[] =
1139 {
1140 {WE6_serviceInd, "Service Indicator", general},
1141 {WE6_chargingInfo, "Charging Information", prcharge},
1142 {WE6_date, "Date", prtext},
1143 {WE6_facSelect, "Facility Select", general},
1144 {WE6_facStatus, "Facility Status", general},
1145 {WE6_statusCalled, "Status Called", general},
1146 {WE6_addTransAttr, "Additional Transmission Attributes", general}
1147 };
1148 #define WE_6_LEN ARRAY_SIZE(we_6)
1149
1150 int
QuickHex(char * txt,u_char * p,int cnt)1151 QuickHex(char *txt, u_char *p, int cnt)
1152 {
1153 register int i;
1154 register char *t = txt;
1155
1156 for (i = 0; i < cnt; i++) {
1157 *t++ = ' ';
1158 *t++ = hex_asc_hi(p[i]);
1159 *t++ = hex_asc_lo(p[i]);
1160 }
1161 *t++ = 0;
1162 return (t - txt);
1163 }
1164
1165 void
LogFrame(struct IsdnCardState * cs,u_char * buf,int size)1166 LogFrame(struct IsdnCardState *cs, u_char *buf, int size)
1167 {
1168 char *dp;
1169
1170 if (size < 1)
1171 return;
1172 dp = cs->dlog;
1173 if (size < MAX_DLOG_SPACE / 3 - 10) {
1174 *dp++ = 'H';
1175 *dp++ = 'E';
1176 *dp++ = 'X';
1177 *dp++ = ':';
1178 dp += QuickHex(dp, buf, size);
1179 dp--;
1180 *dp++ = '\n';
1181 *dp = 0;
1182 HiSax_putstatus(cs, NULL, cs->dlog);
1183 } else
1184 HiSax_putstatus(cs, "LogFrame: ", "warning Frame too big (%d)", size);
1185 }
1186
1187 void
dlogframe(struct IsdnCardState * cs,struct sk_buff * skb,int dir)1188 dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir)
1189 {
1190 u_char *bend, *buf;
1191 char *dp;
1192 unsigned char pd, cr_l, cr, mt;
1193 unsigned char sapi, tei, ftyp;
1194 int i, cset = 0, cs_old = 0, cs_fest = 0;
1195 int size, finish = 0;
1196
1197 if (skb->len < 3)
1198 return;
1199 /* display header */
1200 dp = cs->dlog;
1201 dp += jiftime(dp, jiffies);
1202 *dp++ = ' ';
1203 sapi = skb->data[0] >> 2;
1204 tei = skb->data[1] >> 1;
1205 ftyp = skb->data[2];
1206 buf = skb->data;
1207 dp += sprintf(dp, "frame %s ", dir ? "network->user" : "user->network");
1208 size = skb->len;
1209
1210 if (tei == GROUP_TEI) {
1211 if (sapi == CTRL_SAPI) { /* sapi 0 */
1212 if (ftyp == 3) {
1213 dp += sprintf(dp, "broadcast\n");
1214 buf += 3;
1215 size -= 3;
1216 } else {
1217 dp += sprintf(dp, "no UI broadcast\n");
1218 finish = 1;
1219 }
1220 } else if (sapi == TEI_SAPI) {
1221 dp += sprintf(dp, "tei management\n");
1222 finish = 1;
1223 } else {
1224 dp += sprintf(dp, "unknown sapi %d broadcast\n", sapi);
1225 finish = 1;
1226 }
1227 } else {
1228 if (sapi == CTRL_SAPI) {
1229 if (!(ftyp & 1)) { /* IFrame */
1230 dp += sprintf(dp, "with tei %d\n", tei);
1231 buf += 4;
1232 size -= 4;
1233 } else {
1234 dp += sprintf(dp, "SFrame with tei %d\n", tei);
1235 finish = 1;
1236 }
1237 } else {
1238 dp += sprintf(dp, "unknown sapi %d tei %d\n", sapi, tei);
1239 finish = 1;
1240 }
1241 }
1242 bend = skb->data + skb->len;
1243 if (buf >= bend) {
1244 dp += sprintf(dp, "frame too short\n");
1245 finish = 1;
1246 }
1247 if (finish) {
1248 *dp = 0;
1249 HiSax_putstatus(cs, NULL, cs->dlog);
1250 return;
1251 }
1252 if ((0xfe & buf[0]) == PROTO_DIS_N0) { /* 1TR6 */
1253 /* locate message type */
1254 pd = *buf++;
1255 cr_l = *buf++;
1256 if (cr_l)
1257 cr = *buf++;
1258 else
1259 cr = 0;
1260 mt = *buf++;
1261 if (pd == PROTO_DIS_N0) { /* N0 */
1262 for (i = 0; i < MT_N0_LEN; i++)
1263 if (mt_n0[i].nr == mt)
1264 break;
1265 /* display message type if it exists */
1266 if (i == MT_N0_LEN)
1267 dp += sprintf(dp, "callref %d %s size %d unknown message type N0 %x!\n",
1268 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1269 size, mt);
1270 else
1271 dp += sprintf(dp, "callref %d %s size %d message type %s\n",
1272 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1273 size, mt_n0[i].descr);
1274 } else { /* N1 */
1275 for (i = 0; i < MT_N1_LEN; i++)
1276 if (mt_n1[i].nr == mt)
1277 break;
1278 /* display message type if it exists */
1279 if (i == MT_N1_LEN)
1280 dp += sprintf(dp, "callref %d %s size %d unknown message type N1 %x!\n",
1281 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1282 size, mt);
1283 else
1284 dp += sprintf(dp, "callref %d %s size %d message type %s\n",
1285 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1286 size, mt_n1[i].descr);
1287 }
1288
1289 /* display each information element */
1290 while (buf < bend) {
1291 /* Is it a single octet information element? */
1292 if (*buf & 0x80) {
1293 switch ((*buf >> 4) & 7) {
1294 case 1:
1295 dp += sprintf(dp, " Shift %x\n", *buf & 0xf);
1296 cs_old = cset;
1297 cset = *buf & 7;
1298 cs_fest = *buf & 8;
1299 break;
1300 case 3:
1301 dp += sprintf(dp, " Congestion level %x\n", *buf & 0xf);
1302 break;
1303 case 2:
1304 if (*buf == 0xa0) {
1305 dp += sprintf(dp, " More data\n");
1306 break;
1307 }
1308 if (*buf == 0xa1) {
1309 dp += sprintf(dp, " Sending complete\n");
1310 }
1311 break;
1312 /* fall through */
1313 default:
1314 dp += sprintf(dp, " Reserved %x\n", *buf);
1315 break;
1316 }
1317 buf++;
1318 continue;
1319 }
1320 /* No, locate it in the table */
1321 if (cset == 0) {
1322 for (i = 0; i < WE_0_LEN; i++)
1323 if (*buf == we_0[i].nr)
1324 break;
1325
1326 /* When found, give appropriate msg */
1327 if (i != WE_0_LEN) {
1328 dp += sprintf(dp, " %s\n", we_0[i].descr);
1329 dp += we_0[i].f(dp, buf);
1330 } else
1331 dp += sprintf(dp, " Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
1332 } else if (cset == 6) {
1333 for (i = 0; i < WE_6_LEN; i++)
1334 if (*buf == we_6[i].nr)
1335 break;
1336
1337 /* When found, give appropriate msg */
1338 if (i != WE_6_LEN) {
1339 dp += sprintf(dp, " %s\n", we_6[i].descr);
1340 dp += we_6[i].f(dp, buf);
1341 } else
1342 dp += sprintf(dp, " Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
1343 } else
1344 dp += sprintf(dp, " Unknown Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
1345 /* Skip to next element */
1346 if (cs_fest == 8) {
1347 cset = cs_old;
1348 cs_old = 0;
1349 cs_fest = 0;
1350 }
1351 buf += buf[1] + 2;
1352 }
1353 } else if ((buf[0] == 8) && (cs->protocol == ISDN_PTYPE_NI1)) { /* NI-1 */
1354 /* locate message type */
1355 buf++;
1356 cr_l = *buf++;
1357 if (cr_l)
1358 cr = *buf++;
1359 else
1360 cr = 0;
1361 mt = *buf++;
1362 for (i = 0; i < MTSIZE; i++)
1363 if (mtlist[i].nr == mt)
1364 break;
1365
1366 /* display message type if it exists */
1367 if (i == MTSIZE)
1368 dp += sprintf(dp, "callref %d %s size %d unknown message type %x!\n",
1369 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1370 size, mt);
1371 else
1372 dp += sprintf(dp, "callref %d %s size %d message type %s\n",
1373 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1374 size, mtlist[i].descr);
1375
1376 /* display each information element */
1377 while (buf < bend) {
1378 /* Is it a single octet information element? */
1379 if (*buf & 0x80) {
1380 switch ((*buf >> 4) & 7) {
1381 case 1:
1382 dp += sprintf(dp, " Shift %x\n", *buf & 0xf);
1383 cs_old = cset;
1384 cset = *buf & 7;
1385 cs_fest = *buf & 8;
1386 break;
1387 default:
1388 dp += sprintf(dp, " Unknown single-octet IE %x\n", *buf);
1389 break;
1390 }
1391 buf++;
1392 continue;
1393 }
1394 /* No, locate it in the table */
1395 if (cset == 0) {
1396 for (i = 0; i < IESIZE_NI1; i++)
1397 if (*buf == ielist_ni1[i].nr)
1398 break;
1399
1400 /* When not found, give appropriate msg */
1401 if (i != IESIZE_NI1) {
1402 dp += sprintf(dp, " %s\n", ielist_ni1[i].descr);
1403 dp += ielist_ni1[i].f(dp, buf);
1404 } else
1405 dp += sprintf(dp, " attribute %x attribute size %d\n", *buf, buf[1]);
1406 } else if (cset == 5) {
1407 for (i = 0; i < IESIZE_NI1_CS5; i++)
1408 if (*buf == ielist_ni1_cs5[i].nr)
1409 break;
1410
1411 /* When not found, give appropriate msg */
1412 if (i != IESIZE_NI1_CS5) {
1413 dp += sprintf(dp, " %s\n", ielist_ni1_cs5[i].descr);
1414 dp += ielist_ni1_cs5[i].f(dp, buf);
1415 } else
1416 dp += sprintf(dp, " attribute %x attribute size %d\n", *buf, buf[1]);
1417 } else if (cset == 6) {
1418 for (i = 0; i < IESIZE_NI1_CS6; i++)
1419 if (*buf == ielist_ni1_cs6[i].nr)
1420 break;
1421
1422 /* When not found, give appropriate msg */
1423 if (i != IESIZE_NI1_CS6) {
1424 dp += sprintf(dp, " %s\n", ielist_ni1_cs6[i].descr);
1425 dp += ielist_ni1_cs6[i].f(dp, buf);
1426 } else
1427 dp += sprintf(dp, " attribute %x attribute size %d\n", *buf, buf[1]);
1428 } else
1429 dp += sprintf(dp, " Unknown Codeset %d attribute %x attribute size %d\n", cset, *buf, buf[1]);
1430
1431 /* Skip to next element */
1432 if (cs_fest == 8) {
1433 cset = cs_old;
1434 cs_old = 0;
1435 cs_fest = 0;
1436 }
1437 buf += buf[1] + 2;
1438 }
1439 } else if ((buf[0] == 8) && (cs->protocol == ISDN_PTYPE_EURO)) { /* EURO */
1440 /* locate message type */
1441 buf++;
1442 cr_l = *buf++;
1443 if (cr_l)
1444 cr = *buf++;
1445 else
1446 cr = 0;
1447 mt = *buf++;
1448 for (i = 0; i < MTSIZE; i++)
1449 if (mtlist[i].nr == mt)
1450 break;
1451
1452 /* display message type if it exists */
1453 if (i == MTSIZE)
1454 dp += sprintf(dp, "callref %d %s size %d unknown message type %x!\n",
1455 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1456 size, mt);
1457 else
1458 dp += sprintf(dp, "callref %d %s size %d message type %s\n",
1459 cr & 0x7f, (cr & 0x80) ? "called" : "caller",
1460 size, mtlist[i].descr);
1461
1462 /* display each information element */
1463 while (buf < bend) {
1464 /* Is it a single octet information element? */
1465 if (*buf & 0x80) {
1466 switch ((*buf >> 4) & 7) {
1467 case 1:
1468 dp += sprintf(dp, " Shift %x\n", *buf & 0xf);
1469 break;
1470 case 3:
1471 dp += sprintf(dp, " Congestion level %x\n", *buf & 0xf);
1472 break;
1473 case 5:
1474 dp += sprintf(dp, " Repeat indicator %x\n", *buf & 0xf);
1475 break;
1476 case 2:
1477 if (*buf == 0xa0) {
1478 dp += sprintf(dp, " More data\n");
1479 break;
1480 }
1481 if (*buf == 0xa1) {
1482 dp += sprintf(dp, " Sending complete\n");
1483 }
1484 break;
1485 /* fall through */
1486 default:
1487 dp += sprintf(dp, " Reserved %x\n", *buf);
1488 break;
1489 }
1490 buf++;
1491 continue;
1492 }
1493 /* No, locate it in the table */
1494 for (i = 0; i < IESIZE; i++)
1495 if (*buf == ielist[i].nr)
1496 break;
1497
1498 /* When not found, give appropriate msg */
1499 if (i != IESIZE) {
1500 dp += sprintf(dp, " %s\n", ielist[i].descr);
1501 dp += ielist[i].f(dp, buf);
1502 } else
1503 dp += sprintf(dp, " attribute %x attribute size %d\n", *buf, buf[1]);
1504
1505 /* Skip to next element */
1506 buf += buf[1] + 2;
1507 }
1508 } else {
1509 dp += sprintf(dp, "Unknown protocol %x!", buf[0]);
1510 }
1511 *dp = 0;
1512 HiSax_putstatus(cs, NULL, cs->dlog);
1513 }
1514