2 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 *---------------------------------------------------------------------------
27 * main.c - isdndecode main program file
28 * -------------------------------------
30 * $Id: main.c,v 1.13 2000/02/21 15:17:17 hm Exp $
32 * $FreeBSD: src/usr.sbin/i4b/isdndecode/main.c,v 1.8.2.1 2001/08/01 17:45:05 obrien Exp $
33 * $DragonFly: src/usr.sbin/i4b/isdndecode/main.c,v 1.3 2003/11/16 15:17:35 eirikn Exp $
35 * last edit-date: [Mon Feb 21 16:19:30 2000]
37 *---------------------------------------------------------------------------*/
41 unsigned char buf
[BSIZE
];
61 int enable_trace
= TRACE_D_RX
| TRACE_D_TX
;
63 static char outfilename
[1024];
64 static char BPfilename
[1024];
66 static void dumpbuf( int n
, unsigned char *buf
, i4b_trace_hdr_t
*hdr
);
67 static int switch_driver( int value
, int rx
, int tx
);
68 static void usage( void );
69 static void exit_hdl( void );
70 static void reopenfiles( int );
73 /*---------------------------------------------------------------------------*
75 *---------------------------------------------------------------------------*/
80 fprintf(stderr
,"isdndecode - isdn4bsd package ISDN decoder for passive cards (%d.%d.%d)\n", VERSION
, REL
, STEP
);
81 fprintf(stderr
,"usage: isdntrace -a -b -d -f <file> -h -i -l -n <val> -o -p <file> -r -u <unit>\n");
82 fprintf(stderr
," -x -B -P -R <unit> -T <unit>\n");
83 fprintf(stderr
," -a analyzer mode ................................... (default off)\n");
84 fprintf(stderr
," -b switch B channel trace on ....................... (default off)\n");
85 fprintf(stderr
," -d switch D channel trace off ....................... (default on)\n");
86 fprintf(stderr
," -f <file> write output to file filename ........... (default %s0)\n", DECODE_FILE_NAME
);
87 fprintf(stderr
," -h don't print header for each message ............. (default off)\n");
88 fprintf(stderr
," -i print I.430 (layer 1) INFO signals .............. (default off)\n");
89 fprintf(stderr
," -l don't decode low layer Q.921 messages ........... (default off)\n");
90 fprintf(stderr
," -o don't write output to a file .................... (default off)\n");
91 fprintf(stderr
," -p <file> specify filename for -B and -P ........ (default %s0)\n", BIN_FILE_NAME
);
92 fprintf(stderr
," -u <unit> specify controller unit number ............... (default unit 0)\n");
93 fprintf(stderr
," -x print packets with unknown protocoldiscriminator (default off)\n");
94 fprintf(stderr
," -B write binary trace data to file filename ........ (default off)\n");
95 fprintf(stderr
," -P playback from binary trace data file ............ (default off)\n");
96 fprintf(stderr
," -R <unit> analyze Rx controller unit number (for -a) ... (default unit %d)\n", RxUDEF
);
97 fprintf(stderr
," -T <unit> analyze Tx controller unit number (for -a) ... (default unit %d)\n", TxUDEF
);
102 /*---------------------------------------------------------------------------*
104 *---------------------------------------------------------------------------*/
106 main(int argc
, char *argv
[])
118 char *outfile
= DECODE_FILE_NAME
;
119 char *binfile
= BIN_FILE_NAME
;
123 i4b_trace_hdr_t
*ithp
= NULL
;
126 b
= &buf
[sizeof(i4b_trace_hdr_t
)];
128 while( (c
= getopt(argc
, argv
, "abdf:hiln:op:u:xBPR:T:")) != -1)
137 enable_trace
|= (TRACE_B_RX
| TRACE_B_TX
);
141 enable_trace
&= (~(TRACE_D_TX
| TRACE_D_RX
));
158 enable_trace
|= TRACE_I
;
173 if(unit
< 0 || unit
>= MAX_CONTROLLERS
)
191 if(Rx
< 0 || Rx
>= MAX_CONTROLLERS
)
197 if(Tx
< 0 || Tx
>= MAX_CONTROLLERS
)
208 if(enable_trace
== 0)
219 sprintf(BPfilename
, "%s", binfile
);
221 sprintf(BPfilename
, "%s%d", BIN_FILE_NAME
, unit
);
223 if((BP
= fopen(BPfilename
, "r")) != NULL
)
227 sprintf(buffer
, "%s%s", BPfilename
, DECODE_FILE_NAME_BAK
);
228 rename(BPfilename
, buffer
);
230 if((BP
= fopen(BPfilename
, "w")) == NULL
)
234 sprintf(buffer
, "Error opening file [%s]", BPfilename
);
239 if((setvbuf(BP
, (char *)NULL
, _IONBF
, 0)) != 0)
243 sprintf(buffer
, "Error setting file [%s] to unbuffered", BPfilename
);
252 sprintf(BPfilename
, "%s", binfile
);
254 sprintf(BPfilename
, "%s%d", BIN_FILE_NAME
, unit
);
256 if((BP
= fopen(BPfilename
, "r")) == NULL
)
260 sprintf(buffer
, "Error opening file [%s]", BPfilename
);
267 sprintf(devicename
, "%s%d", I4BTRC_DEVICE
, unit
);
269 if((f
= open(devicename
, O_RDWR
)) < 0)
273 sprintf(buffer
, "Error opening trace device [%s]", devicename
);
282 sprintf(outfilename
, "%s%d", DECODE_FILE_NAME
, unit
);
284 strcpy(outfilename
, outfile
);
287 if((Fout
= fopen(outfilename
, "r")) != NULL
)
291 sprintf(buffer
, "%s%s", outfilename
, DECODE_FILE_NAME_BAK
);
292 rename(outfilename
, buffer
);
295 if((Fout
= fopen(outfilename
, "w")) == NULL
)
299 sprintf(buffer
, "Error opening file [%s]", outfilename
);
304 if((setvbuf(Fout
, (char *)NULL
, _IONBF
, 0)) != 0)
308 sprintf(buffer
, "Error setting file [%s] to unbuffered", outfile
);
314 if((setvbuf(stdout
, (char *)NULL
, _IOLBF
, 0)) != 0)
318 sprintf(buffer
, "Error setting stdout to line-buffered");
325 if((switch_driver(enable_trace
, Rx
, Tx
)) == -1)
331 signal(SIGHUP
, SIG_IGN
); /* ignore hangup signal */
332 signal(SIGUSR1
, reopenfiles
); /* rotate logfile(s) */
338 sprintf(headerbuf
, "\n==== isdnanalyze controller rx #%d - tx #%d ==== started %s",
343 sprintf(headerbuf
, "\n=========== isdntrace controller #%d =========== started %s",
347 printf("%s", headerbuf
);
350 fprintf(Fout
, "%s", headerbuf
);
356 n
= read(f
, buf
, BSIZE
);
360 if((fwrite(buf
, 1, n
, BP
)) != n
)
363 sprintf(buffer
, "Error writing file [%s]", BPfilename
);
369 n
-= sizeof(i4b_trace_hdr_t
);
373 if((fread(buf
, 1, sizeof(i4b_trace_hdr_t
), BP
)) != sizeof(i4b_trace_hdr_t
))
377 printf("\nEnd of playback input file reached.\n");
383 sprintf(buffer
, "Error reading hdr from file [%s]", BPfilename
);
389 ithp
= (i4b_trace_hdr_t
*)buf
;
390 l
= ithp
->length
- sizeof(i4b_trace_hdr_t
);
392 if((n
= fread(buf
+sizeof(i4b_trace_hdr_t
), 1, l
, BP
)) != l
)
395 sprintf(buffer
, "Error reading data from file [%s]", BPfilename
);
404 dumpbuf(n
, b
, (i4b_trace_hdr_t
*)buf
);
409 /*---------------------------------------------------------------------------*
410 * format header into static buffer, return buffer address
411 *---------------------------------------------------------------------------*/
413 fmt_hdr(i4b_trace_hdr_t
*hdr
, int frm_len
)
416 static char hbuf
[256];
419 s
= localtime((time_t *)&(hdr
->time
.tv_sec
));
421 if(hdr
->type
== TRC_CH_I
) /* Layer 1 INFO's */
423 sprintf(hbuf
,"\n-- %s - unit:%d ---------------- time:%2.2d.%2.2d %2.2d:%2.2d:%2.2d.%06u ",
424 ((hdr
->dir
) ? "NT->TE" : "TE->NT"),
431 (u_int32_t
)hdr
->time
.tv_usec
);
437 sprintf(hbuf
,"\n-- %s - unit:%d - frame:%6.6u - time:%2.2d.%2.2d %2.2d:%2.2d:%2.2d.%06u - length:%d (%d) ",
438 ((hdr
->dir
) ? "NT->TE" : "TE->NT"),
446 (u_int32_t
)hdr
->time
.tv_usec
,
452 sprintf(hbuf
,"\n-- %s - unit:%d - frame:%6.6u - time:%2.2d.%2.2d %2.2d:%2.2d:%2.2d.%06u - length:%d ",
453 ((hdr
->dir
) ? "NT->TE" : "TE->NT"),
461 (u_int32_t
)hdr
->time
.tv_usec
,
466 for(i
=strlen(hbuf
); i
<= NCOLS
;)
475 /*---------------------------------------------------------------------------*
476 * decode protocol and output to file(s)
477 *---------------------------------------------------------------------------*/
479 dumpbuf(int n
, unsigned char *buf
, i4b_trace_hdr_t
*hdr
)
481 static char l1buf
[128];
482 static unsigned char l2buf
[32000];
483 static unsigned char l3buf
[32000];
495 case TRC_CH_I
: /* Layer 1 INFO's */
496 if(enable_trace
& TRACE_I
)
500 case TRC_CH_D
: /* D-channel data */
501 cnt
= layer2(l2buf
, buf
, hdr
->dir
, print_q921
);
511 if((*buf
!= 0x08) && (xflag
== 0))
517 layer3(l3buf
, n
, cnt
, buf
);
521 default: /* B-channel data */
525 for (i
= 0; i
< n
; i
+= 16)
527 sprintf((pbuf
+strlen(pbuf
)),"B%d:%.3x ", hdr
->type
, i
);
529 for (j
= 0; j
< 16; j
++)
531 sprintf((pbuf
+strlen(pbuf
)),"%02x ", buf
[i
+ j
]);
533 sprintf((pbuf
+strlen(pbuf
))," ");
535 sprintf((pbuf
+strlen(pbuf
))," ");
537 for (j
= 0; j
< 16 && i
+ j
< n
; j
++)
538 if (isprint(buf
[i
+ j
]))
539 sprintf((pbuf
+strlen(pbuf
)),"%c", buf
[i
+ j
]);
541 sprintf((pbuf
+strlen(pbuf
)),".");
543 sprintf((pbuf
+strlen(pbuf
)),"\n");
548 if(header
&& ((l1buf
[0] != '\0' || l2buf
[0] != '\0') || (l3buf
[0] != 0)))
551 p
= fmt_hdr(hdr
, nsave
);
554 fprintf(Fout
, "%s", p
);
561 fprintf(Fout
, "%s", l1buf
);
568 fprintf(Fout
, "%s", l2buf
);
575 fprintf(Fout
, "%s", l3buf
);
579 /*---------------------------------------------------------------------------*
580 * exit handler function to be called at program exit
581 *---------------------------------------------------------------------------*/
586 switch_driver(TRACE_OFF
, Rx
, Tx
);
589 /*---------------------------------------------------------------------------*
590 * switch driver debugging output on/off
591 *---------------------------------------------------------------------------*/
593 switch_driver(int value
, int rx
, int tx
)
600 if(ioctl(f
, I4B_TRC_SET
, &v
) < 0)
602 sprintf(buffer
, "Error ioctl I4B_TRC_SET, val = %d", v
);
609 if(value
== TRACE_OFF
)
611 if(ioctl(f
, I4B_TRC_RESETA
, &v
) < 0)
613 sprintf(buffer
, "Error ioctl I4B_TRC_RESETA - ");
620 i4b_trace_setupa_t tsa
;
627 if(ioctl(f
, I4B_TRC_SETA
, &tsa
) < 0)
629 sprintf(buffer
, "Error ioctl I4B_TRC_SETA, val = %d", v
);
638 /*---------------------------------------------------------------------------*
639 * reopen files to support rotating logfile(s) on SIGUSR1
641 * based on an idea from Ripley (ripley@nostromo.in-berlin.de)
643 * close file and reopen it for append. this will be a nop
644 * if the previously opened file hasn't moved but will open
645 * a new one otherwise, thus enabling a rotation...
647 *---------------------------------------------------------------------------*/
649 reopenfiles(int dummy
)
655 if((Fout
= fopen(outfilename
, "a")) == NULL
)
659 sprintf(buffer
, "Error re-opening file [%s]", outfilename
);
664 if((setvbuf(Fout
, (char *)NULL
, _IONBF
, 0)) != 0)
668 sprintf(buffer
, "Error re-setting file [%s] to unbuffered", outfilename
);
679 if((BP
= fopen(BPfilename
, "a")) == NULL
)
683 sprintf(buffer
, "Error re-opening file [%s]", BPfilename
);
688 if((setvbuf(BP
, (char *)NULL
, _IONBF
, 0)) != 0)
692 sprintf(buffer
, "Error re-setting file [%s] to unbuffered", BPfilename
);
699 /*---------------------------------------------------------------------------*
700 * decode extension bit
701 *---------------------------------------------------------------------------*/
703 extension(int layer
, char *buffer
, int cnt
, unsigned char value
, unsigned char mask
)
705 sprintline(layer
, buffer
, cnt
, value
, mask
, "Extension Bit = %c (%s)",
706 (value
& mask
) ? '1' : '0',
707 (value
& mask
) ? "no extension, final octet" : "with extension, octet follows");
710 /*---------------------------------------------------------------------------*
711 * print bits as 0/1 available for mask
712 *---------------------------------------------------------------------------*/
714 print_bits(unsigned char val
, unsigned char mask
)
716 static char buffer
[10];
740 /*---------------------------------------------------------------------------*
741 * print one decoded output line
742 *---------------------------------------------------------------------------*/
744 sprintline(int layer
, char *buffer
, int oct_count
, int oct_val
,
745 int oct_mask
, const char *fmt
, ...)
748 static int lastcount
= -1;
754 if(oct_count
!= lastcount
)
756 lastcount
= oct_count
;
758 sprintf(lbuffer
, "L%d %2d %02X %s ",
762 print_bits(oct_val
, oct_mask
));
766 sprintf(lbuffer
, " %s ",
767 print_bits(oct_val
, oct_mask
));
770 vsprintf(lbuffer
+strlen(lbuffer
), fmt
, ap
);
774 sprintf(lbuffer
+strlen(lbuffer
), "\n");
776 if((ptr
= rindex(lbuffer
, '(')) != NULL
)
780 int len
= strlen(lbuffer
);
783 for(s
= lbuffer
; s
< ptr
; *b
++ = *s
++)
785 for(i
= 0;(i
+len
) <= NCOLS
; *b
++ = ' ', i
++)
787 for(; *s
; *b
++ = *s
++)
793 strcpy(buffer
, lbuffer
);