Add a manual page explaining the format of /etc/manpath.config.
[dragonfly/vkernel-mp.git] / usr.sbin / i4b / isdntrace / trace.c
blobce81bb3deb0901227dda15b97f4eda40a3a7926c
1 /*
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
8 * are met:
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
31 * SUCH DAMAGE.
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 $
40 * $FreeBSD: src/usr.sbin/i4b/isdntrace/trace.c,v 1.8.2.1 2001/08/01 17:45:08 obrien Exp $
41 * $DragonFly: src/usr.sbin/i4b/isdntrace/trace.c,v 1.3 2005/11/25 01:58:52 swildner Exp $
43 * last edit-date: [Mon Aug 28 09:03:46 2000]
45 *---------------------------------------------------------------------------*/
47 #include "trace.h"
49 unsigned char buf[BSIZE];
50 FILE *Fout = NULL;
51 FILE *BP = NULL;
52 int outflag = 1;
53 int header = 1;
54 int print_q921 = 1;
55 int unit = 0;
56 int dchan = 0;
57 int bchan = 0;
58 int traceon = 0;
59 int analyze = 0;
60 int Rx = RxUDEF;
61 int Tx = TxUDEF;
62 int f;
63 int Bopt = 0;
64 int Popt = 0;
65 int bpopt = 0;
66 int info = 0;
67 int Fopt = 0;
68 int xopt = 1;
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 /*---------------------------------------------------------------------------*
87 * usage instructions
88 *---------------------------------------------------------------------------*/
89 void
90 usage(void)
92 fprintf(stderr,"\n");
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");
115 exit(1);
118 /*---------------------------------------------------------------------------*
119 * main
120 *---------------------------------------------------------------------------*/
122 main(int argc, char *argv[])
124 extern int optind;
125 extern int opterr;
126 extern char *optarg;
127 char devicename[80];
128 char headerbuf[256];
130 int n;
131 int c;
132 char *b;
134 char *outfile = TRACE_FILE_NAME;
135 char *binfile = BIN_FILE_NAME;
136 int outfileset = 0;
137 int raw = 1;
138 int noct = -1;
139 time_t tm;
140 i4b_trace_hdr_t *ithp = NULL;
141 int l;
142 static struct stat fstnew;
144 b = &buf[sizeof(i4b_trace_hdr_t)];
146 while( (c = getopt(argc, argv, "abdf:hiln:op:ru:xBFPR:T:")) != -1)
148 switch(c)
150 case 'a':
151 analyze = 1;
152 break;
154 case 'b':
155 enable_trace |= (TRACE_B_RX | TRACE_B_TX);
156 break;
158 case 'd':
159 enable_trace &= (~(TRACE_D_TX | TRACE_D_RX));
160 break;
162 case 'o':
163 outflag = 0;
164 break;
166 case 'f':
167 outfile = optarg;
168 outfileset = 1;
169 break;
171 case 'n':
172 noct = atoi(optarg);
173 break;
175 case 'h':
176 header = 0;
177 break;
179 case 'i':
180 enable_trace |= TRACE_I;
181 info = 1;
182 break;
184 case 'l':
185 print_q921 = 0;
186 break;
188 case 'p':
189 binfile = optarg;
190 bpopt = 1;
191 break;
193 case 'r':
194 raw = 0;
195 break;
197 case 'u':
198 unit = atoi(optarg);
199 if(unit < 0 || unit >= MAX_CONTROLLERS)
200 usage();
201 break;
203 case 'x':
204 xopt = 0;
205 break;
207 case 'B':
208 Bopt = 1;
209 break;
211 case 'F':
212 Fopt = 1;
213 break;
215 case 'P':
216 Popt = 1;
217 break;
219 case 'R':
220 Rx = atoi(optarg);
221 if(Rx < 0 || Rx >= MAX_CONTROLLERS)
222 usage();
223 break;
225 case 'T':
226 Tx = atoi(optarg);
227 if(Tx < 0 || Tx >= MAX_CONTROLLERS)
228 usage();
229 break;
231 case '?':
232 default:
233 usage();
234 break;
238 if(enable_trace == 0)
239 usage();
241 if(Bopt && Popt)
242 usage();
244 atexit(exit_hdl);
246 if(Bopt)
248 if(bpopt)
249 sprintf(BPfilename, "%s", binfile);
250 else
251 sprintf(BPfilename, "%s%d", BIN_FILE_NAME, unit);
253 add_datetime(BPfilename, rBPfilename);
255 if((BP = fopen(rBPfilename, "w")) == NULL)
257 char buffer[80];
259 sprintf(buffer, "Error opening file [%s]", rBPfilename);
260 perror(buffer);
261 exit(1);
264 if((setvbuf(BP, (char *)NULL, _IONBF, 0)) != 0)
266 char buffer[80];
268 sprintf(buffer, "Error setting file [%s] to unbuffered", rBPfilename);
269 perror(buffer);
270 exit(1);
274 if(Popt)
276 if(bpopt)
277 sprintf(BPfilename, "%s", binfile);
278 else
279 sprintf(BPfilename, "%s%d", BIN_FILE_NAME, unit);
281 strcpy(rBPfilename, BPfilename);
283 if((BP = fopen(BPfilename, "r")) == NULL)
285 char buffer[80];
287 sprintf(buffer, "Error opening file [%s]", BPfilename);
288 perror(buffer);
289 exit(1);
291 if(Fopt)
293 if(fstat(fileno(BP), &fst))
295 char buffer[80];
296 sprintf(buffer, "Error fstat file [%s]", BPfilename);
297 perror(buffer);
298 exit(1);
302 else
304 sprintf(devicename, "%s%d", I4BTRC_DEVICE, unit);
306 if((f = open(devicename, O_RDWR)) < 0)
308 char buffer[80];
310 sprintf(buffer, "Error opening trace device [%s]", devicename);
311 perror(buffer);
312 exit(1);
316 if(outflag)
318 if(outfileset == 0)
319 sprintf(outfilename, "%s%d", TRACE_FILE_NAME, unit);
320 else
321 strcpy(outfilename, outfile);
323 add_datetime(outfilename, routfilename);
325 if((Fout = fopen(routfilename, "w")) == NULL)
327 char buffer[80];
329 sprintf(buffer, "Error opening file [%s]", routfilename);
330 perror(buffer);
331 exit(1);
334 if((setvbuf(Fout, (char *)NULL, _IONBF, 0)) != 0)
336 char buffer[80];
338 sprintf(buffer, "Error setting file [%s] to unbuffered", routfilename);
339 perror(buffer);
340 exit(1);
344 if((setvbuf(stdout, (char *)NULL, _IOLBF, 0)) != 0)
346 char buffer[80];
348 sprintf(buffer, "Error setting stdout to line-buffered");
349 perror(buffer);
350 exit(1);
353 if(!Popt)
355 if((switch_driver(enable_trace, Rx, Tx)) == -1)
356 exit(1);
357 else
358 traceon = 1;
361 signal(SIGHUP, SIG_IGN); /* ignore hangup signal */
362 signal(SIGUSR1, reopenfiles); /* rotate logfile(s) */
364 time(&tm);
366 if(analyze)
368 sprintf(headerbuf, "\n==== isdnanalyze controller rx #%d - tx #%d ==== started %s",
369 Rx, Tx, ctime(&tm));
371 else
373 sprintf(headerbuf, "\n=========== isdntrace controller #%d =========== started %s",
374 unit, ctime(&tm));
377 printf("%s", headerbuf);
379 if(outflag)
380 fprintf(Fout, "%s", headerbuf);
382 for (;;)
384 if(Popt == 0)
386 n = read(f, buf, BSIZE);
388 if(Bopt)
390 if((fwrite(buf, 1, n, BP)) != n)
392 char buffer[80];
393 sprintf(buffer, "Error writing file [%s]", rBPfilename);
394 perror(buffer);
395 exit(1);
399 n -= sizeof(i4b_trace_hdr_t);
401 else
403 again:
404 if((fread(buf, 1, sizeof(i4b_trace_hdr_t), BP)) != sizeof(i4b_trace_hdr_t))
406 if(feof(BP))
408 if(Fopt)
410 if(ferror(BP))
412 char buffer[80];
413 sprintf(buffer, "Error reading hdr from file [%s]", rBPfilename);
414 perror(buffer);
415 exit(1);
418 usleep(250000);
419 clearerr(BP);
421 if(stat(rBPfilename, &fstnew) != -1)
423 if((fst.st_ino != fstnew.st_ino) ||
424 (fstnew.st_nlink == 0))
426 if((BP = freopen(rBPfilename, "r", BP)) == NULL)
428 char buffer[80];
429 sprintf(buffer, "Error reopening file [%s]", rBPfilename);
430 perror(buffer);
431 exit(1);
433 stat(rBPfilename, &fst);
436 goto again;
438 else
440 printf("\nEnd of playback input file reached.\n");
441 exit(0);
444 else
446 char buffer[80];
447 sprintf(buffer, "Error reading hdr from file [%s]", rBPfilename);
448 perror(buffer);
449 exit(1);
453 ithp = (i4b_trace_hdr_t *)buf;
454 l = ithp->length - sizeof(i4b_trace_hdr_t);
456 if((n = fread(buf+sizeof(i4b_trace_hdr_t), 1, l , BP)) != l)
458 char buffer[80];
459 sprintf(buffer, "Error reading data from file [%s]", rBPfilename);
460 perror(buffer);
461 exit(1);
466 if((n > 0) && (n > noct))
468 dumpbuf(n, b, (i4b_trace_hdr_t *)buf, raw);
473 /*---------------------------------------------------------------------------*
474 * format header into static buffer, return buffer address
475 *---------------------------------------------------------------------------*/
476 char *
477 fmt_hdr(i4b_trace_hdr_t *hdr, int frm_len)
479 struct tm *s;
480 static char hbuf[256];
481 int i = 0;
483 s = localtime((time_t *)&(hdr->time.tv_sec));
485 if(hdr->type == TRC_CH_I) /* Layer 1 INFO's */
487 sprintf(hbuf,"\n-- %s - unit:%d ---------------- time:%2.2d.%2.2d %2.2d:%2.2d:%2.2d.%06u ",
488 ((hdr->dir) ? "NT->TE" : "TE->NT"),
489 hdr->unit,
490 s->tm_mday,
491 s->tm_mon + 1,
492 s->tm_hour,
493 s->tm_min,
494 s->tm_sec,
495 (u_int32_t)hdr->time.tv_usec);
497 else
499 if(hdr->trunc > 0)
501 sprintf(hbuf,"\n-- %s - unit:%d - frame:%6.6u - time:%2.2d.%2.2d %2.2d:%2.2d:%2.2d.%06u - length:%d (%d) ",
502 ((hdr->dir) ? "NT->TE" : "TE->NT"),
503 hdr->unit,
504 hdr->count,
505 s->tm_mday,
506 s->tm_mon + 1,
507 s->tm_hour,
508 s->tm_min,
509 s->tm_sec,
510 (u_int32_t)hdr->time.tv_usec,
511 frm_len,
512 hdr->trunc);
514 else
516 sprintf(hbuf,"\n-- %s - unit:%d - frame:%6.6u - time:%2.2d.%2.2d %2.2d:%2.2d:%2.2d.%06u - length:%d ",
517 ((hdr->dir) ? "NT->TE" : "TE->NT"),
518 hdr->unit,
519 hdr->count,
520 s->tm_mday,
521 s->tm_mon + 1,
522 s->tm_hour,
523 s->tm_min,
524 s->tm_sec,
525 (u_int32_t)hdr->time.tv_usec,
526 frm_len);
530 for(i=strlen(hbuf); i <= NCOLS;)
531 hbuf[i++] = '-';
533 hbuf[i++] = '\n';
534 hbuf[i] = '\0';
536 return(hbuf);
539 /*---------------------------------------------------------------------------*
540 * decode protocol and output to file(s)
541 *---------------------------------------------------------------------------*/
542 static void
543 dumpbuf(int n, unsigned char *buf, i4b_trace_hdr_t *hdr, int raw)
545 static char l1buf[128];
546 static unsigned char l2buf[32000];
547 static unsigned char l3buf[32000];
548 int cnt;
549 int nsave = n;
550 char *pbuf;
551 int i, j;
553 l1buf[0] = '\0';
554 l2buf[0] = '\0';
555 l3buf[0] = '\0';
557 switch(hdr->type)
559 case TRC_CH_I: /* Layer 1 INFO's */
561 /* on playback, don't display layer 1 if -i ! */
562 if(!(enable_trace & TRACE_I))
563 break;
565 pbuf = &l1buf[0];
567 switch(buf[0])
569 case INFO0:
570 sprintf((pbuf+strlen(pbuf)),"I430: INFO0 (No Signal)\n");
571 break;
573 case INFO1_8:
574 sprintf((pbuf+strlen(pbuf)),"I430: INFO1 (Activation Request, Priority = 8, from TE)\n");
575 break;
577 case INFO1_10:
578 sprintf((pbuf+strlen(pbuf)),"I430: INFO1 (Activation Request, Priority = 10, from TE)\n");
579 break;
581 case INFO2:
582 sprintf((pbuf+strlen(pbuf)),"I430: INFO2 (Pending Activation, from NT)\n");
583 break;
585 case INFO3:
586 sprintf((pbuf+strlen(pbuf)),"I430: INFO3 (Synchronized, from TE)\n");
587 break;
589 case INFO4_8:
590 sprintf((pbuf+strlen(pbuf)),"I430: INFO4 (Activated, Priority = 8/9, from NT)\n");
591 break;
593 case INFO4_10:
594 sprintf((pbuf+strlen(pbuf)),"I430: INFO4 (Activated, Priority = 10/11, from NT)\n");
595 break;
597 default:
598 sprintf((pbuf+strlen(pbuf)),"I430: ERROR, invalid INFO value 0x%x!\n", buf[0]);
599 break;
601 break;
603 case TRC_CH_D: /* D-channel data */
605 cnt = decode_lapd(l2buf, n, buf, hdr->dir, raw, print_q921);
607 n -= cnt;
608 buf += cnt;
610 if(n)
612 switch(*buf)
614 case 0x40:
615 case 0x41:
616 decode_1tr6(l3buf, n, cnt, buf, raw);
617 break;
619 case 0x08:
620 decode_q931(l3buf, n, cnt, buf, raw);
621 break;
623 default:
624 if(xopt)
626 l2buf[0] = '\0';
627 l3buf[0] = '\0';
629 else
631 decode_unknownl3(l3buf, n, cnt, buf, raw);
633 break;
636 break;
638 default: /* B-channel data */
640 pbuf = &l2buf[0];
642 for (i = 0; i < n; i += 16)
644 sprintf((pbuf+strlen(pbuf)),"B%d:%.3x ", hdr->type, i);
646 for (j = 0; j < 16; j++)
647 if (i + j < n)
648 sprintf((pbuf+strlen(pbuf)),"%02x ", buf[i + j]);
649 else
650 sprintf((pbuf+strlen(pbuf))," ");
652 sprintf((pbuf+strlen(pbuf))," ");
654 for (j = 0; j < 16 && i + j < n; j++)
655 if (isprint(buf[i + j]))
656 sprintf((pbuf+strlen(pbuf)),"%c", buf[i + j]);
657 else
658 sprintf((pbuf+strlen(pbuf)),".");
660 sprintf((pbuf+strlen(pbuf)),"\n");
662 break;
665 if(header && ((l1buf[0] != '\0' || l2buf[0] != '\0') || (l3buf[0] != 0)))
667 char *p;
668 p = fmt_hdr(hdr, nsave);
669 printf("%s", p);
670 if(outflag)
671 fprintf(Fout, "%s", p);
674 if(l1buf[0] != '\0')
676 printf("%s", l1buf);
677 if(outflag)
678 fprintf(Fout, "%s", l1buf);
681 if(l2buf[0] != '\0')
683 printf("%s", l2buf);
684 if(outflag)
685 fprintf(Fout, "%s", l2buf);
688 if(l3buf[0] != '\0')
690 printf("%s", l3buf);
691 if(outflag)
692 fprintf(Fout, "%s", l3buf);
696 /*---------------------------------------------------------------------------*
697 * exit handler function to be called at program exit
698 *---------------------------------------------------------------------------*/
699 void
700 exit_hdl(void)
702 if(traceon)
703 switch_driver(TRACE_OFF, Rx, Tx);
706 /*---------------------------------------------------------------------------*
707 * switch driver debugging output on/off
708 *---------------------------------------------------------------------------*/
709 static int
710 switch_driver(int value, int rx, int tx)
712 char buffer[80];
713 int v = value;
715 if(analyze == 0)
717 if(ioctl(f, I4B_TRC_SET, &v) < 0)
719 sprintf(buffer, "Error ioctl I4B_TRC_SET, val = %d", v);
720 perror(buffer);
721 return(-1);
724 else
726 if(value == TRACE_OFF)
728 if(ioctl(f, I4B_TRC_RESETA, &v) < 0)
730 sprintf(buffer, "Error ioctl I4B_TRC_RESETA - ");
731 perror(buffer);
732 return(-1);
735 else
737 i4b_trace_setupa_t tsa;
739 tsa.rxunit = rx;
740 tsa.rxflags = value;
741 tsa.txunit = tx;
742 tsa.txflags = value;
744 if(ioctl(f, I4B_TRC_SETA, &tsa) < 0)
746 sprintf(buffer, "Error ioctl I4B_TRC_SETA, val = %d", v);
747 perror(buffer);
748 return(-1);
752 return(0);
755 /*---------------------------------------------------------------------------*
756 * reopen files to support rotating logfile(s) on SIGUSR1
758 * based on an idea from Ripley (ripley@nostromo.in-berlin.de)
760 * close file and reopen it for append. this will be a nop
761 * if the previously opened file hasn't moved but will open
762 * a new one otherwise, thus enabling a rotation...
764 *---------------------------------------------------------------------------*/
765 static void
766 reopenfiles(int dummy)
768 if(outflag)
770 fclose(Fout);
772 add_datetime(outfilename, routfilename);
774 if((Fout = fopen(routfilename, "a")) == NULL)
776 char buffer[80];
778 sprintf(buffer, "Error re-opening file [%s]", routfilename);
779 perror(buffer);
780 exit(1);
783 if((setvbuf(Fout, (char *)NULL, _IONBF, 0)) != 0)
785 char buffer[80];
787 sprintf(buffer, "Error re-setting file [%s] to unbuffered", routfilename);
788 perror(buffer);
789 exit(1);
793 if(Bopt)
796 fclose(BP);
798 add_datetime(BPfilename, rBPfilename);
800 if((BP = fopen(rBPfilename, "a")) == NULL)
802 char buffer[80];
804 sprintf(buffer, "Error re-opening file [%s]", rBPfilename);
805 perror(buffer);
806 exit(1);
809 if((setvbuf(BP, (char *)NULL, _IONBF, 0)) != 0)
811 char buffer[80];
813 sprintf(buffer, "Error re-setting file [%s] to unbuffered", rBPfilename);
814 perror(buffer);
815 exit(1);
820 void
821 add_datetime(char *filename, char *rfilename)
823 time_t timeb;
824 struct tm *tmp;
825 FILE *fx;
827 time(&timeb);
828 tmp = localtime(&timeb);
830 sprintf(rfilename, "%s-", filename);
832 strftime(rfilename+strlen(rfilename), MAXPATHLEN-strlen(rfilename)-1,
833 "%Y%m%d-%H%M%S", tmp);
835 if((fx = fopen(rfilename, "r")) != NULL)
837 fclose(fx);
839 sleep(1);
841 time(&timeb);
842 tmp = localtime(&timeb);
844 sprintf(rfilename, "%s-", filename);
846 strftime(rfilename+strlen(rfilename), MAXPATHLEN-strlen(rfilename)-1,
847 "%Y%m%d-%H%M%S", tmp);
851 /* EOF */