17b6ab19dSGarrett Wollman /* 27b6ab19dSGarrett Wollman * Copyright (c) 1983, 1988, 1993 37b6ab19dSGarrett Wollman * The Regents of the University of California. All rights reserved. 47b6ab19dSGarrett Wollman * 57b6ab19dSGarrett Wollman * Redistribution and use in source and binary forms, with or without 67b6ab19dSGarrett Wollman * modification, are permitted provided that the following conditions 77b6ab19dSGarrett Wollman * are met: 87b6ab19dSGarrett Wollman * 1. Redistributions of source code must retain the above copyright 97b6ab19dSGarrett Wollman * notice, this list of conditions and the following disclaimer. 107b6ab19dSGarrett Wollman * 2. Redistributions in binary form must reproduce the above copyright 117b6ab19dSGarrett Wollman * notice, this list of conditions and the following disclaimer in the 127b6ab19dSGarrett Wollman * documentation and/or other materials provided with the distribution. 137b6ab19dSGarrett Wollman * 3. All advertising materials mentioning features or use of this software 142c7a9781SMark Murray * must display the following acknowledgment: 157b6ab19dSGarrett Wollman * This product includes software developed by the University of 167b6ab19dSGarrett Wollman * California, Berkeley and its contributors. 177b6ab19dSGarrett Wollman * 4. Neither the name of the University nor the names of its contributors 187b6ab19dSGarrett Wollman * may be used to endorse or promote products derived from this software 197b6ab19dSGarrett Wollman * without specific prior written permission. 207b6ab19dSGarrett Wollman * 217b6ab19dSGarrett Wollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 227b6ab19dSGarrett Wollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 237b6ab19dSGarrett Wollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 247b6ab19dSGarrett Wollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 257b6ab19dSGarrett Wollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 267b6ab19dSGarrett Wollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 277b6ab19dSGarrett Wollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 287b6ab19dSGarrett Wollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 297b6ab19dSGarrett Wollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 307b6ab19dSGarrett Wollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 317b6ab19dSGarrett Wollman * SUCH DAMAGE. 327b6ab19dSGarrett Wollman */ 337b6ab19dSGarrett Wollman 347b6ab19dSGarrett Wollman #define RIPCMDS 357b6ab19dSGarrett Wollman #include "defs.h" 367b6ab19dSGarrett Wollman #include "pathnames.h" 377b6ab19dSGarrett Wollman #include <sys/stat.h> 387b6ab19dSGarrett Wollman #include <sys/signal.h> 397b6ab19dSGarrett Wollman #include <fcntl.h> 407b6ab19dSGarrett Wollman 412c7a9781SMark Murray #if !defined(sgi) && !defined(__NetBSD__) 422c7a9781SMark Murray static char sccsid[] __attribute__((unused)) = "@(#)trace.c 8.1 (Berkeley) 6/5/93"; 432c7a9781SMark Murray #elif defined(__NetBSD__) 442c7a9781SMark Murray __RCSID("$NetBSD$"); 452c7a9781SMark Murray #endif 462c7a9781SMark Murray #ident "$Revision: 2.17 $" 472c7a9781SMark Murray 487b6ab19dSGarrett Wollman 497b6ab19dSGarrett Wollman #ifdef sgi 507b6ab19dSGarrett Wollman /* use *stat64 for files on large filesystems */ 517b6ab19dSGarrett Wollman #define stat stat64 527b6ab19dSGarrett Wollman #endif 537b6ab19dSGarrett Wollman 547b6ab19dSGarrett Wollman #define NRECORDS 50 /* size of circular trace buffer */ 557b6ab19dSGarrett Wollman 5671965874SGarrett Wollman int tracelevel, new_tracelevel; 577b6ab19dSGarrett Wollman FILE *ftrace = stdout; /* output trace file */ 582c7a9781SMark Murray static const char *sigtrace_pat = "%s"; 5971965874SGarrett Wollman static char savetracename[MAXPATHLEN+1]; 6071965874SGarrett Wollman char inittracename[MAXPATHLEN+1]; 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); 1892c7a9781SMark Murray (void)fputc('\n',ftrace); 1907b6ab19dSGarrett Wollman fflush(ftrace); 1917b6ab19dSGarrett Wollman } 1927b6ab19dSGarrett Wollman } 1937b6ab19dSGarrett Wollman 1947b6ab19dSGarrett Wollman 1952c7a9781SMark Murray void 1962c7a9781SMark Murray trace_close(int zap_stdio) 1977b6ab19dSGarrett Wollman { 1987b6ab19dSGarrett Wollman int fd; 1997b6ab19dSGarrett Wollman 2007b6ab19dSGarrett Wollman 2017b6ab19dSGarrett Wollman fflush(stdout); 2027b6ab19dSGarrett Wollman fflush(stderr); 2037b6ab19dSGarrett Wollman 2042c7a9781SMark Murray if (ftrace != 0 && zap_stdio) { 20571965874SGarrett Wollman if (ftrace != stdout) 20671965874SGarrett Wollman fclose(ftrace); 20771965874SGarrett Wollman ftrace = 0; 2087b6ab19dSGarrett Wollman fd = open(_PATH_DEVNULL, O_RDWR); 2092c7a9781SMark Murray if (isatty(STDIN_FILENO)) 21071965874SGarrett Wollman (void)dup2(fd, STDIN_FILENO); 2112c7a9781SMark Murray if (isatty(STDOUT_FILENO)) 2127b6ab19dSGarrett Wollman (void)dup2(fd, STDOUT_FILENO); 2132c7a9781SMark Murray if (isatty(STDERR_FILENO)) 2147b6ab19dSGarrett Wollman (void)dup2(fd, STDERR_FILENO); 2157b6ab19dSGarrett Wollman (void)close(fd); 2167b6ab19dSGarrett Wollman } 21771965874SGarrett Wollman lastlog_time.tv_sec = 0; 2187b6ab19dSGarrett Wollman } 2197b6ab19dSGarrett Wollman 2207b6ab19dSGarrett Wollman 2217b6ab19dSGarrett Wollman void 2227b6ab19dSGarrett Wollman trace_flush(void) 2237b6ab19dSGarrett Wollman { 2247b6ab19dSGarrett Wollman if (ftrace != 0) { 2257b6ab19dSGarrett Wollman fflush(ftrace); 2267b6ab19dSGarrett Wollman if (ferror(ftrace)) 2272c7a9781SMark Murray trace_off("tracing off: %s", strerror(ferror(ftrace))); 2287b6ab19dSGarrett Wollman } 2297b6ab19dSGarrett Wollman } 2307b6ab19dSGarrett Wollman 2317b6ab19dSGarrett Wollman 2327b6ab19dSGarrett Wollman void 2332c7a9781SMark Murray trace_off(const char *p, ...) 2347b6ab19dSGarrett Wollman { 2357b6ab19dSGarrett Wollman va_list args; 2367b6ab19dSGarrett Wollman 2377b6ab19dSGarrett Wollman 2387b6ab19dSGarrett Wollman if (ftrace != 0) { 2397b6ab19dSGarrett Wollman lastlog(); 2407b6ab19dSGarrett Wollman va_start(args, p); 2417b6ab19dSGarrett Wollman vfprintf(ftrace, p, args); 2422c7a9781SMark Murray (void)fputc('\n',ftrace); 2437b6ab19dSGarrett Wollman } 2442c7a9781SMark Murray trace_close(file_trace); 2457b6ab19dSGarrett Wollman 2467b6ab19dSGarrett Wollman new_tracelevel = tracelevel = 0; 2477b6ab19dSGarrett Wollman } 2487b6ab19dSGarrett Wollman 2497b6ab19dSGarrett Wollman 25071965874SGarrett Wollman /* log a change in tracing 2517b6ab19dSGarrett Wollman */ 2527b6ab19dSGarrett Wollman void 2532c7a9781SMark Murray tracelevel_msg(const char *pat, 25471965874SGarrett Wollman int dump) /* -1=no dump, 0=default, 1=force */ 2557b6ab19dSGarrett Wollman { 2562c7a9781SMark Murray static const char *off_msgs[MAX_TRACELEVEL] = { 2577b6ab19dSGarrett Wollman "Tracing actions stopped", 2587b6ab19dSGarrett Wollman "Tracing packets stopped", 2597b6ab19dSGarrett Wollman "Tracing packet contents stopped", 2607b6ab19dSGarrett Wollman "Tracing kernel changes stopped", 2617b6ab19dSGarrett Wollman }; 2622c7a9781SMark Murray static const char *on_msgs[MAX_TRACELEVEL] = { 2637b6ab19dSGarrett Wollman "Tracing actions started", 2647b6ab19dSGarrett Wollman "Tracing packets started", 2657b6ab19dSGarrett Wollman "Tracing packet contents started", 2667b6ab19dSGarrett Wollman "Tracing kernel changes started", 2677b6ab19dSGarrett Wollman }; 26871965874SGarrett Wollman u_int old_tracelevel = tracelevel; 2697b6ab19dSGarrett Wollman 2707b6ab19dSGarrett Wollman 27171965874SGarrett Wollman if (new_tracelevel < 0) 27271965874SGarrett Wollman new_tracelevel = 0; 27371965874SGarrett Wollman else if (new_tracelevel > MAX_TRACELEVEL) 2747b6ab19dSGarrett Wollman new_tracelevel = MAX_TRACELEVEL; 27571965874SGarrett Wollman 27671965874SGarrett Wollman if (new_tracelevel < tracelevel) { 27771965874SGarrett Wollman if (new_tracelevel <= 0) { 27871965874SGarrett Wollman trace_off(pat, off_msgs[0]); 27971965874SGarrett Wollman } else do { 28071965874SGarrett Wollman tmsg(pat, off_msgs[tracelevel]); 28171965874SGarrett Wollman } 28271965874SGarrett Wollman while (--tracelevel != new_tracelevel); 28371965874SGarrett Wollman 28471965874SGarrett Wollman } else if (new_tracelevel > tracelevel) { 28571965874SGarrett Wollman do { 28671965874SGarrett Wollman tmsg(pat, on_msgs[tracelevel++]); 28771965874SGarrett Wollman } while (tracelevel != new_tracelevel); 28871965874SGarrett Wollman } 28971965874SGarrett Wollman 29071965874SGarrett Wollman if (dump > 0 29171965874SGarrett Wollman || (dump == 0 && old_tracelevel == 0 && tracelevel != 0)) 29271965874SGarrett Wollman trace_dump(); 29371965874SGarrett Wollman } 29471965874SGarrett Wollman 29571965874SGarrett Wollman 29671965874SGarrett Wollman void 2972c7a9781SMark Murray set_tracefile(const char *filename, 2982c7a9781SMark Murray const char *pat, 29971965874SGarrett Wollman int dump) /* -1=no dump, 0=default, 1=force */ 30071965874SGarrett Wollman { 30171965874SGarrett Wollman struct stat stbuf; 30271965874SGarrett Wollman FILE *n_ftrace; 3032c7a9781SMark Murray const char *fn; 30471965874SGarrett Wollman 30571965874SGarrett Wollman 30671965874SGarrett Wollman /* Allow a null filename to increase the level if the trace file 30771965874SGarrett Wollman * is already open or if coming from a trusted source, such as 30871965874SGarrett Wollman * a signal or the command line. 30971965874SGarrett Wollman */ 31071965874SGarrett Wollman if (filename == 0 || filename[0] == '\0') { 31171965874SGarrett Wollman filename = 0; 31271965874SGarrett Wollman if (ftrace == 0) { 31371965874SGarrett Wollman if (inittracename[0] == '\0') { 31471965874SGarrett Wollman msglog("missing trace file name"); 3157b6ab19dSGarrett Wollman return; 3167b6ab19dSGarrett Wollman } 31771965874SGarrett Wollman fn = inittracename; 31871965874SGarrett Wollman } else { 31971965874SGarrett Wollman fn = 0; 3207b6ab19dSGarrett Wollman } 321d5b718b3SGarrett Wollman 32271965874SGarrett Wollman } else if (!strcmp(filename,"dump/../table")) { 32371965874SGarrett Wollman trace_dump(); 32471965874SGarrett Wollman return; 32571965874SGarrett Wollman 3267b6ab19dSGarrett Wollman } else { 32771965874SGarrett Wollman /* Allow the file specified with "-T file" to be reopened, 32871965874SGarrett Wollman * but require all other names specified over the net to 32971965874SGarrett Wollman * match the official path. The path can specify a directory 33071965874SGarrett Wollman * in which the file is to be created. 33171965874SGarrett Wollman */ 33271965874SGarrett Wollman if (strcmp(filename, inittracename) 33371965874SGarrett Wollman #ifdef _PATH_TRACE 33471965874SGarrett Wollman && (strncmp(filename, _PATH_TRACE, sizeof(_PATH_TRACE)-1) 33571965874SGarrett Wollman || strstr(filename,"../") 33671965874SGarrett Wollman || 0 > stat(_PATH_TRACE, &stbuf)) 33771965874SGarrett Wollman #endif 33871965874SGarrett Wollman ) { 33971965874SGarrett Wollman msglog("wrong trace file \"%s\"", filename); 34071965874SGarrett Wollman return; 3417b6ab19dSGarrett Wollman } 34271965874SGarrett Wollman 34371965874SGarrett Wollman /* If the new tracefile exists, it must be a regular file. 34471965874SGarrett Wollman */ 3452c7a9781SMark Murray if (stat(filename, &stbuf) >= 0 && !S_ISREG(stbuf.st_mode)) { 34671965874SGarrett Wollman msglog("wrong type (%#x) of trace file \"%s\"", 34771965874SGarrett Wollman stbuf.st_mode, filename); 34871965874SGarrett Wollman return; 3497b6ab19dSGarrett Wollman } 35071965874SGarrett Wollman 35171965874SGarrett Wollman fn = filename; 3527b6ab19dSGarrett Wollman } 35371965874SGarrett Wollman 35471965874SGarrett Wollman if (fn != 0) { 35571965874SGarrett Wollman n_ftrace = fopen(fn, "a"); 35671965874SGarrett Wollman if (n_ftrace == 0) { 35771965874SGarrett Wollman msglog("failed to open trace file \"%s\" %s", 35871965874SGarrett Wollman fn, strerror(errno)); 35971965874SGarrett Wollman if (fn == inittracename) 36071965874SGarrett Wollman inittracename[0] = '\0'; 36171965874SGarrett Wollman return; 36271965874SGarrett Wollman } 36371965874SGarrett Wollman 3642c7a9781SMark Murray tmsg("switch to trace file %s", fn); 36571965874SGarrett Wollman 3662c7a9781SMark Murray trace_close(file_trace = 1); 36771965874SGarrett Wollman 36871965874SGarrett Wollman if (fn != savetracename) 36971965874SGarrett Wollman strncpy(savetracename, fn, sizeof(savetracename)-1); 37071965874SGarrett Wollman ftrace = n_ftrace; 37171965874SGarrett Wollman 37271965874SGarrett Wollman fflush(stdout); 37371965874SGarrett Wollman fflush(stderr); 37471965874SGarrett Wollman dup2(fileno(ftrace), STDOUT_FILENO); 37571965874SGarrett Wollman dup2(fileno(ftrace), STDERR_FILENO); 37671965874SGarrett Wollman } 37771965874SGarrett Wollman 37871965874SGarrett Wollman if (new_tracelevel == 0 || filename == 0) 37971965874SGarrett Wollman new_tracelevel++; 38071965874SGarrett Wollman tracelevel_msg(pat, dump != 0 ? dump : (filename != 0)); 38171965874SGarrett Wollman } 38271965874SGarrett Wollman 38371965874SGarrett Wollman 38471965874SGarrett Wollman /* ARGSUSED */ 38571965874SGarrett Wollman void 3862c7a9781SMark Murray sigtrace_on(int s UNUSED) 38771965874SGarrett Wollman { 38871965874SGarrett Wollman new_tracelevel++; 3892c7a9781SMark Murray sigtrace_pat = "SIGUSR1: %s"; 39071965874SGarrett Wollman } 39171965874SGarrett Wollman 39271965874SGarrett Wollman 39371965874SGarrett Wollman /* ARGSUSED */ 39471965874SGarrett Wollman void 3952c7a9781SMark Murray sigtrace_off(int s UNUSED) 39671965874SGarrett Wollman { 39771965874SGarrett Wollman new_tracelevel--; 3982c7a9781SMark Murray sigtrace_pat = "SIGUSR2: %s"; 39971965874SGarrett Wollman } 40071965874SGarrett Wollman 40171965874SGarrett Wollman 40271965874SGarrett Wollman /* Set tracing after a signal. 40371965874SGarrett Wollman */ 40471965874SGarrett Wollman void 40571965874SGarrett Wollman set_tracelevel(void) 40671965874SGarrett Wollman { 40771965874SGarrett Wollman if (new_tracelevel == tracelevel) 40871965874SGarrett Wollman return; 40971965874SGarrett Wollman 41071965874SGarrett Wollman /* If tracing entirely off, and there was no tracefile specified 41171965874SGarrett Wollman * on the command line, then leave it off. 41271965874SGarrett Wollman */ 41371965874SGarrett Wollman if (new_tracelevel > tracelevel && ftrace == 0) { 41471965874SGarrett Wollman if (savetracename[0] != '\0') { 41571965874SGarrett Wollman set_tracefile(savetracename,sigtrace_pat,0); 41671965874SGarrett Wollman } else if (inittracename[0] != '\0') { 41771965874SGarrett Wollman set_tracefile(inittracename,sigtrace_pat,0); 41871965874SGarrett Wollman } else { 41971965874SGarrett Wollman new_tracelevel = 0; 42071965874SGarrett Wollman return; 42171965874SGarrett Wollman } 42271965874SGarrett Wollman } else { 42371965874SGarrett Wollman tracelevel_msg(sigtrace_pat, 0); 42471965874SGarrett Wollman } 4257b6ab19dSGarrett Wollman } 4267b6ab19dSGarrett Wollman 4277b6ab19dSGarrett Wollman 4287b6ab19dSGarrett Wollman /* display an address 4297b6ab19dSGarrett Wollman */ 4307b6ab19dSGarrett Wollman char * 4317b6ab19dSGarrett Wollman addrname(naddr addr, /* in network byte order */ 4327b6ab19dSGarrett Wollman naddr mask, 4337b6ab19dSGarrett Wollman int force) /* 0=show mask if nonstandard, */ 4347b6ab19dSGarrett Wollman { /* 1=always show mask, 2=never */ 4357b6ab19dSGarrett Wollman #define NUM_BUFS 4 4367b6ab19dSGarrett Wollman static int bufno; 4377b6ab19dSGarrett Wollman static struct { 4387b6ab19dSGarrett Wollman char str[15+20]; 4397b6ab19dSGarrett Wollman } bufs[NUM_BUFS]; 4407b6ab19dSGarrett Wollman char *s, *sp; 4417b6ab19dSGarrett Wollman naddr dmask; 4427b6ab19dSGarrett Wollman int i; 4437b6ab19dSGarrett Wollman 4447b6ab19dSGarrett Wollman s = strcpy(bufs[bufno].str, naddr_ntoa(addr)); 4457b6ab19dSGarrett Wollman bufno = (bufno+1) % NUM_BUFS; 4467b6ab19dSGarrett Wollman 4477b6ab19dSGarrett Wollman if (force == 1 || (force == 0 && mask != std_mask(addr))) { 4487b6ab19dSGarrett Wollman sp = &s[strlen(s)]; 4497b6ab19dSGarrett Wollman 4507b6ab19dSGarrett Wollman dmask = mask & -mask; 4517b6ab19dSGarrett Wollman if (mask + dmask == 0) { 4527b6ab19dSGarrett Wollman for (i = 0; i != 32 && ((1<<i) & mask) == 0; i++) 4537b6ab19dSGarrett Wollman continue; 4547b6ab19dSGarrett Wollman (void)sprintf(sp, "/%d", 32-i); 4557b6ab19dSGarrett Wollman 4567b6ab19dSGarrett Wollman } else { 4577b6ab19dSGarrett Wollman (void)sprintf(sp, " (mask %#x)", (u_int)mask); 4587b6ab19dSGarrett Wollman } 4597b6ab19dSGarrett Wollman } 4607b6ab19dSGarrett Wollman 4617b6ab19dSGarrett Wollman return s; 4627b6ab19dSGarrett Wollman #undef NUM_BUFS 4637b6ab19dSGarrett Wollman } 4647b6ab19dSGarrett Wollman 4657b6ab19dSGarrett Wollman 4667b6ab19dSGarrett Wollman /* display a bit-field 4677b6ab19dSGarrett Wollman */ 4687b6ab19dSGarrett Wollman struct bits { 4692c7a9781SMark Murray u_int bits_mask; 4702c7a9781SMark Murray u_int bits_clear; 4712c7a9781SMark Murray const char *bits_name; 4727b6ab19dSGarrett Wollman }; 4737b6ab19dSGarrett Wollman 4747b6ab19dSGarrett Wollman static struct bits if_bits[] = { 4757b6ab19dSGarrett Wollman { IFF_LOOPBACK, 0, "LOOPBACK" }, 4767b6ab19dSGarrett Wollman { IFF_POINTOPOINT, 0, "PT-TO-PT" }, 4777b6ab19dSGarrett Wollman { 0, 0, 0} 4787b6ab19dSGarrett Wollman }; 4797b6ab19dSGarrett Wollman 4807b6ab19dSGarrett Wollman static struct bits is_bits[] = { 481d5b718b3SGarrett Wollman { IS_ALIAS, 0, "ALIAS" }, 4827b6ab19dSGarrett Wollman { IS_SUBNET, 0, "" }, 483d5b718b3SGarrett Wollman { IS_REMOTE, (IS_NO_RDISC 484d5b718b3SGarrett Wollman | IS_BCAST_RDISC), "REMOTE" }, 4857b6ab19dSGarrett Wollman { IS_PASSIVE, (IS_NO_RDISC 4867b6ab19dSGarrett Wollman | IS_NO_RIP 4877b6ab19dSGarrett Wollman | IS_NO_SUPER_AG 4887b6ab19dSGarrett Wollman | IS_PM_RDISC 4897b6ab19dSGarrett Wollman | IS_NO_AG), "PASSIVE" }, 4907b6ab19dSGarrett Wollman { IS_EXTERNAL, 0, "EXTERNAL" }, 4917b6ab19dSGarrett Wollman { IS_CHECKED, 0, "" }, 4927b6ab19dSGarrett Wollman { IS_ALL_HOSTS, 0, "" }, 4937b6ab19dSGarrett Wollman { IS_ALL_ROUTERS, 0, "" }, 494d5b718b3SGarrett Wollman { IS_DISTRUST, 0, "DISTRUST" }, 4957b6ab19dSGarrett Wollman { IS_BROKE, IS_SICK, "BROKEN" }, 4967b6ab19dSGarrett Wollman { IS_SICK, 0, "SICK" }, 497d5b718b3SGarrett Wollman { IS_DUP, 0, "DUPLICATE" }, 49871965874SGarrett Wollman { IS_REDIRECT_OK, 0, "REDIRECT_OK" }, 4997b6ab19dSGarrett Wollman { IS_NEED_NET_SYN, 0, "" }, 5007b6ab19dSGarrett Wollman { IS_NO_AG, IS_NO_SUPER_AG, "NO_AG" }, 5017b6ab19dSGarrett Wollman { IS_NO_SUPER_AG, 0, "NO_SUPER_AG" }, 5027b6ab19dSGarrett Wollman { (IS_NO_RIPV1_IN 5037b6ab19dSGarrett Wollman | IS_NO_RIPV2_IN 5047b6ab19dSGarrett Wollman | IS_NO_RIPV1_OUT 5057b6ab19dSGarrett Wollman | IS_NO_RIPV2_OUT), 0, "NO_RIP" }, 5067b6ab19dSGarrett Wollman { (IS_NO_RIPV1_IN 5077b6ab19dSGarrett Wollman | IS_NO_RIPV1_OUT), 0, "RIPV2" }, 5087b6ab19dSGarrett Wollman { IS_NO_RIPV1_IN, 0, "NO_RIPV1_IN" }, 5097b6ab19dSGarrett Wollman { IS_NO_RIPV2_IN, 0, "NO_RIPV2_IN" }, 5107b6ab19dSGarrett Wollman { IS_NO_RIPV1_OUT, 0, "NO_RIPV1_OUT" }, 5117b6ab19dSGarrett Wollman { IS_NO_RIPV2_OUT, 0, "NO_RIPV2_OUT" }, 5127b6ab19dSGarrett Wollman { (IS_NO_ADV_IN 5137b6ab19dSGarrett Wollman | IS_NO_SOL_OUT 5147b6ab19dSGarrett Wollman | IS_NO_ADV_OUT), IS_BCAST_RDISC, "NO_RDISC" }, 5157b6ab19dSGarrett Wollman { IS_NO_SOL_OUT, 0, "NO_SOLICIT" }, 5167b6ab19dSGarrett Wollman { IS_SOL_OUT, 0, "SEND_SOLICIT" }, 5177b6ab19dSGarrett Wollman { IS_NO_ADV_OUT, IS_BCAST_RDISC, "NO_RDISC_ADV" }, 5187b6ab19dSGarrett Wollman { IS_ADV_OUT, 0, "RDISC_ADV" }, 5197b6ab19dSGarrett Wollman { IS_BCAST_RDISC, 0, "BCAST_RDISC" }, 520d5b718b3SGarrett Wollman { IS_PM_RDISC, 0, "" }, 5217b6ab19dSGarrett Wollman { 0, 0, "%#x"} 5227b6ab19dSGarrett Wollman }; 5237b6ab19dSGarrett Wollman 5247b6ab19dSGarrett Wollman static struct bits rs_bits[] = { 5257b6ab19dSGarrett Wollman { RS_IF, 0, "IF" }, 5267b6ab19dSGarrett Wollman { RS_NET_INT, RS_NET_SYN, "NET_INT" }, 5277b6ab19dSGarrett Wollman { RS_NET_SYN, 0, "NET_SYN" }, 5287b6ab19dSGarrett Wollman { RS_SUBNET, 0, "" }, 5297b6ab19dSGarrett Wollman { RS_LOCAL, 0, "LOCAL" }, 5307b6ab19dSGarrett Wollman { RS_MHOME, 0, "MHOME" }, 5317b6ab19dSGarrett Wollman { RS_STATIC, 0, "STATIC" }, 5327b6ab19dSGarrett Wollman { RS_RDISC, 0, "RDISC" }, 5337b6ab19dSGarrett Wollman { 0, 0, "%#x"} 5347b6ab19dSGarrett Wollman }; 5357b6ab19dSGarrett Wollman 5367b6ab19dSGarrett Wollman 5377b6ab19dSGarrett Wollman static void 5382c7a9781SMark Murray trace_bits(const struct bits *tbl, 5397b6ab19dSGarrett Wollman u_int field, 5407b6ab19dSGarrett Wollman int force) 5417b6ab19dSGarrett Wollman { 5422c7a9781SMark Murray u_int b; 5437b6ab19dSGarrett Wollman char c; 5447b6ab19dSGarrett Wollman 5457b6ab19dSGarrett Wollman if (force) { 5467b6ab19dSGarrett Wollman (void)putc('<', ftrace); 5477b6ab19dSGarrett Wollman c = 0; 5487b6ab19dSGarrett Wollman } else { 5497b6ab19dSGarrett Wollman c = '<'; 5507b6ab19dSGarrett Wollman } 5517b6ab19dSGarrett Wollman 5527b6ab19dSGarrett Wollman while (field != 0 5537b6ab19dSGarrett Wollman && (b = tbl->bits_mask) != 0) { 5547b6ab19dSGarrett Wollman if ((b & field) == b) { 5557b6ab19dSGarrett Wollman if (tbl->bits_name[0] != '\0') { 5567b6ab19dSGarrett Wollman if (c) 5577b6ab19dSGarrett Wollman (void)putc(c, ftrace); 5587b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s", tbl->bits_name); 5597b6ab19dSGarrett Wollman c = '|'; 5607b6ab19dSGarrett Wollman } 5617b6ab19dSGarrett Wollman if (0 == (field &= ~(b | tbl->bits_clear))) 5627b6ab19dSGarrett Wollman break; 5637b6ab19dSGarrett Wollman } 5647b6ab19dSGarrett Wollman tbl++; 5657b6ab19dSGarrett Wollman } 5667b6ab19dSGarrett Wollman if (field != 0 && tbl->bits_name != 0) { 5677b6ab19dSGarrett Wollman if (c) 5687b6ab19dSGarrett Wollman (void)putc(c, ftrace); 5697b6ab19dSGarrett Wollman (void)fprintf(ftrace, tbl->bits_name, field); 5707b6ab19dSGarrett Wollman c = '|'; 5717b6ab19dSGarrett Wollman } 5727b6ab19dSGarrett Wollman 5737b6ab19dSGarrett Wollman if (c != '<' || force) 5747b6ab19dSGarrett Wollman (void)fputs("> ", ftrace); 5757b6ab19dSGarrett Wollman } 5767b6ab19dSGarrett Wollman 5777b6ab19dSGarrett Wollman 5782c7a9781SMark Murray char * 5792c7a9781SMark Murray rtname(naddr dst, 5807b6ab19dSGarrett Wollman naddr mask, 5812c7a9781SMark Murray naddr gate) 5827b6ab19dSGarrett Wollman { 5837b6ab19dSGarrett Wollman static char buf[3*4+3+1+2+3 /* "xxx.xxx.xxx.xxx/xx-->" */ 5847b6ab19dSGarrett Wollman +3*4+3+1]; /* "xxx.xxx.xxx.xxx" */ 5857b6ab19dSGarrett Wollman int i; 5867b6ab19dSGarrett Wollman 5877b6ab19dSGarrett Wollman i = sprintf(buf, "%-16s-->", addrname(dst, mask, 0)); 5882c7a9781SMark Murray (void)sprintf(&buf[i], "%-*s", 15+20-MAX(20,i), naddr_ntoa(gate)); 5897b6ab19dSGarrett Wollman return buf; 5907b6ab19dSGarrett Wollman } 5917b6ab19dSGarrett Wollman 5927b6ab19dSGarrett Wollman 59371965874SGarrett Wollman static void 59471965874SGarrett Wollman print_rts(struct rt_spare *rts, 59571965874SGarrett Wollman int force_metric, /* -1=suppress, 0=default */ 59671965874SGarrett Wollman int force_ifp, /* -1=suppress, 0=default */ 59771965874SGarrett Wollman int force_router, /* -1=suppress, 0=default, 1=display */ 59871965874SGarrett Wollman int force_tag, /* -1=suppress, 0=default, 1=display */ 59971965874SGarrett Wollman int force_time) /* 0=suppress, 1=display */ 60071965874SGarrett Wollman { 6012c7a9781SMark Murray int i; 6022c7a9781SMark Murray 6032c7a9781SMark Murray 60471965874SGarrett Wollman if (force_metric >= 0) 60571965874SGarrett Wollman (void)fprintf(ftrace, "metric=%-2d ", rts->rts_metric); 60671965874SGarrett Wollman if (force_ifp >= 0) 60771965874SGarrett Wollman (void)fprintf(ftrace, "%s ", (rts->rts_ifp == 0 ? 60871965874SGarrett Wollman "if?" : rts->rts_ifp->int_name)); 60971965874SGarrett Wollman if (force_router > 0 61071965874SGarrett Wollman || (force_router == 0 && rts->rts_router != rts->rts_gate)) 61171965874SGarrett Wollman (void)fprintf(ftrace, "router=%s ", 61271965874SGarrett Wollman naddr_ntoa(rts->rts_router)); 61371965874SGarrett Wollman if (force_time > 0) 61471965874SGarrett Wollman (void)fprintf(ftrace, "%s ", ts(rts->rts_time)); 61571965874SGarrett Wollman if (force_tag > 0 61671965874SGarrett Wollman || (force_tag == 0 && rts->rts_tag != 0)) 6172c7a9781SMark Murray (void)fprintf(ftrace, "tag=%#x ", ntohs(rts->rts_tag)); 6182c7a9781SMark Murray if (rts->rts_de_ag != 0) { 6192c7a9781SMark Murray for (i = 1; (u_int)(1 << i) <= rts->rts_de_ag; i++) 6202c7a9781SMark Murray continue; 6212c7a9781SMark Murray (void)fprintf(ftrace, "de_ag=%d ", i); 6222c7a9781SMark Murray } 6232c7a9781SMark Murray 62471965874SGarrett Wollman } 62571965874SGarrett Wollman 62671965874SGarrett Wollman 6277b6ab19dSGarrett Wollman void 6282c7a9781SMark Murray trace_if(const char *act, 6297b6ab19dSGarrett Wollman struct interface *ifp) 6307b6ab19dSGarrett Wollman { 6317b6ab19dSGarrett Wollman if (!TRACEACTIONS || ftrace == 0) 6327b6ab19dSGarrett Wollman return; 6337b6ab19dSGarrett Wollman 6347b6ab19dSGarrett Wollman lastlog(); 635d5b718b3SGarrett Wollman (void)fprintf(ftrace, "%-3s interface %-4s ", act, ifp->int_name); 6367b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%-15s-->%-15s ", 6377b6ab19dSGarrett Wollman naddr_ntoa(ifp->int_addr), 638d5b718b3SGarrett Wollman addrname(((ifp->int_if_flags & IFF_POINTOPOINT) 6397b6ab19dSGarrett Wollman ? ifp->int_dstaddr 640d5b718b3SGarrett Wollman : htonl(ifp->int_net)), 6417b6ab19dSGarrett Wollman ifp->int_mask, 1)); 6427b6ab19dSGarrett Wollman if (ifp->int_metric != 0) 6437b6ab19dSGarrett Wollman (void)fprintf(ftrace, "metric=%d ", ifp->int_metric); 644d5b718b3SGarrett Wollman if (!IS_RIP_OUT_OFF(ifp->int_state) 645d5b718b3SGarrett Wollman && ifp->int_d_metric != 0) 646d5b718b3SGarrett Wollman (void)fprintf(ftrace, "fake_default=%d ", ifp->int_d_metric); 6477b6ab19dSGarrett Wollman trace_bits(if_bits, ifp->int_if_flags, 0); 6487b6ab19dSGarrett Wollman trace_bits(is_bits, ifp->int_state, 0); 6497b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 6507b6ab19dSGarrett Wollman } 6517b6ab19dSGarrett Wollman 6527b6ab19dSGarrett Wollman 6537b6ab19dSGarrett Wollman void 6547b6ab19dSGarrett Wollman trace_upslot(struct rt_entry *rt, 6557b6ab19dSGarrett Wollman struct rt_spare *rts, 6562c7a9781SMark Murray struct rt_spare *new) 6577b6ab19dSGarrett Wollman { 6587b6ab19dSGarrett Wollman if (!TRACEACTIONS || ftrace == 0) 6597b6ab19dSGarrett Wollman return; 66071965874SGarrett Wollman 6612c7a9781SMark Murray if (rts->rts_gate == new->rts_gate 6622c7a9781SMark Murray && rts->rts_router == new->rts_router 6632c7a9781SMark Murray && rts->rts_metric == new->rts_metric 6642c7a9781SMark Murray && rts->rts_tag == new->rts_tag 6652c7a9781SMark Murray && rts->rts_de_ag == new->rts_de_ag) 6667b6ab19dSGarrett Wollman return; 6677b6ab19dSGarrett Wollman 6687b6ab19dSGarrett Wollman lastlog(); 6692c7a9781SMark Murray if (new->rts_gate == 0) { 6702c7a9781SMark Murray (void)fprintf(ftrace, "Del #%d %-35s ", 6712c7a9781SMark Murray (int)(rts - rt->rt_spares), 6722c7a9781SMark Murray rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate)); 6732c7a9781SMark Murray print_rts(rts, 0,0,0,0, 6742c7a9781SMark Murray (rts != rt->rt_spares 6752c7a9781SMark Murray || AGE_RT(rt->rt_state,new->rts_ifp))); 6762c7a9781SMark Murray 6772c7a9781SMark Murray } else if (rts->rts_gate != RIP_DEFAULT) { 6787b6ab19dSGarrett Wollman (void)fprintf(ftrace, "Chg #%d %-35s ", 6792c7a9781SMark Murray (int)(rts - rt->rt_spares), 6802c7a9781SMark Murray rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate)); 68171965874SGarrett Wollman print_rts(rts, 0,0, 6822c7a9781SMark Murray rts->rts_gate != new->rts_gate, 6832c7a9781SMark Murray rts->rts_tag != new->rts_tag, 68471965874SGarrett Wollman rts != rt->rt_spares || AGE_RT(rt->rt_state, 68571965874SGarrett Wollman rt->rt_ifp)); 6867b6ab19dSGarrett Wollman 68771965874SGarrett Wollman (void)fprintf(ftrace, "\n %19s%-16s ", "", 6882c7a9781SMark Murray (new->rts_gate != rts->rts_gate 6892c7a9781SMark Murray ? naddr_ntoa(new->rts_gate) : "")); 6902c7a9781SMark Murray print_rts(new, 6912c7a9781SMark Murray -(new->rts_metric == rts->rts_metric), 6922c7a9781SMark Murray -(new->rts_ifp == rts->rts_ifp), 69371965874SGarrett Wollman 0, 6942c7a9781SMark Murray rts->rts_tag != new->rts_tag, 6952c7a9781SMark Murray (new->rts_time != rts->rts_time 6962c7a9781SMark Murray && (rts != rt->rt_spares 6972c7a9781SMark Murray || AGE_RT(rt->rt_state, new->rts_ifp)))); 6987b6ab19dSGarrett Wollman 6997b6ab19dSGarrett Wollman } else { 7007b6ab19dSGarrett Wollman (void)fprintf(ftrace, "Add #%d %-35s ", 7012c7a9781SMark Murray (int)(rts - rt->rt_spares), 7022c7a9781SMark Murray rtname(rt->rt_dst, rt->rt_mask, new->rts_gate)); 7032c7a9781SMark Murray print_rts(new, 0,0,0,0, 7042c7a9781SMark Murray (rts != rt->rt_spares 7052c7a9781SMark Murray || AGE_RT(rt->rt_state,new->rts_ifp))); 7067b6ab19dSGarrett Wollman } 70771965874SGarrett Wollman (void)fputc('\n',ftrace); 7087b6ab19dSGarrett Wollman } 7097b6ab19dSGarrett Wollman 7107b6ab19dSGarrett Wollman 7112c7a9781SMark Murray /* miscellaneous message checked by the caller 7127b6ab19dSGarrett Wollman */ 7137b6ab19dSGarrett Wollman void 7142c7a9781SMark Murray trace_misc(const char *p, ...) 7157b6ab19dSGarrett Wollman { 7167b6ab19dSGarrett Wollman va_list args; 7177b6ab19dSGarrett Wollman 7182c7a9781SMark Murray if (ftrace == 0) 7197b6ab19dSGarrett Wollman return; 7207b6ab19dSGarrett Wollman 7217b6ab19dSGarrett Wollman lastlog(); 7227b6ab19dSGarrett Wollman va_start(args, p); 7237b6ab19dSGarrett Wollman vfprintf(ftrace, p, args); 7242c7a9781SMark Murray (void)fputc('\n',ftrace); 7257b6ab19dSGarrett Wollman } 7267b6ab19dSGarrett Wollman 7277b6ab19dSGarrett Wollman 7287b6ab19dSGarrett Wollman /* display a message if tracing actions 7297b6ab19dSGarrett Wollman */ 7307b6ab19dSGarrett Wollman void 7312c7a9781SMark Murray trace_act(const char *p, ...) 7327b6ab19dSGarrett Wollman { 7337b6ab19dSGarrett Wollman va_list args; 7347b6ab19dSGarrett Wollman 7357b6ab19dSGarrett Wollman if (!TRACEACTIONS || ftrace == 0) 7367b6ab19dSGarrett Wollman return; 7377b6ab19dSGarrett Wollman 7387b6ab19dSGarrett Wollman lastlog(); 7397b6ab19dSGarrett Wollman va_start(args, p); 7407b6ab19dSGarrett Wollman vfprintf(ftrace, p, args); 741d5b718b3SGarrett Wollman (void)fputc('\n',ftrace); 7427b6ab19dSGarrett Wollman } 7437b6ab19dSGarrett Wollman 7447b6ab19dSGarrett Wollman 7457b6ab19dSGarrett Wollman /* display a message if tracing packets 7467b6ab19dSGarrett Wollman */ 7477b6ab19dSGarrett Wollman void 7482c7a9781SMark Murray trace_pkt(const char *p, ...) 7497b6ab19dSGarrett Wollman { 7507b6ab19dSGarrett Wollman va_list args; 7517b6ab19dSGarrett Wollman 7527b6ab19dSGarrett Wollman if (!TRACEPACKETS || ftrace == 0) 7537b6ab19dSGarrett Wollman return; 7547b6ab19dSGarrett Wollman 7557b6ab19dSGarrett Wollman lastlog(); 7567b6ab19dSGarrett Wollman va_start(args, p); 7577b6ab19dSGarrett Wollman vfprintf(ftrace, p, args); 758d5b718b3SGarrett Wollman (void)fputc('\n',ftrace); 7597b6ab19dSGarrett Wollman } 7607b6ab19dSGarrett Wollman 7617b6ab19dSGarrett Wollman 7627b6ab19dSGarrett Wollman void 7637b6ab19dSGarrett Wollman trace_change(struct rt_entry *rt, 7647b6ab19dSGarrett Wollman u_int state, 7652c7a9781SMark Murray struct rt_spare *new, 7662c7a9781SMark Murray const char *label) 7677b6ab19dSGarrett Wollman { 7687b6ab19dSGarrett Wollman if (ftrace == 0) 7697b6ab19dSGarrett Wollman return; 7707b6ab19dSGarrett Wollman 7712c7a9781SMark Murray if (rt->rt_metric == new->rts_metric 7722c7a9781SMark Murray && rt->rt_gate == new->rts_gate 7732c7a9781SMark Murray && rt->rt_router == new->rts_router 7747b6ab19dSGarrett Wollman && rt->rt_state == state 7752c7a9781SMark Murray && rt->rt_tag == new->rts_tag 7762c7a9781SMark Murray && rt->rt_de_ag == new->rts_de_ag) 7777b6ab19dSGarrett Wollman return; 7787b6ab19dSGarrett Wollman 7797b6ab19dSGarrett Wollman lastlog(); 78071965874SGarrett Wollman (void)fprintf(ftrace, "%s %-35s ", 7817b6ab19dSGarrett Wollman label, 7822c7a9781SMark Murray rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate)); 78371965874SGarrett Wollman print_rts(rt->rt_spares, 78471965874SGarrett Wollman 0,0,0,0, AGE_RT(rt->rt_state, rt->rt_ifp)); 7857b6ab19dSGarrett Wollman trace_bits(rs_bits, rt->rt_state, rt->rt_state != state); 7867b6ab19dSGarrett Wollman 78771965874SGarrett Wollman (void)fprintf(ftrace, "\n%*s %19s%-16s ", 7882c7a9781SMark Murray (int)strlen(label), "", "", 7892c7a9781SMark Murray (rt->rt_gate != new->rts_gate 7902c7a9781SMark Murray ? naddr_ntoa(new->rts_gate) : "")); 7912c7a9781SMark Murray print_rts(new, 7922c7a9781SMark Murray -(new->rts_metric == rt->rt_metric), 7932c7a9781SMark Murray -(new->rts_ifp == rt->rt_ifp), 79471965874SGarrett Wollman 0, 7952c7a9781SMark Murray rt->rt_tag != new->rts_tag, 7962c7a9781SMark Murray (rt->rt_time != new->rts_time 7972c7a9781SMark Murray && AGE_RT(rt->rt_state,new->rts_ifp))); 7987b6ab19dSGarrett Wollman if (rt->rt_state != state) 7997b6ab19dSGarrett Wollman trace_bits(rs_bits, state, 1); 80071965874SGarrett Wollman (void)fputc('\n',ftrace); 8017b6ab19dSGarrett Wollman } 8027b6ab19dSGarrett Wollman 8037b6ab19dSGarrett Wollman 8047b6ab19dSGarrett Wollman void 8052c7a9781SMark Murray trace_add_del(const char * action, struct rt_entry *rt) 8067b6ab19dSGarrett Wollman { 8077b6ab19dSGarrett Wollman if (ftrace == 0) 8087b6ab19dSGarrett Wollman return; 8097b6ab19dSGarrett Wollman 8107b6ab19dSGarrett Wollman lastlog(); 81171965874SGarrett Wollman (void)fprintf(ftrace, "%s %-35s ", 8127b6ab19dSGarrett Wollman action, 8132c7a9781SMark Murray rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate)); 81471965874SGarrett Wollman print_rts(rt->rt_spares, 0,0,0,0,AGE_RT(rt->rt_state,rt->rt_ifp)); 81571965874SGarrett Wollman trace_bits(rs_bits, rt->rt_state, 0); 81671965874SGarrett Wollman (void)fputc('\n',ftrace); 8177b6ab19dSGarrett Wollman } 8187b6ab19dSGarrett Wollman 8197b6ab19dSGarrett Wollman 8207b6ab19dSGarrett Wollman /* ARGSUSED */ 8217b6ab19dSGarrett Wollman static int 8227b6ab19dSGarrett Wollman walk_trace(struct radix_node *rn, 8232c7a9781SMark Murray struct walkarg *w UNUSED) 8247b6ab19dSGarrett Wollman { 8257b6ab19dSGarrett Wollman #define RT ((struct rt_entry *)rn) 8267b6ab19dSGarrett Wollman struct rt_spare *rts; 8272c7a9781SMark Murray int i; 8287b6ab19dSGarrett Wollman 8292c7a9781SMark Murray (void)fprintf(ftrace, " %-35s ", 8302c7a9781SMark Murray rtname(RT->rt_dst, RT->rt_mask, RT->rt_gate)); 8312c7a9781SMark Murray print_rts(&RT->rt_spares[0], 0,0,0,0, AGE_RT(RT->rt_state, RT->rt_ifp)); 8327b6ab19dSGarrett Wollman trace_bits(rs_bits, RT->rt_state, 0); 83371965874SGarrett Wollman if (RT->rt_poison_time >= now_garbage 83471965874SGarrett Wollman && RT->rt_poison_metric < RT->rt_metric) 83571965874SGarrett Wollman (void)fprintf(ftrace, "pm=%d@%s", 8362c7a9781SMark Murray RT->rt_poison_metric, ts(RT->rt_poison_time)); 8377b6ab19dSGarrett Wollman 8387b6ab19dSGarrett Wollman rts = &RT->rt_spares[1]; 8397b6ab19dSGarrett Wollman for (i = 1; i < NUM_SPARES; i++, rts++) { 84071965874SGarrett Wollman if (rts->rts_gate != RIP_DEFAULT) { 84171965874SGarrett Wollman (void)fprintf(ftrace,"\n #%d%15s%-16s ", 84271965874SGarrett Wollman i, "", naddr_ntoa(rts->rts_gate)); 84371965874SGarrett Wollman print_rts(rts, 0,0,0,0,1); 8447b6ab19dSGarrett Wollman } 8457b6ab19dSGarrett Wollman } 8467b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 8477b6ab19dSGarrett Wollman 8487b6ab19dSGarrett Wollman return 0; 8497b6ab19dSGarrett Wollman } 8507b6ab19dSGarrett Wollman 8517b6ab19dSGarrett Wollman 8527b6ab19dSGarrett Wollman static void 8537b6ab19dSGarrett Wollman trace_dump(void) 8547b6ab19dSGarrett Wollman { 855d5b718b3SGarrett Wollman struct interface *ifp; 856d5b718b3SGarrett Wollman 8577b6ab19dSGarrett Wollman if (ftrace == 0) 8587b6ab19dSGarrett Wollman return; 8597b6ab19dSGarrett Wollman lastlog(); 8607b6ab19dSGarrett Wollman 86171965874SGarrett Wollman (void)fputs("current daemon state:\n", ftrace); 862d5b718b3SGarrett Wollman for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) 863d5b718b3SGarrett Wollman trace_if("", ifp); 8647b6ab19dSGarrett Wollman (void)rn_walktree(rhead, walk_trace, 0); 8657b6ab19dSGarrett Wollman } 8667b6ab19dSGarrett Wollman 8677b6ab19dSGarrett Wollman 8687b6ab19dSGarrett Wollman void 8692c7a9781SMark Murray trace_rip(const char *dir1, const char *dir2, 8707b6ab19dSGarrett Wollman struct sockaddr_in *who, 8717b6ab19dSGarrett Wollman struct interface *ifp, 8727b6ab19dSGarrett Wollman struct rip *msg, 8737b6ab19dSGarrett Wollman int size) /* total size of message */ 8747b6ab19dSGarrett Wollman { 8757b6ab19dSGarrett Wollman struct netinfo *n, *lim; 8762c7a9781SMark Murray # define NA ((struct netauth*)n) 877d5b718b3SGarrett Wollman int i, seen_route; 8787b6ab19dSGarrett Wollman 8797b6ab19dSGarrett Wollman if (!TRACEPACKETS || ftrace == 0) 8807b6ab19dSGarrett Wollman return; 8817b6ab19dSGarrett Wollman 8827b6ab19dSGarrett Wollman lastlog(); 8837b6ab19dSGarrett Wollman if (msg->rip_cmd >= RIPCMD_MAX 8847b6ab19dSGarrett Wollman || msg->rip_vers == 0) { 8857b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s bad RIPv%d cmd=%d %s" 8867b6ab19dSGarrett Wollman " %s.%d size=%d\n", 8877b6ab19dSGarrett Wollman dir1, msg->rip_vers, msg->rip_cmd, dir2, 8887b6ab19dSGarrett Wollman naddr_ntoa(who->sin_addr.s_addr), 8897b6ab19dSGarrett Wollman ntohs(who->sin_port), 8907b6ab19dSGarrett Wollman size); 8917b6ab19dSGarrett Wollman return; 8927b6ab19dSGarrett Wollman } 8937b6ab19dSGarrett Wollman 8947b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s RIPv%d %s %s %s.%d%s%s\n", 8957b6ab19dSGarrett Wollman dir1, msg->rip_vers, ripcmds[msg->rip_cmd], dir2, 8967b6ab19dSGarrett Wollman naddr_ntoa(who->sin_addr.s_addr), ntohs(who->sin_port), 8977b6ab19dSGarrett Wollman ifp ? " via " : "", ifp ? ifp->int_name : ""); 8987b6ab19dSGarrett Wollman if (!TRACECONTENTS) 8997b6ab19dSGarrett Wollman return; 9007b6ab19dSGarrett Wollman 901d5b718b3SGarrett Wollman seen_route = 0; 9027b6ab19dSGarrett Wollman switch (msg->rip_cmd) { 9037b6ab19dSGarrett Wollman case RIPCMD_REQUEST: 9047b6ab19dSGarrett Wollman case RIPCMD_RESPONSE: 9057b6ab19dSGarrett Wollman n = msg->rip_nets; 9067b6ab19dSGarrett Wollman lim = (struct netinfo *)((char*)msg + size); 9077b6ab19dSGarrett Wollman for (; n < lim; n++) { 908d5b718b3SGarrett Wollman if (!seen_route 909d5b718b3SGarrett Wollman && n->n_family == RIP_AF_UNSPEC 9107b6ab19dSGarrett Wollman && ntohl(n->n_metric) == HOPCNT_INFINITY 911d5b718b3SGarrett Wollman && msg->rip_cmd == RIPCMD_REQUEST 912d5b718b3SGarrett Wollman && (n+1 == lim 913d5b718b3SGarrett Wollman || (n+2 == lim 914d5b718b3SGarrett Wollman && (n+1)->n_family == RIP_AF_AUTH))) { 9157b6ab19dSGarrett Wollman (void)fputs("\tQUERY ", ftrace); 9167b6ab19dSGarrett Wollman if (n->n_dst != 0) 9177b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%s ", 9187b6ab19dSGarrett Wollman naddr_ntoa(n->n_dst)); 9197b6ab19dSGarrett Wollman if (n->n_mask != 0) 9207b6ab19dSGarrett Wollman (void)fprintf(ftrace, "mask=%#x ", 9217b6ab19dSGarrett Wollman (u_int)ntohl(n->n_mask)); 9227b6ab19dSGarrett Wollman if (n->n_nhop != 0) 9237b6ab19dSGarrett Wollman (void)fprintf(ftrace, "nhop=%s ", 9247b6ab19dSGarrett Wollman naddr_ntoa(n->n_nhop)); 9257b6ab19dSGarrett Wollman if (n->n_tag != 0) 9267b6ab19dSGarrett Wollman (void)fprintf(ftrace, "tag=%#x ", 9277b6ab19dSGarrett Wollman ntohs(n->n_tag)); 9287b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 9297b6ab19dSGarrett Wollman continue; 9307b6ab19dSGarrett Wollman } 9317b6ab19dSGarrett Wollman 9327b6ab19dSGarrett Wollman if (n->n_family == RIP_AF_AUTH) { 933d5b718b3SGarrett Wollman if (NA->a_type == RIP_AUTH_PW 934d5b718b3SGarrett Wollman && n == msg->rip_nets) { 935d5b718b3SGarrett Wollman (void)fprintf(ftrace, "\tPassword" 936d5b718b3SGarrett Wollman " Authentication:" 937d5b718b3SGarrett Wollman " \"%s\"\n", 938d5b718b3SGarrett Wollman qstring(NA->au.au_pw, 939d5b718b3SGarrett Wollman RIP_AUTH_PW_LEN)); 940d5b718b3SGarrett Wollman continue; 941d5b718b3SGarrett Wollman } 942d5b718b3SGarrett Wollman 943d5b718b3SGarrett Wollman if (NA->a_type == RIP_AUTH_MD5 944d5b718b3SGarrett Wollman && n == msg->rip_nets) { 9457b6ab19dSGarrett Wollman (void)fprintf(ftrace, 9462c7a9781SMark Murray "\tMD5 Auth" 9472c7a9781SMark Murray " pkt_len=%d KeyID=%u" 9482c7a9781SMark Murray " auth_len=%d" 9492c7a9781SMark Murray " seqno=%#x" 950d5b718b3SGarrett Wollman " rsvd=%#x,%#x\n", 9512c7a9781SMark Murray ntohs(NA->au.a_md5.md5_pkt_len), 952d5b718b3SGarrett Wollman NA->au.a_md5.md5_keyid, 9532c7a9781SMark Murray NA->au.a_md5.md5_auth_len, 9542c7a9781SMark Murray (int)ntohl(NA->au.a_md5.md5_seqno), 9552c7a9781SMark Murray (int)ntohs(NA->au.a_md5.rsvd[0]), 9562c7a9781SMark Murray (int)ntohs(NA->au.a_md5.rsvd[1])); 957d5b718b3SGarrett Wollman continue; 958d5b718b3SGarrett Wollman } 959d5b718b3SGarrett Wollman (void)fprintf(ftrace, 9602c7a9781SMark Murray "\tAuthentication type %d: ", 961d5b718b3SGarrett Wollman ntohs(NA->a_type)); 9627b6ab19dSGarrett Wollman for (i = 0; 9632c7a9781SMark Murray i < (int)sizeof(NA->au.au_pw); 9647b6ab19dSGarrett Wollman i++) 9657b6ab19dSGarrett Wollman (void)fprintf(ftrace, "%02x ", 966d5b718b3SGarrett Wollman NA->au.au_pw[i]); 9677b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 9687b6ab19dSGarrett Wollman continue; 9697b6ab19dSGarrett Wollman } 9707b6ab19dSGarrett Wollman 971d5b718b3SGarrett Wollman seen_route = 1; 9727b6ab19dSGarrett Wollman if (n->n_family != RIP_AF_INET) { 9737b6ab19dSGarrett Wollman (void)fprintf(ftrace, 9747b6ab19dSGarrett Wollman "\t(af %d) %-18s mask=%#x ", 9757b6ab19dSGarrett Wollman ntohs(n->n_family), 9767b6ab19dSGarrett Wollman naddr_ntoa(n->n_dst), 9777b6ab19dSGarrett Wollman (u_int)ntohl(n->n_mask)); 9787b6ab19dSGarrett Wollman } else if (msg->rip_vers == RIPv1) { 9797b6ab19dSGarrett Wollman (void)fprintf(ftrace, "\t%-18s ", 9807b6ab19dSGarrett Wollman addrname(n->n_dst, 9817b6ab19dSGarrett Wollman ntohl(n->n_mask), 9827b6ab19dSGarrett Wollman n->n_mask==0 ? 2 : 1)); 9837b6ab19dSGarrett Wollman } else { 9847b6ab19dSGarrett Wollman (void)fprintf(ftrace, "\t%-18s ", 9857b6ab19dSGarrett Wollman addrname(n->n_dst, 9867b6ab19dSGarrett Wollman ntohl(n->n_mask), 9877b6ab19dSGarrett Wollman n->n_mask==0 ? 2 : 0)); 9887b6ab19dSGarrett Wollman } 9897b6ab19dSGarrett Wollman (void)fprintf(ftrace, "metric=%-2d ", 9907b6ab19dSGarrett Wollman (u_int)ntohl(n->n_metric)); 9917b6ab19dSGarrett Wollman if (n->n_nhop != 0) 9927b6ab19dSGarrett Wollman (void)fprintf(ftrace, " nhop=%s ", 9937b6ab19dSGarrett Wollman naddr_ntoa(n->n_nhop)); 9947b6ab19dSGarrett Wollman if (n->n_tag != 0) 9957b6ab19dSGarrett Wollman (void)fprintf(ftrace, "tag=%#x", 9967b6ab19dSGarrett Wollman ntohs(n->n_tag)); 9977b6ab19dSGarrett Wollman (void)fputc('\n',ftrace); 9987b6ab19dSGarrett Wollman } 9997b6ab19dSGarrett Wollman if (size != (char *)n - (char *)msg) 10007b6ab19dSGarrett Wollman (void)fprintf(ftrace, "truncated record, len %d\n", 10017b6ab19dSGarrett Wollman size); 10027b6ab19dSGarrett Wollman break; 10037b6ab19dSGarrett Wollman 10047b6ab19dSGarrett Wollman case RIPCMD_TRACEON: 100571965874SGarrett Wollman fprintf(ftrace, "\tfile=\"%.*s\"\n", size-4, 100671965874SGarrett Wollman msg->rip_tracefile); 10077b6ab19dSGarrett Wollman break; 10087b6ab19dSGarrett Wollman 10097b6ab19dSGarrett Wollman case RIPCMD_TRACEOFF: 10107b6ab19dSGarrett Wollman break; 10117b6ab19dSGarrett Wollman } 10127b6ab19dSGarrett Wollman } 1013