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 * 4. Neither the name of the University nor the names of its contributors 147b6ab19dSGarrett Wollman * may be used to endorse or promote products derived from this software 157b6ab19dSGarrett Wollman * without specific prior written permission. 167b6ab19dSGarrett Wollman * 177b6ab19dSGarrett Wollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 187b6ab19dSGarrett Wollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 197b6ab19dSGarrett Wollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 207b6ab19dSGarrett Wollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 217b6ab19dSGarrett Wollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 227b6ab19dSGarrett Wollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 237b6ab19dSGarrett Wollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 247b6ab19dSGarrett Wollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 257b6ab19dSGarrett Wollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 267b6ab19dSGarrett Wollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 277b6ab19dSGarrett Wollman * SUCH DAMAGE. 28c90fe7dcSMark Murray * 297f3dea24SPeter Wemm * $FreeBSD$ 307b6ab19dSGarrett Wollman */ 317b6ab19dSGarrett Wollman 327b6ab19dSGarrett Wollman #define RIPCMDS 337b6ab19dSGarrett Wollman #include "defs.h" 347b6ab19dSGarrett Wollman #include "pathnames.h" 357b6ab19dSGarrett Wollman #include <sys/stat.h> 367b6ab19dSGarrett Wollman #include <sys/signal.h> 377b6ab19dSGarrett Wollman #include <fcntl.h> 387b6ab19dSGarrett Wollman 39caa79e36SBruce M Simpson #ifdef __NetBSD__ 402c7a9781SMark Murray __RCSID("$NetBSD$"); 41caa79e36SBruce M Simpson #elif defined(__FreeBSD__) 42caa79e36SBruce M Simpson __RCSID("$FreeBSD$"); 43caa79e36SBruce M Simpson #else 44caa79e36SBruce M Simpson __RCSID("$Revision: 2.27 $"); 45caa79e36SBruce M Simpson #ident "$Revision: 2.27 $" 462c7a9781SMark Murray #endif 472c7a9781SMark Murray 487b6ab19dSGarrett Wollman 497b6ab19dSGarrett Wollman #ifdef sgi 507b6ab19dSGarrett Wollman /* use *stat64 for files on large file systems */ 517b6ab19dSGarrett Wollman #define stat stat64 527b6ab19dSGarrett Wollman #endif 537b6ab19dSGarrett Wollman 547b6ab19dSGarrett Wollman #define NRECORDS 50 /* size of circular trace buffer */ 557b6ab19dSGarrett Wollman 5671965874SGarrett Wollman int tracelevel, new_tracelevel; 5798815cc7SPeter Wemm FILE *ftrace; /* output trace file */ 582c7a9781SMark Murray static const char *sigtrace_pat = "%s"; 59534734edSWarner Losh static char savetracename[PATH_MAX]; 60534734edSWarner Losh char inittracename[PATH_MAX]; 6171965874SGarrett Wollman int file_trace; /* 1=tracing to file, not stdout */ 627b6ab19dSGarrett Wollman 637b6ab19dSGarrett Wollman static void trace_dump(void); 642c7a9781SMark Murray static void tmsg(const char *, ...) PATTRIB(1,2); 657b6ab19dSGarrett Wollman 667b6ab19dSGarrett Wollman 67d5b718b3SGarrett Wollman /* convert string to printable characters 68d5b718b3SGarrett Wollman */ 69d5b718b3SGarrett Wollman static char * 70d5b718b3SGarrett Wollman qstring(u_char *s, int len) 71d5b718b3SGarrett Wollman { 72d5b718b3SGarrett Wollman static char buf[8*20+1]; 73d5b718b3SGarrett Wollman char *p; 74d5b718b3SGarrett Wollman u_char *s2, c; 75d5b718b3SGarrett Wollman 76d5b718b3SGarrett Wollman 77d5b718b3SGarrett Wollman for (p = buf; len != 0 && p < &buf[sizeof(buf)-1]; len--) { 78d5b718b3SGarrett Wollman c = *s++; 79d5b718b3SGarrett Wollman if (c == '\0') { 80d5b718b3SGarrett Wollman for (s2 = s+1; s2 < &s[len]; s2++) { 81d5b718b3SGarrett Wollman if (*s2 != '\0') 82d5b718b3SGarrett Wollman break; 83d5b718b3SGarrett Wollman } 84d5b718b3SGarrett Wollman if (s2 >= &s[len]) 85d5b718b3SGarrett Wollman goto exit; 86d5b718b3SGarrett Wollman } 87d5b718b3SGarrett Wollman 88d5b718b3SGarrett Wollman if (c >= ' ' && c < 0x7f && c != '\\') { 89d5b718b3SGarrett Wollman *p++ = c; 90d5b718b3SGarrett Wollman continue; 91d5b718b3SGarrett Wollman } 92d5b718b3SGarrett Wollman *p++ = '\\'; 93d5b718b3SGarrett Wollman switch (c) { 94d5b718b3SGarrett Wollman case '\\': 95d5b718b3SGarrett Wollman *p++ = '\\'; 96d5b718b3SGarrett Wollman break; 97d5b718b3SGarrett Wollman case '\n': 98d5b718b3SGarrett Wollman *p++= 'n'; 99d5b718b3SGarrett Wollman break; 100d5b718b3SGarrett Wollman case '\r': 101d5b718b3SGarrett Wollman *p++= 'r'; 102d5b718b3SGarrett Wollman break; 103d5b718b3SGarrett Wollman case '\t': 104d5b718b3SGarrett Wollman *p++ = 't'; 105d5b718b3SGarrett Wollman break; 106d5b718b3SGarrett Wollman case '\b': 107d5b718b3SGarrett Wollman *p++ = 'b'; 108d5b718b3SGarrett Wollman break; 109d5b718b3SGarrett Wollman default: 110d5b718b3SGarrett Wollman p += sprintf(p,"%o",c); 111d5b718b3SGarrett Wollman break; 112d5b718b3SGarrett Wollman } 113d5b718b3SGarrett Wollman } 114d5b718b3SGarrett Wollman exit: 115d5b718b3SGarrett Wollman *p = '\0'; 116d5b718b3SGarrett Wollman return buf; 117d5b718b3SGarrett Wollman } 118d5b718b3SGarrett Wollman 119d5b718b3SGarrett Wollman 1207b6ab19dSGarrett Wollman /* convert IP address to a string, but not into a single buffer 1217b6ab19dSGarrett Wollman */ 1227b6ab19dSGarrett Wollman char * 1237b6ab19dSGarrett Wollman naddr_ntoa(naddr a) 1247b6ab19dSGarrett Wollman { 1257b6ab19dSGarrett Wollman #define NUM_BUFS 4 1267b6ab19dSGarrett Wollman static int bufno; 1277b6ab19dSGarrett Wollman static struct { 1287b6ab19dSGarrett Wollman char str[16]; /* xxx.xxx.xxx.xxx\0 */ 1297b6ab19dSGarrett Wollman } bufs[NUM_BUFS]; 1307b6ab19dSGarrett Wollman char *s; 1317b6ab19dSGarrett Wollman struct in_addr addr; 1327b6ab19dSGarrett Wollman 1337b6ab19dSGarrett Wollman addr.s_addr = a; 1347b6ab19dSGarrett Wollman s = strcpy(bufs[bufno].str, inet_ntoa(addr)); 1357b6ab19dSGarrett Wollman bufno = (bufno+1) % NUM_BUFS; 1367b6ab19dSGarrett Wollman return s; 1377b6ab19dSGarrett Wollman #undef NUM_BUFS 1387b6ab19dSGarrett Wollman } 1397b6ab19dSGarrett Wollman 1407b6ab19dSGarrett Wollman 1412c7a9781SMark Murray const char * 1427b6ab19dSGarrett Wollman saddr_ntoa(struct sockaddr *sa) 1437b6ab19dSGarrett Wollman { 1447b6ab19dSGarrett Wollman return (sa == 0) ? "?" : naddr_ntoa(S_ADDR(sa)); 1457b6ab19dSGarrett Wollman } 1467b6ab19dSGarrett Wollman 1477b6ab19dSGarrett Wollman 1487b6ab19dSGarrett Wollman static char * 1497b6ab19dSGarrett Wollman ts(time_t secs) { 1507b6ab19dSGarrett Wollman static char s[20]; 1517b6ab19dSGarrett Wollman 1527b6ab19dSGarrett Wollman secs += epoch.tv_sec; 1537b6ab19dSGarrett Wollman #ifdef sgi 1547b6ab19dSGarrett Wollman (void)cftime(s, "%T", &secs); 1557b6ab19dSGarrett Wollman #else 1562c7a9781SMark Murray memcpy(s, ctime(&secs)+11, 8); 1577b6ab19dSGarrett Wollman s[8] = '\0'; 1587b6ab19dSGarrett Wollman #endif 1597b6ab19dSGarrett Wollman return s; 1607b6ab19dSGarrett Wollman } 1617b6ab19dSGarrett Wollman 1627b6ab19dSGarrett Wollman 1637b6ab19dSGarrett Wollman /* On each event, display a time stamp. 1647b6ab19dSGarrett Wollman * This assumes that 'now' is update once for each event, and 1657b6ab19dSGarrett Wollman * that at least now.tv_usec changes. 1667b6ab19dSGarrett Wollman */ 16771965874SGarrett Wollman static struct timeval lastlog_time; 16871965874SGarrett Wollman 1697b6ab19dSGarrett Wollman void 1707b6ab19dSGarrett Wollman lastlog(void) 1717b6ab19dSGarrett Wollman { 17271965874SGarrett Wollman if (lastlog_time.tv_sec != now.tv_sec 17371965874SGarrett Wollman || lastlog_time.tv_usec != now.tv_usec) { 1747b6ab19dSGarrett Wollman (void)fprintf(ftrace, "-- %s --\n", ts(now.tv_sec)); 17571965874SGarrett Wollman lastlog_time = now; 1767b6ab19dSGarrett Wollman } 1777b6ab19dSGarrett Wollman } 1787b6ab19dSGarrett Wollman 1797b6ab19dSGarrett Wollman 1807b6ab19dSGarrett Wollman static void 1812c7a9781SMark Murray tmsg(const char *p, ...) 1827b6ab19dSGarrett Wollman { 1837b6ab19dSGarrett Wollman va_list args; 1847b6ab19dSGarrett Wollman 1857b6ab19dSGarrett Wollman if (ftrace != 0) { 1867b6ab19dSGarrett Wollman lastlog(); 1877b6ab19dSGarrett Wollman va_start(args, p); 1887b6ab19dSGarrett Wollman vfprintf(ftrace, p, args); 189caa79e36SBruce M Simpson va_end(args); 1902c7a9781SMark Murray (void)fputc('\n',ftrace); 1917b6ab19dSGarrett Wollman fflush(ftrace); 1927b6ab19dSGarrett Wollman } 1937b6ab19dSGarrett Wollman } 1947b6ab19dSGarrett Wollman 1957b6ab19dSGarrett Wollman 1962c7a9781SMark Murray void 1972c7a9781SMark Murray trace_close(int zap_stdio) 1987b6ab19dSGarrett Wollman { 1997b6ab19dSGarrett Wollman int fd; 2007b6ab19dSGarrett Wollman 2017b6ab19dSGarrett Wollman 2027b6ab19dSGarrett Wollman fflush(stdout); 2037b6ab19dSGarrett Wollman fflush(stderr); 2047b6ab19dSGarrett Wollman 2052c7a9781SMark Murray if (ftrace != 0 && zap_stdio) { 20671965874SGarrett Wollman if (ftrace != stdout) 20771965874SGarrett Wollman fclose(ftrace); 20871965874SGarrett Wollman ftrace = 0; 2097b6ab19dSGarrett Wollman fd = open(_PATH_DEVNULL, O_RDWR); 2102c7a9781SMark Murray if (isatty(STDIN_FILENO)) 21171965874SGarrett Wollman (void)dup2(fd, STDIN_FILENO); 2122c7a9781SMark Murray if (isatty(STDOUT_FILENO)) 2137b6ab19dSGarrett Wollman (void)dup2(fd, STDOUT_FILENO); 2142c7a9781SMark Murray if (isatty(STDERR_FILENO)) 2157b6ab19dSGarrett Wollman (void)dup2(fd, STDERR_FILENO); 2167b6ab19dSGarrett Wollman (void)close(fd); 2177b6ab19dSGarrett Wollman } 21871965874SGarrett Wollman lastlog_time.tv_sec = 0; 2197b6ab19dSGarrett Wollman } 2207b6ab19dSGarrett Wollman 2217b6ab19dSGarrett Wollman 2227b6ab19dSGarrett Wollman void 2237b6ab19dSGarrett Wollman trace_flush(void) 2247b6ab19dSGarrett Wollman { 2257b6ab19dSGarrett Wollman if (ftrace != 0) { 2267b6ab19dSGarrett Wollman fflush(ftrace); 2277b6ab19dSGarrett Wollman if (ferror(ftrace)) 2282c7a9781SMark Murray trace_off("tracing off: %s", strerror(ferror(ftrace))); 2297b6ab19dSGarrett Wollman } 2307b6ab19dSGarrett Wollman } 2317b6ab19dSGarrett Wollman 2327b6ab19dSGarrett Wollman 2337b6ab19dSGarrett Wollman void 2342c7a9781SMark Murray trace_off(const char *p, ...) 2357b6ab19dSGarrett Wollman { 2367b6ab19dSGarrett Wollman va_list args; 2377b6ab19dSGarrett Wollman 2387b6ab19dSGarrett Wollman 2397b6ab19dSGarrett Wollman if (ftrace != 0) { 2407b6ab19dSGarrett Wollman lastlog(); 2417b6ab19dSGarrett Wollman va_start(args, p); 2427b6ab19dSGarrett Wollman vfprintf(ftrace, p, args); 243caa79e36SBruce M Simpson va_end(args); 2442c7a9781SMark Murray (void)fputc('\n',ftrace); 2457b6ab19dSGarrett Wollman } 2462c7a9781SMark Murray trace_close(file_trace); 2477b6ab19dSGarrett Wollman 2487b6ab19dSGarrett Wollman new_tracelevel = tracelevel = 0; 2497b6ab19dSGarrett Wollman } 2507b6ab19dSGarrett Wollman 2517b6ab19dSGarrett Wollman 25271965874SGarrett Wollman /* log a change in tracing 2537b6ab19dSGarrett Wollman */ 2547b6ab19dSGarrett Wollman void 2552c7a9781SMark Murray tracelevel_msg(const char *pat, 25671965874SGarrett Wollman int dump) /* -1=no dump, 0=default, 1=force */ 2577b6ab19dSGarrett Wollman { 2582c7a9781SMark Murray static const char *off_msgs[MAX_TRACELEVEL] = { 2597b6ab19dSGarrett Wollman "Tracing actions stopped", 2607b6ab19dSGarrett Wollman "Tracing packets stopped", 2617b6ab19dSGarrett Wollman "Tracing packet contents stopped", 2627b6ab19dSGarrett Wollman "Tracing kernel changes stopped", 2637b6ab19dSGarrett Wollman }; 2642c7a9781SMark Murray static const char *on_msgs[MAX_TRACELEVEL] = { 2657b6ab19dSGarrett Wollman "Tracing actions started", 2667b6ab19dSGarrett Wollman "Tracing packets started", 2677b6ab19dSGarrett Wollman "Tracing packet contents started", 2687b6ab19dSGarrett Wollman "Tracing kernel changes started", 2697b6ab19dSGarrett Wollman }; 27071965874SGarrett Wollman u_int old_tracelevel = tracelevel; 2717b6ab19dSGarrett Wollman 2727b6ab19dSGarrett Wollman 27371965874SGarrett Wollman if (new_tracelevel < 0) 27471965874SGarrett Wollman new_tracelevel = 0; 27571965874SGarrett Wollman else if (new_tracelevel > MAX_TRACELEVEL) 2767b6ab19dSGarrett Wollman new_tracelevel = MAX_TRACELEVEL; 27771965874SGarrett Wollman 27871965874SGarrett Wollman if (new_tracelevel < tracelevel) { 27971965874SGarrett Wollman if (new_tracelevel <= 0) { 28071965874SGarrett Wollman trace_off(pat, off_msgs[0]); 28171965874SGarrett Wollman } else do { 28271965874SGarrett Wollman tmsg(pat, off_msgs[tracelevel]); 28371965874SGarrett Wollman } 28471965874SGarrett Wollman while (--tracelevel != new_tracelevel); 28571965874SGarrett Wollman 28671965874SGarrett Wollman } else if (new_tracelevel > tracelevel) { 28771965874SGarrett Wollman do { 28871965874SGarrett Wollman tmsg(pat, on_msgs[tracelevel++]); 28971965874SGarrett Wollman } while (tracelevel != new_tracelevel); 29071965874SGarrett Wollman } 29171965874SGarrett Wollman 29271965874SGarrett Wollman if (dump > 0 29371965874SGarrett Wollman || (dump == 0 && old_tracelevel == 0 && tracelevel != 0)) 29471965874SGarrett Wollman trace_dump(); 29571965874SGarrett Wollman } 29671965874SGarrett Wollman 29771965874SGarrett Wollman 29871965874SGarrett Wollman void 2992c7a9781SMark Murray set_tracefile(const char *filename, 3002c7a9781SMark Murray const char *pat, 30171965874SGarrett Wollman int dump) /* -1=no dump, 0=default, 1=force */ 30271965874SGarrett Wollman { 30371965874SGarrett Wollman struct stat stbuf; 30471965874SGarrett Wollman FILE *n_ftrace; 3052c7a9781SMark Murray const char *fn; 30671965874SGarrett Wollman 30771965874SGarrett Wollman 30871965874SGarrett Wollman /* Allow a null filename to increase the level if the trace file 30971965874SGarrett Wollman * is already open or if coming from a trusted source, such as 31071965874SGarrett Wollman * a signal or the command line. 31171965874SGarrett Wollman */ 31271965874SGarrett Wollman if (filename == 0 || filename[0] == '\0') { 31371965874SGarrett Wollman filename = 0; 31471965874SGarrett Wollman if (ftrace == 0) { 31571965874SGarrett Wollman if (inittracename[0] == '\0') { 31671965874SGarrett Wollman msglog("missing trace file name"); 3177b6ab19dSGarrett Wollman return; 3187b6ab19dSGarrett Wollman } 31971965874SGarrett Wollman fn = inittracename; 32071965874SGarrett Wollman } else { 32171965874SGarrett Wollman fn = 0; 3227b6ab19dSGarrett Wollman } 323d5b718b3SGarrett Wollman 32471965874SGarrett Wollman } else if (!strcmp(filename,"dump/../table")) { 32571965874SGarrett Wollman trace_dump(); 32671965874SGarrett Wollman return; 32771965874SGarrett Wollman 3287b6ab19dSGarrett Wollman } else { 32971965874SGarrett Wollman /* Allow the file specified with "-T file" to be reopened, 33071965874SGarrett Wollman * but require all other names specified over the net to 33171965874SGarrett Wollman * match the official path. The path can specify a directory 33271965874SGarrett Wollman * in which the file is to be created. 33371965874SGarrett Wollman */ 33471965874SGarrett Wollman if (strcmp(filename, inittracename) 33571965874SGarrett Wollman #ifdef _PATH_TRACE 33671965874SGarrett Wollman && (strncmp(filename, _PATH_TRACE, sizeof(_PATH_TRACE)-1) 33771965874SGarrett Wollman || strstr(filename,"../") 33871965874SGarrett Wollman || 0 > stat(_PATH_TRACE, &stbuf)) 33971965874SGarrett Wollman #endif 34071965874SGarrett Wollman ) { 34171965874SGarrett Wollman msglog("wrong trace file \"%s\"", filename); 34271965874SGarrett Wollman return; 3437b6ab19dSGarrett Wollman } 34471965874SGarrett Wollman 34571965874SGarrett Wollman /* If the new tracefile exists, it must be a regular file. 34671965874SGarrett Wollman */ 3472c7a9781SMark Murray if (stat(filename, &stbuf) >= 0 && !S_ISREG(stbuf.st_mode)) { 34871965874SGarrett Wollman msglog("wrong type (%#x) of trace file \"%s\"", 34971965874SGarrett Wollman stbuf.st_mode, filename); 35071965874SGarrett Wollman return; 3517b6ab19dSGarrett Wollman } 35271965874SGarrett Wollman 35371965874SGarrett Wollman fn = filename; 3547b6ab19dSGarrett Wollman } 35571965874SGarrett Wollman 35671965874SGarrett Wollman if (fn != 0) { 35771965874SGarrett Wollman n_ftrace = fopen(fn, "a"); 35871965874SGarrett Wollman if (n_ftrace == 0) { 35971965874SGarrett Wollman msglog("failed to open trace file \"%s\" %s", 36071965874SGarrett Wollman fn, strerror(errno)); 36171965874SGarrett Wollman if (fn == inittracename) 36271965874SGarrett Wollman inittracename[0] = '\0'; 36371965874SGarrett Wollman return; 36471965874SGarrett Wollman } 36571965874SGarrett Wollman 3662c7a9781SMark Murray tmsg("switch to trace file %s", fn); 36771965874SGarrett Wollman 3682c7a9781SMark Murray trace_close(file_trace = 1); 36971965874SGarrett Wollman 37071965874SGarrett Wollman if (fn != savetracename) 37171965874SGarrett Wollman strncpy(savetracename, fn, sizeof(savetracename)-1); 37271965874SGarrett Wollman ftrace = n_ftrace; 37371965874SGarrett Wollman 37471965874SGarrett Wollman fflush(stdout); 37571965874SGarrett Wollman fflush(stderr); 37671965874SGarrett Wollman dup2(fileno(ftrace), STDOUT_FILENO); 37771965874SGarrett Wollman dup2(fileno(ftrace), STDERR_FILENO); 37871965874SGarrett Wollman } 37971965874SGarrett Wollman 38071965874SGarrett Wollman if (new_tracelevel == 0 || filename == 0) 38171965874SGarrett Wollman new_tracelevel++; 38271965874SGarrett Wollman tracelevel_msg(pat, dump != 0 ? dump : (filename != 0)); 38371965874SGarrett Wollman } 38471965874SGarrett Wollman 38571965874SGarrett Wollman 38671965874SGarrett Wollman /* ARGSUSED */ 38771965874SGarrett Wollman void 3882c7a9781SMark Murray sigtrace_on(int s UNUSED) 38971965874SGarrett Wollman { 39071965874SGarrett Wollman new_tracelevel++; 3912c7a9781SMark Murray sigtrace_pat = "SIGUSR1: %s"; 39271965874SGarrett Wollman } 39371965874SGarrett Wollman 39471965874SGarrett Wollman 39571965874SGarrett Wollman /* ARGSUSED */ 39671965874SGarrett Wollman void 3972c7a9781SMark Murray sigtrace_off(int s UNUSED) 39871965874SGarrett Wollman { 39971965874SGarrett Wollman new_tracelevel--; 4002c7a9781SMark Murray sigtrace_pat = "SIGUSR2: %s"; 40171965874SGarrett Wollman } 40271965874SGarrett Wollman 40371965874SGarrett Wollman 40471965874SGarrett Wollman /* Set tracing after a signal. 40571965874SGarrett Wollman */ 40671965874SGarrett Wollman void 40771965874SGarrett Wollman set_tracelevel(void) 40871965874SGarrett Wollman { 40971965874SGarrett Wollman if (new_tracelevel == tracelevel) 41071965874SGarrett Wollman return; 41171965874SGarrett Wollman 41271965874SGarrett Wollman /* If tracing entirely off, and there was no tracefile specified 41371965874SGarrett Wollman * on the command line, then leave it off. 41471965874SGarrett Wollman */ 41571965874SGarrett Wollman if (new_tracelevel > tracelevel && ftrace == 0) { 41671965874SGarrett Wollman if (savetracename[0] != '\0') { 41771965874SGarrett Wollman set_tracefile(savetracename,sigtrace_pat,0); 41871965874SGarrett Wollman } else if (inittracename[0] != '\0') { 41971965874SGarrett Wollman set_tracefile(inittracename,sigtrace_pat,0); 42071965874SGarrett Wollman } else { 42171965874SGarrett Wollman new_tracelevel = 0; 42271965874SGarrett Wollman return; 42371965874SGarrett Wollman } 42471965874SGarrett Wollman } else { 42571965874SGarrett Wollman tracelevel_msg(sigtrace_pat, 0); 42671965874SGarrett Wollman } 4277b6ab19dSGarrett Wollman } 4287b6ab19dSGarrett Wollman 4297b6ab19dSGarrett Wollman 4307b6ab19dSGarrett Wollman /* display an address 4317b6ab19dSGarrett Wollman */ 4327b6ab19dSGarrett Wollman char * 4337b6ab19dSGarrett Wollman addrname(naddr addr, /* in network byte order */ 4347b6ab19dSGarrett Wollman naddr mask, 4357b6ab19dSGarrett Wollman int force) /* 0=show mask if nonstandard, */ 4367b6ab19dSGarrett Wollman { /* 1=always show mask, 2=never */ 4377b6ab19dSGarrett Wollman #define NUM_BUFS 4 4387b6ab19dSGarrett Wollman static int bufno; 4397b6ab19dSGarrett Wollman static struct { 4407b6ab19dSGarrett Wollman char str[15+20]; 4417b6ab19dSGarrett Wollman } bufs[NUM_BUFS]; 4427b6ab19dSGarrett Wollman char *s, *sp; 4437b6ab19dSGarrett Wollman naddr dmask; 4447b6ab19dSGarrett Wollman int i; 4457b6ab19dSGarrett Wollman 4467b6ab19dSGarrett Wollman s = strcpy(bufs[bufno].str, naddr_ntoa(addr)); 4477b6ab19dSGarrett Wollman bufno = (bufno+1) % NUM_BUFS; 4487b6ab19dSGarrett Wollman 4497b6ab19dSGarrett Wollman if (force == 1 || (force == 0 && mask != std_mask(addr))) { 4507b6ab19dSGarrett Wollman sp = &s[strlen(s)]; 4517b6ab19dSGarrett Wollman 4527b6ab19dSGarrett Wollman dmask = mask & -mask; 4537b6ab19dSGarrett Wollman if (mask + dmask == 0) { 4547b6ab19dSGarrett Wollman for (i = 0; i != 32 && ((1<<i) & mask) == 0; i++) 4557b6ab19dSGarrett Wollman continue; 4567b6ab19dSGarrett Wollman (void)sprintf(sp, "/%d", 32-i); 4577b6ab19dSGarrett Wollman 4587b6ab19dSGarrett Wollman } else { 4597b6ab19dSGarrett Wollman (void)sprintf(sp, " (mask %#x)", (u_int)mask); 4607b6ab19dSGarrett Wollman } 4617b6ab19dSGarrett Wollman } 4627b6ab19dSGarrett Wollman 4637b6ab19dSGarrett Wollman return s; 4647b6ab19dSGarrett Wollman #undef NUM_BUFS 4657b6ab19dSGarrett Wollman } 4667b6ab19dSGarrett Wollman 4677b6ab19dSGarrett Wollman 4687b6ab19dSGarrett Wollman /* display a bit-field 4697b6ab19dSGarrett Wollman */ 4707b6ab19dSGarrett Wollman struct bits { 4712c7a9781SMark Murray u_int bits_mask; 4722c7a9781SMark Murray u_int bits_clear; 4732c7a9781SMark Murray const char *bits_name; 4747b6ab19dSGarrett Wollman }; 4757b6ab19dSGarrett Wollman 4767b6ab19dSGarrett Wollman static struct bits if_bits[] = { 4777b6ab19dSGarrett Wollman { IFF_LOOPBACK, 0, "LOOPBACK" }, 4787b6ab19dSGarrett Wollman { IFF_POINTOPOINT, 0, "PT-TO-PT" }, 4797b6ab19dSGarrett Wollman { 0, 0, 0} 4807b6ab19dSGarrett Wollman }; 4817b6ab19dSGarrett Wollman 4827b6ab19dSGarrett Wollman static struct bits is_bits[] = { 483d5b718b3SGarrett Wollman { IS_ALIAS, 0, "ALIAS" }, 4847b6ab19dSGarrett Wollman { IS_SUBNET, 0, "" }, 485d5b718b3SGarrett Wollman { IS_REMOTE, (IS_NO_RDISC 486d5b718b3SGarrett Wollman | IS_BCAST_RDISC), "REMOTE" }, 4877b6ab19dSGarrett Wollman { IS_PASSIVE, (IS_NO_RDISC 4887b6ab19dSGarrett Wollman | IS_NO_RIP 4897b6ab19dSGarrett Wollman | IS_NO_SUPER_AG 4907b6ab19dSGarrett Wollman | IS_PM_RDISC 4917b6ab19dSGarrett Wollman | IS_NO_AG), "PASSIVE" }, 4927b6ab19dSGarrett Wollman { IS_EXTERNAL, 0, "EXTERNAL" }, 4937b6ab19dSGarrett Wollman { IS_CHECKED, 0, "" }, 4947b6ab19dSGarrett Wollman { IS_ALL_HOSTS, 0, "" }, 4957b6ab19dSGarrett Wollman { IS_ALL_ROUTERS, 0, "" }, 496d5b718b3SGarrett Wollman { IS_DISTRUST, 0, "DISTRUST" }, 4977b6ab19dSGarrett Wollman { IS_BROKE, IS_SICK, "BROKEN" }, 4987b6ab19dSGarrett Wollman { IS_SICK, 0, "SICK" }, 499d5b718b3SGarrett Wollman { IS_DUP, 0, "DUPLICATE" }, 50071965874SGarrett Wollman { IS_REDIRECT_OK, 0, "REDIRECT_OK" }, 5017b6ab19dSGarrett Wollman { IS_NEED_NET_SYN, 0, "" }, 5027b6ab19dSGarrett Wollman { IS_NO_AG, IS_NO_SUPER_AG, "NO_AG" }, 5037b6ab19dSGarrett Wollman { IS_NO_SUPER_AG, 0, "NO_SUPER_AG" }, 5047b6ab19dSGarrett Wollman { (IS_NO_RIPV1_IN 5057b6ab19dSGarrett Wollman | IS_NO_RIPV2_IN 5067b6ab19dSGarrett Wollman | IS_NO_RIPV1_OUT 5077b6ab19dSGarrett Wollman | IS_NO_RIPV2_OUT), 0, "NO_RIP" }, 5087b6ab19dSGarrett Wollman { (IS_NO_RIPV1_IN 5097b6ab19dSGarrett Wollman | IS_NO_RIPV1_OUT), 0, "RIPV2" }, 5107b6ab19dSGarrett Wollman { IS_NO_RIPV1_IN, 0, "NO_RIPV1_IN" }, 5117b6ab19dSGarrett Wollman { IS_NO_RIPV2_IN, 0, "NO_RIPV2_IN" }, 5127b6ab19dSGarrett Wollman { IS_NO_RIPV1_OUT, 0, "NO_RIPV1_OUT" }, 5137b6ab19dSGarrett Wollman { IS_NO_RIPV2_OUT, 0, "NO_RIPV2_OUT" }, 5147b6ab19dSGarrett Wollman { (IS_NO_ADV_IN 5157b6ab19dSGarrett Wollman | IS_NO_SOL_OUT 5167b6ab19dSGarrett Wollman | IS_NO_ADV_OUT), IS_BCAST_RDISC, "NO_RDISC" }, 5177b6ab19dSGarrett Wollman { IS_NO_SOL_OUT, 0, "NO_SOLICIT" }, 5187b6ab19dSGarrett Wollman { IS_SOL_OUT, 0, "SEND_SOLICIT" }, 5197b6ab19dSGarrett Wollman { IS_NO_ADV_OUT, IS_BCAST_RDISC, "NO_RDISC_ADV" }, 5207b6ab19dSGarrett Wollman { IS_ADV_OUT, 0, "RDISC_ADV" }, 5217b6ab19dSGarrett Wollman { IS_BCAST_RDISC, 0, "BCAST_RDISC" }, 522d5b718b3SGarrett Wollman { IS_PM_RDISC, 0, "" }, 5237b6ab19dSGarrett Wollman { 0, 0, "%#x"} 5247b6ab19dSGarrett Wollman }; 5257b6ab19dSGarrett Wollman 5267b6ab19dSGarrett Wollman static struct bits rs_bits[] = { 5277b6ab19dSGarrett Wollman { RS_IF, 0, "IF" }, 5287b6ab19dSGarrett Wollman { RS_NET_INT, RS_NET_SYN, "NET_INT" }, 5297b6ab19dSGarrett Wollman { RS_NET_SYN, 0, "NET_SYN" }, 5307b6ab19dSGarrett Wollman { RS_SUBNET, 0, "" }, 5317b6ab19dSGarrett Wollman { RS_LOCAL, 0, "LOCAL" }, 5327b6ab19dSGarrett Wollman { RS_MHOME, 0, "MHOME" }, 5337b6ab19dSGarrett Wollman { RS_STATIC, 0, "STATIC" }, 5347b6ab19dSGarrett Wollman { RS_RDISC, 0, "RDISC" }, 5357b6ab19dSGarrett Wollman { 0, 0, "%#x"} 5367b6ab19dSGarrett Wollman }; 5377b6ab19dSGarrett Wollman 5387b6ab19dSGarrett Wollman 5397b6ab19dSGarrett Wollman static void 5402c7a9781SMark Murray trace_bits(const struct bits *tbl, 5417b6ab19dSGarrett Wollman u_int field, 5427b6ab19dSGarrett Wollman int force) 5437b6ab19dSGarrett Wollman { 5442c7a9781SMark Murray u_int b; 5457b6ab19dSGarrett Wollman char c; 5467b6ab19dSGarrett Wollman 5477b6ab19dSGarrett Wollman if (force) { 5487b6ab19dSGarrett Wollman (void)putc('<', ftrace); 5497b6ab19dSGarrett Wollman c = 0; 5507b6ab19dSGarrett Wollman } else { 5517b6ab19dSGarrett Wollman c = '<'; 5527b6ab19dSGarrett Wollman } 5537b6ab19dSGarrett Wollman 5547b6ab19dSGarrett Wollman while (field != 0 5557b6ab19dSGarrett Wollman && (b = tbl->bits_mask) != 0) { 5567b6ab19dSGarrett Wollman if ((b & field) == b) { 5577b6ab19dSGarrett Wollman if (tbl->bits_name[0] != '\0') { 5587b6ab19dSGarrett Wollman if (c) 5597b6ab19dSGarrett Wollman (void)putc(c, ftrace); 5607b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s", tbl->bits_name); 5617b6ab19dSGarrett Wollman c = '|'; 5627b6ab19dSGarrett Wollman } 5637b6ab19dSGarrett Wollman if (0 == (field &= ~(b | tbl->bits_clear))) 5647b6ab19dSGarrett Wollman break; 5657b6ab19dSGarrett Wollman } 5667b6ab19dSGarrett Wollman tbl++; 5677b6ab19dSGarrett Wollman } 5687b6ab19dSGarrett Wollman if (field != 0 && tbl->bits_name != 0) { 5697b6ab19dSGarrett Wollman if (c) 5707b6ab19dSGarrett Wollman (void)putc(c, ftrace); 5717b6ab19dSGarrett Wollman (void)fprintf(ftrace, tbl->bits_name, field); 5727b6ab19dSGarrett Wollman c = '|'; 5737b6ab19dSGarrett Wollman } 5747b6ab19dSGarrett Wollman 5757b6ab19dSGarrett Wollman if (c != '<' || force) 5767b6ab19dSGarrett Wollman (void)fputs("> ", ftrace); 5777b6ab19dSGarrett Wollman } 5787b6ab19dSGarrett Wollman 5797b6ab19dSGarrett Wollman 5802c7a9781SMark Murray char * 5812c7a9781SMark Murray rtname(naddr dst, 5827b6ab19dSGarrett Wollman naddr mask, 5832c7a9781SMark Murray naddr gate) 5847b6ab19dSGarrett Wollman { 5857b6ab19dSGarrett Wollman static char buf[3*4+3+1+2+3 /* "xxx.xxx.xxx.xxx/xx-->" */ 5867b6ab19dSGarrett Wollman +3*4+3+1]; /* "xxx.xxx.xxx.xxx" */ 5877b6ab19dSGarrett Wollman int i; 5887b6ab19dSGarrett Wollman 5897b6ab19dSGarrett Wollman i = sprintf(buf, "%-16s-->", addrname(dst, mask, 0)); 5902c7a9781SMark Murray (void)sprintf(&buf[i], "%-*s", 15+20-MAX(20,i), naddr_ntoa(gate)); 5917b6ab19dSGarrett Wollman return buf; 5927b6ab19dSGarrett Wollman } 5937b6ab19dSGarrett Wollman 5947b6ab19dSGarrett Wollman 59571965874SGarrett Wollman static void 59671965874SGarrett Wollman print_rts(struct rt_spare *rts, 59771965874SGarrett Wollman int force_metric, /* -1=suppress, 0=default */ 59871965874SGarrett Wollman int force_ifp, /* -1=suppress, 0=default */ 59971965874SGarrett Wollman int force_router, /* -1=suppress, 0=default, 1=display */ 60071965874SGarrett Wollman int force_tag, /* -1=suppress, 0=default, 1=display */ 60171965874SGarrett Wollman int force_time) /* 0=suppress, 1=display */ 60271965874SGarrett Wollman { 6032c7a9781SMark Murray int i; 6042c7a9781SMark Murray 6052c7a9781SMark Murray 60671965874SGarrett Wollman if (force_metric >= 0) 60771965874SGarrett Wollman (void)fprintf(ftrace, "metric=%-2d ", rts->rts_metric); 60871965874SGarrett Wollman if (force_ifp >= 0) 60971965874SGarrett Wollman (void)fprintf(ftrace, "%s ", (rts->rts_ifp == 0 ? 61071965874SGarrett Wollman "if?" : rts->rts_ifp->int_name)); 61171965874SGarrett Wollman if (force_router > 0 61271965874SGarrett Wollman || (force_router == 0 && rts->rts_router != rts->rts_gate)) 61371965874SGarrett Wollman (void)fprintf(ftrace, "router=%s ", 61471965874SGarrett Wollman naddr_ntoa(rts->rts_router)); 61571965874SGarrett Wollman if (force_time > 0) 61671965874SGarrett Wollman (void)fprintf(ftrace, "%s ", ts(rts->rts_time)); 61771965874SGarrett Wollman if (force_tag > 0 61871965874SGarrett Wollman || (force_tag == 0 && rts->rts_tag != 0)) 6192c7a9781SMark Murray (void)fprintf(ftrace, "tag=%#x ", ntohs(rts->rts_tag)); 6202c7a9781SMark Murray if (rts->rts_de_ag != 0) { 6212c7a9781SMark Murray for (i = 1; (u_int)(1 << i) <= rts->rts_de_ag; i++) 6222c7a9781SMark Murray continue; 6232c7a9781SMark Murray (void)fprintf(ftrace, "de_ag=%d ", i); 6242c7a9781SMark Murray } 6252c7a9781SMark Murray 62671965874SGarrett Wollman } 62771965874SGarrett Wollman 62871965874SGarrett Wollman 6297b6ab19dSGarrett Wollman void 6302c7a9781SMark Murray trace_if(const char *act, 6317b6ab19dSGarrett Wollman struct interface *ifp) 6327b6ab19dSGarrett Wollman { 6337b6ab19dSGarrett Wollman if (!TRACEACTIONS || ftrace == 0) 6347b6ab19dSGarrett Wollman return; 6357b6ab19dSGarrett Wollman 6367b6ab19dSGarrett Wollman lastlog(); 637d5b718b3SGarrett Wollman (void)fprintf(ftrace, "%-3s interface %-4s ", act, ifp->int_name); 6387b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%-15s-->%-15s ", 6397b6ab19dSGarrett Wollman naddr_ntoa(ifp->int_addr), 640d5b718b3SGarrett Wollman addrname(((ifp->int_if_flags & IFF_POINTOPOINT) 6417b6ab19dSGarrett Wollman ? ifp->int_dstaddr 642d5b718b3SGarrett Wollman : htonl(ifp->int_net)), 6437b6ab19dSGarrett Wollman ifp->int_mask, 1)); 6447b6ab19dSGarrett Wollman if (ifp->int_metric != 0) 6457b6ab19dSGarrett Wollman (void)fprintf(ftrace, "metric=%d ", ifp->int_metric); 646caa79e36SBruce M Simpson if (ifp->int_adj_inmetric != 0) 647caa79e36SBruce M Simpson (void)fprintf(ftrace, "adj_inmetric=%u ", 648caa79e36SBruce M Simpson ifp->int_adj_inmetric); 649caa79e36SBruce M Simpson if (ifp->int_adj_outmetric != 0) 650caa79e36SBruce M Simpson (void)fprintf(ftrace, "adj_outmetric=%u ", 651caa79e36SBruce M Simpson ifp->int_adj_outmetric); 652d5b718b3SGarrett Wollman if (!IS_RIP_OUT_OFF(ifp->int_state) 653d5b718b3SGarrett Wollman && ifp->int_d_metric != 0) 654caa79e36SBruce M Simpson (void)fprintf(ftrace, "fake_default=%u ", ifp->int_d_metric); 6557b6ab19dSGarrett Wollman trace_bits(if_bits, ifp->int_if_flags, 0); 6567b6ab19dSGarrett Wollman trace_bits(is_bits, ifp->int_state, 0); 6577b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 6587b6ab19dSGarrett Wollman } 6597b6ab19dSGarrett Wollman 6607b6ab19dSGarrett Wollman 6617b6ab19dSGarrett Wollman void 6627b6ab19dSGarrett Wollman trace_upslot(struct rt_entry *rt, 6637b6ab19dSGarrett Wollman struct rt_spare *rts, 6642c7a9781SMark Murray struct rt_spare *new) 6657b6ab19dSGarrett Wollman { 6667b6ab19dSGarrett Wollman if (!TRACEACTIONS || ftrace == 0) 6677b6ab19dSGarrett Wollman return; 66871965874SGarrett Wollman 6692c7a9781SMark Murray if (rts->rts_gate == new->rts_gate 6702c7a9781SMark Murray && rts->rts_router == new->rts_router 6712c7a9781SMark Murray && rts->rts_metric == new->rts_metric 6722c7a9781SMark Murray && rts->rts_tag == new->rts_tag 6732c7a9781SMark Murray && rts->rts_de_ag == new->rts_de_ag) 6747b6ab19dSGarrett Wollman return; 6757b6ab19dSGarrett Wollman 6767b6ab19dSGarrett Wollman lastlog(); 6772c7a9781SMark Murray if (new->rts_gate == 0) { 6782c7a9781SMark Murray (void)fprintf(ftrace, "Del #%d %-35s ", 6792c7a9781SMark Murray (int)(rts - rt->rt_spares), 6802c7a9781SMark Murray rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate)); 6812c7a9781SMark Murray print_rts(rts, 0,0,0,0, 6822c7a9781SMark Murray (rts != rt->rt_spares 6832c7a9781SMark Murray || AGE_RT(rt->rt_state,new->rts_ifp))); 6842c7a9781SMark Murray 6852c7a9781SMark Murray } else if (rts->rts_gate != RIP_DEFAULT) { 6867b6ab19dSGarrett Wollman (void)fprintf(ftrace, "Chg #%d %-35s ", 6872c7a9781SMark Murray (int)(rts - rt->rt_spares), 6882c7a9781SMark Murray rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate)); 68971965874SGarrett Wollman print_rts(rts, 0,0, 6902c7a9781SMark Murray rts->rts_gate != new->rts_gate, 6912c7a9781SMark Murray rts->rts_tag != new->rts_tag, 69271965874SGarrett Wollman rts != rt->rt_spares || AGE_RT(rt->rt_state, 69371965874SGarrett Wollman rt->rt_ifp)); 6947b6ab19dSGarrett Wollman 69571965874SGarrett Wollman (void)fprintf(ftrace, "\n %19s%-16s ", "", 6962c7a9781SMark Murray (new->rts_gate != rts->rts_gate 6972c7a9781SMark Murray ? naddr_ntoa(new->rts_gate) : "")); 6982c7a9781SMark Murray print_rts(new, 6992c7a9781SMark Murray -(new->rts_metric == rts->rts_metric), 7002c7a9781SMark Murray -(new->rts_ifp == rts->rts_ifp), 70171965874SGarrett Wollman 0, 7022c7a9781SMark Murray rts->rts_tag != new->rts_tag, 7032c7a9781SMark Murray (new->rts_time != rts->rts_time 7042c7a9781SMark Murray && (rts != rt->rt_spares 7052c7a9781SMark Murray || AGE_RT(rt->rt_state, new->rts_ifp)))); 7067b6ab19dSGarrett Wollman 7077b6ab19dSGarrett Wollman } else { 7087b6ab19dSGarrett Wollman (void)fprintf(ftrace, "Add #%d %-35s ", 7092c7a9781SMark Murray (int)(rts - rt->rt_spares), 7102c7a9781SMark Murray rtname(rt->rt_dst, rt->rt_mask, new->rts_gate)); 7112c7a9781SMark Murray print_rts(new, 0,0,0,0, 7122c7a9781SMark Murray (rts != rt->rt_spares 7132c7a9781SMark Murray || AGE_RT(rt->rt_state,new->rts_ifp))); 7147b6ab19dSGarrett Wollman } 71571965874SGarrett Wollman (void)fputc('\n',ftrace); 7167b6ab19dSGarrett Wollman } 7177b6ab19dSGarrett Wollman 7187b6ab19dSGarrett Wollman 7192c7a9781SMark Murray /* miscellaneous message checked by the caller 7207b6ab19dSGarrett Wollman */ 7217b6ab19dSGarrett Wollman void 7222c7a9781SMark Murray trace_misc(const char *p, ...) 7237b6ab19dSGarrett Wollman { 7247b6ab19dSGarrett Wollman va_list args; 7257b6ab19dSGarrett Wollman 7262c7a9781SMark Murray if (ftrace == 0) 7277b6ab19dSGarrett Wollman return; 7287b6ab19dSGarrett Wollman 7297b6ab19dSGarrett Wollman lastlog(); 7307b6ab19dSGarrett Wollman va_start(args, p); 7317b6ab19dSGarrett Wollman vfprintf(ftrace, p, args); 732caa79e36SBruce M Simpson va_end(args); 7332c7a9781SMark Murray (void)fputc('\n',ftrace); 7347b6ab19dSGarrett Wollman } 7357b6ab19dSGarrett Wollman 7367b6ab19dSGarrett Wollman 7377b6ab19dSGarrett Wollman /* display a message if tracing actions 7387b6ab19dSGarrett Wollman */ 7397b6ab19dSGarrett Wollman void 7402c7a9781SMark Murray trace_act(const char *p, ...) 7417b6ab19dSGarrett Wollman { 7427b6ab19dSGarrett Wollman va_list args; 7437b6ab19dSGarrett Wollman 7447b6ab19dSGarrett Wollman if (!TRACEACTIONS || ftrace == 0) 7457b6ab19dSGarrett Wollman return; 7467b6ab19dSGarrett Wollman 7477b6ab19dSGarrett Wollman lastlog(); 7487b6ab19dSGarrett Wollman va_start(args, p); 7497b6ab19dSGarrett Wollman vfprintf(ftrace, p, args); 750caa79e36SBruce M Simpson va_end(args); 751d5b718b3SGarrett Wollman (void)fputc('\n',ftrace); 7527b6ab19dSGarrett Wollman } 7537b6ab19dSGarrett Wollman 7547b6ab19dSGarrett Wollman 7557b6ab19dSGarrett Wollman /* display a message if tracing packets 7567b6ab19dSGarrett Wollman */ 7577b6ab19dSGarrett Wollman void 7582c7a9781SMark Murray trace_pkt(const char *p, ...) 7597b6ab19dSGarrett Wollman { 7607b6ab19dSGarrett Wollman va_list args; 7617b6ab19dSGarrett Wollman 7627b6ab19dSGarrett Wollman if (!TRACEPACKETS || ftrace == 0) 7637b6ab19dSGarrett Wollman return; 7647b6ab19dSGarrett Wollman 7657b6ab19dSGarrett Wollman lastlog(); 7667b6ab19dSGarrett Wollman va_start(args, p); 7677b6ab19dSGarrett Wollman vfprintf(ftrace, p, args); 768caa79e36SBruce M Simpson va_end(args); 769d5b718b3SGarrett Wollman (void)fputc('\n',ftrace); 7707b6ab19dSGarrett Wollman } 7717b6ab19dSGarrett Wollman 7727b6ab19dSGarrett Wollman 7737b6ab19dSGarrett Wollman void 7747b6ab19dSGarrett Wollman trace_change(struct rt_entry *rt, 7757b6ab19dSGarrett Wollman u_int state, 7762c7a9781SMark Murray struct rt_spare *new, 7772c7a9781SMark Murray const char *label) 7787b6ab19dSGarrett Wollman { 7797b6ab19dSGarrett Wollman if (ftrace == 0) 7807b6ab19dSGarrett Wollman return; 7817b6ab19dSGarrett Wollman 7822c7a9781SMark Murray if (rt->rt_metric == new->rts_metric 7832c7a9781SMark Murray && rt->rt_gate == new->rts_gate 7842c7a9781SMark Murray && rt->rt_router == new->rts_router 7857b6ab19dSGarrett Wollman && rt->rt_state == state 7862c7a9781SMark Murray && rt->rt_tag == new->rts_tag 7872c7a9781SMark Murray && rt->rt_de_ag == new->rts_de_ag) 7887b6ab19dSGarrett Wollman return; 7897b6ab19dSGarrett Wollman 7907b6ab19dSGarrett Wollman lastlog(); 79171965874SGarrett Wollman (void)fprintf(ftrace, "%s %-35s ", 7927b6ab19dSGarrett Wollman label, 7932c7a9781SMark Murray rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate)); 79471965874SGarrett Wollman print_rts(rt->rt_spares, 79571965874SGarrett Wollman 0,0,0,0, AGE_RT(rt->rt_state, rt->rt_ifp)); 7967b6ab19dSGarrett Wollman trace_bits(rs_bits, rt->rt_state, rt->rt_state != state); 7977b6ab19dSGarrett Wollman 79871965874SGarrett Wollman (void)fprintf(ftrace, "\n%*s %19s%-16s ", 7992c7a9781SMark Murray (int)strlen(label), "", "", 8002c7a9781SMark Murray (rt->rt_gate != new->rts_gate 8012c7a9781SMark Murray ? naddr_ntoa(new->rts_gate) : "")); 8022c7a9781SMark Murray print_rts(new, 8032c7a9781SMark Murray -(new->rts_metric == rt->rt_metric), 8042c7a9781SMark Murray -(new->rts_ifp == rt->rt_ifp), 80571965874SGarrett Wollman 0, 8062c7a9781SMark Murray rt->rt_tag != new->rts_tag, 8072c7a9781SMark Murray (rt->rt_time != new->rts_time 8082c7a9781SMark Murray && AGE_RT(rt->rt_state,new->rts_ifp))); 8097b6ab19dSGarrett Wollman if (rt->rt_state != state) 8107b6ab19dSGarrett Wollman trace_bits(rs_bits, state, 1); 81171965874SGarrett Wollman (void)fputc('\n',ftrace); 8127b6ab19dSGarrett Wollman } 8137b6ab19dSGarrett Wollman 8147b6ab19dSGarrett Wollman 8157b6ab19dSGarrett Wollman void 8162c7a9781SMark Murray trace_add_del(const char * action, struct rt_entry *rt) 8177b6ab19dSGarrett Wollman { 8187b6ab19dSGarrett Wollman if (ftrace == 0) 8197b6ab19dSGarrett Wollman return; 8207b6ab19dSGarrett Wollman 8217b6ab19dSGarrett Wollman lastlog(); 82271965874SGarrett Wollman (void)fprintf(ftrace, "%s %-35s ", 8237b6ab19dSGarrett Wollman action, 8242c7a9781SMark Murray rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate)); 82571965874SGarrett Wollman print_rts(rt->rt_spares, 0,0,0,0,AGE_RT(rt->rt_state,rt->rt_ifp)); 82671965874SGarrett Wollman trace_bits(rs_bits, rt->rt_state, 0); 82771965874SGarrett Wollman (void)fputc('\n',ftrace); 8287b6ab19dSGarrett Wollman } 8297b6ab19dSGarrett Wollman 8307b6ab19dSGarrett Wollman 8317b6ab19dSGarrett Wollman /* ARGSUSED */ 8327b6ab19dSGarrett Wollman static int 8337b6ab19dSGarrett Wollman walk_trace(struct radix_node *rn, 8342c7a9781SMark Murray struct walkarg *w UNUSED) 8357b6ab19dSGarrett Wollman { 8367b6ab19dSGarrett Wollman #define RT ((struct rt_entry *)rn) 8377b6ab19dSGarrett Wollman struct rt_spare *rts; 8382c7a9781SMark Murray int i; 8397b6ab19dSGarrett Wollman 8402c7a9781SMark Murray (void)fprintf(ftrace, " %-35s ", 8412c7a9781SMark Murray rtname(RT->rt_dst, RT->rt_mask, RT->rt_gate)); 8422c7a9781SMark Murray print_rts(&RT->rt_spares[0], 0,0,0,0, AGE_RT(RT->rt_state, RT->rt_ifp)); 8437b6ab19dSGarrett Wollman trace_bits(rs_bits, RT->rt_state, 0); 84471965874SGarrett Wollman if (RT->rt_poison_time >= now_garbage 84571965874SGarrett Wollman && RT->rt_poison_metric < RT->rt_metric) 84671965874SGarrett Wollman (void)fprintf(ftrace, "pm=%d@%s", 8472c7a9781SMark Murray RT->rt_poison_metric, ts(RT->rt_poison_time)); 8487b6ab19dSGarrett Wollman 8497b6ab19dSGarrett Wollman rts = &RT->rt_spares[1]; 8507b6ab19dSGarrett Wollman for (i = 1; i < NUM_SPARES; i++, rts++) { 85171965874SGarrett Wollman if (rts->rts_gate != RIP_DEFAULT) { 85271965874SGarrett Wollman (void)fprintf(ftrace,"\n #%d%15s%-16s ", 85371965874SGarrett Wollman i, "", naddr_ntoa(rts->rts_gate)); 85471965874SGarrett Wollman print_rts(rts, 0,0,0,0,1); 8557b6ab19dSGarrett Wollman } 8567b6ab19dSGarrett Wollman } 8577b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 8587b6ab19dSGarrett Wollman 8597b6ab19dSGarrett Wollman return 0; 8607b6ab19dSGarrett Wollman } 8617b6ab19dSGarrett Wollman 8627b6ab19dSGarrett Wollman 8637b6ab19dSGarrett Wollman static void 8647b6ab19dSGarrett Wollman trace_dump(void) 8657b6ab19dSGarrett Wollman { 866d5b718b3SGarrett Wollman struct interface *ifp; 867d5b718b3SGarrett Wollman 8687b6ab19dSGarrett Wollman if (ftrace == 0) 8697b6ab19dSGarrett Wollman return; 8707b6ab19dSGarrett Wollman lastlog(); 8717b6ab19dSGarrett Wollman 87271965874SGarrett Wollman (void)fputs("current daemon state:\n", ftrace); 87338ae6523SPoul-Henning Kamp LIST_FOREACH(ifp, &ifnet, int_list) 874d5b718b3SGarrett Wollman trace_if("", ifp); 8757b6ab19dSGarrett Wollman (void)rn_walktree(rhead, walk_trace, 0); 8767b6ab19dSGarrett Wollman } 8777b6ab19dSGarrett Wollman 8787b6ab19dSGarrett Wollman 8797b6ab19dSGarrett Wollman void 8802c7a9781SMark Murray trace_rip(const char *dir1, const char *dir2, 8817b6ab19dSGarrett Wollman struct sockaddr_in *who, 8827b6ab19dSGarrett Wollman struct interface *ifp, 8837b6ab19dSGarrett Wollman struct rip *msg, 8847b6ab19dSGarrett Wollman int size) /* total size of message */ 8857b6ab19dSGarrett Wollman { 8867b6ab19dSGarrett Wollman struct netinfo *n, *lim; 8872c7a9781SMark Murray # define NA ((struct netauth*)n) 888d5b718b3SGarrett Wollman int i, seen_route; 8897b6ab19dSGarrett Wollman 8907b6ab19dSGarrett Wollman if (!TRACEPACKETS || ftrace == 0) 8917b6ab19dSGarrett Wollman return; 8927b6ab19dSGarrett Wollman 8937b6ab19dSGarrett Wollman lastlog(); 8947b6ab19dSGarrett Wollman if (msg->rip_cmd >= RIPCMD_MAX 8957b6ab19dSGarrett Wollman || msg->rip_vers == 0) { 8967b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s bad RIPv%d cmd=%d %s" 8977b6ab19dSGarrett Wollman " %s.%d size=%d\n", 8987b6ab19dSGarrett Wollman dir1, msg->rip_vers, msg->rip_cmd, dir2, 8997b6ab19dSGarrett Wollman naddr_ntoa(who->sin_addr.s_addr), 9007b6ab19dSGarrett Wollman ntohs(who->sin_port), 9017b6ab19dSGarrett Wollman size); 9027b6ab19dSGarrett Wollman return; 9037b6ab19dSGarrett Wollman } 9047b6ab19dSGarrett Wollman 9057b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s RIPv%d %s %s %s.%d%s%s\n", 9067b6ab19dSGarrett Wollman dir1, msg->rip_vers, ripcmds[msg->rip_cmd], dir2, 9077b6ab19dSGarrett Wollman naddr_ntoa(who->sin_addr.s_addr), ntohs(who->sin_port), 9087b6ab19dSGarrett Wollman ifp ? " via " : "", ifp ? ifp->int_name : ""); 9097b6ab19dSGarrett Wollman if (!TRACECONTENTS) 9107b6ab19dSGarrett Wollman return; 9117b6ab19dSGarrett Wollman 912d5b718b3SGarrett Wollman seen_route = 0; 9137b6ab19dSGarrett Wollman switch (msg->rip_cmd) { 9147b6ab19dSGarrett Wollman case RIPCMD_REQUEST: 9157b6ab19dSGarrett Wollman case RIPCMD_RESPONSE: 9167b6ab19dSGarrett Wollman n = msg->rip_nets; 9177b6ab19dSGarrett Wollman lim = (struct netinfo *)((char*)msg + size); 9187b6ab19dSGarrett Wollman for (; n < lim; n++) { 919d5b718b3SGarrett Wollman if (!seen_route 920d5b718b3SGarrett Wollman && n->n_family == RIP_AF_UNSPEC 9217b6ab19dSGarrett Wollman && ntohl(n->n_metric) == HOPCNT_INFINITY 922d5b718b3SGarrett Wollman && msg->rip_cmd == RIPCMD_REQUEST 923d5b718b3SGarrett Wollman && (n+1 == lim 924d5b718b3SGarrett Wollman || (n+2 == lim 925d5b718b3SGarrett Wollman && (n+1)->n_family == RIP_AF_AUTH))) { 9267b6ab19dSGarrett Wollman (void)fputs("\tQUERY ", ftrace); 9277b6ab19dSGarrett Wollman if (n->n_dst != 0) 9287b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s ", 9297b6ab19dSGarrett Wollman naddr_ntoa(n->n_dst)); 9307b6ab19dSGarrett Wollman if (n->n_mask != 0) 9317b6ab19dSGarrett Wollman (void)fprintf(ftrace, "mask=%#x ", 9327b6ab19dSGarrett Wollman (u_int)ntohl(n->n_mask)); 9337b6ab19dSGarrett Wollman if (n->n_nhop != 0) 9347b6ab19dSGarrett Wollman (void)fprintf(ftrace, "nhop=%s ", 9357b6ab19dSGarrett Wollman naddr_ntoa(n->n_nhop)); 9367b6ab19dSGarrett Wollman if (n->n_tag != 0) 9377b6ab19dSGarrett Wollman (void)fprintf(ftrace, "tag=%#x ", 9387b6ab19dSGarrett Wollman ntohs(n->n_tag)); 9397b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 9407b6ab19dSGarrett Wollman continue; 9417b6ab19dSGarrett Wollman } 9427b6ab19dSGarrett Wollman 9437b6ab19dSGarrett Wollman if (n->n_family == RIP_AF_AUTH) { 944d5b718b3SGarrett Wollman if (NA->a_type == RIP_AUTH_PW 945d5b718b3SGarrett Wollman && n == msg->rip_nets) { 946d5b718b3SGarrett Wollman (void)fprintf(ftrace, "\tPassword" 947d5b718b3SGarrett Wollman " Authentication:" 948d5b718b3SGarrett Wollman " \"%s\"\n", 949d5b718b3SGarrett Wollman qstring(NA->au.au_pw, 950d5b718b3SGarrett Wollman RIP_AUTH_PW_LEN)); 951d5b718b3SGarrett Wollman continue; 952d5b718b3SGarrett Wollman } 953d5b718b3SGarrett Wollman 954d5b718b3SGarrett Wollman if (NA->a_type == RIP_AUTH_MD5 955d5b718b3SGarrett Wollman && n == msg->rip_nets) { 9567b6ab19dSGarrett Wollman (void)fprintf(ftrace, 9572c7a9781SMark Murray "\tMD5 Auth" 9582c7a9781SMark Murray " pkt_len=%d KeyID=%u" 9592c7a9781SMark Murray " auth_len=%d" 9602c7a9781SMark Murray " seqno=%#x" 961d5b718b3SGarrett Wollman " rsvd=%#x,%#x\n", 9622c7a9781SMark Murray ntohs(NA->au.a_md5.md5_pkt_len), 963d5b718b3SGarrett Wollman NA->au.a_md5.md5_keyid, 9642c7a9781SMark Murray NA->au.a_md5.md5_auth_len, 9652c7a9781SMark Murray (int)ntohl(NA->au.a_md5.md5_seqno), 9662c7a9781SMark Murray (int)ntohs(NA->au.a_md5.rsvd[0]), 9672c7a9781SMark Murray (int)ntohs(NA->au.a_md5.rsvd[1])); 968d5b718b3SGarrett Wollman continue; 969d5b718b3SGarrett Wollman } 970d5b718b3SGarrett Wollman (void)fprintf(ftrace, 9712c7a9781SMark Murray "\tAuthentication type %d: ", 972d5b718b3SGarrett Wollman ntohs(NA->a_type)); 9737b6ab19dSGarrett Wollman for (i = 0; 9742c7a9781SMark Murray i < (int)sizeof(NA->au.au_pw); 9757b6ab19dSGarrett Wollman i++) 9767b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%02x ", 977d5b718b3SGarrett Wollman NA->au.au_pw[i]); 9787b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 9797b6ab19dSGarrett Wollman continue; 9807b6ab19dSGarrett Wollman } 9817b6ab19dSGarrett Wollman 982d5b718b3SGarrett Wollman seen_route = 1; 9837b6ab19dSGarrett Wollman if (n->n_family != RIP_AF_INET) { 9847b6ab19dSGarrett Wollman (void)fprintf(ftrace, 9857b6ab19dSGarrett Wollman "\t(af %d) %-18s mask=%#x ", 9867b6ab19dSGarrett Wollman ntohs(n->n_family), 9877b6ab19dSGarrett Wollman naddr_ntoa(n->n_dst), 9887b6ab19dSGarrett Wollman (u_int)ntohl(n->n_mask)); 9897b6ab19dSGarrett Wollman } else if (msg->rip_vers == RIPv1) { 9907b6ab19dSGarrett Wollman (void)fprintf(ftrace, "\t%-18s ", 9917b6ab19dSGarrett Wollman addrname(n->n_dst, 9927b6ab19dSGarrett Wollman ntohl(n->n_mask), 9937b6ab19dSGarrett Wollman n->n_mask==0 ? 2 : 1)); 9947b6ab19dSGarrett Wollman } else { 9957b6ab19dSGarrett Wollman (void)fprintf(ftrace, "\t%-18s ", 9967b6ab19dSGarrett Wollman addrname(n->n_dst, 9977b6ab19dSGarrett Wollman ntohl(n->n_mask), 9987b6ab19dSGarrett Wollman n->n_mask==0 ? 2 : 0)); 9997b6ab19dSGarrett Wollman } 10007b6ab19dSGarrett Wollman (void)fprintf(ftrace, "metric=%-2d ", 10017b6ab19dSGarrett Wollman (u_int)ntohl(n->n_metric)); 10027b6ab19dSGarrett Wollman if (n->n_nhop != 0) 10037b6ab19dSGarrett Wollman (void)fprintf(ftrace, " nhop=%s ", 10047b6ab19dSGarrett Wollman naddr_ntoa(n->n_nhop)); 10057b6ab19dSGarrett Wollman if (n->n_tag != 0) 10067b6ab19dSGarrett Wollman (void)fprintf(ftrace, "tag=%#x", 10077b6ab19dSGarrett Wollman ntohs(n->n_tag)); 10087b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 10097b6ab19dSGarrett Wollman } 10107b6ab19dSGarrett Wollman if (size != (char *)n - (char *)msg) 10117b6ab19dSGarrett Wollman (void)fprintf(ftrace, "truncated record, len %d\n", 10127b6ab19dSGarrett Wollman size); 10137b6ab19dSGarrett Wollman break; 10147b6ab19dSGarrett Wollman 10157b6ab19dSGarrett Wollman case RIPCMD_TRACEON: 101671965874SGarrett Wollman fprintf(ftrace, "\tfile=\"%.*s\"\n", size-4, 101771965874SGarrett Wollman msg->rip_tracefile); 10187b6ab19dSGarrett Wollman break; 10197b6ab19dSGarrett Wollman 10207b6ab19dSGarrett Wollman case RIPCMD_TRACEOFF: 10217b6ab19dSGarrett Wollman break; 10227b6ab19dSGarrett Wollman } 10237b6ab19dSGarrett Wollman } 1024