17b6ab19dSGarrett Wollman /* 27b6ab19dSGarrett Wollman * Copyright (c) 1983, 1988, 1993 37b6ab19dSGarrett Wollman * The Regents of the University of California. All rights reserved. 47b6ab19dSGarrett Wollman * 57b6ab19dSGarrett Wollman * Redistribution and use in source and binary forms, with or without 67b6ab19dSGarrett Wollman * modification, are permitted provided that the following conditions 77b6ab19dSGarrett Wollman * are met: 87b6ab19dSGarrett Wollman * 1. Redistributions of source code must retain the above copyright 97b6ab19dSGarrett Wollman * notice, this list of conditions and the following disclaimer. 107b6ab19dSGarrett Wollman * 2. Redistributions in binary form must reproduce the above copyright 117b6ab19dSGarrett Wollman * notice, this list of conditions and the following disclaimer in the 127b6ab19dSGarrett Wollman * documentation and/or other materials provided with the distribution. 137b6ab19dSGarrett Wollman * 3. All advertising materials mentioning features or use of this software 147b6ab19dSGarrett Wollman * must display the following acknowledgement: 157b6ab19dSGarrett Wollman * This product includes software developed by the University of 167b6ab19dSGarrett Wollman * California, Berkeley and its contributors. 177b6ab19dSGarrett Wollman * 4. Neither the name of the University nor the names of its contributors 187b6ab19dSGarrett Wollman * may be used to endorse or promote products derived from this software 197b6ab19dSGarrett Wollman * without specific prior written permission. 207b6ab19dSGarrett Wollman * 217b6ab19dSGarrett Wollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 227b6ab19dSGarrett Wollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 237b6ab19dSGarrett Wollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 247b6ab19dSGarrett Wollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 257b6ab19dSGarrett Wollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 267b6ab19dSGarrett Wollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 277b6ab19dSGarrett Wollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 287b6ab19dSGarrett Wollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 297b6ab19dSGarrett Wollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 307b6ab19dSGarrett Wollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 317b6ab19dSGarrett Wollman * SUCH DAMAGE. 327b6ab19dSGarrett Wollman */ 337b6ab19dSGarrett Wollman 347b6ab19dSGarrett Wollman #if !defined(lint) && !defined(sgi) && !defined(__NetBSD__) 357b6ab19dSGarrett Wollman static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93"; 367b6ab19dSGarrett Wollman #elif defined(__NetBSD__) 377b6ab19dSGarrett Wollman static char rcsid[] = "$NetBSD$"; 387b6ab19dSGarrett Wollman #endif 39d5b718b3SGarrett Wollman #ident "$Revision: 1.14 $" 407b6ab19dSGarrett Wollman 417b6ab19dSGarrett Wollman #define RIPCMDS 427b6ab19dSGarrett Wollman #include "defs.h" 437b6ab19dSGarrett Wollman #include "pathnames.h" 447b6ab19dSGarrett Wollman #include <sys/stat.h> 457b6ab19dSGarrett Wollman #include <sys/signal.h> 467b6ab19dSGarrett Wollman #include <fcntl.h> 477b6ab19dSGarrett Wollman 487b6ab19dSGarrett Wollman 497b6ab19dSGarrett Wollman #ifdef sgi 507b6ab19dSGarrett Wollman /* use *stat64 for files on large filesystems */ 517b6ab19dSGarrett Wollman #define stat stat64 527b6ab19dSGarrett Wollman #endif 537b6ab19dSGarrett Wollman 547b6ab19dSGarrett Wollman #define NRECORDS 50 /* size of circular trace buffer */ 557b6ab19dSGarrett Wollman 567b6ab19dSGarrett Wollman u_int tracelevel, new_tracelevel; 577b6ab19dSGarrett Wollman FILE *ftrace = stdout; /* output trace file */ 587b6ab19dSGarrett Wollman static char *tracelevel_pat = "%s\n"; 597b6ab19dSGarrett Wollman 607b6ab19dSGarrett Wollman char savetracename[MAXPATHLEN+1]; 617b6ab19dSGarrett Wollman 627b6ab19dSGarrett Wollman static void trace_dump(void); 637b6ab19dSGarrett Wollman 647b6ab19dSGarrett Wollman 65d5b718b3SGarrett Wollman /* convert string to printable characters 66d5b718b3SGarrett Wollman */ 67d5b718b3SGarrett Wollman static char * 68d5b718b3SGarrett Wollman qstring(u_char *s, int len) 69d5b718b3SGarrett Wollman { 70d5b718b3SGarrett Wollman static char buf[8*20+1]; 71d5b718b3SGarrett Wollman char *p; 72d5b718b3SGarrett Wollman u_char *s2, c; 73d5b718b3SGarrett Wollman 74d5b718b3SGarrett Wollman 75d5b718b3SGarrett Wollman for (p = buf; len != 0 && p < &buf[sizeof(buf)-1]; len--) { 76d5b718b3SGarrett Wollman c = *s++; 77d5b718b3SGarrett Wollman if (c == '\0') { 78d5b718b3SGarrett Wollman for (s2 = s+1; s2 < &s[len]; s2++) { 79d5b718b3SGarrett Wollman if (*s2 != '\0') 80d5b718b3SGarrett Wollman break; 81d5b718b3SGarrett Wollman } 82d5b718b3SGarrett Wollman if (s2 >= &s[len]) 83d5b718b3SGarrett Wollman goto exit; 84d5b718b3SGarrett Wollman } 85d5b718b3SGarrett Wollman 86d5b718b3SGarrett Wollman if (c >= ' ' && c < 0x7f && c != '\\') { 87d5b718b3SGarrett Wollman *p++ = c; 88d5b718b3SGarrett Wollman continue; 89d5b718b3SGarrett Wollman } 90d5b718b3SGarrett Wollman *p++ = '\\'; 91d5b718b3SGarrett Wollman switch (c) { 92d5b718b3SGarrett Wollman case '\\': 93d5b718b3SGarrett Wollman *p++ = '\\'; 94d5b718b3SGarrett Wollman break; 95d5b718b3SGarrett Wollman case '\n': 96d5b718b3SGarrett Wollman *p++= 'n'; 97d5b718b3SGarrett Wollman break; 98d5b718b3SGarrett Wollman case '\r': 99d5b718b3SGarrett Wollman *p++= 'r'; 100d5b718b3SGarrett Wollman break; 101d5b718b3SGarrett Wollman case '\t': 102d5b718b3SGarrett Wollman *p++ = 't'; 103d5b718b3SGarrett Wollman break; 104d5b718b3SGarrett Wollman case '\b': 105d5b718b3SGarrett Wollman *p++ = 'b'; 106d5b718b3SGarrett Wollman break; 107d5b718b3SGarrett Wollman default: 108d5b718b3SGarrett Wollman p += sprintf(p,"%o",c); 109d5b718b3SGarrett Wollman break; 110d5b718b3SGarrett Wollman } 111d5b718b3SGarrett Wollman } 112d5b718b3SGarrett Wollman exit: 113d5b718b3SGarrett Wollman *p = '\0'; 114d5b718b3SGarrett Wollman return buf; 115d5b718b3SGarrett Wollman } 116d5b718b3SGarrett Wollman 117d5b718b3SGarrett Wollman 1187b6ab19dSGarrett Wollman /* convert IP address to a string, but not into a single buffer 1197b6ab19dSGarrett Wollman */ 1207b6ab19dSGarrett Wollman char * 1217b6ab19dSGarrett Wollman naddr_ntoa(naddr a) 1227b6ab19dSGarrett Wollman { 1237b6ab19dSGarrett Wollman #define NUM_BUFS 4 1247b6ab19dSGarrett Wollman static int bufno; 1257b6ab19dSGarrett Wollman static struct { 1267b6ab19dSGarrett Wollman char str[16]; /* xxx.xxx.xxx.xxx\0 */ 1277b6ab19dSGarrett Wollman } bufs[NUM_BUFS]; 1287b6ab19dSGarrett Wollman char *s; 1297b6ab19dSGarrett Wollman struct in_addr addr; 1307b6ab19dSGarrett Wollman 1317b6ab19dSGarrett Wollman addr.s_addr = a; 1327b6ab19dSGarrett Wollman s = strcpy(bufs[bufno].str, inet_ntoa(addr)); 1337b6ab19dSGarrett Wollman bufno = (bufno+1) % NUM_BUFS; 1347b6ab19dSGarrett Wollman return s; 1357b6ab19dSGarrett Wollman #undef NUM_BUFS 1367b6ab19dSGarrett Wollman } 1377b6ab19dSGarrett Wollman 1387b6ab19dSGarrett Wollman 1397b6ab19dSGarrett Wollman char * 1407b6ab19dSGarrett Wollman saddr_ntoa(struct sockaddr *sa) 1417b6ab19dSGarrett Wollman { 1427b6ab19dSGarrett Wollman return (sa == 0) ? "?" : naddr_ntoa(S_ADDR(sa)); 1437b6ab19dSGarrett Wollman } 1447b6ab19dSGarrett Wollman 1457b6ab19dSGarrett Wollman 1467b6ab19dSGarrett Wollman static char * 1477b6ab19dSGarrett Wollman ts(time_t secs) { 1487b6ab19dSGarrett Wollman static char s[20]; 1497b6ab19dSGarrett Wollman 1507b6ab19dSGarrett Wollman secs += epoch.tv_sec; 1517b6ab19dSGarrett Wollman #ifdef sgi 1527b6ab19dSGarrett Wollman (void)cftime(s, "%T", &secs); 1537b6ab19dSGarrett Wollman #else 1547b6ab19dSGarrett Wollman bcopy(ctime(&secs)+11, s, 8); 1557b6ab19dSGarrett Wollman s[8] = '\0'; 1567b6ab19dSGarrett Wollman #endif 1577b6ab19dSGarrett Wollman return s; 1587b6ab19dSGarrett Wollman } 1597b6ab19dSGarrett Wollman 1607b6ab19dSGarrett Wollman 1617b6ab19dSGarrett Wollman /* On each event, display a time stamp. 1627b6ab19dSGarrett Wollman * This assumes that 'now' is update once for each event, and 1637b6ab19dSGarrett Wollman * that at least now.tv_usec changes. 1647b6ab19dSGarrett Wollman */ 1657b6ab19dSGarrett Wollman void 1667b6ab19dSGarrett Wollman lastlog(void) 1677b6ab19dSGarrett Wollman { 1687b6ab19dSGarrett Wollman static struct timeval last; 1697b6ab19dSGarrett Wollman 1707b6ab19dSGarrett Wollman if (last.tv_sec != now.tv_sec 1717b6ab19dSGarrett Wollman || last.tv_usec != now.tv_usec) { 1727b6ab19dSGarrett Wollman (void)fprintf(ftrace, "-- %s --\n", ts(now.tv_sec)); 1737b6ab19dSGarrett Wollman last = now; 1747b6ab19dSGarrett Wollman } 1757b6ab19dSGarrett Wollman } 1767b6ab19dSGarrett Wollman 1777b6ab19dSGarrett Wollman 1787b6ab19dSGarrett Wollman static void 1797b6ab19dSGarrett Wollman tmsg(char *p, ...) 1807b6ab19dSGarrett Wollman { 1817b6ab19dSGarrett Wollman va_list args; 1827b6ab19dSGarrett Wollman 1837b6ab19dSGarrett Wollman if (ftrace != 0) { 1847b6ab19dSGarrett Wollman lastlog(); 1857b6ab19dSGarrett Wollman va_start(args, p); 1867b6ab19dSGarrett Wollman vfprintf(ftrace, p, args); 1877b6ab19dSGarrett Wollman fflush(ftrace); 1887b6ab19dSGarrett Wollman } 1897b6ab19dSGarrett Wollman } 1907b6ab19dSGarrett Wollman 1917b6ab19dSGarrett Wollman 1927b6ab19dSGarrett Wollman static void 1937b6ab19dSGarrett Wollman trace_close(void) 1947b6ab19dSGarrett Wollman { 1957b6ab19dSGarrett Wollman int fd; 1967b6ab19dSGarrett Wollman 1977b6ab19dSGarrett Wollman 1987b6ab19dSGarrett Wollman fflush(stdout); 1997b6ab19dSGarrett Wollman fflush(stderr); 2007b6ab19dSGarrett Wollman 2017b6ab19dSGarrett Wollman if (ftrace != 0 2027b6ab19dSGarrett Wollman && savetracename[0] != '\0') { 2037b6ab19dSGarrett Wollman fd = open(_PATH_DEVNULL, O_RDWR); 2047b6ab19dSGarrett Wollman (void)dup2(fd, STDOUT_FILENO); 2057b6ab19dSGarrett Wollman (void)dup2(fd, STDERR_FILENO); 2067b6ab19dSGarrett Wollman (void)close(fd); 2077b6ab19dSGarrett Wollman fclose(ftrace); 2087b6ab19dSGarrett Wollman ftrace = 0; 2097b6ab19dSGarrett Wollman } 2107b6ab19dSGarrett Wollman } 2117b6ab19dSGarrett Wollman 2127b6ab19dSGarrett Wollman 2137b6ab19dSGarrett Wollman void 2147b6ab19dSGarrett Wollman trace_flush(void) 2157b6ab19dSGarrett Wollman { 2167b6ab19dSGarrett Wollman if (ftrace != 0) { 2177b6ab19dSGarrett Wollman fflush(ftrace); 2187b6ab19dSGarrett Wollman if (ferror(ftrace)) 2197b6ab19dSGarrett Wollman trace_off("tracing off: ", strerror(ferror(ftrace))); 2207b6ab19dSGarrett Wollman } 2217b6ab19dSGarrett Wollman } 2227b6ab19dSGarrett Wollman 2237b6ab19dSGarrett Wollman 2247b6ab19dSGarrett Wollman void 2257b6ab19dSGarrett Wollman trace_off(char *p, ...) 2267b6ab19dSGarrett Wollman { 2277b6ab19dSGarrett Wollman va_list args; 2287b6ab19dSGarrett Wollman 2297b6ab19dSGarrett Wollman 2307b6ab19dSGarrett Wollman if (ftrace != 0) { 2317b6ab19dSGarrett Wollman lastlog(); 2327b6ab19dSGarrett Wollman va_start(args, p); 2337b6ab19dSGarrett Wollman vfprintf(ftrace, p, args); 2347b6ab19dSGarrett Wollman fflush(ftrace); 2357b6ab19dSGarrett Wollman } 2367b6ab19dSGarrett Wollman trace_close(); 2377b6ab19dSGarrett Wollman 2387b6ab19dSGarrett Wollman new_tracelevel = tracelevel = 0; 2397b6ab19dSGarrett Wollman } 2407b6ab19dSGarrett Wollman 2417b6ab19dSGarrett Wollman 2427b6ab19dSGarrett Wollman void 2437b6ab19dSGarrett Wollman trace_on(char *filename, 244d5b718b3SGarrett Wollman int initial) /* 1=setting from command line */ 2457b6ab19dSGarrett Wollman { 2467b6ab19dSGarrett Wollman struct stat stbuf; 2477b6ab19dSGarrett Wollman FILE *n_ftrace; 248d5b718b3SGarrett Wollman u_int old_tracelevel; 2497b6ab19dSGarrett Wollman 2507b6ab19dSGarrett Wollman 2517b6ab19dSGarrett Wollman /* Given a null filename when tracing is already on, increase the 2527b6ab19dSGarrett Wollman * debugging level and re-open the file in case it has been unlinked. 2537b6ab19dSGarrett Wollman */ 2547b6ab19dSGarrett Wollman if (filename[0] == '\0') { 2557b6ab19dSGarrett Wollman if (tracelevel != 0) { 2567b6ab19dSGarrett Wollman new_tracelevel++; 2577b6ab19dSGarrett Wollman tracelevel_pat = "trace command: %s\n"; 2587b6ab19dSGarrett Wollman } else if (savetracename[0] == '\0') { 2597b6ab19dSGarrett Wollman msglog("missing trace file name"); 2607b6ab19dSGarrett Wollman return; 2617b6ab19dSGarrett Wollman } 2627b6ab19dSGarrett Wollman filename = savetracename; 2637b6ab19dSGarrett Wollman 2647b6ab19dSGarrett Wollman } else if (!strcmp(filename,"dump/../table")) { 2657b6ab19dSGarrett Wollman trace_dump(); 2667b6ab19dSGarrett Wollman return; 2677b6ab19dSGarrett Wollman 2687b6ab19dSGarrett Wollman } else { 2697b6ab19dSGarrett Wollman if (stat(filename, &stbuf) >= 0 2707b6ab19dSGarrett Wollman && (stbuf.st_mode & S_IFMT) != S_IFREG) { 2717b6ab19dSGarrett Wollman msglog("wrong type (%#x) of trace file \"%s\"", 2727b6ab19dSGarrett Wollman stbuf.st_mode, filename); 2737b6ab19dSGarrett Wollman return; 2747b6ab19dSGarrett Wollman } 2757b6ab19dSGarrett Wollman 276d5b718b3SGarrett Wollman if (!initial 2777b6ab19dSGarrett Wollman #ifdef _PATH_TRACE 2787b6ab19dSGarrett Wollman && (strncmp(filename, _PATH_TRACE, sizeof(_PATH_TRACE)-1) 2797b6ab19dSGarrett Wollman || strstr(filename,"../") 2807b6ab19dSGarrett Wollman || 0 > stat(_PATH_TRACE, &stbuf)) 2817b6ab19dSGarrett Wollman #endif 2827b6ab19dSGarrett Wollman && strcmp(filename, savetracename)) { 2837b6ab19dSGarrett Wollman msglog("wrong directory for trace file \"%s\"", 2847b6ab19dSGarrett Wollman filename); 2857b6ab19dSGarrett Wollman return; 2867b6ab19dSGarrett Wollman } 2877b6ab19dSGarrett Wollman } 2887b6ab19dSGarrett Wollman 2897b6ab19dSGarrett Wollman n_ftrace = fopen(filename, "a"); 2907b6ab19dSGarrett Wollman if (n_ftrace == 0) { 2917b6ab19dSGarrett Wollman msglog("failed to open trace file \"%s\" %s", 2927b6ab19dSGarrett Wollman filename, strerror(errno)); 2937b6ab19dSGarrett Wollman return; 2947b6ab19dSGarrett Wollman } 2957b6ab19dSGarrett Wollman 2967b6ab19dSGarrett Wollman tmsg("switch to trace file %s\n", filename); 2977b6ab19dSGarrett Wollman trace_close(); 2987b6ab19dSGarrett Wollman if (filename != savetracename) 2997b6ab19dSGarrett Wollman strncpy(savetracename, filename, sizeof(savetracename)-1); 3007b6ab19dSGarrett Wollman ftrace = n_ftrace; 3017b6ab19dSGarrett Wollman 3027b6ab19dSGarrett Wollman fflush(stdout); 3037b6ab19dSGarrett Wollman fflush(stderr); 3047b6ab19dSGarrett Wollman dup2(fileno(ftrace), STDOUT_FILENO); 3057b6ab19dSGarrett Wollman dup2(fileno(ftrace), STDERR_FILENO); 3067b6ab19dSGarrett Wollman 3077b6ab19dSGarrett Wollman if (new_tracelevel == 0) 3087b6ab19dSGarrett Wollman new_tracelevel = 1; 309d5b718b3SGarrett Wollman old_tracelevel = tracelevel; 310d5b718b3SGarrett Wollman set_tracelevel(initial); 311d5b718b3SGarrett Wollman 312d5b718b3SGarrett Wollman if (!initial && old_tracelevel == 0) 313d5b718b3SGarrett Wollman trace_dump(); 3147b6ab19dSGarrett Wollman } 3157b6ab19dSGarrett Wollman 3167b6ab19dSGarrett Wollman 3177b6ab19dSGarrett Wollman /* ARGSUSED */ 3187b6ab19dSGarrett Wollman void 3197b6ab19dSGarrett Wollman sigtrace_on(int s) 3207b6ab19dSGarrett Wollman { 3217b6ab19dSGarrett Wollman new_tracelevel++; 3227b6ab19dSGarrett Wollman tracelevel_pat = "SIGUSR1: %s\n"; 3237b6ab19dSGarrett Wollman } 3247b6ab19dSGarrett Wollman 3257b6ab19dSGarrett Wollman 3267b6ab19dSGarrett Wollman /* ARGSUSED */ 3277b6ab19dSGarrett Wollman void 3287b6ab19dSGarrett Wollman sigtrace_off(int s) 3297b6ab19dSGarrett Wollman { 3307b6ab19dSGarrett Wollman new_tracelevel--; 3317b6ab19dSGarrett Wollman tracelevel_pat = "SIGUSR2: %s\n"; 3327b6ab19dSGarrett Wollman } 3337b6ab19dSGarrett Wollman 3347b6ab19dSGarrett Wollman 3357b6ab19dSGarrett Wollman /* Move to next higher level of tracing when -t option processed or 3367b6ab19dSGarrett Wollman * SIGUSR1 is received. Successive levels are: 3377b6ab19dSGarrett Wollman * actions 3387b6ab19dSGarrett Wollman * actions + packets 3397b6ab19dSGarrett Wollman * actions + packets + contents 3407b6ab19dSGarrett Wollman */ 3417b6ab19dSGarrett Wollman void 342d5b718b3SGarrett Wollman set_tracelevel(int initial) 3437b6ab19dSGarrett Wollman { 3447b6ab19dSGarrett Wollman static char *off_msgs[MAX_TRACELEVEL] = { 3457b6ab19dSGarrett Wollman "Tracing actions stopped", 3467b6ab19dSGarrett Wollman "Tracing packets stopped", 3477b6ab19dSGarrett Wollman "Tracing packet contents stopped", 3487b6ab19dSGarrett Wollman "Tracing kernel changes stopped", 3497b6ab19dSGarrett Wollman }; 3507b6ab19dSGarrett Wollman static char *on_msgs[MAX_TRACELEVEL] = { 3517b6ab19dSGarrett Wollman "Tracing actions started", 3527b6ab19dSGarrett Wollman "Tracing packets started", 3537b6ab19dSGarrett Wollman "Tracing packet contents started", 3547b6ab19dSGarrett Wollman "Tracing kernel changes started", 3557b6ab19dSGarrett Wollman }; 3567b6ab19dSGarrett Wollman 3577b6ab19dSGarrett Wollman 3587b6ab19dSGarrett Wollman if (new_tracelevel > MAX_TRACELEVEL) { 3597b6ab19dSGarrett Wollman new_tracelevel = MAX_TRACELEVEL; 3607b6ab19dSGarrett Wollman if (new_tracelevel == tracelevel) { 3617b6ab19dSGarrett Wollman tmsg(tracelevel_pat, on_msgs[tracelevel-1]); 3627b6ab19dSGarrett Wollman return; 3637b6ab19dSGarrett Wollman } 3647b6ab19dSGarrett Wollman } 365d5b718b3SGarrett Wollman 366d5b718b3SGarrett Wollman for (; new_tracelevel != tracelevel; tracelevel++) { 3677b6ab19dSGarrett Wollman if (new_tracelevel < tracelevel) { 3687b6ab19dSGarrett Wollman if (--tracelevel == 0) 3697b6ab19dSGarrett Wollman trace_off(tracelevel_pat, off_msgs[0]); 3707b6ab19dSGarrett Wollman else 3717b6ab19dSGarrett Wollman tmsg(tracelevel_pat, off_msgs[tracelevel]); 3727b6ab19dSGarrett Wollman } else { 3737b6ab19dSGarrett Wollman if (ftrace == 0) { 3747b6ab19dSGarrett Wollman if (savetracename[0] != '\0') 3757b6ab19dSGarrett Wollman trace_on(savetracename, 1); 3767b6ab19dSGarrett Wollman else 3777b6ab19dSGarrett Wollman ftrace = stdout; 3787b6ab19dSGarrett Wollman } 379d5b718b3SGarrett Wollman if (!initial || tracelevel+1 == new_tracelevel) 380d5b718b3SGarrett Wollman tmsg(tracelevel_pat, on_msgs[tracelevel]); 3817b6ab19dSGarrett Wollman } 3827b6ab19dSGarrett Wollman } 3837b6ab19dSGarrett Wollman tracelevel_pat = "%s\n"; 3847b6ab19dSGarrett Wollman } 3857b6ab19dSGarrett Wollman 3867b6ab19dSGarrett Wollman 3877b6ab19dSGarrett Wollman /* display an address 3887b6ab19dSGarrett Wollman */ 3897b6ab19dSGarrett Wollman char * 3907b6ab19dSGarrett Wollman addrname(naddr addr, /* in network byte order */ 3917b6ab19dSGarrett Wollman naddr mask, 3927b6ab19dSGarrett Wollman int force) /* 0=show mask if nonstandard, */ 3937b6ab19dSGarrett Wollman { /* 1=always show mask, 2=never */ 3947b6ab19dSGarrett Wollman #define NUM_BUFS 4 3957b6ab19dSGarrett Wollman static int bufno; 3967b6ab19dSGarrett Wollman static struct { 3977b6ab19dSGarrett Wollman char str[15+20]; 3987b6ab19dSGarrett Wollman } bufs[NUM_BUFS]; 3997b6ab19dSGarrett Wollman char *s, *sp; 4007b6ab19dSGarrett Wollman naddr dmask; 4017b6ab19dSGarrett Wollman int i; 4027b6ab19dSGarrett Wollman 4037b6ab19dSGarrett Wollman s = strcpy(bufs[bufno].str, naddr_ntoa(addr)); 4047b6ab19dSGarrett Wollman bufno = (bufno+1) % NUM_BUFS; 4057b6ab19dSGarrett Wollman 4067b6ab19dSGarrett Wollman if (force == 1 || (force == 0 && mask != std_mask(addr))) { 4077b6ab19dSGarrett Wollman sp = &s[strlen(s)]; 4087b6ab19dSGarrett Wollman 4097b6ab19dSGarrett Wollman dmask = mask & -mask; 4107b6ab19dSGarrett Wollman if (mask + dmask == 0) { 4117b6ab19dSGarrett Wollman for (i = 0; i != 32 && ((1<<i) & mask) == 0; i++) 4127b6ab19dSGarrett Wollman continue; 4137b6ab19dSGarrett Wollman (void)sprintf(sp, "/%d", 32-i); 4147b6ab19dSGarrett Wollman 4157b6ab19dSGarrett Wollman } else { 4167b6ab19dSGarrett Wollman (void)sprintf(sp, " (mask %#x)", (u_int)mask); 4177b6ab19dSGarrett Wollman } 4187b6ab19dSGarrett Wollman } 4197b6ab19dSGarrett Wollman 4207b6ab19dSGarrett Wollman return s; 4217b6ab19dSGarrett Wollman #undef NUM_BUFS 4227b6ab19dSGarrett Wollman } 4237b6ab19dSGarrett Wollman 4247b6ab19dSGarrett Wollman 4257b6ab19dSGarrett Wollman /* display a bit-field 4267b6ab19dSGarrett Wollman */ 4277b6ab19dSGarrett Wollman struct bits { 4287b6ab19dSGarrett Wollman int bits_mask; 4297b6ab19dSGarrett Wollman int bits_clear; 4307b6ab19dSGarrett Wollman char *bits_name; 4317b6ab19dSGarrett Wollman }; 4327b6ab19dSGarrett Wollman 4337b6ab19dSGarrett Wollman static struct bits if_bits[] = { 4347b6ab19dSGarrett Wollman { IFF_LOOPBACK, 0, "LOOPBACK" }, 4357b6ab19dSGarrett Wollman { IFF_POINTOPOINT, 0, "PT-TO-PT" }, 4367b6ab19dSGarrett Wollman { 0, 0, 0} 4377b6ab19dSGarrett Wollman }; 4387b6ab19dSGarrett Wollman 4397b6ab19dSGarrett Wollman static struct bits is_bits[] = { 440d5b718b3SGarrett Wollman { IS_ALIAS, 0, "ALIAS" }, 4417b6ab19dSGarrett Wollman { IS_SUBNET, 0, "" }, 442d5b718b3SGarrett Wollman { IS_REMOTE, (IS_NO_RDISC 443d5b718b3SGarrett Wollman | IS_BCAST_RDISC), "REMOTE" }, 4447b6ab19dSGarrett Wollman { IS_PASSIVE, (IS_NO_RDISC 4457b6ab19dSGarrett Wollman | IS_NO_RIP 4467b6ab19dSGarrett Wollman | IS_NO_SUPER_AG 4477b6ab19dSGarrett Wollman | IS_PM_RDISC 4487b6ab19dSGarrett Wollman | IS_NO_AG), "PASSIVE" }, 4497b6ab19dSGarrett Wollman { IS_EXTERNAL, 0, "EXTERNAL" }, 4507b6ab19dSGarrett Wollman { IS_CHECKED, 0, "" }, 4517b6ab19dSGarrett Wollman { IS_ALL_HOSTS, 0, "" }, 4527b6ab19dSGarrett Wollman { IS_ALL_ROUTERS, 0, "" }, 453d5b718b3SGarrett Wollman { IS_DISTRUST, 0, "DISTRUST" }, 4547b6ab19dSGarrett Wollman { IS_BROKE, IS_SICK, "BROKEN" }, 4557b6ab19dSGarrett Wollman { IS_SICK, 0, "SICK" }, 456d5b718b3SGarrett Wollman { IS_DUP, 0, "DUPLICATE" }, 4577b6ab19dSGarrett Wollman { IS_NEED_NET_SYN, 0, "" }, 4587b6ab19dSGarrett Wollman { IS_NO_AG, IS_NO_SUPER_AG, "NO_AG" }, 4597b6ab19dSGarrett Wollman { IS_NO_SUPER_AG, 0, "NO_SUPER_AG" }, 4607b6ab19dSGarrett Wollman { (IS_NO_RIPV1_IN 4617b6ab19dSGarrett Wollman | IS_NO_RIPV2_IN 4627b6ab19dSGarrett Wollman | IS_NO_RIPV1_OUT 4637b6ab19dSGarrett Wollman | IS_NO_RIPV2_OUT), 0, "NO_RIP" }, 4647b6ab19dSGarrett Wollman { (IS_NO_RIPV1_IN 4657b6ab19dSGarrett Wollman | IS_NO_RIPV1_OUT), 0, "RIPV2" }, 4667b6ab19dSGarrett Wollman { IS_NO_RIPV1_IN, 0, "NO_RIPV1_IN" }, 4677b6ab19dSGarrett Wollman { IS_NO_RIPV2_IN, 0, "NO_RIPV2_IN" }, 4687b6ab19dSGarrett Wollman { IS_NO_RIPV1_OUT, 0, "NO_RIPV1_OUT" }, 4697b6ab19dSGarrett Wollman { IS_NO_RIPV2_OUT, 0, "NO_RIPV2_OUT" }, 4707b6ab19dSGarrett Wollman { (IS_NO_ADV_IN 4717b6ab19dSGarrett Wollman | IS_NO_SOL_OUT 4727b6ab19dSGarrett Wollman | IS_NO_ADV_OUT), IS_BCAST_RDISC, "NO_RDISC" }, 4737b6ab19dSGarrett Wollman { IS_NO_SOL_OUT, 0, "NO_SOLICIT" }, 4747b6ab19dSGarrett Wollman { IS_SOL_OUT, 0, "SEND_SOLICIT" }, 4757b6ab19dSGarrett Wollman { IS_NO_ADV_OUT, IS_BCAST_RDISC, "NO_RDISC_ADV" }, 4767b6ab19dSGarrett Wollman { IS_ADV_OUT, 0, "RDISC_ADV" }, 4777b6ab19dSGarrett Wollman { IS_BCAST_RDISC, 0, "BCAST_RDISC" }, 478d5b718b3SGarrett Wollman { IS_PM_RDISC, 0, "" }, 4797b6ab19dSGarrett Wollman { 0, 0, "%#x"} 4807b6ab19dSGarrett Wollman }; 4817b6ab19dSGarrett Wollman 4827b6ab19dSGarrett Wollman static struct bits rs_bits[] = { 4837b6ab19dSGarrett Wollman { RS_IF, 0, "IF" }, 4847b6ab19dSGarrett Wollman { RS_NET_INT, RS_NET_SYN, "NET_INT" }, 4857b6ab19dSGarrett Wollman { RS_NET_SYN, 0, "NET_SYN" }, 4867b6ab19dSGarrett Wollman { RS_SUBNET, 0, "" }, 4877b6ab19dSGarrett Wollman { RS_LOCAL, 0, "LOCAL" }, 4887b6ab19dSGarrett Wollman { RS_MHOME, 0, "MHOME" }, 4897b6ab19dSGarrett Wollman { RS_STATIC, 0, "STATIC" }, 4907b6ab19dSGarrett Wollman { RS_RDISC, 0, "RDISC" }, 4917b6ab19dSGarrett Wollman { 0, 0, "%#x"} 4927b6ab19dSGarrett Wollman }; 4937b6ab19dSGarrett Wollman 4947b6ab19dSGarrett Wollman 4957b6ab19dSGarrett Wollman static void 4967b6ab19dSGarrett Wollman trace_bits(struct bits *tbl, 4977b6ab19dSGarrett Wollman u_int field, 4987b6ab19dSGarrett Wollman int force) 4997b6ab19dSGarrett Wollman { 5007b6ab19dSGarrett Wollman int b; 5017b6ab19dSGarrett Wollman char c; 5027b6ab19dSGarrett Wollman 5037b6ab19dSGarrett Wollman if (force) { 5047b6ab19dSGarrett Wollman (void)putc('<', ftrace); 5057b6ab19dSGarrett Wollman c = 0; 5067b6ab19dSGarrett Wollman } else { 5077b6ab19dSGarrett Wollman c = '<'; 5087b6ab19dSGarrett Wollman } 5097b6ab19dSGarrett Wollman 5107b6ab19dSGarrett Wollman while (field != 0 5117b6ab19dSGarrett Wollman && (b = tbl->bits_mask) != 0) { 5127b6ab19dSGarrett Wollman if ((b & field) == b) { 5137b6ab19dSGarrett Wollman if (tbl->bits_name[0] != '\0') { 5147b6ab19dSGarrett Wollman if (c) 5157b6ab19dSGarrett Wollman (void)putc(c, ftrace); 5167b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s", tbl->bits_name); 5177b6ab19dSGarrett Wollman c = '|'; 5187b6ab19dSGarrett Wollman } 5197b6ab19dSGarrett Wollman if (0 == (field &= ~(b | tbl->bits_clear))) 5207b6ab19dSGarrett Wollman break; 5217b6ab19dSGarrett Wollman } 5227b6ab19dSGarrett Wollman tbl++; 5237b6ab19dSGarrett Wollman } 5247b6ab19dSGarrett Wollman if (field != 0 && tbl->bits_name != 0) { 5257b6ab19dSGarrett Wollman if (c) 5267b6ab19dSGarrett Wollman (void)putc(c, ftrace); 5277b6ab19dSGarrett Wollman (void)fprintf(ftrace, tbl->bits_name, field); 5287b6ab19dSGarrett Wollman c = '|'; 5297b6ab19dSGarrett Wollman } 5307b6ab19dSGarrett Wollman 5317b6ab19dSGarrett Wollman if (c != '<' || force) 5327b6ab19dSGarrett Wollman (void)fputs("> ", ftrace); 5337b6ab19dSGarrett Wollman } 5347b6ab19dSGarrett Wollman 5357b6ab19dSGarrett Wollman 5367b6ab19dSGarrett Wollman static char * 5377b6ab19dSGarrett Wollman trace_pair(naddr dst, 5387b6ab19dSGarrett Wollman naddr mask, 5397b6ab19dSGarrett Wollman char *gate) 5407b6ab19dSGarrett Wollman { 5417b6ab19dSGarrett Wollman static char buf[3*4+3+1+2+3 /* "xxx.xxx.xxx.xxx/xx-->" */ 5427b6ab19dSGarrett Wollman +3*4+3+1]; /* "xxx.xxx.xxx.xxx" */ 5437b6ab19dSGarrett Wollman int i; 5447b6ab19dSGarrett Wollman 5457b6ab19dSGarrett Wollman i = sprintf(buf, "%-16s-->", addrname(dst, mask, 0)); 5467b6ab19dSGarrett Wollman (void)sprintf(&buf[i], "%-*s", 15+20-MAX(20,i), gate); 5477b6ab19dSGarrett Wollman return buf; 5487b6ab19dSGarrett Wollman } 5497b6ab19dSGarrett Wollman 5507b6ab19dSGarrett Wollman 5517b6ab19dSGarrett Wollman void 5527b6ab19dSGarrett Wollman trace_if(char *act, 5537b6ab19dSGarrett Wollman struct interface *ifp) 5547b6ab19dSGarrett Wollman { 5557b6ab19dSGarrett Wollman if (!TRACEACTIONS || ftrace == 0) 5567b6ab19dSGarrett Wollman return; 5577b6ab19dSGarrett Wollman 5587b6ab19dSGarrett Wollman lastlog(); 559d5b718b3SGarrett Wollman (void)fprintf(ftrace, "%-3s interface %-4s ", act, ifp->int_name); 5607b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%-15s-->%-15s ", 5617b6ab19dSGarrett Wollman naddr_ntoa(ifp->int_addr), 562d5b718b3SGarrett Wollman addrname(((ifp->int_if_flags & IFF_POINTOPOINT) 5637b6ab19dSGarrett Wollman ? ifp->int_dstaddr 564d5b718b3SGarrett Wollman : htonl(ifp->int_net)), 5657b6ab19dSGarrett Wollman ifp->int_mask, 1)); 5667b6ab19dSGarrett Wollman if (ifp->int_metric != 0) 5677b6ab19dSGarrett Wollman (void)fprintf(ftrace, "metric=%d ", ifp->int_metric); 568d5b718b3SGarrett Wollman if (!IS_RIP_OUT_OFF(ifp->int_state) 569d5b718b3SGarrett Wollman && ifp->int_d_metric != 0) 570d5b718b3SGarrett Wollman (void)fprintf(ftrace, "fake_default=%d ", ifp->int_d_metric); 5717b6ab19dSGarrett Wollman trace_bits(if_bits, ifp->int_if_flags, 0); 5727b6ab19dSGarrett Wollman trace_bits(is_bits, ifp->int_state, 0); 5737b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 5747b6ab19dSGarrett Wollman } 5757b6ab19dSGarrett Wollman 5767b6ab19dSGarrett Wollman 5777b6ab19dSGarrett Wollman void 5787b6ab19dSGarrett Wollman trace_upslot(struct rt_entry *rt, 5797b6ab19dSGarrett Wollman struct rt_spare *rts, 5807b6ab19dSGarrett Wollman naddr gate, 5817b6ab19dSGarrett Wollman naddr router, 5827b6ab19dSGarrett Wollman struct interface *ifp, 5837b6ab19dSGarrett Wollman int metric, 5847b6ab19dSGarrett Wollman u_short tag, 5857b6ab19dSGarrett Wollman time_t new_time) 5867b6ab19dSGarrett Wollman { 5877b6ab19dSGarrett Wollman if (!TRACEACTIONS || ftrace == 0) 5887b6ab19dSGarrett Wollman return; 5897b6ab19dSGarrett Wollman if (rts->rts_gate == gate 5907b6ab19dSGarrett Wollman && rts->rts_router == router 5917b6ab19dSGarrett Wollman && rts->rts_metric == metric 5927b6ab19dSGarrett Wollman && rts->rts_tag == tag) 5937b6ab19dSGarrett Wollman return; 5947b6ab19dSGarrett Wollman 5957b6ab19dSGarrett Wollman lastlog(); 5967b6ab19dSGarrett Wollman if (rts->rts_gate != RIP_DEFAULT) { 5977b6ab19dSGarrett Wollman (void)fprintf(ftrace, "Chg #%d %-35s ", 5987b6ab19dSGarrett Wollman rts - rt->rt_spares, 5997b6ab19dSGarrett Wollman trace_pair(rt->rt_dst, rt->rt_mask, 6007b6ab19dSGarrett Wollman naddr_ntoa(rts->rts_gate))); 6017b6ab19dSGarrett Wollman if (rts->rts_gate != rts->rts_gate) 6027b6ab19dSGarrett Wollman (void)fprintf(ftrace, "router=%s ", 6037b6ab19dSGarrett Wollman naddr_ntoa(rts->rts_gate)); 6047b6ab19dSGarrett Wollman if (rts->rts_tag != 0) 6057b6ab19dSGarrett Wollman (void)fprintf(ftrace, "tag=%#x ", ntohs(rts->rts_tag)); 6067b6ab19dSGarrett Wollman (void)fprintf(ftrace, "metric=%-2d ", rts->rts_metric); 6077b6ab19dSGarrett Wollman if (rts->rts_ifp != 0) 6087b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s ", 6097b6ab19dSGarrett Wollman rts->rts_ifp->int_name); 6107b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s\n", ts(rts->rts_time)); 6117b6ab19dSGarrett Wollman 6127b6ab19dSGarrett Wollman (void)fprintf(ftrace, " %19s%-16s ", 6137b6ab19dSGarrett Wollman "", 6147b6ab19dSGarrett Wollman gate != rts->rts_gate ? naddr_ntoa(gate) : ""); 6157b6ab19dSGarrett Wollman if (gate != router) 6167b6ab19dSGarrett Wollman (void)fprintf(ftrace,"router=%s ",naddr_ntoa(router)); 6177b6ab19dSGarrett Wollman if (tag != rts->rts_tag) 6187b6ab19dSGarrett Wollman (void)fprintf(ftrace, "tag=%#x ", ntohs(tag)); 6197b6ab19dSGarrett Wollman if (metric != rts->rts_metric) 6207b6ab19dSGarrett Wollman (void)fprintf(ftrace, "metric=%-2d ", metric); 6217b6ab19dSGarrett Wollman if (ifp != rts->rts_ifp && ifp != 0 ) 6227b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s ", ifp->int_name); 6237b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s\n", 6247b6ab19dSGarrett Wollman new_time != rts->rts_time ? ts(new_time) : ""); 6257b6ab19dSGarrett Wollman 6267b6ab19dSGarrett Wollman } else { 6277b6ab19dSGarrett Wollman (void)fprintf(ftrace, "Add #%d %-35s ", 6287b6ab19dSGarrett Wollman rts - rt->rt_spares, 6297b6ab19dSGarrett Wollman trace_pair(rt->rt_dst, rt->rt_mask, 6307b6ab19dSGarrett Wollman naddr_ntoa(gate))); 6317b6ab19dSGarrett Wollman if (gate != router) 6327b6ab19dSGarrett Wollman (void)fprintf(ftrace, "router=%s ", naddr_ntoa(gate)); 6337b6ab19dSGarrett Wollman if (tag != 0) 6347b6ab19dSGarrett Wollman (void)fprintf(ftrace, "tag=%#x ", ntohs(tag)); 6357b6ab19dSGarrett Wollman (void)fprintf(ftrace, "metric=%-2d ", metric); 6367b6ab19dSGarrett Wollman if (ifp != 0) 6377b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s ", ifp->int_name); 6387b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s\n", ts(new_time)); 6397b6ab19dSGarrett Wollman } 6407b6ab19dSGarrett Wollman } 6417b6ab19dSGarrett Wollman 6427b6ab19dSGarrett Wollman 6437b6ab19dSGarrett Wollman /* talk about a change made to the kernel table 6447b6ab19dSGarrett Wollman */ 6457b6ab19dSGarrett Wollman void 6467b6ab19dSGarrett Wollman trace_kernel(char *p, ...) 6477b6ab19dSGarrett Wollman { 6487b6ab19dSGarrett Wollman va_list args; 6497b6ab19dSGarrett Wollman 6507b6ab19dSGarrett Wollman if (!TRACEKERNEL || ftrace == 0) 6517b6ab19dSGarrett Wollman return; 6527b6ab19dSGarrett Wollman 6537b6ab19dSGarrett Wollman lastlog(); 6547b6ab19dSGarrett Wollman va_start(args, p); 6557b6ab19dSGarrett Wollman vfprintf(ftrace, p, args); 6567b6ab19dSGarrett Wollman } 6577b6ab19dSGarrett Wollman 6587b6ab19dSGarrett Wollman 6597b6ab19dSGarrett Wollman /* display a message if tracing actions 6607b6ab19dSGarrett Wollman */ 6617b6ab19dSGarrett Wollman void 6627b6ab19dSGarrett Wollman trace_act(char *p, ...) 6637b6ab19dSGarrett Wollman { 6647b6ab19dSGarrett Wollman va_list args; 6657b6ab19dSGarrett Wollman 6667b6ab19dSGarrett Wollman if (!TRACEACTIONS || ftrace == 0) 6677b6ab19dSGarrett Wollman return; 6687b6ab19dSGarrett Wollman 6697b6ab19dSGarrett Wollman lastlog(); 6707b6ab19dSGarrett Wollman va_start(args, p); 6717b6ab19dSGarrett Wollman vfprintf(ftrace, p, args); 672d5b718b3SGarrett Wollman (void)fputc('\n',ftrace); 6737b6ab19dSGarrett Wollman } 6747b6ab19dSGarrett Wollman 6757b6ab19dSGarrett Wollman 6767b6ab19dSGarrett Wollman /* display a message if tracing packets 6777b6ab19dSGarrett Wollman */ 6787b6ab19dSGarrett Wollman void 6797b6ab19dSGarrett Wollman trace_pkt(char *p, ...) 6807b6ab19dSGarrett Wollman { 6817b6ab19dSGarrett Wollman va_list args; 6827b6ab19dSGarrett Wollman 6837b6ab19dSGarrett Wollman if (!TRACEPACKETS || ftrace == 0) 6847b6ab19dSGarrett Wollman return; 6857b6ab19dSGarrett Wollman 6867b6ab19dSGarrett Wollman lastlog(); 6877b6ab19dSGarrett Wollman va_start(args, p); 6887b6ab19dSGarrett Wollman vfprintf(ftrace, p, args); 689d5b718b3SGarrett Wollman (void)fputc('\n',ftrace); 6907b6ab19dSGarrett Wollman } 6917b6ab19dSGarrett Wollman 6927b6ab19dSGarrett Wollman 6937b6ab19dSGarrett Wollman void 6947b6ab19dSGarrett Wollman trace_change(struct rt_entry *rt, 6957b6ab19dSGarrett Wollman u_int state, 6967b6ab19dSGarrett Wollman naddr gate, /* forward packets here */ 6977b6ab19dSGarrett Wollman naddr router, /* on the authority of this router */ 6987b6ab19dSGarrett Wollman int metric, 6997b6ab19dSGarrett Wollman u_short tag, 7007b6ab19dSGarrett Wollman struct interface *ifp, 7017b6ab19dSGarrett Wollman time_t new_time, 7027b6ab19dSGarrett Wollman char *label) 7037b6ab19dSGarrett Wollman { 7047b6ab19dSGarrett Wollman if (ftrace == 0) 7057b6ab19dSGarrett Wollman return; 7067b6ab19dSGarrett Wollman 7077b6ab19dSGarrett Wollman if (rt->rt_metric == metric 7087b6ab19dSGarrett Wollman && rt->rt_gate == gate 7097b6ab19dSGarrett Wollman && rt->rt_router == router 7107b6ab19dSGarrett Wollman && rt->rt_state == state 7117b6ab19dSGarrett Wollman && rt->rt_tag == tag) 7127b6ab19dSGarrett Wollman return; 7137b6ab19dSGarrett Wollman 7147b6ab19dSGarrett Wollman lastlog(); 7157b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s %-35s metric=%-2d ", 7167b6ab19dSGarrett Wollman label, 7177b6ab19dSGarrett Wollman trace_pair(rt->rt_dst, rt->rt_mask, 7187b6ab19dSGarrett Wollman naddr_ntoa(rt->rt_gate)), 7197b6ab19dSGarrett Wollman rt->rt_metric); 7207b6ab19dSGarrett Wollman if (rt->rt_router != rt->rt_gate) 7217b6ab19dSGarrett Wollman (void)fprintf(ftrace, "router=%s ", 7227b6ab19dSGarrett Wollman naddr_ntoa(rt->rt_router)); 7237b6ab19dSGarrett Wollman if (rt->rt_tag != 0) 7247b6ab19dSGarrett Wollman (void)fprintf(ftrace, "tag=%#x ", ntohs(rt->rt_tag)); 7257b6ab19dSGarrett Wollman trace_bits(rs_bits, rt->rt_state, rt->rt_state != state); 7267b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s ", 7277b6ab19dSGarrett Wollman rt->rt_ifp == 0 ? "?" : rt->rt_ifp->int_name); 7287b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s\n", 7297b6ab19dSGarrett Wollman AGE_RT(rt->rt_state, rt->rt_ifp) ? ts(rt->rt_time) : ""); 7307b6ab19dSGarrett Wollman 7317b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%*s %19s%-16s ", 7327b6ab19dSGarrett Wollman strlen(label), "", "", 7337b6ab19dSGarrett Wollman rt->rt_gate != gate ? naddr_ntoa(gate) : ""); 7347b6ab19dSGarrett Wollman if (rt->rt_metric != metric) 7357b6ab19dSGarrett Wollman (void)fprintf(ftrace, "metric=%-2d ", metric); 7367b6ab19dSGarrett Wollman if (router != gate) 7377b6ab19dSGarrett Wollman (void)fprintf(ftrace, "router=%s ", naddr_ntoa(router)); 7387b6ab19dSGarrett Wollman if (rt->rt_tag != tag) 7397b6ab19dSGarrett Wollman (void)fprintf(ftrace, "tag=%#x ", ntohs(tag)); 7407b6ab19dSGarrett Wollman if (rt->rt_state != state) 7417b6ab19dSGarrett Wollman trace_bits(rs_bits, state, 1); 7427b6ab19dSGarrett Wollman if (rt->rt_ifp != ifp) 7437b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s ", 7447b6ab19dSGarrett Wollman ifp != 0 ? ifp->int_name : "?"); 7457b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s\n", 7467b6ab19dSGarrett Wollman ((rt->rt_time == new_time || !AGE_RT(rt->rt_state, ifp)) 7477b6ab19dSGarrett Wollman ? "" : ts(new_time))); 7487b6ab19dSGarrett Wollman } 7497b6ab19dSGarrett Wollman 7507b6ab19dSGarrett Wollman 7517b6ab19dSGarrett Wollman void 7527b6ab19dSGarrett Wollman trace_add_del(char * action, struct rt_entry *rt) 7537b6ab19dSGarrett Wollman { 7547b6ab19dSGarrett Wollman u_int state = rt->rt_state; 7557b6ab19dSGarrett Wollman 7567b6ab19dSGarrett Wollman if (ftrace == 0) 7577b6ab19dSGarrett Wollman return; 7587b6ab19dSGarrett Wollman 7597b6ab19dSGarrett Wollman lastlog(); 7607b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s %-35s metric=%-2d ", 7617b6ab19dSGarrett Wollman action, 7627b6ab19dSGarrett Wollman trace_pair(rt->rt_dst, rt->rt_mask, 7637b6ab19dSGarrett Wollman naddr_ntoa(rt->rt_gate)), 7647b6ab19dSGarrett Wollman rt->rt_metric); 7657b6ab19dSGarrett Wollman if (rt->rt_router != rt->rt_gate) 7667b6ab19dSGarrett Wollman (void)fprintf(ftrace, "router=%s ", 7677b6ab19dSGarrett Wollman naddr_ntoa(rt->rt_router)); 7687b6ab19dSGarrett Wollman if (rt->rt_tag != 0) 7697b6ab19dSGarrett Wollman (void)fprintf(ftrace, "tag=%#x ", ntohs(rt->rt_tag)); 7707b6ab19dSGarrett Wollman trace_bits(rs_bits, state, 0); 7717b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s ", 7727b6ab19dSGarrett Wollman rt->rt_ifp != 0 ? rt->rt_ifp->int_name : "?"); 7737b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s\n", ts(rt->rt_time)); 7747b6ab19dSGarrett Wollman } 7757b6ab19dSGarrett Wollman 7767b6ab19dSGarrett Wollman 7777b6ab19dSGarrett Wollman /* ARGSUSED */ 7787b6ab19dSGarrett Wollman static int 7797b6ab19dSGarrett Wollman walk_trace(struct radix_node *rn, 7807b6ab19dSGarrett Wollman struct walkarg *w) 7817b6ab19dSGarrett Wollman { 7827b6ab19dSGarrett Wollman #define RT ((struct rt_entry *)rn) 7837b6ab19dSGarrett Wollman struct rt_spare *rts; 7847b6ab19dSGarrett Wollman int i, age; 7857b6ab19dSGarrett Wollman 7867b6ab19dSGarrett Wollman (void)fprintf(ftrace, " %-35s metric=%-2d ", 7877b6ab19dSGarrett Wollman trace_pair(RT->rt_dst, RT->rt_mask, 7887b6ab19dSGarrett Wollman naddr_ntoa(RT->rt_gate)), 7897b6ab19dSGarrett Wollman RT->rt_metric); 7907b6ab19dSGarrett Wollman if (RT->rt_router != RT->rt_gate) 7917b6ab19dSGarrett Wollman (void)fprintf(ftrace, "router=%s ", 7927b6ab19dSGarrett Wollman naddr_ntoa(RT->rt_router)); 7937b6ab19dSGarrett Wollman if (RT->rt_tag != 0) 7947b6ab19dSGarrett Wollman (void)fprintf(ftrace, "tag=%#x ", 7957b6ab19dSGarrett Wollman ntohs(RT->rt_tag)); 7967b6ab19dSGarrett Wollman trace_bits(rs_bits, RT->rt_state, 0); 7977b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s ", 7987b6ab19dSGarrett Wollman RT->rt_ifp == 0 ? "?" : RT->rt_ifp->int_name); 7997b6ab19dSGarrett Wollman age = AGE_RT(RT->rt_state, RT->rt_ifp); 8007b6ab19dSGarrett Wollman if (age) 8017b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s", ts(RT->rt_time)); 8027b6ab19dSGarrett Wollman 8037b6ab19dSGarrett Wollman rts = &RT->rt_spares[1]; 8047b6ab19dSGarrett Wollman for (i = 1; i < NUM_SPARES; i++, rts++) { 8057b6ab19dSGarrett Wollman if (rts->rts_metric != HOPCNT_INFINITY) { 8067b6ab19dSGarrett Wollman (void)fprintf(ftrace,"\n #%d%15s%-16s metric=%-2d ", 8077b6ab19dSGarrett Wollman i, "", naddr_ntoa(rts->rts_gate), 8087b6ab19dSGarrett Wollman rts->rts_metric); 8097b6ab19dSGarrett Wollman if (rts->rts_router != rts->rts_gate) 8107b6ab19dSGarrett Wollman (void)fprintf(ftrace, "router=%s ", 8117b6ab19dSGarrett Wollman naddr_ntoa(rts->rts_router)); 8127b6ab19dSGarrett Wollman if (rts->rts_tag != 0) 8137b6ab19dSGarrett Wollman (void)fprintf(ftrace, "tag=%#x ", 8147b6ab19dSGarrett Wollman ntohs(rts->rts_tag)); 8157b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s ", 8167b6ab19dSGarrett Wollman (rts->rts_ifp == 0 8177b6ab19dSGarrett Wollman ? "?" : rts->rts_ifp->int_name)); 8187b6ab19dSGarrett Wollman if (age) 8197b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s", ts(rts->rts_time)); 8207b6ab19dSGarrett Wollman } 8217b6ab19dSGarrett Wollman } 8227b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 8237b6ab19dSGarrett Wollman 8247b6ab19dSGarrett Wollman return 0; 8257b6ab19dSGarrett Wollman } 8267b6ab19dSGarrett Wollman 8277b6ab19dSGarrett Wollman 8287b6ab19dSGarrett Wollman static void 8297b6ab19dSGarrett Wollman trace_dump(void) 8307b6ab19dSGarrett Wollman { 831d5b718b3SGarrett Wollman struct interface *ifp; 832d5b718b3SGarrett Wollman 8337b6ab19dSGarrett Wollman if (ftrace == 0) 8347b6ab19dSGarrett Wollman return; 8357b6ab19dSGarrett Wollman lastlog(); 8367b6ab19dSGarrett Wollman 837d5b718b3SGarrett Wollman for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) 838d5b718b3SGarrett Wollman trace_if("", ifp); 8397b6ab19dSGarrett Wollman (void)rn_walktree(rhead, walk_trace, 0); 8407b6ab19dSGarrett Wollman } 8417b6ab19dSGarrett Wollman 8427b6ab19dSGarrett Wollman 8437b6ab19dSGarrett Wollman void 8447b6ab19dSGarrett Wollman trace_rip(char *dir1, char *dir2, 8457b6ab19dSGarrett Wollman struct sockaddr_in *who, 8467b6ab19dSGarrett Wollman struct interface *ifp, 8477b6ab19dSGarrett Wollman struct rip *msg, 8487b6ab19dSGarrett Wollman int size) /* total size of message */ 8497b6ab19dSGarrett Wollman { 8507b6ab19dSGarrett Wollman struct netinfo *n, *lim; 851d5b718b3SGarrett Wollman # define NA (msg->rip_auths) 852d5b718b3SGarrett Wollman int i, seen_route; 8537b6ab19dSGarrett Wollman 8547b6ab19dSGarrett Wollman if (!TRACEPACKETS || ftrace == 0) 8557b6ab19dSGarrett Wollman return; 8567b6ab19dSGarrett Wollman 8577b6ab19dSGarrett Wollman lastlog(); 8587b6ab19dSGarrett Wollman if (msg->rip_cmd >= RIPCMD_MAX 8597b6ab19dSGarrett Wollman || msg->rip_vers == 0) { 8607b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s bad RIPv%d cmd=%d %s" 8617b6ab19dSGarrett Wollman " %s.%d size=%d\n", 8627b6ab19dSGarrett Wollman dir1, msg->rip_vers, msg->rip_cmd, dir2, 8637b6ab19dSGarrett Wollman naddr_ntoa(who->sin_addr.s_addr), 8647b6ab19dSGarrett Wollman ntohs(who->sin_port), 8657b6ab19dSGarrett Wollman size); 8667b6ab19dSGarrett Wollman return; 8677b6ab19dSGarrett Wollman } 8687b6ab19dSGarrett Wollman 8697b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s RIPv%d %s %s %s.%d%s%s\n", 8707b6ab19dSGarrett Wollman dir1, msg->rip_vers, ripcmds[msg->rip_cmd], dir2, 8717b6ab19dSGarrett Wollman naddr_ntoa(who->sin_addr.s_addr), ntohs(who->sin_port), 8727b6ab19dSGarrett Wollman ifp ? " via " : "", ifp ? ifp->int_name : ""); 8737b6ab19dSGarrett Wollman if (!TRACECONTENTS) 8747b6ab19dSGarrett Wollman return; 8757b6ab19dSGarrett Wollman 876d5b718b3SGarrett Wollman seen_route = 0; 8777b6ab19dSGarrett Wollman switch (msg->rip_cmd) { 8787b6ab19dSGarrett Wollman case RIPCMD_REQUEST: 8797b6ab19dSGarrett Wollman case RIPCMD_RESPONSE: 8807b6ab19dSGarrett Wollman n = msg->rip_nets; 8817b6ab19dSGarrett Wollman lim = (struct netinfo *)((char*)msg + size); 8827b6ab19dSGarrett Wollman for (; n < lim; n++) { 883d5b718b3SGarrett Wollman if (!seen_route 884d5b718b3SGarrett Wollman && n->n_family == RIP_AF_UNSPEC 8857b6ab19dSGarrett Wollman && ntohl(n->n_metric) == HOPCNT_INFINITY 886d5b718b3SGarrett Wollman && msg->rip_cmd == RIPCMD_REQUEST 887d5b718b3SGarrett Wollman && (n+1 == lim 888d5b718b3SGarrett Wollman || (n+2 == lim 889d5b718b3SGarrett Wollman && (n+1)->n_family == RIP_AF_AUTH))) { 8907b6ab19dSGarrett Wollman (void)fputs("\tQUERY ", ftrace); 8917b6ab19dSGarrett Wollman if (n->n_dst != 0) 8927b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s ", 8937b6ab19dSGarrett Wollman naddr_ntoa(n->n_dst)); 8947b6ab19dSGarrett Wollman if (n->n_mask != 0) 8957b6ab19dSGarrett Wollman (void)fprintf(ftrace, "mask=%#x ", 8967b6ab19dSGarrett Wollman (u_int)ntohl(n->n_mask)); 8977b6ab19dSGarrett Wollman if (n->n_nhop != 0) 8987b6ab19dSGarrett Wollman (void)fprintf(ftrace, "nhop=%s ", 8997b6ab19dSGarrett Wollman naddr_ntoa(n->n_nhop)); 9007b6ab19dSGarrett Wollman if (n->n_tag != 0) 9017b6ab19dSGarrett Wollman (void)fprintf(ftrace, "tag=%#x ", 9027b6ab19dSGarrett Wollman ntohs(n->n_tag)); 9037b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 9047b6ab19dSGarrett Wollman continue; 9057b6ab19dSGarrett Wollman } 9067b6ab19dSGarrett Wollman 9077b6ab19dSGarrett Wollman if (n->n_family == RIP_AF_AUTH) { 908d5b718b3SGarrett Wollman if (NA->a_type == RIP_AUTH_PW 909d5b718b3SGarrett Wollman && n == msg->rip_nets) { 910d5b718b3SGarrett Wollman (void)fprintf(ftrace, "\tPassword" 911d5b718b3SGarrett Wollman " Authentication:" 912d5b718b3SGarrett Wollman " \"%s\"\n", 913d5b718b3SGarrett Wollman qstring(NA->au.au_pw, 914d5b718b3SGarrett Wollman RIP_AUTH_PW_LEN)); 915d5b718b3SGarrett Wollman continue; 916d5b718b3SGarrett Wollman } 917d5b718b3SGarrett Wollman 918d5b718b3SGarrett Wollman if (NA->a_type == RIP_AUTH_MD5 919d5b718b3SGarrett Wollman && n == msg->rip_nets) { 9207b6ab19dSGarrett Wollman (void)fprintf(ftrace, 921d5b718b3SGarrett Wollman "\tMD5 Authentication" 922d5b718b3SGarrett Wollman " len=%d KeyID=%u" 923d5b718b3SGarrett Wollman " seqno=%u" 924d5b718b3SGarrett Wollman " rsvd=%#x,%#x\n", 925d5b718b3SGarrett Wollman NA->au.a_md5.md5_pkt_len, 926d5b718b3SGarrett Wollman NA->au.a_md5.md5_keyid, 927d5b718b3SGarrett Wollman NA->au.a_md5.md5_seqno, 928d5b718b3SGarrett Wollman NA->au.a_md5.rsvd[0], 929d5b718b3SGarrett Wollman NA->au.a_md5.rsvd[1]); 930d5b718b3SGarrett Wollman continue; 931d5b718b3SGarrett Wollman } 932d5b718b3SGarrett Wollman (void)fprintf(ftrace, 933d5b718b3SGarrett Wollman "\tAuthentication" 934d5b718b3SGarrett Wollman " type %d: ", 935d5b718b3SGarrett Wollman ntohs(NA->a_type)); 9367b6ab19dSGarrett Wollman for (i = 0; 937d5b718b3SGarrett Wollman i < sizeof(NA->au.au_pw); 9387b6ab19dSGarrett Wollman i++) 9397b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%02x ", 940d5b718b3SGarrett Wollman NA->au.au_pw[i]); 9417b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 9427b6ab19dSGarrett Wollman continue; 9437b6ab19dSGarrett Wollman } 9447b6ab19dSGarrett Wollman 945d5b718b3SGarrett Wollman seen_route = 1; 9467b6ab19dSGarrett Wollman if (n->n_family != RIP_AF_INET) { 9477b6ab19dSGarrett Wollman (void)fprintf(ftrace, 9487b6ab19dSGarrett Wollman "\t(af %d) %-18s mask=%#x ", 9497b6ab19dSGarrett Wollman ntohs(n->n_family), 9507b6ab19dSGarrett Wollman naddr_ntoa(n->n_dst), 9517b6ab19dSGarrett Wollman (u_int)ntohl(n->n_mask)); 9527b6ab19dSGarrett Wollman } else if (msg->rip_vers == RIPv1) { 9537b6ab19dSGarrett Wollman (void)fprintf(ftrace, "\t%-18s ", 9547b6ab19dSGarrett Wollman addrname(n->n_dst, 9557b6ab19dSGarrett Wollman ntohl(n->n_mask), 9567b6ab19dSGarrett Wollman n->n_mask==0 ? 2 : 1)); 9577b6ab19dSGarrett Wollman } else { 9587b6ab19dSGarrett Wollman (void)fprintf(ftrace, "\t%-18s ", 9597b6ab19dSGarrett Wollman addrname(n->n_dst, 9607b6ab19dSGarrett Wollman ntohl(n->n_mask), 9617b6ab19dSGarrett Wollman n->n_mask==0 ? 2 : 0)); 9627b6ab19dSGarrett Wollman } 9637b6ab19dSGarrett Wollman (void)fprintf(ftrace, "metric=%-2d ", 9647b6ab19dSGarrett Wollman (u_int)ntohl(n->n_metric)); 9657b6ab19dSGarrett Wollman if (n->n_nhop != 0) 9667b6ab19dSGarrett Wollman (void)fprintf(ftrace, " nhop=%s ", 9677b6ab19dSGarrett Wollman naddr_ntoa(n->n_nhop)); 9687b6ab19dSGarrett Wollman if (n->n_tag != 0) 9697b6ab19dSGarrett Wollman (void)fprintf(ftrace, "tag=%#x", 9707b6ab19dSGarrett Wollman ntohs(n->n_tag)); 9717b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 9727b6ab19dSGarrett Wollman } 9737b6ab19dSGarrett Wollman if (size != (char *)n - (char *)msg) 9747b6ab19dSGarrett Wollman (void)fprintf(ftrace, "truncated record, len %d\n", 9757b6ab19dSGarrett Wollman size); 9767b6ab19dSGarrett Wollman break; 9777b6ab19dSGarrett Wollman 9787b6ab19dSGarrett Wollman case RIPCMD_TRACEON: 9797b6ab19dSGarrett Wollman fprintf(ftrace, "\tfile=%*s\n", size-4, msg->rip_tracefile); 9807b6ab19dSGarrett Wollman break; 9817b6ab19dSGarrett Wollman 9827b6ab19dSGarrett Wollman case RIPCMD_TRACEOFF: 9837b6ab19dSGarrett Wollman break; 9847b6ab19dSGarrett Wollman } 9857b6ab19dSGarrett Wollman } 986