MFC: following 4 commits:
[dragonfly.git] / usr.sbin / i4b / isdndecode / main.c
blobf9c38f7d0c79ccac651d110f1536076abb440024
1 /*
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
6 * are met:
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
23 * SUCH DAMAGE.
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 *---------------------------------------------------------------------------*/
39 #include "decode.h"
41 unsigned char buf[BSIZE];
42 FILE *Fout = NULL;
43 FILE *BP = NULL;
44 int outflag = 1;
45 int header = 1;
46 int print_q921 = 1;
47 int unit = 0;
48 int dchan = 0;
49 int bchan = 0;
50 int traceon = 0;
51 int analyze = 0;
52 int Rx = RxUDEF;
53 int Tx = TxUDEF;
54 int f;
55 int Bopt = 0;
56 int Popt = 0;
57 int bpopt = 0;
58 int info = 0;
59 int xflag = 0;
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 /*---------------------------------------------------------------------------*
74 * usage intructions
75 *---------------------------------------------------------------------------*/
76 void
77 usage(void)
79 fprintf(stderr,"\n");
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);
98 fprintf(stderr,"\n");
99 exit(1);
102 /*---------------------------------------------------------------------------*
103 * main
104 *---------------------------------------------------------------------------*/
106 main(int argc, char *argv[])
108 extern int optind;
109 extern int opterr;
110 extern char *optarg;
111 char devicename[80];
112 char headerbuf[256];
114 int n;
115 int c;
116 char *b;
118 char *outfile = DECODE_FILE_NAME;
119 char *binfile = BIN_FILE_NAME;
120 int outfileset = 0;
121 time_t tm;
123 i4b_trace_hdr_t *ithp = NULL;
124 int l;
126 b = &buf[sizeof(i4b_trace_hdr_t)];
128 while( (c = getopt(argc, argv, "abdf:hiln:op:u:xBPR:T:")) != -1)
130 switch(c)
132 case 'a':
133 analyze = 1;
134 break;
136 case 'b':
137 enable_trace |= (TRACE_B_RX | TRACE_B_TX);
138 break;
140 case 'd':
141 enable_trace &= (~(TRACE_D_TX | TRACE_D_RX));
142 break;
144 case 'o':
145 outflag = 0;
146 break;
148 case 'f':
149 outfile = optarg;
150 outfileset = 1;
151 break;
153 case 'h':
154 header = 0;
155 break;
157 case 'i':
158 enable_trace |= TRACE_I;
159 info = 1;
160 break;
162 case 'l':
163 print_q921 = 0;
164 break;
166 case 'p':
167 binfile = optarg;
168 bpopt = 1;
169 break;
171 case 'u':
172 unit = atoi(optarg);
173 if(unit < 0 || unit >= MAX_CONTROLLERS)
174 usage();
175 break;
177 case 'x':
178 xflag = 1;
179 break;
181 case 'B':
182 Bopt = 1;
183 break;
185 case 'P':
186 Popt = 1;
187 break;
189 case 'R':
190 Rx = atoi(optarg);
191 if(Rx < 0 || Rx >= MAX_CONTROLLERS)
192 usage();
193 break;
195 case 'T':
196 Tx = atoi(optarg);
197 if(Tx < 0 || Tx >= MAX_CONTROLLERS)
198 usage();
199 break;
201 case '?':
202 default:
203 usage();
204 break;
208 if(enable_trace == 0)
209 usage();
211 if(Bopt && Popt)
212 usage();
214 atexit(exit_hdl);
216 if(Bopt)
218 if(bpopt)
219 sprintf(BPfilename, "%s", binfile);
220 else
221 sprintf(BPfilename, "%s%d", BIN_FILE_NAME, unit);
223 if((BP = fopen(BPfilename, "r")) != NULL)
225 char buffer[1024];
226 fclose(BP);
227 sprintf(buffer, "%s%s", BPfilename, DECODE_FILE_NAME_BAK);
228 rename(BPfilename, buffer);
230 if((BP = fopen(BPfilename, "w")) == NULL)
232 char buffer[80];
234 sprintf(buffer, "Error opening file [%s]", BPfilename);
235 perror(buffer);
236 exit(1);
239 if((setvbuf(BP, (char *)NULL, _IONBF, 0)) != 0)
241 char buffer[80];
243 sprintf(buffer, "Error setting file [%s] to unbuffered", BPfilename);
244 perror(buffer);
245 exit(1);
249 if(Popt)
251 if(bpopt)
252 sprintf(BPfilename, "%s", binfile);
253 else
254 sprintf(BPfilename, "%s%d", BIN_FILE_NAME, unit);
256 if((BP = fopen(BPfilename, "r")) == NULL)
258 char buffer[80];
260 sprintf(buffer, "Error opening file [%s]", BPfilename);
261 perror(buffer);
262 exit(1);
265 else
267 sprintf(devicename, "%s%d", I4BTRC_DEVICE, unit);
269 if((f = open(devicename, O_RDWR)) < 0)
271 char buffer[80];
273 sprintf(buffer, "Error opening trace device [%s]", devicename);
274 perror(buffer);
275 exit(1);
279 if(outflag)
281 if(outfileset == 0)
282 sprintf(outfilename, "%s%d", DECODE_FILE_NAME, unit);
283 else
284 strcpy(outfilename, outfile);
287 if((Fout = fopen(outfilename, "r")) != NULL)
289 char buffer[1024];
290 fclose(Fout);
291 sprintf(buffer, "%s%s", outfilename, DECODE_FILE_NAME_BAK);
292 rename(outfilename, buffer);
295 if((Fout = fopen(outfilename, "w")) == NULL)
297 char buffer[80];
299 sprintf(buffer, "Error opening file [%s]", outfilename);
300 perror(buffer);
301 exit(1);
304 if((setvbuf(Fout, (char *)NULL, _IONBF, 0)) != 0)
306 char buffer[80];
308 sprintf(buffer, "Error setting file [%s] to unbuffered", outfile);
309 perror(buffer);
310 exit(1);
314 if((setvbuf(stdout, (char *)NULL, _IOLBF, 0)) != 0)
316 char buffer[80];
318 sprintf(buffer, "Error setting stdout to line-buffered");
319 perror(buffer);
320 exit(1);
323 if(!Popt)
325 if((switch_driver(enable_trace, Rx, Tx)) == -1)
326 exit(1);
327 else
328 traceon = 1;
331 signal(SIGHUP, SIG_IGN); /* ignore hangup signal */
332 signal(SIGUSR1, reopenfiles); /* rotate logfile(s) */
334 time(&tm);
336 if(analyze)
338 sprintf(headerbuf, "\n==== isdnanalyze controller rx #%d - tx #%d ==== started %s",
339 Rx, Tx, ctime(&tm));
341 else
343 sprintf(headerbuf, "\n=========== isdntrace controller #%d =========== started %s",
344 unit, ctime(&tm));
347 printf("%s", headerbuf);
349 if(outflag)
350 fprintf(Fout, "%s", headerbuf);
352 for (;;)
354 if(Popt == 0)
356 n = read(f, buf, BSIZE);
358 if(Bopt)
360 if((fwrite(buf, 1, n, BP)) != n)
362 char buffer[80];
363 sprintf(buffer, "Error writing file [%s]", BPfilename);
364 perror(buffer);
365 exit(1);
369 n -= sizeof(i4b_trace_hdr_t);
371 else
373 if((fread(buf, 1, sizeof(i4b_trace_hdr_t), BP)) != sizeof(i4b_trace_hdr_t))
375 if(feof(BP))
377 printf("\nEnd of playback input file reached.\n");
378 exit(0);
380 else
382 char buffer[80];
383 sprintf(buffer, "Error reading hdr from file [%s]", BPfilename);
384 perror(buffer);
385 exit(1);
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)
394 char buffer[80];
395 sprintf(buffer, "Error reading data from file [%s]", BPfilename);
396 perror(buffer);
397 exit(1);
402 if(n > 0)
404 dumpbuf(n, b, (i4b_trace_hdr_t *)buf);
409 /*---------------------------------------------------------------------------*
410 * format header into static buffer, return buffer address
411 *---------------------------------------------------------------------------*/
412 char *
413 fmt_hdr(i4b_trace_hdr_t *hdr, int frm_len)
415 struct tm *s;
416 static char hbuf[256];
417 int i = 0;
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"),
425 hdr->unit,
426 s->tm_mday,
427 s->tm_mon + 1,
428 s->tm_hour,
429 s->tm_min,
430 s->tm_sec,
431 (u_int32_t)hdr->time.tv_usec);
433 else
435 if(hdr->trunc > 0)
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"),
439 hdr->unit,
440 hdr->count,
441 s->tm_mday,
442 s->tm_mon + 1,
443 s->tm_hour,
444 s->tm_min,
445 s->tm_sec,
446 (u_int32_t)hdr->time.tv_usec,
447 frm_len,
448 hdr->trunc);
450 else
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"),
454 hdr->unit,
455 hdr->count,
456 s->tm_mday,
457 s->tm_mon + 1,
458 s->tm_hour,
459 s->tm_min,
460 s->tm_sec,
461 (u_int32_t)hdr->time.tv_usec,
462 frm_len);
466 for(i=strlen(hbuf); i <= NCOLS;)
467 hbuf[i++] = '-';
469 hbuf[i++] = '\n';
470 hbuf[i] = '\0';
472 return(hbuf);
475 /*---------------------------------------------------------------------------*
476 * decode protocol and output to file(s)
477 *---------------------------------------------------------------------------*/
478 static void
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];
484 int cnt;
485 int nsave = n;
486 char *pbuf;
487 int i, j;
489 l1buf[0] = '\0';
490 l2buf[0] = '\0';
491 l3buf[0] = '\0';
493 switch(hdr->type)
495 case TRC_CH_I: /* Layer 1 INFO's */
496 if(enable_trace & TRACE_I)
497 layer1(l1buf, buf);
498 break;
500 case TRC_CH_D: /* D-channel data */
501 cnt = layer2(l2buf, buf, hdr->dir, print_q921);
503 if(print_q921 == 0)
504 l2buf[0] = '\0';
506 n -= cnt;
507 buf += cnt;
509 if(n)
511 if((*buf != 0x08) && (xflag == 0))
513 l2buf[0] = '\0';
514 l3buf[0] = '\0';
515 break;
517 layer3(l3buf, n, cnt, buf);
519 break;
521 default: /* B-channel data */
523 pbuf = &l2buf[0];
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++)
530 if (i + j < n)
531 sprintf((pbuf+strlen(pbuf)),"%02x ", buf[i + j]);
532 else
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]);
540 else
541 sprintf((pbuf+strlen(pbuf)),".");
543 sprintf((pbuf+strlen(pbuf)),"\n");
545 break;
548 if(header && ((l1buf[0] != '\0' || l2buf[0] != '\0') || (l3buf[0] != 0)))
550 char *p;
551 p = fmt_hdr(hdr, nsave);
552 printf("%s", p);
553 if(outflag)
554 fprintf(Fout, "%s", p);
557 if(l1buf[0] != '\0')
559 printf("%s", l1buf);
560 if(outflag)
561 fprintf(Fout, "%s", l1buf);
564 if(l2buf[0] != '\0')
566 printf("%s", l2buf);
567 if(outflag)
568 fprintf(Fout, "%s", l2buf);
571 if(l3buf[0] != '\0')
573 printf("%s", l3buf);
574 if(outflag)
575 fprintf(Fout, "%s", l3buf);
579 /*---------------------------------------------------------------------------*
580 * exit handler function to be called at program exit
581 *---------------------------------------------------------------------------*/
582 void
583 exit_hdl(void)
585 if(traceon)
586 switch_driver(TRACE_OFF, Rx, Tx);
589 /*---------------------------------------------------------------------------*
590 * switch driver debugging output on/off
591 *---------------------------------------------------------------------------*/
592 static int
593 switch_driver(int value, int rx, int tx)
595 char buffer[80];
596 int v = value;
598 if(analyze == 0)
600 if(ioctl(f, I4B_TRC_SET, &v) < 0)
602 sprintf(buffer, "Error ioctl I4B_TRC_SET, val = %d", v);
603 perror(buffer);
604 return(-1);
607 else
609 if(value == TRACE_OFF)
611 if(ioctl(f, I4B_TRC_RESETA, &v) < 0)
613 sprintf(buffer, "Error ioctl I4B_TRC_RESETA - ");
614 perror(buffer);
615 return(-1);
618 else
620 i4b_trace_setupa_t tsa;
622 tsa.rxunit = rx;
623 tsa.rxflags = value;
624 tsa.txunit = tx;
625 tsa.txflags = value;
627 if(ioctl(f, I4B_TRC_SETA, &tsa) < 0)
629 sprintf(buffer, "Error ioctl I4B_TRC_SETA, val = %d", v);
630 perror(buffer);
631 return(-1);
635 return(0);
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 *---------------------------------------------------------------------------*/
648 static void
649 reopenfiles(int dummy)
651 if(outflag)
653 fclose(Fout);
655 if((Fout = fopen(outfilename, "a")) == NULL)
657 char buffer[80];
659 sprintf(buffer, "Error re-opening file [%s]", outfilename);
660 perror(buffer);
661 exit(1);
664 if((setvbuf(Fout, (char *)NULL, _IONBF, 0)) != 0)
666 char buffer[80];
668 sprintf(buffer, "Error re-setting file [%s] to unbuffered", outfilename);
669 perror(buffer);
670 exit(1);
674 if(Bopt)
677 fclose(BP);
679 if((BP = fopen(BPfilename, "a")) == NULL)
681 char buffer[80];
683 sprintf(buffer, "Error re-opening file [%s]", BPfilename);
684 perror(buffer);
685 exit(1);
688 if((setvbuf(BP, (char *)NULL, _IONBF, 0)) != 0)
690 char buffer[80];
692 sprintf(buffer, "Error re-setting file [%s] to unbuffered", BPfilename);
693 perror(buffer);
694 exit(1);
699 /*---------------------------------------------------------------------------*
700 * decode extension bit
701 *---------------------------------------------------------------------------*/
702 void
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 *---------------------------------------------------------------------------*/
713 static char *
714 print_bits(unsigned char val, unsigned char mask)
716 static char buffer[10];
717 int i = 0;
718 int length = 8;
720 while(length--)
722 if(mask & 0x80)
724 if(val & 0x80)
725 buffer[i++] = '1';
726 else
727 buffer[i++] = '0';
729 else
731 buffer[i++] = '-';
733 val = val << 1;
734 mask = mask << 1;
736 buffer[i] = '\0';
737 return(buffer);
740 /*---------------------------------------------------------------------------*
741 * print one decoded output line
742 *---------------------------------------------------------------------------*/
743 void
744 sprintline(int layer, char *buffer, int oct_count, int oct_val,
745 int oct_mask, const char *fmt, ...)
747 char lbuffer[256];
748 static int lastcount = -1;
749 char *ptr;
750 va_list ap;
752 va_start(ap, fmt);
754 if(oct_count != lastcount)
756 lastcount = oct_count;
758 sprintf(lbuffer, "L%d %2d %02X %s ",
759 layer,
760 oct_count,
761 oct_val,
762 print_bits(oct_val, oct_mask));
764 else
766 sprintf(lbuffer, " %s ",
767 print_bits(oct_val, oct_mask));
770 vsprintf(lbuffer+strlen(lbuffer), fmt, ap);
772 va_end(ap);
774 sprintf(lbuffer+strlen(lbuffer), "\n");
776 if((ptr = rindex(lbuffer, '(')) != NULL)
778 char *s = lbuffer;
779 char *b = buffer;
780 int len = strlen(lbuffer);
781 int i;
783 for(s = lbuffer; s < ptr; *b++ = *s++)
785 for(i = 0;(i+len) <= NCOLS; *b++ = ' ', i++)
787 for(; *s; *b++ = *s++)
789 *b = '\0';
791 else
793 strcpy(buffer, lbuffer);
797 /* EOF */