2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
5 * Copyright (c) 1983, 1988, 1993
6 * The Regents of the University of California. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgment:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * $FreeBSD: src/sbin/routed/trace.c,v 1.6 2000/08/11 08:24:38 sheldonh Exp $
40 #include "pathnames.h"
43 #include <sys/signal.h>
46 #include <protocols/routed.h>
48 #define NRECORDS 50 /* size of circular trace buffer */
50 int tracelevel
, new_tracelevel
;
51 FILE *ftrace
; /* output trace file */
52 static const char *sigtrace_pat
= "%s";
53 static char savetracename
[MAXPATHLEN
+1];
54 static char *ripcmds
[RIPCMD_MAX
] =
55 {"#0", "REQUEST", "RESPONSE", "TRACEON", "TRACEOFF", "POLL",
57 char inittracename
[MAXPATHLEN
+1];
58 static boolean_t file_trace
; /* 1=tracing to file, not stdout */
60 static void tmsg(const char *, ...);
65 const char *cp
= strerror(err
);
66 static char msgbuf
[64];
72 (void) snprintf(msgbuf
, sizeof (msgbuf
),
73 "unknown error %d", err
);
80 /* convert IP address to a string, but not into a single buffer */
82 naddr_ntoa(in_addr_t a
)
87 char str
[INET_ADDRSTRLEN
]; /* xxx.xxx.xxx.xxx\0 */
93 s
= strcpy(bufs
[bufno
].str
, inet_ntoa(addr
));
94 bufno
= (bufno
+1) % NUM_BUFS
;
101 saddr_ntoa(struct sockaddr_storage
*ss
)
103 return (ss
== NULL
) ? "?" : naddr_ntoa(S_ADDR(ss
));
112 secs
+= epoch
.tv_sec
;
113 (void) strftime(s
, sizeof (s
), "%T", localtime(&secs
));
118 ts_full(struct timeval
*tv
)
124 secs
= tv
->tv_sec
+ epoch
.tv_sec
;
125 (void) strftime(s
, sizeof (s
), "%Y/%m/%d %T", localtime(&secs
));
127 (void) snprintf(s
+ len
, sizeof (s
) - len
, ".%06ld", tv
->tv_usec
);
132 * On each event, display a time stamp.
133 * This assumes that 'now' is update once for each event, and
134 * that at least now.tv_usec changes.
136 static struct timeval lastlog_time
;
141 if (lastlog_time
.tv_sec
!= now
.tv_sec
||
142 lastlog_time
.tv_usec
!= now
.tv_usec
) {
143 (void) fprintf(ftrace
, "-- %s --\n", ts_full(&now
));
150 tmsg(const char *p
, ...)
154 if (ftrace
!= NULL
) {
157 (void) vfprintf(ftrace
, p
, args
);
158 (void) fputc('\n', ftrace
);
159 (void) fflush(ftrace
);
166 trace_close(int zap_stdio
)
171 (void) fflush(stdout
);
172 (void) fflush(stderr
);
174 if (ftrace
!= NULL
&& zap_stdio
) {
175 if (ftrace
!= stdout
)
176 (void) fclose(ftrace
);
178 fd
= open("/dev/null", O_RDWR
);
179 if (isatty(STDIN_FILENO
))
180 (void) dup2(fd
, STDIN_FILENO
);
181 if (isatty(STDOUT_FILENO
))
182 (void) dup2(fd
, STDOUT_FILENO
);
183 if (isatty(STDERR_FILENO
))
184 (void) dup2(fd
, STDERR_FILENO
);
187 lastlog_time
.tv_sec
= 0;
194 if (ftrace
!= NULL
) {
195 (void) fflush(ftrace
);
197 trace_off("tracing off: %s",
198 rip_strerror(ferror(ftrace
)));
204 trace_off(const char *p
, ...)
209 if (ftrace
!= NULL
) {
212 (void) vfprintf(ftrace
, p
, args
);
213 (void) fputc('\n', ftrace
);
216 trace_close(file_trace
);
218 new_tracelevel
= tracelevel
= 0;
222 /* log a change in tracing */
224 tracelevel_msg(const char *pat
,
225 int dump
) /* -1=no dump, 0=default, 1=force */
227 static const char *off_msgs
[MAX_TRACELEVEL
] = {
228 "Tracing actions stopped",
229 "Tracing packets stopped",
230 "Tracing packet contents stopped",
231 "Tracing kernel changes stopped",
232 "Tracing routing socket messages stopped",
234 static const char *on_msgs
[MAX_TRACELEVEL
] = {
235 "Tracing actions started",
236 "Tracing packets started",
237 "Tracing packet contents started",
238 "Tracing kernel changes started",
239 "Tracing routing socket messages started",
241 uint_t old_tracelevel
= tracelevel
;
244 if (new_tracelevel
< 0)
246 else if (new_tracelevel
> MAX_TRACELEVEL
)
247 new_tracelevel
= MAX_TRACELEVEL
;
249 if (new_tracelevel
< tracelevel
) {
250 if (new_tracelevel
<= 0) {
251 trace_off(pat
, off_msgs
[0]);
254 tmsg(pat
, off_msgs
[tracelevel
]);
255 } while (--tracelevel
!= new_tracelevel
);
258 } else if (new_tracelevel
> tracelevel
) {
260 tmsg(pat
, on_msgs
[tracelevel
++]);
261 } while (tracelevel
!= new_tracelevel
);
265 (dump
== 0 && old_tracelevel
== 0 && tracelevel
!= 0))
270 set_tracefile(const char *filename
,
272 int dump
) /* -1=no dump, 0=default, 1=force */
279 boolean_t allow_create
;
282 * main() calls this routine with "dump == -1". All others
283 * call it with 0, so we take dump == -1 to mean "can create
286 allow_create
= (dump
== -1);
289 * Allow a null filename to increase the level if the trace file
290 * is already open or if coming from a trusted source, such as
291 * a signal or the command line.
293 if (filename
== NULL
|| filename
[0] == '\0') {
295 if (ftrace
== NULL
) {
296 if (inittracename
[0] == '\0') {
297 msglog("missing trace file name");
305 } else if (strcmp(filename
, "dump/../table") == 0) {
311 * Allow the file specified with "-T file" to be reopened,
312 * but require all other names specified over the net to
313 * match the official path. The path can specify a directory
314 * in which the file is to be created.
317 if (strcmp(filename
, inittracename
) != 0) {
318 if (strncmp(filename
, PATH_TRACE
,
319 sizeof (PATH_TRACE
)-1) != 0 ||
320 (strstr(filename
, "../") != NULL
)) {
321 msglog("wrong trace file \"%s\"", filename
);
324 if (stat(PATH_TRACE
, &stbuf
) == -1) {
328 if (filename
[sizeof (PATH_TRACE
) - 1] != '\0' &&
329 (filename
[sizeof (PATH_TRACE
) - 1] != '/' ||
330 !S_ISDIR(stbuf
.st_mode
))) {
333 if (S_ISDIR(stbuf
.st_mode
))
334 allow_create
= _B_TRUE
;
339 /* fn cannot be null here */
341 /* If the new tracefile exists, it must be a regular file. */
342 if (lstat(fn
, &stbuf
) == -1) {
345 nfd
= open(fn
, O_CREAT
|O_EXCL
|O_WRONLY
, 0644);
346 if (nfd
!= -1 && fstat(nfd
, &stbuf
) == -1) {
350 } else if (S_ISREG(stbuf
.st_mode
)) {
351 nfd
= open(fn
, O_APPEND
|O_WRONLY
, 0644);
356 if (nfd
== -1 || (n_ftrace
= fdopen(nfd
, "a")) == NULL
) {
357 msglog("failed to open trace file \"%s\" %s", fn
,
358 rip_strerror(errno
));
359 if (fn
== inittracename
)
360 inittracename
[0] = '\0';
366 if (fstat(nfd
, &stbuf2
) == -1 || !S_ISREG(stbuf2
.st_mode
) ||
367 stbuf2
.st_dev
!= stbuf
.st_dev
|| stbuf2
.st_ino
!= stbuf
.st_ino
) {
368 msglog("trace file \"%s\" moved", fn
);
369 (void) fclose(n_ftrace
);
373 tmsg("switch to trace file %s", fn
);
374 trace_close(file_trace
= _B_TRUE
);
375 (void) dup2(nfd
, STDOUT_FILENO
);
376 (void) dup2(nfd
, STDERR_FILENO
);
378 if (fn
!= savetracename
)
379 (void) strlcpy(savetracename
, fn
, sizeof (savetracename
) - 1);
383 if (new_tracelevel
== 0 || filename
== NULL
)
385 tracelevel_msg(pat
, dump
!= 0 ? dump
: (filename
!= NULL
));
389 msglog("trace \"%s\" missing", fn
);
393 msglog("wrong type (%#x) of trace file \"%s\"", stbuf
.st_mode
, fn
);
402 sigtrace_pat
= "SIGUSR1: %s";
403 if (signal(s
, sigtrace_more
) == SIG_ERR
)
404 msglog("signal: %s", rip_strerror(errno
));
413 sigtrace_pat
= "SIGUSR2: %s";
414 if (signal(s
, sigtrace_less
) == SIG_ERR
)
415 msglog("signal: %s", rip_strerror(errno
));
423 if (signal(s
, sigtrace_dump
) == SIG_ERR
)
424 msglog("signal: %s", rip_strerror(errno
));
427 /* Set tracing after a signal. */
431 if (new_tracelevel
== tracelevel
)
435 * If tracing entirely off, and there was no tracefile specified
436 * on the command line, then leave it off.
438 if (new_tracelevel
> tracelevel
&& ftrace
== NULL
) {
439 if (savetracename
[0] != '\0') {
440 set_tracefile(savetracename
, sigtrace_pat
, 0);
441 } else if (inittracename
[0] != '\0') {
442 set_tracefile(inittracename
, sigtrace_pat
, 0);
448 tracelevel_msg(sigtrace_pat
, 0);
453 /* display an address */
455 addrname(in_addr_t addr
, /* in network byte order */
457 int force
) /* 0=show mask if nonstandard, */
458 { /* 1=always show mask, 2=never */
463 * this array can hold either of the following strings terminated
464 * by a null character:
465 * "xxx.xxx.xxx.xxx/xx"
466 * "xxx.xxx.xxx.xxx (mask xxx.xxx.xxx.xxx)"
469 char str
[2*INET_ADDRSTRLEN
+ sizeof (" (mask )")];
474 struct in_addr tmp_addr
;
476 tmp_addr
.s_addr
= addr
;
477 len
= strlcpy(bufs
[bufno
].str
, inet_ntoa(tmp_addr
),
478 sizeof (bufs
[bufno
].str
));
480 bufno
= (bufno
+1) % NUM_BUFS
;
482 if (force
== 1 || (force
== 0 && mask
!= std_mask(addr
))) {
485 dmask
= mask
& -mask
;
486 if (mask
+ dmask
== 0) {
489 (sizeof (bufs
[bufno
].str
) - len
), "/%d",
490 (NBBY
* sizeof (in_addr_t
) + 1) - i
);
494 (sizeof (bufs
[bufno
].str
) - len
), " (mask %s)",
495 naddr_ntoa(htonl(mask
)));
504 /* display a bit-field */
507 const char *origin_name
;
510 static struct or_bits origin_bits
[] = {
512 { RO_RDISC
, "RDISC" },
513 { RO_STATIC
, "STATIC" },
514 { RO_LOOPBCK
, "LOOPBCK" },
515 { RO_PTOPT
, "PTOPT" },
516 { RO_NET_SYN
, "NET_SYN" },
523 /* display a bit-field */
527 const char *bits_name
;
530 static struct bits if_bits
[] = {
531 { IFF_BROADCAST
, 0, "BROADCAST" },
532 { IFF_DEBUG
, 0, "DEBUG" },
533 { IFF_LOOPBACK
, 0, "LOOPBACK" },
534 { IFF_POINTOPOINT
, 0, "POINTOPOINT" },
535 { IFF_NOTRAILERS
, 0, "NOTRAILERS" },
536 { IFF_RUNNING
, 0, "RUNNING" },
537 { IFF_NOARP
, 0, "NOARP" },
538 { IFF_PROMISC
, 0, "PROMISC" },
539 { IFF_ALLMULTI
, 0, "ALLMULTI" },
540 { IFF_INTELLIGENT
, 0, "INTELLIGENT" },
541 { IFF_MULTICAST
, 0, "MULTICAST" },
542 { IFF_MULTI_BCAST
, 0, "MULTI_BCAST" },
543 { IFF_UNNUMBERED
, 0, "UNNUMBERED" },
544 { IFF_DHCPRUNNING
, 0, "DHCP" },
545 { IFF_PRIVATE
, 0, "PRIVATE" },
546 { IFF_NOXMIT
, 0, "NOXMIT" },
547 { IFF_NOLOCAL
, 0, "NOLOCAL" },
548 { IFF_DEPRECATED
, 0, "DEPRECATED" },
549 { IFF_ADDRCONF
, 0, "ADDRCONF" },
550 { IFF_ROUTER
, 0, "ROUTER" },
551 { IFF_NONUD
, 0, "NONUD" },
552 { IFF_ANYCAST
, 0, "ANYCAST" },
553 { IFF_NORTEXCH
, 0, "NORTEXCH" },
554 { IFF_IPV4
, 0, "IPv4" },
555 { IFF_IPV6
, 0, "IPv6" },
556 { IFF_NOFAILOVER
, 0, "NOFAILOVER" },
557 { IFF_FAILED
, 0, "FAILED" },
558 { IFF_STANDBY
, 0, "STANDBY" },
559 { IFF_INACTIVE
, 0, "INACTIVE" },
560 { IFF_OFFLINE
, 0, "OFFLINE" },
561 { IFF_XRESOLV
, 0, "XRESOLV" },
562 { IFF_COS_ENABLED
, 0, "CoS" },
563 { IFF_PREFERRED
, 0, "PREFERRED" },
564 { IFF_TEMPORARY
, 0, "TEMPORARY" },
565 { IFF_FIXEDMTU
, 0, "FIXEDMTU" },
566 { IFF_VIRTUAL
, 0, "VIRTUAL"},
567 { IFF_IPMP
, 0, "IPMP"},
571 static struct bits is_bits
[] = {
572 { IS_ALIAS
, 0, "ALIAS" },
573 { IS_SUBNET
, 0, "" },
574 { IS_REMOTE
, (IS_NO_RDISC
|
575 IS_BCAST_RDISC
), "REMOTE" },
576 { IS_PASSIVE
, (IS_NO_RDISC
|
580 IS_NO_AG
), "PASSIVE" },
581 { IS_EXTERNAL
, 0, "EXTERNAL" },
582 { IS_CHECKED
, 0, "" },
583 { IS_ALL_HOSTS
, 0, "" },
584 { IS_ALL_ROUTERS
, 0, "" },
585 { IS_DISTRUST
, 0, "DISTRUST" },
586 { IS_BROKE
, IS_SICK
, "BROKEN" },
587 { IS_SICK
, 0, "SICK" },
588 { IS_DUP
, 0, "DUPLICATE" },
589 { IS_REDIRECT_OK
, 0, "REDIRECT_OK" },
590 { IS_NEED_NET_SYN
, 0, "" },
591 { IS_NO_AG
, IS_NO_SUPER_AG
, "NO_AG" },
592 { IS_NO_SUPER_AG
, 0, "NO_SUPER_AG" },
596 IS_NO_RIPV2_OUT
), 0, "NO_RIP" },
598 IS_NO_RIPV1_OUT
), 0, "RIPV2" },
599 { IS_NO_RIPV1_IN
, 0, "NO_RIPV1_IN" },
600 { IS_NO_RIPV2_IN
, 0, "NO_RIPV2_IN" },
601 { IS_NO_RIPV1_OUT
, 0, "NO_RIPV1_OUT" },
602 { IS_NO_RIPV2_OUT
, 0, "NO_RIPV2_OUT" },
603 { IS_NO_RIP_MCAST
, 0, "NO_RIP_MCAST" },
606 IS_NO_ADV_OUT
), IS_BCAST_RDISC
, "NO_RDISC" },
607 { IS_NO_SOL_OUT
, 0, "NO_SOLICIT" },
608 { IS_SOL_OUT
, 0, "SEND_SOLICIT" },
609 { IS_NO_ADV_OUT
, IS_BCAST_RDISC
, "NO_RDISC_ADV" },
610 { IS_ADV_OUT
, 0, "RDISC_ADV" },
611 { IS_BCAST_RDISC
, 0, "BCAST_RDISC" },
612 { IS_PM_RDISC
, 0, "" },
613 { IS_NO_HOST
, 0, "NO_HOST" },
614 { IS_SUPPRESS_RDISC
, 0, "SUPPRESS_RDISC" },
615 { IS_FLUSH_RDISC
, 0, "FLUSH_RDISC" },
619 static struct bits rs_bits
[] = {
621 { RS_NET_INT
, RS_NET_SYN
, "NET_INT" },
622 { RS_NET_SYN
, 0, "NET_SYN" },
623 { RS_SUBNET
, 0, "" },
624 { RS_LOCAL
, 0, "LOCAL" },
625 { RS_MHOME
, 0, "MHOME" },
626 { RS_STATIC
, 0, "STATIC" },
627 { RS_NOPROPAGATE
, 0, "NOPROP" },
628 { RS_BADIF
, 0, "BADIF" },
632 static struct bits ks_bits
[] = {
633 { KS_NEW
, 0, "NEW" },
634 { KS_DELETE
, 0, "DELETE" },
635 { KS_ADD
, 0, "ADD" },
636 { KS_CHANGE
, 0, "CHANGE" },
637 { KS_DEL_ADD
, 0, "DEL_ADD" },
638 { KS_STATIC
, 0, "STATIC" },
639 { KS_GATEWAY
, 0, "GATEWAY" },
640 { KS_DYNAMIC
, 0, "DYNAMIC" },
641 { KS_DELETED
, 0, "DELETED" },
642 { KS_PRIVATE
, 0, "PRIVATE" },
643 { KS_CHECK
, 0, "CHECK" },
645 { KS_PASSIVE
, 0, "PASSIVE" },
646 { KS_DEPRE_IF
, 0, "DEPRE_IF" },
647 { KS_FILE
, 0, "FILE" },
652 trace_bits(const struct bits
*tbl
,
660 (void) putc('<', ftrace
);
667 (b
= tbl
->bits_mask
) != 0) {
668 if ((b
& field
) == b
) {
669 if (tbl
->bits_name
[0] != '\0') {
671 (void) putc(c
, ftrace
);
672 (void) fprintf(ftrace
, "%s", tbl
->bits_name
);
675 field
&= ~(b
| tbl
->bits_clear
);
681 (void) putc(c
, ftrace
);
682 (void) fprintf(ftrace
, "%#llx", field
);
686 if (c
!= '<' || force
)
687 (void) fputs("> ", ftrace
);
691 trace_string(const struct bits
*tbl
, uint_t field
, boolean_t force
)
693 const struct bits
*tbp
;
694 char *sbuf
, *cp
, chr
;
697 /* minimum default string */
698 slen
= sizeof ("<0x12345678>");
699 for (tbp
= tbl
; tbp
->bits_mask
!= 0; tbp
++)
700 if (tbp
->bits_name
[0] != '\0')
701 slen
+= strlen(tbp
->bits_name
) + 1;
702 if ((sbuf
= malloc(slen
)) == NULL
)
713 while (field
!= 0 && tbl
->bits_mask
!= 0) {
714 if ((tbl
->bits_mask
& field
) == tbl
->bits_mask
) {
715 if (tbl
->bits_name
[0] != '\0') {
718 (void) strcpy(cp
, tbl
->bits_name
);
719 cp
+= strlen(tbl
->bits_name
);
722 field
&= ~(tbl
->bits_mask
| tbl
->bits_clear
);
729 cp
+= sprintf(cp
, "%#x", field
);
733 if (chr
!= '<' || force
)
740 if_bit_string(uint_t field
, boolean_t force
)
742 return (trace_string(if_bits
, field
, force
));
746 rtname(in_addr_t dst
,
750 static char buf
[sizeof ("xxx.xxx.xxx.xxx/xx-->xxx.xxx.xxx.xxx")];
753 (void) snprintf(buf
, sizeof (buf
), "%-16s-->", addrname(dst
, mask
, 0));
755 (void) snprintf(&buf
[i
], (sizeof (buf
) -i
), "%-*s", 15+24-MAX(24, i
),
762 print_rts(struct rt_spare
*rts
,
763 int force_metric
, /* -1=suppress, 0=default */
764 int force_ifp
, /* -1=suppress, 0=default */
765 int force_router
, /* -1=suppress, 0=default, 1=display */
766 int force_tag
, /* -1=suppress, 0=default, 1=display */
767 int force_time
) /* 0=suppress, 1=display */
771 if (force_metric
>= 0)
772 (void) fprintf(ftrace
, "metric=%-2d ", rts
->rts_metric
);
774 (void) fprintf(ftrace
, "%s ", (rts
->rts_ifp
== 0 ?
775 "if?" : rts
->rts_ifp
->int_name
));
776 if (force_router
> 0 ||
777 (force_router
== 0 && rts
->rts_router
!= rts
->rts_gate
))
778 (void) fprintf(ftrace
, "router=%s ",
779 naddr_ntoa(rts
->rts_router
));
781 (void) fprintf(ftrace
, "%s ", ts(rts
->rts_time
));
783 (force_tag
== 0 && rts
->rts_tag
!= 0))
784 (void) fprintf(ftrace
, "tag=%#x ", ntohs(rts
->rts_tag
));
785 if (rts
->rts_de_ag
!= 0) {
786 for (i
= 1; (uint_t
)(1 << i
) <= rts
->rts_de_ag
; i
++)
788 (void) fprintf(ftrace
, "de_ag=%d ", i
);
790 (void) fprintf(ftrace
, "flags 0x%x ", rts
->rts_flags
);
796 print_rtsorigin(const struct or_bits
*tbl
, uint8_t route_origin
)
800 while ((tblentry
= tbl
->origin
) != 0) {
801 if (tblentry
== route_origin
) {
802 (void) fprintf(ftrace
, "origin=%s ", tbl
->origin_name
);
810 trace_if(const char *act
, struct interface
*ifp
)
812 if (!TRACEACTIONS
|| ftrace
== NULL
)
816 (void) fprintf(ftrace
, "%-3s interface %-4s #%-3d ", act
,
818 ifp
->int_phys
!= NULL
? ifp
->int_phys
->phyi_index
: 0);
819 (void) fprintf(ftrace
, "%-15s-->%-15s",
820 naddr_ntoa(ifp
->int_addr
),
821 addrname(((ifp
->int_if_flags
& IFF_POINTOPOINT
) ?
822 ifp
->int_dstaddr
: htonl(ifp
->int_net
)),
824 if (ifp
->int_metric
!= 0)
825 (void) fprintf(ftrace
, " metric=%d", ifp
->int_metric
);
826 if (!IS_RIP_OUT_OFF(ifp
->int_state
) &&
827 ifp
->int_d_metric
!= 0)
828 (void) fprintf(ftrace
, " fake_default=%d", ifp
->int_d_metric
);
829 (void) fputs("\n ", ftrace
);
830 trace_bits(if_bits
, ifp
->int_if_flags
, _B_FALSE
);
831 trace_bits(is_bits
, ifp
->int_state
, _B_FALSE
);
832 (void) fputc('\n', ftrace
);
836 trace_khash(const struct khash
*krt
)
842 (void) fprintf(ftrace
, " %-15s-->%-15s metric=%d ",
843 addrname(krt
->k_dst
, krt
->k_mask
, 0),
844 naddr_ntoa(krt
->k_gate
), krt
->k_metric
);
845 if (krt
->k_ifp
!= NULL
)
846 (void) fprintf(ftrace
, "ifp %s ", krt
->k_ifp
->int_name
);
848 (void) fprintf(ftrace
, "ifp NULL ");
849 (void) fprintf(ftrace
, "%s ", ts(krt
->k_keep
));
850 (void) fprintf(ftrace
, "%s ", ts(krt
->k_redirect_time
));
851 trace_bits(ks_bits
, krt
->k_state
, _B_TRUE
);
852 (void) fputc('\n', ftrace
);
856 trace_dr(const struct dr
*drp
)
862 (void) fprintf(ftrace
, " %-4s %-15s %s ",
863 drp
->dr_ifp
!= NULL
? drp
->dr_ifp
->int_name
: "?",
864 naddr_ntoa(drp
->dr_gate
), ts(drp
->dr_ts
));
865 (void) fprintf(ftrace
, "%s %d %u\n", ts(drp
->dr_life
),
866 SIGN_PREF(drp
->dr_recv_pref
), drp
->dr_pref
);
870 trace_upslot(struct rt_entry
*rt
,
871 struct rt_spare
*rts
,
872 struct rt_spare
*new)
874 if (!TRACEACTIONS
|| ftrace
== NULL
)
877 if (rts
->rts_gate
== new->rts_gate
&&
878 rts
->rts_router
== new->rts_router
&&
879 rts
->rts_metric
== new->rts_metric
&&
880 rts
->rts_tag
== new->rts_tag
&&
881 rts
->rts_de_ag
== new->rts_de_ag
)
885 if (new->rts_gate
== 0) {
886 (void) fprintf(ftrace
, "Del #%d %-35s ",
887 (int)(rts
- rt
->rt_spares
),
888 rtname(rt
->rt_dst
, rt
->rt_mask
, rts
->rts_gate
));
889 print_rts(rts
, 0, 0, 0, 0,
890 (rts
!= rt
->rt_spares
||
891 AGE_RT(rt
->rt_state
, rts
->rts_origin
, new->rts_ifp
)));
893 } else if (rts
->rts_gate
!= RIP_DEFAULT
) {
894 (void) fprintf(ftrace
, "Chg #%d %-35s ",
895 (int)(rts
- rt
->rt_spares
),
896 rtname(rt
->rt_dst
, rt
->rt_mask
, rts
->rts_gate
));
898 rts
->rts_gate
!= new->rts_gate
,
899 rts
->rts_tag
!= new->rts_tag
,
900 rts
!= rt
->rt_spares
||
901 AGE_RT(rt
->rt_state
, rts
->rts_origin
, rt
->rt_ifp
));
903 (void) fprintf(ftrace
, "\n %19s%-16s ", "",
904 (new->rts_gate
!= rts
->rts_gate
?
905 naddr_ntoa(new->rts_gate
) : ""));
907 ((new->rts_metric
== rts
->rts_metric
) ? -1 : 0),
908 ((new->rts_ifp
== rts
->rts_ifp
) ? -1 : 0),
910 rts
->rts_tag
!= new->rts_tag
,
911 (new->rts_time
!= rts
->rts_time
&&
912 (rts
!= rt
->rt_spares
||
913 AGE_RT(rt
->rt_state
, new->rts_origin
, new->rts_ifp
))));
916 (void) fprintf(ftrace
, "Add #%d %-35s ",
917 (int)(rts
- rt
->rt_spares
),
918 rtname(rt
->rt_dst
, rt
->rt_mask
, new->rts_gate
));
919 print_rts(new, 0, 0, 0, 0,
920 (rts
!= rt
->rt_spares
||
921 AGE_RT(rt
->rt_state
, new->rts_origin
, new->rts_ifp
)));
923 (void) fputc('\n', ftrace
);
927 /* miscellaneous message checked by the caller */
929 trace_misc(const char *p
, ...)
938 (void) vfprintf(ftrace
, p
, args
);
939 (void) fputc('\n', ftrace
);
944 /* display a message if tracing actions */
946 trace_act(const char *p
, ...)
950 if (!TRACEACTIONS
|| ftrace
== NULL
)
955 (void) vfprintf(ftrace
, p
, args
);
956 (void) fputc('\n', ftrace
);
961 /* display a message if tracing packets */
963 trace_pkt(const char *p
, ...)
967 if (!TRACEPACKETS
|| ftrace
== NULL
)
972 (void) vfprintf(ftrace
, p
, args
);
973 (void) fputc('\n', ftrace
);
979 trace_change(struct rt_entry
*rt
,
981 struct rt_spare
*new,
987 if (rt
->rt_metric
== new->rts_metric
&&
988 rt
->rt_gate
== new->rts_gate
&&
989 rt
->rt_router
== new->rts_router
&&
990 rt
->rt_state
== state
&&
991 rt
->rt_tag
== new->rts_tag
&&
992 rt
->rt_de_ag
== new->rts_de_ag
)
996 (void) fprintf(ftrace
, "%s %-35s ",
998 rtname(rt
->rt_dst
, rt
->rt_mask
, rt
->rt_gate
));
999 print_rts(rt
->rt_spares
,
1000 0, 0, 0, 0, AGE_RT(rt
->rt_state
, rt
->rt_spares
->rts_origin
,
1002 print_rtsorigin(origin_bits
, rt
->rt_spares
->rts_origin
);
1003 trace_bits(rs_bits
, rt
->rt_state
, rt
->rt_state
!= state
);
1005 (void) fprintf(ftrace
, "\n%*s %19s%-16s ",
1006 strlen(label
), "", "",
1007 (rt
->rt_gate
!= new->rts_gate
?
1008 naddr_ntoa(new->rts_gate
) : ""));
1010 ((new->rts_metric
== rt
->rt_metric
) ? -1 : 0),
1011 ((new->rts_ifp
== rt
->rt_ifp
) ? -1 : 0),
1013 rt
->rt_tag
!= new->rts_tag
,
1014 (rt
->rt_time
!= new->rts_time
&&
1015 AGE_RT(rt
->rt_state
, new->rts_origin
, new->rts_ifp
)));
1016 if (rt
->rt_state
!= state
) {
1017 print_rtsorigin(origin_bits
, new->rts_origin
);
1018 trace_bits(rs_bits
, state
, _B_TRUE
);
1020 (void) fputc('\n', ftrace
);
1025 trace_add_del(const char *action
, struct rt_entry
*rt
)
1031 (void) fprintf(ftrace
, "%s %-35s ",
1033 rtname(rt
->rt_dst
, rt
->rt_mask
, rt
->rt_gate
));
1034 print_rts(rt
->rt_spares
, 0, 0, 0, 0, AGE_RT(rt
->rt_state
,
1035 rt
->rt_spares
->rts_origin
, rt
->rt_ifp
));
1036 print_rtsorigin(origin_bits
, rt
->rt_spares
->rts_origin
);
1037 trace_bits(rs_bits
, rt
->rt_state
, _B_FALSE
);
1038 (void) fputc('\n', ftrace
);
1044 walk_trace(struct radix_node
*rn
,
1047 #define RT ((struct rt_entry *)rn)
1048 struct rt_spare
*rts
;
1051 (void) fprintf(ftrace
, " %-35s ",
1052 rtname(RT
->rt_dst
, RT
->rt_mask
, RT
->rt_gate
));
1053 print_rts(&RT
->rt_spares
[0], 0, 0, 0, 0,
1054 AGE_RT(RT
->rt_state
, RT
->rt_spares
[0].rts_origin
, RT
->rt_ifp
));
1055 print_rtsorigin(origin_bits
, RT
->rt_spares
[0].rts_origin
);
1056 trace_bits(rs_bits
, RT
->rt_state
, _B_FALSE
);
1057 if (RT
->rt_poison_time
>= now_garbage
&&
1058 RT
->rt_poison_metric
< RT
->rt_metric
)
1059 (void) fprintf(ftrace
, "pm=%d@%s",
1060 RT
->rt_poison_metric
, ts(RT
->rt_poison_time
));
1061 (void) fprintf(ftrace
, "%d spare slots", RT
->rt_num_spares
);
1063 rts
= &RT
->rt_spares
[1];
1064 for (i
= 1; i
< RT
->rt_num_spares
; i
++, rts
++) {
1065 if (rts
->rts_gate
!= RIP_DEFAULT
) {
1066 (void) fprintf(ftrace
, "\n #%d%15s%-16s ",
1067 i
, "", naddr_ntoa(rts
->rts_gate
));
1068 print_rts(rts
, 0, 0, 0, 0, 1);
1069 print_rtsorigin(origin_bits
, rts
->rts_origin
);
1072 (void) fputc('\n', ftrace
);
1081 struct interface
*ifp
;
1088 * Warning: the rtquery.trace.* family of STC tests depend on
1089 * the log file format here. If you need to change this next
1090 * message, make sure that you change the TRACE_DUMP variable
1093 (void) fputs("current daemon state:\n", ftrace
);
1094 for (ifp
= ifnet
; ifp
!= NULL
; ifp
= ifp
->int_next
)
1096 (void) fputs("Routes:\n", ftrace
);
1097 (void) rn_walktree(rhead
, walk_trace
, NULL
);
1098 (void) fputs("Kernel routes:\n", ftrace
);
1100 (void) fputs("Discovered routers:\n", ftrace
);
1106 trace_rip(const char *dir1
, const char *dir2
,
1107 struct sockaddr_in
*who
,
1108 struct interface
*ifp
,
1110 int size
) /* total size of message */
1112 struct netinfo
*n
, *lim
;
1113 #define NA ((struct netauth *)n)
1115 struct in_addr tmp_mask
;
1117 if (!TRACEPACKETS
|| ftrace
== NULL
)
1121 if (msg
->rip_cmd
>= RIPCMD_MAX
|| msg
->rip_vers
== 0) {
1122 (void) fprintf(ftrace
, "%s bad RIPv%d cmd=%d %s"
1124 dir1
, msg
->rip_vers
, msg
->rip_cmd
, dir2
,
1125 naddr_ntoa(who
->sin_addr
.s_addr
),
1126 ntohs(who
->sin_port
),
1131 (void) fprintf(ftrace
, "%s RIPv%d %s %s %s.%d%s%s\n",
1132 dir1
, msg
->rip_vers
, ripcmds
[msg
->rip_cmd
], dir2
,
1133 naddr_ntoa(who
->sin_addr
.s_addr
), ntohs(who
->sin_port
),
1134 ifp
? " via " : "", ifp
? ifp
->int_name
: "");
1139 switch (msg
->rip_cmd
) {
1140 case RIPCMD_REQUEST
:
1141 case RIPCMD_RESPONSE
:
1144 tmp_mask
.s_addr
= n
->n_mask
;
1145 lim
= n
+ (size
- 4) / sizeof (struct netinfo
);
1146 for (; n
< lim
; n
++) {
1148 n
->n_family
== RIP_AF_UNSPEC
&&
1149 ntohl(n
->n_metric
) == HOPCNT_INFINITY
&&
1150 msg
->rip_cmd
== RIPCMD_REQUEST
&&
1153 (n
+1)->n_family
== RIP_AF_AUTH
))) {
1154 (void) fputs("\tQUERY ", ftrace
);
1156 (void) fprintf(ftrace
, "%s ",
1157 naddr_ntoa(n
->n_dst
));
1159 (void) fprintf(ftrace
, "mask=%s ",
1160 inet_ntoa(tmp_mask
));
1162 (void) fprintf(ftrace
, "nhop=%s ",
1163 naddr_ntoa(n
->n_nhop
));
1165 (void) fprintf(ftrace
, "tag=%#x ",
1167 (void) fputc('\n', ftrace
);
1171 if (n
->n_family
== RIP_AF_AUTH
) {
1172 if (NA
->a_type
== RIP_AUTH_PW
&&
1173 n
== msg
->rip_nets
) {
1174 (void) fprintf(ftrace
, "\tPassword"
1175 " Authentication: \"%s\"\n",
1176 qstring(NA
->au
.au_pw
,
1181 if (NA
->a_type
== RIP_AUTH_MD5
&&
1182 n
== msg
->rip_nets
) {
1183 (void) fprintf(ftrace
,
1185 " pkt_len=%d KeyID=%u"
1188 " rsvd=%#hx,%#hx\n",
1189 ntohs(NA
->au
.a_md5
.md5_pkt_len
),
1190 NA
->au
.a_md5
.md5_keyid
,
1191 NA
->au
.a_md5
.md5_auth_len
,
1192 ntohl(NA
->au
.a_md5
.md5_seqno
),
1193 ntohs(NA
->au
.a_md5
.rsvd
[0]),
1194 ntohs(NA
->au
.a_md5
.rsvd
[1]));
1197 (void) fprintf(ftrace
,
1198 "\tAuthentication type %d: ",
1200 for (i
= 0; i
< (int)sizeof (NA
->au
.au_pw
);
1202 (void) fprintf(ftrace
, "%02x ",
1204 (void) fputc('\n', ftrace
);
1209 if (n
->n_family
!= RIP_AF_INET
) {
1210 (void) fprintf(ftrace
,
1211 "\t(af %d) %-18s mask=%s ",
1213 naddr_ntoa(n
->n_dst
),
1214 inet_ntoa(tmp_mask
));
1215 } else if (msg
->rip_vers
== RIPv1
) {
1216 (void) fprintf(ftrace
, "\t%-18s ",
1217 addrname(n
->n_dst
, ntohl(n
->n_mask
),
1218 n
->n_mask
== 0 ? 2 : 1));
1220 (void) fprintf(ftrace
, "\t%-18s ",
1221 addrname(n
->n_dst
, ntohl(n
->n_mask
),
1222 n
->n_mask
== 0 ? 2 : 0));
1224 (void) fprintf(ftrace
, "metric=%-2lu ",
1225 (unsigned long)ntohl(n
->n_metric
));
1227 (void) fprintf(ftrace
, " nhop=%s ",
1228 naddr_ntoa(n
->n_nhop
));
1230 (void) fprintf(ftrace
, "tag=%#x",
1232 (void) fputc('\n', ftrace
);
1234 if (size
!= (char *)n
- (char *)msg
)
1235 (void) fprintf(ftrace
, "truncated record, len %d\n",
1239 case RIPCMD_TRACEON
:
1240 (void) fprintf(ftrace
, "\tfile=\"%.*s\"\n", size
- 4,
1241 msg
->rip_tracefile
);
1244 case RIPCMD_TRACEOFF
: