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.19 2000/08/28 07:06:42 hm Exp $
42 * last edit-date: [Mon Aug 28 09:03:46 2000]
44 *---------------------------------------------------------------------------*/
49 unsigned char buf[BSIZE];
70 int enable_trace = TRACE_D_RX | TRACE_D_TX;
72 static char outfilename[MAXPATHLEN];
73 static char routfilename[MAXPATHLEN];
74 static char BPfilename[MAXPATHLEN];
75 static char rBPfilename[MAXPATHLEN];
77 static struct stat fst;
79 static void dumpbuf( int n, unsigned char *buf, i4b_trace_hdr_t *hdr, int raw );
80 static int switch_driver( int value, int rx, int tx );
81 static void usage( void );
82 static void exit_hdl( void );
83 static void reopenfiles( int );
84 void add_datetime(char *filename, char *rfilename);
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[])
131 char *outfile = TRACE_FILE_NAME;
132 char *binfile = BIN_FILE_NAME;
137 i4b_trace_hdr_t *ithp = NULL;
139 static struct stat fstnew;
141 b = &buf[sizeof(i4b_trace_hdr_t)];
143 while( (c = getopt(argc, argv, "abdf:hiln:op:ru:xBFPR:T:")) != -1)
152 enable_trace |= (TRACE_B_RX | TRACE_B_TX);
156 enable_trace &= (~(TRACE_D_TX | TRACE_D_RX));
177 enable_trace |= TRACE_I;
196 if(unit < 0 || unit >= MAX_CONTROLLERS)
218 if(Rx < 0 || Rx >= MAX_CONTROLLERS)
224 if(Tx < 0 || Tx >= MAX_CONTROLLERS)
235 if(enable_trace == 0)
246 sprintf(BPfilename, "%s", binfile);
248 sprintf(BPfilename, "%s%d", BIN_FILE_NAME, unit);
250 add_datetime(BPfilename, rBPfilename);
252 if((BP = fopen(rBPfilename, "w")) == NULL)
256 sprintf(buffer, "Error opening file [%s]", rBPfilename);
261 if((setvbuf(BP, (char *)NULL, _IONBF, 0)) != 0)
265 sprintf(buffer, "Error setting file [%s] to unbuffered", rBPfilename);
274 sprintf(BPfilename, "%s", binfile);
276 sprintf(BPfilename, "%s%d", BIN_FILE_NAME, unit);
278 strcpy(rBPfilename, BPfilename);
280 if((BP = fopen(BPfilename, "r")) == NULL)
284 sprintf(buffer, "Error opening file [%s]", BPfilename);
290 if(fstat(fileno(BP), &fst))
293 sprintf(buffer, "Error fstat file [%s]", BPfilename);
301 sprintf(devicename, "%s%d", I4BTRC_DEVICE, unit);
303 if((f = open(devicename, O_RDWR)) < 0)
307 sprintf(buffer, "Error opening trace device [%s]", devicename);
316 sprintf(outfilename, "%s%d", TRACE_FILE_NAME, unit);
318 strcpy(outfilename, outfile);
320 add_datetime(outfilename, routfilename);
322 if((Fout = fopen(routfilename, "w")) == NULL)
326 sprintf(buffer, "Error opening file [%s]", routfilename);
331 if((setvbuf(Fout, (char *)NULL, _IONBF, 0)) != 0)
335 sprintf(buffer, "Error setting file [%s] to unbuffered", routfilename);
341 if((setvbuf(stdout, (char *)NULL, _IOLBF, 0)) != 0)
345 sprintf(buffer, "Error setting stdout to line-buffered");
352 if((switch_driver(enable_trace, Rx, Tx)) == -1)
358 signal(SIGHUP, SIG_IGN); /* ignore hangup signal */
359 signal(SIGUSR1, reopenfiles); /* rotate logfile(s) */
365 sprintf(headerbuf, "\n==== isdnanalyze controller rx #%d - tx #%d ==== started %s",
370 sprintf(headerbuf, "\n=========== isdntrace controller #%d =========== started %s",
374 printf("%s", headerbuf);
377 fprintf(Fout, "%s", headerbuf);
383 n = read(f, buf, BSIZE);
387 if((fwrite(buf, 1, n, BP)) != n)
390 sprintf(buffer, "Error writing file [%s]", rBPfilename);
396 n -= sizeof(i4b_trace_hdr_t);
401 if((fread(buf, 1, sizeof(i4b_trace_hdr_t), BP)) != sizeof(i4b_trace_hdr_t))
410 sprintf(buffer, "Error reading hdr from file [%s]", rBPfilename);
418 if(stat(rBPfilename, &fstnew) != -1)
420 if((fst.st_ino != fstnew.st_ino) ||
421 (fstnew.st_nlink == 0))
423 if((BP = freopen(rBPfilename, "r", BP)) == NULL)
426 sprintf(buffer, "Error reopening file [%s]", rBPfilename);
430 stat(rBPfilename, &fst);
437 printf("\nEnd of playback input file reached.\n");
444 sprintf(buffer, "Error reading hdr from file [%s]", rBPfilename);
450 ithp = (i4b_trace_hdr_t *)buf;
451 l = ithp->length - sizeof(i4b_trace_hdr_t);
453 if((n = fread(buf+sizeof(i4b_trace_hdr_t), 1, l , BP)) != l)
456 sprintf(buffer, "Error reading data from file [%s]", rBPfilename);
463 if((n > 0) && (n > noct))
465 dumpbuf(n, b, (i4b_trace_hdr_t *)buf, raw);
470 /*---------------------------------------------------------------------------*
471 * format header into static buffer, return buffer address
472 *---------------------------------------------------------------------------*/
474 fmt_hdr(i4b_trace_hdr_t *hdr, int frm_len)
477 static char hbuf[256];
480 s = localtime((time_t *)&(hdr->time.tv_sec));
482 if(hdr->type == TRC_CH_I) /* Layer 1 INFO's */
484 sprintf(hbuf,"\n-- %s - unit:%d ---------------- time:%2.2d.%2.2d %2.2d:%2.2d:%2.2d.%06u ",
485 ((hdr->dir) ? "NT->TE" : "TE->NT"),
492 (u_int32_t)hdr->time.tv_usec);
498 sprintf(hbuf,"\n-- %s - unit:%d - frame:%6.6u - time:%2.2d.%2.2d %2.2d:%2.2d:%2.2d.%06u - length:%d (%d) ",
499 ((hdr->dir) ? "NT->TE" : "TE->NT"),
507 (u_int32_t)hdr->time.tv_usec,
513 sprintf(hbuf,"\n-- %s - unit:%d - frame:%6.6u - time:%2.2d.%2.2d %2.2d:%2.2d:%2.2d.%06u - length:%d ",
514 ((hdr->dir) ? "NT->TE" : "TE->NT"),
522 (u_int32_t)hdr->time.tv_usec,
527 for(i=strlen(hbuf); i <= NCOLS;)
536 /*---------------------------------------------------------------------------*
537 * decode protocol and output to file(s)
538 *---------------------------------------------------------------------------*/
540 dumpbuf(int n, unsigned char *buf, i4b_trace_hdr_t *hdr, int raw)
542 static char l1buf[128];
543 static unsigned char l2buf[32000];
544 static unsigned char l3buf[32000];
556 case TRC_CH_I: /* Layer 1 INFO's */
558 /* on playback, don't display layer 1 if -i ! */
559 if(!(enable_trace & TRACE_I))
567 sprintf((pbuf+strlen(pbuf)),"I430: INFO0 (No Signal)\n");
571 sprintf((pbuf+strlen(pbuf)),"I430: INFO1 (Activation Request, Priority = 8, from TE)\n");
575 sprintf((pbuf+strlen(pbuf)),"I430: INFO1 (Activation Request, Priority = 10, from TE)\n");
579 sprintf((pbuf+strlen(pbuf)),"I430: INFO2 (Pending Activation, from NT)\n");
583 sprintf((pbuf+strlen(pbuf)),"I430: INFO3 (Synchronized, from TE)\n");
587 sprintf((pbuf+strlen(pbuf)),"I430: INFO4 (Activated, Priority = 8/9, from NT)\n");
591 sprintf((pbuf+strlen(pbuf)),"I430: INFO4 (Activated, Priority = 10/11, from NT)\n");
595 sprintf((pbuf+strlen(pbuf)),"I430: ERROR, invalid INFO value 0x%x!\n", buf[0]);
600 case TRC_CH_D: /* D-channel data */
602 cnt = decode_lapd(l2buf, n, buf, hdr->dir, raw, print_q921);
613 decode_1tr6(l3buf, n, cnt, buf, raw);
617 decode_q931(l3buf, n, cnt, buf, raw);
628 decode_unknownl3(l3buf, n, cnt, buf, raw);
635 default: /* B-channel data */
639 for (i = 0; i < n; i += 16)
641 sprintf((pbuf+strlen(pbuf)),"B%d:%.3x ", hdr->type, i);
643 for (j = 0; j < 16; j++)
645 sprintf((pbuf+strlen(pbuf)),"%02x ", buf[i + j]);
647 sprintf((pbuf+strlen(pbuf))," ");
649 sprintf((pbuf+strlen(pbuf))," ");
651 for (j = 0; j < 16 && i + j < n; j++)
652 if (isprint(buf[i + j]))
653 sprintf((pbuf+strlen(pbuf)),"%c", buf[i + j]);
655 sprintf((pbuf+strlen(pbuf)),".");
657 sprintf((pbuf+strlen(pbuf)),"\n");
662 if(header && ((l1buf[0] != '\0' || l2buf[0] != '\0') || (l3buf[0] != 0)))
665 p = fmt_hdr(hdr, nsave);
668 fprintf(Fout, "%s", p);
675 fprintf(Fout, "%s", l1buf);
682 fprintf(Fout, "%s", l2buf);
689 fprintf(Fout, "%s", l3buf);
693 /*---------------------------------------------------------------------------*
694 * exit handler function to be called at program exit
695 *---------------------------------------------------------------------------*/
700 switch_driver(TRACE_OFF, Rx, Tx);
703 /*---------------------------------------------------------------------------*
704 * switch driver debugging output on/off
705 *---------------------------------------------------------------------------*/
707 switch_driver(int value, int rx, int tx)
714 if(ioctl(f, I4B_TRC_SET, &v) < 0)
716 sprintf(buffer, "Error ioctl I4B_TRC_SET, val = %d", v);
723 if(value == TRACE_OFF)
725 if(ioctl(f, I4B_TRC_RESETA, &v) < 0)
727 sprintf(buffer, "Error ioctl I4B_TRC_RESETA - ");
734 i4b_trace_setupa_t tsa;
741 if(ioctl(f, I4B_TRC_SETA, &tsa) < 0)
743 sprintf(buffer, "Error ioctl I4B_TRC_SETA, val = %d", v);
752 /*---------------------------------------------------------------------------*
753 * reopen files to support rotating logfile(s) on SIGUSR1
755 * based on an idea from Ripley (ripley@nostromo.in-berlin.de)
757 * close file and reopen it for append. this will be a nop
758 * if the previously opened file hasn't moved but will open
759 * a new one otherwise, thus enabling a rotation...
761 *---------------------------------------------------------------------------*/
763 reopenfiles(int dummy)
769 add_datetime(outfilename, routfilename);
771 if((Fout = fopen(routfilename, "a")) == NULL)
775 sprintf(buffer, "Error re-opening file [%s]", routfilename);
780 if((setvbuf(Fout, (char *)NULL, _IONBF, 0)) != 0)
784 sprintf(buffer, "Error re-setting file [%s] to unbuffered", routfilename);
795 add_datetime(BPfilename, rBPfilename);
797 if((BP = fopen(rBPfilename, "a")) == NULL)
801 sprintf(buffer, "Error re-opening file [%s]", rBPfilename);
806 if((setvbuf(BP, (char *)NULL, _IONBF, 0)) != 0)
810 sprintf(buffer, "Error re-setting file [%s] to unbuffered", rBPfilename);
818 add_datetime(char *filename, char *rfilename)
825 tmp = localtime(&timeb);
827 sprintf(rfilename, "%s-", filename);
829 strftime(rfilename+strlen(rfilename), MAXPATHLEN-strlen(rfilename)-1,
830 "%Y%m%d-%H%M%S", tmp);
832 if((fx = fopen(rfilename, "r")) != NULL)
839 tmp = localtime(&timeb);
841 sprintf(rfilename, "%s-", filename);
843 strftime(rfilename+strlen(rfilename), MAXPATHLEN-strlen(rfilename)-1,
844 "%Y%m%d-%H%M%S", tmp);