Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
q931.c
Go to the documentation of this file.
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
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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++ & 80)) {
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, "Orignal 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
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
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
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
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
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
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 }