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. 13*fbbd9655SWarner Losh * 3. 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 5471965874SGarrett Wollman int tracelevel, new_tracelevel; 5598815cc7SPeter Wemm FILE *ftrace; /* output trace file */ 562c7a9781SMark Murray static const char *sigtrace_pat = "%s"; 57534734edSWarner Losh static char savetracename[PATH_MAX]; 58534734edSWarner Losh char inittracename[PATH_MAX]; 59f2ca6d8aSPoul-Henning Kamp static int file_trace; /* 1=tracing to file, not stdout */ 607b6ab19dSGarrett Wollman 617b6ab19dSGarrett Wollman static void trace_dump(void); 622c7a9781SMark Murray static void tmsg(const char *, ...) PATTRIB(1,2); 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 1392c7a9781SMark Murray const char * 1407b6ab19dSGarrett Wollman saddr_ntoa(struct sockaddr *sa) 1417b6ab19dSGarrett Wollman { 142562c5a82SPedro F. Giffuni return (sa == NULL) ? "?" : 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 1542c7a9781SMark Murray memcpy(s, ctime(&secs)+11, 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 */ 16571965874SGarrett Wollman static struct timeval lastlog_time; 16671965874SGarrett Wollman 1677b6ab19dSGarrett Wollman void 1687b6ab19dSGarrett Wollman lastlog(void) 1697b6ab19dSGarrett Wollman { 17071965874SGarrett Wollman if (lastlog_time.tv_sec != now.tv_sec 17171965874SGarrett Wollman || lastlog_time.tv_usec != now.tv_usec) { 1727b6ab19dSGarrett Wollman (void)fprintf(ftrace, "-- %s --\n", ts(now.tv_sec)); 17371965874SGarrett Wollman lastlog_time = now; 1747b6ab19dSGarrett Wollman } 1757b6ab19dSGarrett Wollman } 1767b6ab19dSGarrett Wollman 1777b6ab19dSGarrett Wollman 1787b6ab19dSGarrett Wollman static void 1792c7a9781SMark Murray tmsg(const char *p, ...) 1807b6ab19dSGarrett Wollman { 1817b6ab19dSGarrett Wollman va_list args; 1827b6ab19dSGarrett Wollman 183562c5a82SPedro F. Giffuni if (ftrace != NULL) { 1847b6ab19dSGarrett Wollman lastlog(); 1857b6ab19dSGarrett Wollman va_start(args, p); 1867b6ab19dSGarrett Wollman vfprintf(ftrace, p, args); 187caa79e36SBruce M Simpson va_end(args); 1882c7a9781SMark Murray (void)fputc('\n',ftrace); 1897b6ab19dSGarrett Wollman fflush(ftrace); 1907b6ab19dSGarrett Wollman } 1917b6ab19dSGarrett Wollman } 1927b6ab19dSGarrett Wollman 1937b6ab19dSGarrett Wollman 1942c7a9781SMark Murray void 1952c7a9781SMark Murray trace_close(int zap_stdio) 1967b6ab19dSGarrett Wollman { 1977b6ab19dSGarrett Wollman int fd; 1987b6ab19dSGarrett Wollman 1997b6ab19dSGarrett Wollman 2007b6ab19dSGarrett Wollman fflush(stdout); 2017b6ab19dSGarrett Wollman fflush(stderr); 2027b6ab19dSGarrett Wollman 203562c5a82SPedro F. Giffuni if (ftrace != NULL && zap_stdio) { 20471965874SGarrett Wollman if (ftrace != stdout) 20571965874SGarrett Wollman fclose(ftrace); 206562c5a82SPedro F. Giffuni ftrace = NULL; 2077b6ab19dSGarrett Wollman fd = open(_PATH_DEVNULL, O_RDWR); 208e09d48f6SPedro F. Giffuni if (fd < 0) 209e09d48f6SPedro F. Giffuni return; 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 { 225562c5a82SPedro F. Giffuni if (ftrace != NULL) { 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 239562c5a82SPedro F. Giffuni if (ftrace != NULL) { 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 { 258a3e04ddcSPoul-Henning Kamp static const char * const 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 }; 264a3e04ddcSPoul-Henning Kamp static const char * const 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 */ 312562c5a82SPedro F. Giffuni if (filename == NULL || filename[0] == '\0') { 313562c5a82SPedro F. Giffuni filename = NULL; 314562c5a82SPedro F. Giffuni if (ftrace == NULL) { 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 { 321562c5a82SPedro F. Giffuni fn = NULL; 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 356562c5a82SPedro F. Giffuni if (fn != NULL) { 35771965874SGarrett Wollman n_ftrace = fopen(fn, "a"); 358562c5a82SPedro F. Giffuni if (n_ftrace == NULL) { 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 380562c5a82SPedro F. Giffuni if (new_tracelevel == 0 || filename == NULL) 38171965874SGarrett Wollman new_tracelevel++; 382562c5a82SPedro F. Giffuni tracelevel_msg(pat, dump != 0 ? dump : (filename != NULL)); 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 */ 415562c5a82SPedro F. Giffuni if (new_tracelevel > tracelevel && ftrace == NULL) { 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; 444e09d48f6SPedro F. Giffuni size_t l; 4457b6ab19dSGarrett Wollman int i; 4467b6ab19dSGarrett Wollman 447e09d48f6SPedro F. Giffuni strlcpy(bufs[bufno].str, naddr_ntoa(addr), sizeof(bufs[bufno].str)); 448e09d48f6SPedro F. Giffuni s = bufs[bufno].str; 449e09d48f6SPedro F. Giffuni l = sizeof(bufs[bufno].str); 4507b6ab19dSGarrett Wollman bufno = (bufno+1) % NUM_BUFS; 4517b6ab19dSGarrett Wollman 4527b6ab19dSGarrett Wollman if (force == 1 || (force == 0 && mask != std_mask(addr))) { 4537b6ab19dSGarrett Wollman sp = &s[strlen(s)]; 4547b6ab19dSGarrett Wollman 4557b6ab19dSGarrett Wollman dmask = mask & -mask; 4567b6ab19dSGarrett Wollman if (mask + dmask == 0) { 4577b6ab19dSGarrett Wollman for (i = 0; i != 32 && ((1<<i) & mask) == 0; i++) 4587b6ab19dSGarrett Wollman continue; 459e09d48f6SPedro F. Giffuni (void)snprintf(sp, s + l - sp, "/%d", 32-i); 4607b6ab19dSGarrett Wollman 4617b6ab19dSGarrett Wollman } else { 462e09d48f6SPedro F. Giffuni (void)snprintf(sp, s + l - sp, " (mask %#x)", 463e09d48f6SPedro F. Giffuni (u_int)mask); 4647b6ab19dSGarrett Wollman } 4657b6ab19dSGarrett Wollman } 4667b6ab19dSGarrett Wollman 4677b6ab19dSGarrett Wollman return s; 4687b6ab19dSGarrett Wollman #undef NUM_BUFS 4697b6ab19dSGarrett Wollman } 4707b6ab19dSGarrett Wollman 4717b6ab19dSGarrett Wollman 4727b6ab19dSGarrett Wollman /* display a bit-field 4737b6ab19dSGarrett Wollman */ 4747b6ab19dSGarrett Wollman struct bits { 4752c7a9781SMark Murray u_int bits_mask; 4762c7a9781SMark Murray u_int bits_clear; 4772c7a9781SMark Murray const char *bits_name; 4787b6ab19dSGarrett Wollman }; 4797b6ab19dSGarrett Wollman 480a3e04ddcSPoul-Henning Kamp static const struct bits if_bits[] = { 4817b6ab19dSGarrett Wollman { IFF_LOOPBACK, 0, "LOOPBACK" }, 4827b6ab19dSGarrett Wollman { IFF_POINTOPOINT, 0, "PT-TO-PT" }, 4837b6ab19dSGarrett Wollman { 0, 0, 0} 4847b6ab19dSGarrett Wollman }; 4857b6ab19dSGarrett Wollman 486a3e04ddcSPoul-Henning Kamp static const struct bits is_bits[] = { 487d5b718b3SGarrett Wollman { IS_ALIAS, 0, "ALIAS" }, 4887b6ab19dSGarrett Wollman { IS_SUBNET, 0, "" }, 489d5b718b3SGarrett Wollman { IS_REMOTE, (IS_NO_RDISC 490d5b718b3SGarrett Wollman | IS_BCAST_RDISC), "REMOTE" }, 4917b6ab19dSGarrett Wollman { IS_PASSIVE, (IS_NO_RDISC 4927b6ab19dSGarrett Wollman | IS_NO_RIP 4937b6ab19dSGarrett Wollman | IS_NO_SUPER_AG 4947b6ab19dSGarrett Wollman | IS_PM_RDISC 4957b6ab19dSGarrett Wollman | IS_NO_AG), "PASSIVE" }, 4967b6ab19dSGarrett Wollman { IS_EXTERNAL, 0, "EXTERNAL" }, 4977b6ab19dSGarrett Wollman { IS_CHECKED, 0, "" }, 4987b6ab19dSGarrett Wollman { IS_ALL_HOSTS, 0, "" }, 4997b6ab19dSGarrett Wollman { IS_ALL_ROUTERS, 0, "" }, 500d5b718b3SGarrett Wollman { IS_DISTRUST, 0, "DISTRUST" }, 5017b6ab19dSGarrett Wollman { IS_BROKE, IS_SICK, "BROKEN" }, 5027b6ab19dSGarrett Wollman { IS_SICK, 0, "SICK" }, 503d5b718b3SGarrett Wollman { IS_DUP, 0, "DUPLICATE" }, 50471965874SGarrett Wollman { IS_REDIRECT_OK, 0, "REDIRECT_OK" }, 5057b6ab19dSGarrett Wollman { IS_NEED_NET_SYN, 0, "" }, 5067b6ab19dSGarrett Wollman { IS_NO_AG, IS_NO_SUPER_AG, "NO_AG" }, 5077b6ab19dSGarrett Wollman { IS_NO_SUPER_AG, 0, "NO_SUPER_AG" }, 5087b6ab19dSGarrett Wollman { (IS_NO_RIPV1_IN 5097b6ab19dSGarrett Wollman | IS_NO_RIPV2_IN 5107b6ab19dSGarrett Wollman | IS_NO_RIPV1_OUT 5117b6ab19dSGarrett Wollman | IS_NO_RIPV2_OUT), 0, "NO_RIP" }, 5127b6ab19dSGarrett Wollman { (IS_NO_RIPV1_IN 5137b6ab19dSGarrett Wollman | IS_NO_RIPV1_OUT), 0, "RIPV2" }, 5147b6ab19dSGarrett Wollman { IS_NO_RIPV1_IN, 0, "NO_RIPV1_IN" }, 5157b6ab19dSGarrett Wollman { IS_NO_RIPV2_IN, 0, "NO_RIPV2_IN" }, 5167b6ab19dSGarrett Wollman { IS_NO_RIPV1_OUT, 0, "NO_RIPV1_OUT" }, 5177b6ab19dSGarrett Wollman { IS_NO_RIPV2_OUT, 0, "NO_RIPV2_OUT" }, 5187b6ab19dSGarrett Wollman { (IS_NO_ADV_IN 5197b6ab19dSGarrett Wollman | IS_NO_SOL_OUT 5207b6ab19dSGarrett Wollman | IS_NO_ADV_OUT), IS_BCAST_RDISC, "NO_RDISC" }, 5217b6ab19dSGarrett Wollman { IS_NO_SOL_OUT, 0, "NO_SOLICIT" }, 5227b6ab19dSGarrett Wollman { IS_SOL_OUT, 0, "SEND_SOLICIT" }, 5237b6ab19dSGarrett Wollman { IS_NO_ADV_OUT, IS_BCAST_RDISC, "NO_RDISC_ADV" }, 5247b6ab19dSGarrett Wollman { IS_ADV_OUT, 0, "RDISC_ADV" }, 5257b6ab19dSGarrett Wollman { IS_BCAST_RDISC, 0, "BCAST_RDISC" }, 526d5b718b3SGarrett Wollman { IS_PM_RDISC, 0, "" }, 5277b6ab19dSGarrett Wollman { 0, 0, "%#x"} 5287b6ab19dSGarrett Wollman }; 5297b6ab19dSGarrett Wollman 530a3e04ddcSPoul-Henning Kamp static const struct bits rs_bits[] = { 5317b6ab19dSGarrett Wollman { RS_IF, 0, "IF" }, 5327b6ab19dSGarrett Wollman { RS_NET_INT, RS_NET_SYN, "NET_INT" }, 5337b6ab19dSGarrett Wollman { RS_NET_SYN, 0, "NET_SYN" }, 5347b6ab19dSGarrett Wollman { RS_SUBNET, 0, "" }, 5357b6ab19dSGarrett Wollman { RS_LOCAL, 0, "LOCAL" }, 5367b6ab19dSGarrett Wollman { RS_MHOME, 0, "MHOME" }, 5377b6ab19dSGarrett Wollman { RS_STATIC, 0, "STATIC" }, 5387b6ab19dSGarrett Wollman { RS_RDISC, 0, "RDISC" }, 5397b6ab19dSGarrett Wollman { 0, 0, "%#x"} 5407b6ab19dSGarrett Wollman }; 5417b6ab19dSGarrett Wollman 5427b6ab19dSGarrett Wollman 5437b6ab19dSGarrett Wollman static void 5442c7a9781SMark Murray trace_bits(const struct bits *tbl, 5457b6ab19dSGarrett Wollman u_int field, 5467b6ab19dSGarrett Wollman int force) 5477b6ab19dSGarrett Wollman { 5482c7a9781SMark Murray u_int b; 5497b6ab19dSGarrett Wollman char c; 5507b6ab19dSGarrett Wollman 5517b6ab19dSGarrett Wollman if (force) { 5527b6ab19dSGarrett Wollman (void)putc('<', ftrace); 5537b6ab19dSGarrett Wollman c = 0; 5547b6ab19dSGarrett Wollman } else { 5557b6ab19dSGarrett Wollman c = '<'; 5567b6ab19dSGarrett Wollman } 5577b6ab19dSGarrett Wollman 5587b6ab19dSGarrett Wollman while (field != 0 5597b6ab19dSGarrett Wollman && (b = tbl->bits_mask) != 0) { 5607b6ab19dSGarrett Wollman if ((b & field) == b) { 5617b6ab19dSGarrett Wollman if (tbl->bits_name[0] != '\0') { 5627b6ab19dSGarrett Wollman if (c) 5637b6ab19dSGarrett Wollman (void)putc(c, ftrace); 5647b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s", tbl->bits_name); 5657b6ab19dSGarrett Wollman c = '|'; 5667b6ab19dSGarrett Wollman } 5677b6ab19dSGarrett Wollman if (0 == (field &= ~(b | tbl->bits_clear))) 5687b6ab19dSGarrett Wollman break; 5697b6ab19dSGarrett Wollman } 5707b6ab19dSGarrett Wollman tbl++; 5717b6ab19dSGarrett Wollman } 572562c5a82SPedro F. Giffuni if (field != 0 && tbl->bits_name != NULL) { 5737b6ab19dSGarrett Wollman if (c) 5747b6ab19dSGarrett Wollman (void)putc(c, ftrace); 5757b6ab19dSGarrett Wollman (void)fprintf(ftrace, tbl->bits_name, field); 5767b6ab19dSGarrett Wollman c = '|'; 5777b6ab19dSGarrett Wollman } 5787b6ab19dSGarrett Wollman 5797b6ab19dSGarrett Wollman if (c != '<' || force) 5807b6ab19dSGarrett Wollman (void)fputs("> ", ftrace); 5817b6ab19dSGarrett Wollman } 5827b6ab19dSGarrett Wollman 5837b6ab19dSGarrett Wollman 5842c7a9781SMark Murray char * 5852c7a9781SMark Murray rtname(naddr dst, 5867b6ab19dSGarrett Wollman naddr mask, 5872c7a9781SMark Murray naddr gate) 5887b6ab19dSGarrett Wollman { 5897b6ab19dSGarrett Wollman static char buf[3*4+3+1+2+3 /* "xxx.xxx.xxx.xxx/xx-->" */ 5907b6ab19dSGarrett Wollman +3*4+3+1]; /* "xxx.xxx.xxx.xxx" */ 5917b6ab19dSGarrett Wollman int i; 5927b6ab19dSGarrett Wollman 5937b6ab19dSGarrett Wollman i = sprintf(buf, "%-16s-->", addrname(dst, mask, 0)); 5942c7a9781SMark Murray (void)sprintf(&buf[i], "%-*s", 15+20-MAX(20,i), naddr_ntoa(gate)); 5957b6ab19dSGarrett Wollman return buf; 5967b6ab19dSGarrett Wollman } 5977b6ab19dSGarrett Wollman 5987b6ab19dSGarrett Wollman 59971965874SGarrett Wollman static void 60071965874SGarrett Wollman print_rts(struct rt_spare *rts, 60171965874SGarrett Wollman int force_metric, /* -1=suppress, 0=default */ 60271965874SGarrett Wollman int force_ifp, /* -1=suppress, 0=default */ 60371965874SGarrett Wollman int force_router, /* -1=suppress, 0=default, 1=display */ 60471965874SGarrett Wollman int force_tag, /* -1=suppress, 0=default, 1=display */ 60571965874SGarrett Wollman int force_time) /* 0=suppress, 1=display */ 60671965874SGarrett Wollman { 6072c7a9781SMark Murray int i; 6082c7a9781SMark Murray 6092c7a9781SMark Murray 61071965874SGarrett Wollman if (force_metric >= 0) 61171965874SGarrett Wollman (void)fprintf(ftrace, "metric=%-2d ", rts->rts_metric); 61271965874SGarrett Wollman if (force_ifp >= 0) 613562c5a82SPedro F. Giffuni (void)fprintf(ftrace, "%s ", (rts->rts_ifp == NULL ? 61471965874SGarrett Wollman "if?" : rts->rts_ifp->int_name)); 61571965874SGarrett Wollman if (force_router > 0 61671965874SGarrett Wollman || (force_router == 0 && rts->rts_router != rts->rts_gate)) 61771965874SGarrett Wollman (void)fprintf(ftrace, "router=%s ", 61871965874SGarrett Wollman naddr_ntoa(rts->rts_router)); 61971965874SGarrett Wollman if (force_time > 0) 62071965874SGarrett Wollman (void)fprintf(ftrace, "%s ", ts(rts->rts_time)); 62171965874SGarrett Wollman if (force_tag > 0 62271965874SGarrett Wollman || (force_tag == 0 && rts->rts_tag != 0)) 6232c7a9781SMark Murray (void)fprintf(ftrace, "tag=%#x ", ntohs(rts->rts_tag)); 6242c7a9781SMark Murray if (rts->rts_de_ag != 0) { 6252c7a9781SMark Murray for (i = 1; (u_int)(1 << i) <= rts->rts_de_ag; i++) 6262c7a9781SMark Murray continue; 6272c7a9781SMark Murray (void)fprintf(ftrace, "de_ag=%d ", i); 6282c7a9781SMark Murray } 6292c7a9781SMark Murray 63071965874SGarrett Wollman } 63171965874SGarrett Wollman 63271965874SGarrett Wollman 6337b6ab19dSGarrett Wollman void 6342c7a9781SMark Murray trace_if(const char *act, 6357b6ab19dSGarrett Wollman struct interface *ifp) 6367b6ab19dSGarrett Wollman { 637562c5a82SPedro F. Giffuni if (!TRACEACTIONS || ftrace == NULL) 6387b6ab19dSGarrett Wollman return; 6397b6ab19dSGarrett Wollman 6407b6ab19dSGarrett Wollman lastlog(); 641d5b718b3SGarrett Wollman (void)fprintf(ftrace, "%-3s interface %-4s ", act, ifp->int_name); 6427b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%-15s-->%-15s ", 6437b6ab19dSGarrett Wollman naddr_ntoa(ifp->int_addr), 644d5b718b3SGarrett Wollman addrname(((ifp->int_if_flags & IFF_POINTOPOINT) 6457b6ab19dSGarrett Wollman ? ifp->int_dstaddr 646d5b718b3SGarrett Wollman : htonl(ifp->int_net)), 6477b6ab19dSGarrett Wollman ifp->int_mask, 1)); 6487b6ab19dSGarrett Wollman if (ifp->int_metric != 0) 6497b6ab19dSGarrett Wollman (void)fprintf(ftrace, "metric=%d ", ifp->int_metric); 650caa79e36SBruce M Simpson if (ifp->int_adj_inmetric != 0) 651caa79e36SBruce M Simpson (void)fprintf(ftrace, "adj_inmetric=%u ", 652caa79e36SBruce M Simpson ifp->int_adj_inmetric); 653caa79e36SBruce M Simpson if (ifp->int_adj_outmetric != 0) 654caa79e36SBruce M Simpson (void)fprintf(ftrace, "adj_outmetric=%u ", 655caa79e36SBruce M Simpson ifp->int_adj_outmetric); 656d5b718b3SGarrett Wollman if (!IS_RIP_OUT_OFF(ifp->int_state) 657d5b718b3SGarrett Wollman && ifp->int_d_metric != 0) 658caa79e36SBruce M Simpson (void)fprintf(ftrace, "fake_default=%u ", ifp->int_d_metric); 6597b6ab19dSGarrett Wollman trace_bits(if_bits, ifp->int_if_flags, 0); 6607b6ab19dSGarrett Wollman trace_bits(is_bits, ifp->int_state, 0); 6617b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 6627b6ab19dSGarrett Wollman } 6637b6ab19dSGarrett Wollman 6647b6ab19dSGarrett Wollman 6657b6ab19dSGarrett Wollman void 6667b6ab19dSGarrett Wollman trace_upslot(struct rt_entry *rt, 6677b6ab19dSGarrett Wollman struct rt_spare *rts, 6682c7a9781SMark Murray struct rt_spare *new) 6697b6ab19dSGarrett Wollman { 670562c5a82SPedro F. Giffuni if (!TRACEACTIONS || ftrace == NULL) 6717b6ab19dSGarrett Wollman return; 67271965874SGarrett Wollman 6732c7a9781SMark Murray if (rts->rts_gate == new->rts_gate 6742c7a9781SMark Murray && rts->rts_router == new->rts_router 6752c7a9781SMark Murray && rts->rts_metric == new->rts_metric 6762c7a9781SMark Murray && rts->rts_tag == new->rts_tag 6772c7a9781SMark Murray && rts->rts_de_ag == new->rts_de_ag) 6787b6ab19dSGarrett Wollman return; 6797b6ab19dSGarrett Wollman 6807b6ab19dSGarrett Wollman lastlog(); 6812c7a9781SMark Murray if (new->rts_gate == 0) { 6822c7a9781SMark Murray (void)fprintf(ftrace, "Del #%d %-35s ", 6832c7a9781SMark Murray (int)(rts - rt->rt_spares), 6842c7a9781SMark Murray rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate)); 6852c7a9781SMark Murray print_rts(rts, 0,0,0,0, 6862c7a9781SMark Murray (rts != rt->rt_spares 6872c7a9781SMark Murray || AGE_RT(rt->rt_state,new->rts_ifp))); 6882c7a9781SMark Murray 6892c7a9781SMark Murray } else if (rts->rts_gate != RIP_DEFAULT) { 6907b6ab19dSGarrett Wollman (void)fprintf(ftrace, "Chg #%d %-35s ", 6912c7a9781SMark Murray (int)(rts - rt->rt_spares), 6922c7a9781SMark Murray rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate)); 69371965874SGarrett Wollman print_rts(rts, 0,0, 6942c7a9781SMark Murray rts->rts_gate != new->rts_gate, 6952c7a9781SMark Murray rts->rts_tag != new->rts_tag, 69671965874SGarrett Wollman rts != rt->rt_spares || AGE_RT(rt->rt_state, 69771965874SGarrett Wollman rt->rt_ifp)); 6987b6ab19dSGarrett Wollman 69971965874SGarrett Wollman (void)fprintf(ftrace, "\n %19s%-16s ", "", 7002c7a9781SMark Murray (new->rts_gate != rts->rts_gate 7012c7a9781SMark Murray ? naddr_ntoa(new->rts_gate) : "")); 7022c7a9781SMark Murray print_rts(new, 7032c7a9781SMark Murray -(new->rts_metric == rts->rts_metric), 7042c7a9781SMark Murray -(new->rts_ifp == rts->rts_ifp), 70571965874SGarrett Wollman 0, 7062c7a9781SMark Murray rts->rts_tag != new->rts_tag, 7072c7a9781SMark Murray (new->rts_time != rts->rts_time 7082c7a9781SMark Murray && (rts != rt->rt_spares 7092c7a9781SMark Murray || AGE_RT(rt->rt_state, new->rts_ifp)))); 7107b6ab19dSGarrett Wollman 7117b6ab19dSGarrett Wollman } else { 7127b6ab19dSGarrett Wollman (void)fprintf(ftrace, "Add #%d %-35s ", 7132c7a9781SMark Murray (int)(rts - rt->rt_spares), 7142c7a9781SMark Murray rtname(rt->rt_dst, rt->rt_mask, new->rts_gate)); 7152c7a9781SMark Murray print_rts(new, 0,0,0,0, 7162c7a9781SMark Murray (rts != rt->rt_spares 7172c7a9781SMark Murray || AGE_RT(rt->rt_state,new->rts_ifp))); 7187b6ab19dSGarrett Wollman } 71971965874SGarrett Wollman (void)fputc('\n',ftrace); 7207b6ab19dSGarrett Wollman } 7217b6ab19dSGarrett Wollman 7227b6ab19dSGarrett Wollman 7232c7a9781SMark Murray /* miscellaneous message checked by the caller 7247b6ab19dSGarrett Wollman */ 7257b6ab19dSGarrett Wollman void 7262c7a9781SMark Murray trace_misc(const char *p, ...) 7277b6ab19dSGarrett Wollman { 7287b6ab19dSGarrett Wollman va_list args; 7297b6ab19dSGarrett Wollman 730562c5a82SPedro F. Giffuni if (ftrace == NULL) 7317b6ab19dSGarrett Wollman return; 7327b6ab19dSGarrett Wollman 7337b6ab19dSGarrett Wollman lastlog(); 7347b6ab19dSGarrett Wollman va_start(args, p); 7357b6ab19dSGarrett Wollman vfprintf(ftrace, p, args); 736caa79e36SBruce M Simpson va_end(args); 7372c7a9781SMark Murray (void)fputc('\n',ftrace); 7387b6ab19dSGarrett Wollman } 7397b6ab19dSGarrett Wollman 7407b6ab19dSGarrett Wollman 7417b6ab19dSGarrett Wollman /* display a message if tracing actions 7427b6ab19dSGarrett Wollman */ 7437b6ab19dSGarrett Wollman void 7442c7a9781SMark Murray trace_act(const char *p, ...) 7457b6ab19dSGarrett Wollman { 7467b6ab19dSGarrett Wollman va_list args; 7477b6ab19dSGarrett Wollman 748562c5a82SPedro F. Giffuni if (!TRACEACTIONS || ftrace == NULL) 7497b6ab19dSGarrett Wollman return; 7507b6ab19dSGarrett Wollman 7517b6ab19dSGarrett Wollman lastlog(); 7527b6ab19dSGarrett Wollman va_start(args, p); 7537b6ab19dSGarrett Wollman vfprintf(ftrace, p, args); 754caa79e36SBruce M Simpson va_end(args); 755d5b718b3SGarrett Wollman (void)fputc('\n',ftrace); 7567b6ab19dSGarrett Wollman } 7577b6ab19dSGarrett Wollman 7587b6ab19dSGarrett Wollman 7597b6ab19dSGarrett Wollman /* display a message if tracing packets 7607b6ab19dSGarrett Wollman */ 7617b6ab19dSGarrett Wollman void 7622c7a9781SMark Murray trace_pkt(const char *p, ...) 7637b6ab19dSGarrett Wollman { 7647b6ab19dSGarrett Wollman va_list args; 7657b6ab19dSGarrett Wollman 766562c5a82SPedro F. Giffuni if (!TRACEPACKETS || ftrace == NULL) 7677b6ab19dSGarrett Wollman return; 7687b6ab19dSGarrett Wollman 7697b6ab19dSGarrett Wollman lastlog(); 7707b6ab19dSGarrett Wollman va_start(args, p); 7717b6ab19dSGarrett Wollman vfprintf(ftrace, p, args); 772caa79e36SBruce M Simpson va_end(args); 773d5b718b3SGarrett Wollman (void)fputc('\n',ftrace); 7747b6ab19dSGarrett Wollman } 7757b6ab19dSGarrett Wollman 7767b6ab19dSGarrett Wollman 7777b6ab19dSGarrett Wollman void 7787b6ab19dSGarrett Wollman trace_change(struct rt_entry *rt, 7797b6ab19dSGarrett Wollman u_int state, 7802c7a9781SMark Murray struct rt_spare *new, 7812c7a9781SMark Murray const char *label) 7827b6ab19dSGarrett Wollman { 783562c5a82SPedro F. Giffuni if (ftrace == NULL) 7847b6ab19dSGarrett Wollman return; 7857b6ab19dSGarrett Wollman 7862c7a9781SMark Murray if (rt->rt_metric == new->rts_metric 7872c7a9781SMark Murray && rt->rt_gate == new->rts_gate 7882c7a9781SMark Murray && rt->rt_router == new->rts_router 7897b6ab19dSGarrett Wollman && rt->rt_state == state 7902c7a9781SMark Murray && rt->rt_tag == new->rts_tag 7912c7a9781SMark Murray && rt->rt_de_ag == new->rts_de_ag) 7927b6ab19dSGarrett Wollman return; 7937b6ab19dSGarrett Wollman 7947b6ab19dSGarrett Wollman lastlog(); 79571965874SGarrett Wollman (void)fprintf(ftrace, "%s %-35s ", 7967b6ab19dSGarrett Wollman label, 7972c7a9781SMark Murray rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate)); 79871965874SGarrett Wollman print_rts(rt->rt_spares, 79971965874SGarrett Wollman 0,0,0,0, AGE_RT(rt->rt_state, rt->rt_ifp)); 8007b6ab19dSGarrett Wollman trace_bits(rs_bits, rt->rt_state, rt->rt_state != state); 8017b6ab19dSGarrett Wollman 80271965874SGarrett Wollman (void)fprintf(ftrace, "\n%*s %19s%-16s ", 8032c7a9781SMark Murray (int)strlen(label), "", "", 8042c7a9781SMark Murray (rt->rt_gate != new->rts_gate 8052c7a9781SMark Murray ? naddr_ntoa(new->rts_gate) : "")); 8062c7a9781SMark Murray print_rts(new, 8072c7a9781SMark Murray -(new->rts_metric == rt->rt_metric), 8082c7a9781SMark Murray -(new->rts_ifp == rt->rt_ifp), 80971965874SGarrett Wollman 0, 8102c7a9781SMark Murray rt->rt_tag != new->rts_tag, 8112c7a9781SMark Murray (rt->rt_time != new->rts_time 8122c7a9781SMark Murray && AGE_RT(rt->rt_state,new->rts_ifp))); 8137b6ab19dSGarrett Wollman if (rt->rt_state != state) 8147b6ab19dSGarrett Wollman trace_bits(rs_bits, state, 1); 81571965874SGarrett Wollman (void)fputc('\n',ftrace); 8167b6ab19dSGarrett Wollman } 8177b6ab19dSGarrett Wollman 8187b6ab19dSGarrett Wollman 8197b6ab19dSGarrett Wollman void 8202c7a9781SMark Murray trace_add_del(const char * action, struct rt_entry *rt) 8217b6ab19dSGarrett Wollman { 822562c5a82SPedro F. Giffuni if (ftrace == NULL) 8237b6ab19dSGarrett Wollman return; 8247b6ab19dSGarrett Wollman 8257b6ab19dSGarrett Wollman lastlog(); 82671965874SGarrett Wollman (void)fprintf(ftrace, "%s %-35s ", 8277b6ab19dSGarrett Wollman action, 8282c7a9781SMark Murray rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate)); 82971965874SGarrett Wollman print_rts(rt->rt_spares, 0,0,0,0,AGE_RT(rt->rt_state,rt->rt_ifp)); 83071965874SGarrett Wollman trace_bits(rs_bits, rt->rt_state, 0); 83171965874SGarrett Wollman (void)fputc('\n',ftrace); 8327b6ab19dSGarrett Wollman } 8337b6ab19dSGarrett Wollman 8347b6ab19dSGarrett Wollman 8357b6ab19dSGarrett Wollman /* ARGSUSED */ 8367b6ab19dSGarrett Wollman static int 8377b6ab19dSGarrett Wollman walk_trace(struct radix_node *rn, 8382c7a9781SMark Murray struct walkarg *w UNUSED) 8397b6ab19dSGarrett Wollman { 8407b6ab19dSGarrett Wollman #define RT ((struct rt_entry *)rn) 8417b6ab19dSGarrett Wollman struct rt_spare *rts; 8422c7a9781SMark Murray int i; 8437b6ab19dSGarrett Wollman 8442c7a9781SMark Murray (void)fprintf(ftrace, " %-35s ", 8452c7a9781SMark Murray rtname(RT->rt_dst, RT->rt_mask, RT->rt_gate)); 8462c7a9781SMark Murray print_rts(&RT->rt_spares[0], 0,0,0,0, AGE_RT(RT->rt_state, RT->rt_ifp)); 8477b6ab19dSGarrett Wollman trace_bits(rs_bits, RT->rt_state, 0); 84871965874SGarrett Wollman if (RT->rt_poison_time >= now_garbage 84971965874SGarrett Wollman && RT->rt_poison_metric < RT->rt_metric) 85071965874SGarrett Wollman (void)fprintf(ftrace, "pm=%d@%s", 8512c7a9781SMark Murray RT->rt_poison_metric, ts(RT->rt_poison_time)); 8527b6ab19dSGarrett Wollman 8537b6ab19dSGarrett Wollman rts = &RT->rt_spares[1]; 8547b6ab19dSGarrett Wollman for (i = 1; i < NUM_SPARES; i++, rts++) { 85571965874SGarrett Wollman if (rts->rts_gate != RIP_DEFAULT) { 85671965874SGarrett Wollman (void)fprintf(ftrace,"\n #%d%15s%-16s ", 85771965874SGarrett Wollman i, "", naddr_ntoa(rts->rts_gate)); 85871965874SGarrett Wollman print_rts(rts, 0,0,0,0,1); 8597b6ab19dSGarrett Wollman } 8607b6ab19dSGarrett Wollman } 8617b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 8627b6ab19dSGarrett Wollman 8637b6ab19dSGarrett Wollman return 0; 8647b6ab19dSGarrett Wollman } 8657b6ab19dSGarrett Wollman 8667b6ab19dSGarrett Wollman 8677b6ab19dSGarrett Wollman static void 8687b6ab19dSGarrett Wollman trace_dump(void) 8697b6ab19dSGarrett Wollman { 870d5b718b3SGarrett Wollman struct interface *ifp; 871d5b718b3SGarrett Wollman 872562c5a82SPedro F. Giffuni if (ftrace == NULL) 8737b6ab19dSGarrett Wollman return; 8747b6ab19dSGarrett Wollman lastlog(); 8757b6ab19dSGarrett Wollman 87671965874SGarrett Wollman (void)fputs("current daemon state:\n", ftrace); 87738ae6523SPoul-Henning Kamp LIST_FOREACH(ifp, &ifnet, int_list) 878d5b718b3SGarrett Wollman trace_if("", ifp); 8797b6ab19dSGarrett Wollman (void)rn_walktree(rhead, walk_trace, 0); 8807b6ab19dSGarrett Wollman } 8817b6ab19dSGarrett Wollman 8827b6ab19dSGarrett Wollman 8837b6ab19dSGarrett Wollman void 8842c7a9781SMark Murray trace_rip(const char *dir1, const char *dir2, 8857b6ab19dSGarrett Wollman struct sockaddr_in *who, 8867b6ab19dSGarrett Wollman struct interface *ifp, 8877b6ab19dSGarrett Wollman struct rip *msg, 8887b6ab19dSGarrett Wollman int size) /* total size of message */ 8897b6ab19dSGarrett Wollman { 8907b6ab19dSGarrett Wollman struct netinfo *n, *lim; 8912c7a9781SMark Murray # define NA ((struct netauth*)n) 892d5b718b3SGarrett Wollman int i, seen_route; 8937b6ab19dSGarrett Wollman 894562c5a82SPedro F. Giffuni if (!TRACEPACKETS || ftrace == NULL) 8957b6ab19dSGarrett Wollman return; 8967b6ab19dSGarrett Wollman 8977b6ab19dSGarrett Wollman lastlog(); 8987b6ab19dSGarrett Wollman if (msg->rip_cmd >= RIPCMD_MAX 8997b6ab19dSGarrett Wollman || msg->rip_vers == 0) { 9007b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s bad RIPv%d cmd=%d %s" 9017b6ab19dSGarrett Wollman " %s.%d size=%d\n", 9027b6ab19dSGarrett Wollman dir1, msg->rip_vers, msg->rip_cmd, dir2, 9037b6ab19dSGarrett Wollman naddr_ntoa(who->sin_addr.s_addr), 9047b6ab19dSGarrett Wollman ntohs(who->sin_port), 9057b6ab19dSGarrett Wollman size); 9067b6ab19dSGarrett Wollman return; 9077b6ab19dSGarrett Wollman } 9087b6ab19dSGarrett Wollman 9097b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s RIPv%d %s %s %s.%d%s%s\n", 9107b6ab19dSGarrett Wollman dir1, msg->rip_vers, ripcmds[msg->rip_cmd], dir2, 9117b6ab19dSGarrett Wollman naddr_ntoa(who->sin_addr.s_addr), ntohs(who->sin_port), 9127b6ab19dSGarrett Wollman ifp ? " via " : "", ifp ? ifp->int_name : ""); 9137b6ab19dSGarrett Wollman if (!TRACECONTENTS) 9147b6ab19dSGarrett Wollman return; 9157b6ab19dSGarrett Wollman 916d5b718b3SGarrett Wollman seen_route = 0; 9177b6ab19dSGarrett Wollman switch (msg->rip_cmd) { 9187b6ab19dSGarrett Wollman case RIPCMD_REQUEST: 9197b6ab19dSGarrett Wollman case RIPCMD_RESPONSE: 9207b6ab19dSGarrett Wollman n = msg->rip_nets; 9217b6ab19dSGarrett Wollman lim = (struct netinfo *)((char*)msg + size); 9227b6ab19dSGarrett Wollman for (; n < lim; n++) { 923d5b718b3SGarrett Wollman if (!seen_route 924d5b718b3SGarrett Wollman && n->n_family == RIP_AF_UNSPEC 9257b6ab19dSGarrett Wollman && ntohl(n->n_metric) == HOPCNT_INFINITY 926d5b718b3SGarrett Wollman && msg->rip_cmd == RIPCMD_REQUEST 927d5b718b3SGarrett Wollman && (n+1 == lim 928d5b718b3SGarrett Wollman || (n+2 == lim 929d5b718b3SGarrett Wollman && (n+1)->n_family == RIP_AF_AUTH))) { 9307b6ab19dSGarrett Wollman (void)fputs("\tQUERY ", ftrace); 9317b6ab19dSGarrett Wollman if (n->n_dst != 0) 9327b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s ", 9337b6ab19dSGarrett Wollman naddr_ntoa(n->n_dst)); 9347b6ab19dSGarrett Wollman if (n->n_mask != 0) 9357b6ab19dSGarrett Wollman (void)fprintf(ftrace, "mask=%#x ", 9367b6ab19dSGarrett Wollman (u_int)ntohl(n->n_mask)); 9377b6ab19dSGarrett Wollman if (n->n_nhop != 0) 9387b6ab19dSGarrett Wollman (void)fprintf(ftrace, "nhop=%s ", 9397b6ab19dSGarrett Wollman naddr_ntoa(n->n_nhop)); 9407b6ab19dSGarrett Wollman if (n->n_tag != 0) 9417b6ab19dSGarrett Wollman (void)fprintf(ftrace, "tag=%#x ", 9427b6ab19dSGarrett Wollman ntohs(n->n_tag)); 9437b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 9447b6ab19dSGarrett Wollman continue; 9457b6ab19dSGarrett Wollman } 9467b6ab19dSGarrett Wollman 9477b6ab19dSGarrett Wollman if (n->n_family == RIP_AF_AUTH) { 948d5b718b3SGarrett Wollman if (NA->a_type == RIP_AUTH_PW 949d5b718b3SGarrett Wollman && n == msg->rip_nets) { 950d5b718b3SGarrett Wollman (void)fprintf(ftrace, "\tPassword" 951d5b718b3SGarrett Wollman " Authentication:" 952d5b718b3SGarrett Wollman " \"%s\"\n", 953d5b718b3SGarrett Wollman qstring(NA->au.au_pw, 954d5b718b3SGarrett Wollman RIP_AUTH_PW_LEN)); 955d5b718b3SGarrett Wollman continue; 956d5b718b3SGarrett Wollman } 957d5b718b3SGarrett Wollman 958d5b718b3SGarrett Wollman if (NA->a_type == RIP_AUTH_MD5 959d5b718b3SGarrett Wollman && n == msg->rip_nets) { 9607b6ab19dSGarrett Wollman (void)fprintf(ftrace, 9612c7a9781SMark Murray "\tMD5 Auth" 9622c7a9781SMark Murray " pkt_len=%d KeyID=%u" 9632c7a9781SMark Murray " auth_len=%d" 9642c7a9781SMark Murray " seqno=%#x" 965d5b718b3SGarrett Wollman " rsvd=%#x,%#x\n", 9662c7a9781SMark Murray ntohs(NA->au.a_md5.md5_pkt_len), 967d5b718b3SGarrett Wollman NA->au.a_md5.md5_keyid, 9682c7a9781SMark Murray NA->au.a_md5.md5_auth_len, 9692c7a9781SMark Murray (int)ntohl(NA->au.a_md5.md5_seqno), 9702c7a9781SMark Murray (int)ntohs(NA->au.a_md5.rsvd[0]), 9712c7a9781SMark Murray (int)ntohs(NA->au.a_md5.rsvd[1])); 972d5b718b3SGarrett Wollman continue; 973d5b718b3SGarrett Wollman } 974d5b718b3SGarrett Wollman (void)fprintf(ftrace, 9752c7a9781SMark Murray "\tAuthentication type %d: ", 976d5b718b3SGarrett Wollman ntohs(NA->a_type)); 9777b6ab19dSGarrett Wollman for (i = 0; 9782c7a9781SMark Murray i < (int)sizeof(NA->au.au_pw); 9797b6ab19dSGarrett Wollman i++) 9807b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%02x ", 981d5b718b3SGarrett Wollman NA->au.au_pw[i]); 9827b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 9837b6ab19dSGarrett Wollman continue; 9847b6ab19dSGarrett Wollman } 9857b6ab19dSGarrett Wollman 986d5b718b3SGarrett Wollman seen_route = 1; 9877b6ab19dSGarrett Wollman if (n->n_family != RIP_AF_INET) { 9887b6ab19dSGarrett Wollman (void)fprintf(ftrace, 9897b6ab19dSGarrett Wollman "\t(af %d) %-18s mask=%#x ", 9907b6ab19dSGarrett Wollman ntohs(n->n_family), 9917b6ab19dSGarrett Wollman naddr_ntoa(n->n_dst), 9927b6ab19dSGarrett Wollman (u_int)ntohl(n->n_mask)); 9937b6ab19dSGarrett Wollman } else if (msg->rip_vers == RIPv1) { 9947b6ab19dSGarrett Wollman (void)fprintf(ftrace, "\t%-18s ", 9957b6ab19dSGarrett Wollman addrname(n->n_dst, 9967b6ab19dSGarrett Wollman ntohl(n->n_mask), 9977b6ab19dSGarrett Wollman n->n_mask==0 ? 2 : 1)); 9987b6ab19dSGarrett Wollman } else { 9997b6ab19dSGarrett Wollman (void)fprintf(ftrace, "\t%-18s ", 10007b6ab19dSGarrett Wollman addrname(n->n_dst, 10017b6ab19dSGarrett Wollman ntohl(n->n_mask), 10027b6ab19dSGarrett Wollman n->n_mask==0 ? 2 : 0)); 10037b6ab19dSGarrett Wollman } 10047b6ab19dSGarrett Wollman (void)fprintf(ftrace, "metric=%-2d ", 10057b6ab19dSGarrett Wollman (u_int)ntohl(n->n_metric)); 10067b6ab19dSGarrett Wollman if (n->n_nhop != 0) 10077b6ab19dSGarrett Wollman (void)fprintf(ftrace, " nhop=%s ", 10087b6ab19dSGarrett Wollman naddr_ntoa(n->n_nhop)); 10097b6ab19dSGarrett Wollman if (n->n_tag != 0) 10107b6ab19dSGarrett Wollman (void)fprintf(ftrace, "tag=%#x", 10117b6ab19dSGarrett Wollman ntohs(n->n_tag)); 10127b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 10137b6ab19dSGarrett Wollman } 10147b6ab19dSGarrett Wollman if (size != (char *)n - (char *)msg) 10157b6ab19dSGarrett Wollman (void)fprintf(ftrace, "truncated record, len %d\n", 10167b6ab19dSGarrett Wollman size); 10177b6ab19dSGarrett Wollman break; 10187b6ab19dSGarrett Wollman 10197b6ab19dSGarrett Wollman case RIPCMD_TRACEON: 102071965874SGarrett Wollman fprintf(ftrace, "\tfile=\"%.*s\"\n", size-4, 102171965874SGarrett Wollman msg->rip_tracefile); 10227b6ab19dSGarrett Wollman break; 10237b6ab19dSGarrett Wollman 10247b6ab19dSGarrett Wollman case RIPCMD_TRACEOFF: 10257b6ab19dSGarrett Wollman break; 10267b6ab19dSGarrett Wollman } 10277b6ab19dSGarrett Wollman } 1028