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