2 * Copyright (c) 1996, 2000 Hellmuth Michaelis. All rights reserved.
4 * Copyright (c) 1996 Gary Jennejohn. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the author nor the names of any co-contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 * 4. Altered versions must be plainly marked as such, and must not be
19 * misrepresented as being the original software and/or documentation.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 *---------------------------------------------------------------------------*
35 * trace.c - print traces of D (B) channel activity for isdn4bsd
36 * -------------------------------------------------------------
38 * $Id: trace.c,v 1.10 2009/04/16 05:56:33 lukem Exp $
42 * last edit-date: [Sat Jan 6 13:06:03 2001]
44 *---------------------------------------------------------------------------*/
48 unsigned char buf
[BSIZE
];
69 int enable_trace
= TRACE_D_RX
| TRACE_D_TX
;
71 static char outfilename
[MAXPATHLEN
];
72 static char routfilename
[MAXPATHLEN
];
73 static char BPfilename
[MAXPATHLEN
];
74 static char rBPfilename
[MAXPATHLEN
];
76 static struct stat fst
;
78 static void dumpbuf( int n
, unsigned char *buf
, struct i4b_trace_hdr
*hdr
, int raw
);
79 static int switch_driver( int value
, int rx
, int tx
);
80 static void usage( void );
81 static void exit_hdl( void );
82 static void reopenfiles( int );
83 void add_datetime(char *filename
, char *rfilename
);
84 char * fmt_hdr(struct i4b_trace_hdr
*hdr
, int frm_len
);
86 /*---------------------------------------------------------------------------*
88 *---------------------------------------------------------------------------*/
93 fprintf(stderr
,"isdntrace - i4b package ISDN trace facility for passive cards (%02d.%02d.%d)\n", VERSION
, REL
, STEP
);
94 fprintf(stderr
,"usage: isdntrace -a -b -d -f <file> -h -i -l -n <val> -o -p <file> -r -u <unit>\n");
95 fprintf(stderr
," -x -B -F -P -R <unit> -T <unit>\n");
96 fprintf(stderr
," -a analyzer mode ................................... (default off)\n");
97 fprintf(stderr
," -b switch B channel trace on ....................... (default off)\n");
98 fprintf(stderr
," -d switch D channel trace off ....................... (default on)\n");
99 fprintf(stderr
," -f <file> write output to file filename ............ (default %s0)\n", TRACE_FILE_NAME
);
100 fprintf(stderr
," -h don't print header for each message ............. (default off)\n");
101 fprintf(stderr
," -i print I.430 (layer 1) INFO signals .............. (default off)\n");
102 fprintf(stderr
," -l don't decode low layer Q.921 messages ........... (default off)\n");
103 fprintf(stderr
," -n <val> process packet if it is longer than <val> octetts . (default 0)\n");
104 fprintf(stderr
," -o don't write output to a file .................... (default off)\n");
105 fprintf(stderr
," -p <file> specify filename for -B and -P ........ (default %s0)\n", BIN_FILE_NAME
);
106 fprintf(stderr
," -r don't print raw hex/ASCII dump of protocol ...... (default off)\n");
107 fprintf(stderr
," -u <unit> specify controller unit number ............... (default unit 0)\n");
108 fprintf(stderr
," -x show packets with unknown protocol discriminator (default off)\n");
109 fprintf(stderr
," -B write binary trace data to file filename ........ (default off)\n");
110 fprintf(stderr
," -F with -P and -p: wait for more data at EOF ....... (default off)\n");
111 fprintf(stderr
," -P playback from binary trace data file ............ (default off)\n");
112 fprintf(stderr
," -R <unit> analyze Rx controller unit number (for -a) ... (default unit %d)\n", RxUDEF
);
113 fprintf(stderr
," -T <unit> analyze Tx controller unit number (for -a) ... (default unit %d)\n", TxUDEF
);
114 fprintf(stderr
,"\n");
118 /*---------------------------------------------------------------------------*
120 *---------------------------------------------------------------------------*/
122 main(int argc
, char *argv
[])
134 const char *outfile
= TRACE_FILE_NAME
;
135 const char *binfile
= BIN_FILE_NAME
;
140 struct i4b_trace_hdr
*ithp
= NULL
;
142 static struct stat fstnew
;
144 b
= &buf
[sizeof(struct i4b_trace_hdr
)];
146 while( (c
= getopt(argc
, argv
, "abdf:hiln:op:ru:xBFPR:T:")) != -1)
155 enable_trace
|= (TRACE_B_RX
| TRACE_B_TX
);
159 enable_trace
&= (~(TRACE_D_TX
| TRACE_D_RX
));
180 enable_trace
|= TRACE_I
;
232 if (enable_trace
== 0)
243 snprintf(BPfilename
, sizeof(BPfilename
), "%s", binfile
);
245 snprintf(BPfilename
, sizeof(BPfilename
), "%s%d",
246 BIN_FILE_NAME
, unit
);
248 add_datetime(BPfilename
, rBPfilename
);
250 if ((BP
= fopen(rBPfilename
, "w")) == NULL
)
254 snprintf(buffer
, sizeof(buffer
),
255 "Error opening file [%s]", rBPfilename
);
260 if ((setvbuf(BP
, (char *)NULL
, _IONBF
, 0)) != 0)
264 snprintf(buffer
, sizeof(buffer
),
265 "Error setting file [%s] to unbuffered",
275 snprintf(BPfilename
, sizeof(BPfilename
), "%s", binfile
);
277 snprintf(BPfilename
, sizeof(BPfilename
), "%s%d",
278 BIN_FILE_NAME
, unit
);
280 strlcpy(rBPfilename
, BPfilename
, sizeof(rBPfilename
));
282 if ((BP
= fopen(BPfilename
, "r")) == NULL
)
286 snprintf(buffer
, sizeof(buffer
),
287 "Error opening file [%s]", BPfilename
);
293 if (fstat(fileno(BP
), &fst
))
296 snprintf(buffer
, sizeof(buffer
),
297 "Error fstat file [%s]", BPfilename
);
305 snprintf(devicename
, sizeof(devicename
), "%s%d",
306 I4BTRC_DEVICE
, unit
);
308 if ((f
= open(devicename
, O_RDWR
)) < 0)
312 snprintf(buffer
, sizeof(buffer
),
313 "Error opening trace device [%s]", devicename
);
322 snprintf(outfilename
, sizeof(outfilename
), "%s%d",
323 TRACE_FILE_NAME
, unit
);
325 strlcpy(outfilename
, outfile
, sizeof(outfilename
));
327 add_datetime(outfilename
, routfilename
);
329 if ((Fout
= fopen(routfilename
, "w")) == NULL
)
333 snprintf(buffer
, sizeof(buffer
),
334 "Error opening file [%s]", routfilename
);
339 if ((setvbuf(Fout
, (char *)NULL
, _IONBF
, 0)) != 0)
343 snprintf(buffer
, sizeof(buffer
),
344 "Error setting file [%s] to unbuffered",
351 if ((setvbuf(stdout
, (char *)NULL
, _IOLBF
, 0)) != 0)
355 snprintf(buffer
, sizeof(buffer
),
356 "Error setting stdout to line-buffered");
363 if ((switch_driver(enable_trace
, Rx
, Tx
)) == -1)
369 signal(SIGHUP
, SIG_IGN
); /* ignore hangup signal */
370 signal(SIGUSR1
, reopenfiles
); /* rotate logfile(s) */
376 snprintf(headerbuf
, sizeof(headerbuf
),
377 "\n==== isdnanalyze controller rx #%d - tx #%d ==== started %s",
382 snprintf(headerbuf
, sizeof(headerbuf
),
383 "\n=========== isdntrace controller #%d =========== started %s",
387 printf("%s", headerbuf
);
390 fprintf(Fout
, "%s", headerbuf
);
397 n
= read(f
, buf
, BSIZE
);
400 snprintf(buffer
, sizeof(buffer
),
401 "Error reading trace device");
408 if ((int)(fwrite(buf
, 1, n
, BP
)) != n
)
410 snprintf(buffer
, sizeof(buffer
),
411 "Error writing file [%s]",
418 n
-= sizeof(struct i4b_trace_hdr
);
423 if ((fread(buf
, 1, sizeof(struct i4b_trace_hdr
), BP
)) != sizeof(struct i4b_trace_hdr
))
432 snprintf(buffer
, sizeof(buffer
), "Error reading hdr from file [%s]", rBPfilename
);
440 if (stat(rBPfilename
, &fstnew
) != -1)
442 if ((fst
.st_ino
!= fstnew
.st_ino
) ||
443 (fstnew
.st_nlink
== 0))
445 if ((BP
= freopen(rBPfilename
, "r", BP
)) == NULL
)
448 snprintf(buffer
, sizeof(buffer
), "Error reopening file [%s]", rBPfilename
);
452 stat(rBPfilename
, &fst
);
459 printf("\nEnd of playback input file reached.\n");
466 snprintf(buffer
, sizeof(buffer
),
467 "Error reading hdr from file [%s]",
474 ithp
= (struct i4b_trace_hdr
*)buf
;
475 l
= ithp
->length
- sizeof(struct i4b_trace_hdr
);
477 if ((n
= fread(buf
+sizeof(struct i4b_trace_hdr
), 1, l
, BP
)) != l
)
480 snprintf(buffer
, sizeof(buffer
),
481 "Error reading data from file [%s]",
489 if ((n
> 0) && (n
> noct
))
491 dumpbuf(n
, b
, (struct i4b_trace_hdr
*)buf
, raw
);
496 /*---------------------------------------------------------------------------*
497 * format header into static buffer, return buffer address
498 *---------------------------------------------------------------------------*/
500 fmt_hdr(struct i4b_trace_hdr
*hdr
, int frm_len
)
503 static char hbuf
[256];
505 time_t secs
= hdr
->time
.tv_sec
;
507 s
= localtime(&secs
);
509 if (hdr
->type
== TRC_CH_I
) /* Layer 1 INFO's */
511 snprintf(hbuf
, sizeof(hbuf
),
512 "\n-- %s - isdnif:%d ------------- time:%2.2d.%2.2d %2.2d:%2.2d:%2.2d.%06u ",
513 ((hdr
->dir
) ? "NT->TE" : "TE->NT"), hdr
->isdnif
,
514 s
->tm_mday
, s
->tm_mon
+ 1, s
->tm_hour
, s
->tm_min
,
515 s
->tm_sec
, (u_int32_t
)hdr
->time
.tv_usec
);
521 snprintf(hbuf
, sizeof(hbuf
),
522 "\n-- %s - isdnif:%d - frame:%6.6u - time:%2.2d.%2.2d %2.2d:%2.2d:%2.2d.%06u - length:%d (%d) ",
523 ((hdr
->dir
) ? "NT->TE" : "TE->NT"), hdr
->isdnif
,
524 hdr
->count
, s
->tm_mday
, s
->tm_mon
+ 1, s
->tm_hour
,
525 s
->tm_min
, s
->tm_sec
, (u_int32_t
)hdr
->time
.tv_usec
,
526 frm_len
, hdr
->trunc
);
530 snprintf(hbuf
, sizeof(hbuf
),
531 "\n-- %s - isdnif:%d - frame:%6.6u - time:%2.2d.%2.2d %2.2d:%2.2d:%2.2d.%06u - length:%d ", ((hdr
->dir
) ? "NT->TE" : "TE->NT"),
532 hdr
->isdnif
, hdr
->count
, s
->tm_mday
, s
->tm_mon
+ 1,
533 s
->tm_hour
, s
->tm_min
, s
->tm_sec
,
534 (u_int32_t
)hdr
->time
.tv_usec
, frm_len
);
538 for (i
= strlen(hbuf
); i
<= NCOLS
;)
547 /*---------------------------------------------------------------------------*
548 * decode protocol and output to file(s)
549 *---------------------------------------------------------------------------*/
551 dumpbuf(int n
, unsigned char *dbuf
, struct i4b_trace_hdr
*hdr
, int raw
)
553 static char l1buf
[128];
554 static unsigned char l2buf
[32000];
555 static unsigned char l3buf
[32000];
567 case TRC_CH_I
: /* Layer 1 INFO's */
569 /* on playback, don't display layer 1 if -i ! */
570 if (!(enable_trace
& TRACE_I
))
578 sprintf((pbuf
+strlen(pbuf
)),"I430: INFO0 (No Signal)\n");
582 sprintf((pbuf
+strlen(pbuf
)),"I430: INFO1 (Activation Request, Priority = 8, from TE)\n");
586 sprintf((pbuf
+strlen(pbuf
)),"I430: INFO1 (Activation Request, Priority = 10, from TE)\n");
590 sprintf((pbuf
+strlen(pbuf
)),"I430: INFO2 (Pending Activation, from NT)\n");
594 sprintf((pbuf
+strlen(pbuf
)),"I430: INFO3 (Synchronized, from TE)\n");
598 sprintf((pbuf
+strlen(pbuf
)),"I430: INFO4 (Activated, Priority = 8/9, from NT)\n");
602 sprintf((pbuf
+strlen(pbuf
)),"I430: INFO4 (Activated, Priority = 10/11, from NT)\n");
606 sprintf((pbuf
+strlen(pbuf
)),"I430: ERROR, invalid INFO value 0x%x!\n", dbuf
[0]);
611 case TRC_CH_D
: /* D-channel data */
613 cnt
= decode_lapd(l2buf
, n
, dbuf
, hdr
->dir
, raw
, print_q921
);
624 decode_1tr6(l3buf
, n
, cnt
, dbuf
, raw
);
628 decode_q931(l3buf
, n
, cnt
, dbuf
, raw
);
639 decode_unknownl3(l3buf
, n
, cnt
, dbuf
, raw
);
646 default: /* B-channel data */
650 for (i
= 0; i
< n
; i
+= 16)
652 sprintf((pbuf
+strlen(pbuf
)),"B%d:%.3x ", hdr
->type
, i
);
654 for (j
= 0; j
< 16; j
++)
656 sprintf((pbuf
+strlen(pbuf
)),"%02x ", dbuf
[i
+ j
]);
658 sprintf((pbuf
+strlen(pbuf
))," ");
660 sprintf((pbuf
+strlen(pbuf
))," ");
662 for (j
= 0; j
< 16 && i
+ j
< n
; j
++)
663 if (isprint(dbuf
[i
+ j
]))
664 sprintf((pbuf
+strlen(pbuf
)),"%c", dbuf
[i
+ j
]);
666 sprintf((pbuf
+strlen(pbuf
)),".");
668 sprintf((pbuf
+strlen(pbuf
)),"\n");
673 if (header
&& ((l1buf
[0] != '\0' || l2buf
[0] != '\0') || (l3buf
[0] != 0)))
676 p
= fmt_hdr(hdr
, nsave
);
679 fprintf(Fout
, "%s", p
);
682 if (l1buf
[0] != '\0')
686 fprintf(Fout
, "%s", l1buf
);
689 if (l2buf
[0] != '\0')
693 fprintf(Fout
, "%s", l2buf
);
696 if (l3buf
[0] != '\0')
700 fprintf(Fout
, "%s", l3buf
);
704 /*---------------------------------------------------------------------------*
705 * exit handler function to be called at program exit
706 *---------------------------------------------------------------------------*/
711 switch_driver(TRACE_OFF
, Rx
, Tx
);
714 /*---------------------------------------------------------------------------*
715 * switch driver debugging output on/off
716 *---------------------------------------------------------------------------*/
718 switch_driver(int value
, int rx
, int tx
)
725 if (ioctl(f
, I4B_TRC_SET
, &v
) < 0)
727 snprintf(buffer
, sizeof(buffer
),
728 "Error ioctl I4B_TRC_SET, val = %d", v
);
735 if (value
== TRACE_OFF
)
737 if (ioctl(f
, I4B_TRC_RESETA
, &v
) < 0)
739 snprintf(buffer
, sizeof(buffer
),
740 "Error ioctl I4B_TRC_RESETA - ");
747 i4b_trace_setupa_t tsa
;
754 if (ioctl(f
, I4B_TRC_SETA
, &tsa
) < 0)
756 snprintf(buffer
, sizeof(buffer
),
757 "Error ioctl I4B_TRC_SETA, val = %d", v
);
766 /*---------------------------------------------------------------------------*
767 * reopen files to support rotating logfile(s) on SIGUSR1
769 * based on an idea from Ripley (ripley@nostromo.in-berlin.de)
771 * close file and reopen it for append. this will be a nop
772 * if the previously opened file hasn't moved but will open
773 * a new one otherwise, thus enabling a rotation...
775 *---------------------------------------------------------------------------*/
777 reopenfiles(int dummy
)
783 add_datetime(outfilename
, routfilename
);
785 if ((Fout
= fopen(routfilename
, "a")) == NULL
)
789 snprintf(buffer
, sizeof(buffer
),
790 "Error re-opening file [%s]", routfilename
);
795 if ((setvbuf(Fout
, (char *)NULL
, _IONBF
, 0)) != 0)
799 snprintf(buffer
, sizeof(buffer
),
800 "Error re-setting file [%s] to unbuffered",
812 add_datetime(BPfilename
, rBPfilename
);
814 if ((BP
= fopen(rBPfilename
, "a")) == NULL
)
818 snprintf(buffer
, sizeof(buffer
),
819 "Error re-opening file [%s]", rBPfilename
);
824 if ((setvbuf(BP
, (char *)NULL
, _IONBF
, 0)) != 0)
828 snprintf(buffer
, sizeof(buffer
),
829 "Error re-setting file [%s] to unbuffered",
838 add_datetime(char *filename
, char *rfilename
)
845 tmp
= localtime(&timeb
);
847 snprintf(rfilename
, sizeof(rfilename
), "%s-", filename
);
849 strftime(rfilename
+strlen(rfilename
), MAXPATHLEN
-strlen(rfilename
)-1,
850 "%Y%m%d-%H%M%S", tmp
);
852 if ((fx
= fopen(rfilename
, "r")) != NULL
)
859 tmp
= localtime(&timeb
);
861 snprintf(rfilename
, sizeof(rfilename
), "%s-", filename
);
863 strftime(rfilename
+strlen(rfilename
), MAXPATHLEN
-strlen(rfilename
)-1,
864 "%Y%m%d-%H%M%S", tmp
);