trace.c revision 46303
118316Swollman/* 218316Swollman * Copyright (c) 1983, 1988, 1993 318316Swollman * The Regents of the University of California. All rights reserved. 418316Swollman * 518316Swollman * Redistribution and use in source and binary forms, with or without 618316Swollman * modification, are permitted provided that the following conditions 718316Swollman * are met: 818316Swollman * 1. Redistributions of source code must retain the above copyright 918316Swollman * notice, this list of conditions and the following disclaimer. 1018316Swollman * 2. Redistributions in binary form must reproduce the above copyright 1118316Swollman * notice, this list of conditions and the following disclaimer in the 1218316Swollman * documentation and/or other materials provided with the distribution. 1318316Swollman * 3. All advertising materials mentioning features or use of this software 1446303Smarkm * must display the following acknowledgment: 1518316Swollman * This product includes software developed by the University of 1618316Swollman * California, Berkeley and its contributors. 1718316Swollman * 4. Neither the name of the University nor the names of its contributors 1818316Swollman * may be used to endorse or promote products derived from this software 1918316Swollman * without specific prior written permission. 2018316Swollman * 2118316Swollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2218316Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2318316Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2418316Swollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2518316Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2618316Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2718316Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2818316Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2918316Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3018316Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3118316Swollman * SUCH DAMAGE. 3246303Smarkm * 3346303Smarkm * $Id$ 3418316Swollman */ 3518316Swollman 3618316Swollman#define RIPCMDS 3718316Swollman#include "defs.h" 3818316Swollman#include "pathnames.h" 3918316Swollman#include <sys/stat.h> 4046303Smarkm#include <sys/signal.h> 4118316Swollman#include <fcntl.h> 4218316Swollman 4346303Smarkm#if !defined(sgi) && !defined(__NetBSD__) 4446303Smarkmstatic char sccsid[] __attribute__((unused)) = "@(#)trace.c 8.1 (Berkeley) 6/5/93"; 4546303Smarkm#elif defined(__NetBSD__) 4646303Smarkm__RCSID("$NetBSD$"); 4746303Smarkm#endif 4846303Smarkm#ident "$Revision: 2.17 $" 4946303Smarkm 5046303Smarkm 5118316Swollman#ifdef sgi 5218316Swollman/* use *stat64 for files on large filesystems */ 5318316Swollman#define stat stat64 5418316Swollman#endif 5518316Swollman 5618316Swollman#define NRECORDS 50 /* size of circular trace buffer */ 5718316Swollman 5820339Swollmanint tracelevel, new_tracelevel; 5918316SwollmanFILE *ftrace = stdout; /* output trace file */ 6046303Smarkmstatic const char *sigtrace_pat = "%s"; 6120339Swollmanstatic char savetracename[MAXPATHLEN+1]; 6220339Swollmanchar inittracename[MAXPATHLEN+1]; 6320339Swollmanint file_trace; /* 1=tracing to file, not stdout */ 6418316Swollman 6518316Swollmanstatic void trace_dump(void); 6646303Smarkmstatic void tmsg(const char *, ...) PATTRIB(1,2); 6718316Swollman 6818316Swollman 6919880Swollman/* convert string to printable characters 7019880Swollman */ 7119880Swollmanstatic char * 7219880Swollmanqstring(u_char *s, int len) 7319880Swollman{ 7419880Swollman static char buf[8*20+1]; 7519880Swollman char *p; 7619880Swollman u_char *s2, c; 7719880Swollman 7819880Swollman 7919880Swollman for (p = buf; len != 0 && p < &buf[sizeof(buf)-1]; len--) { 8019880Swollman c = *s++; 8119880Swollman if (c == '\0') { 8219880Swollman for (s2 = s+1; s2 < &s[len]; s2++) { 8319880Swollman if (*s2 != '\0') 8419880Swollman break; 8519880Swollman } 8619880Swollman if (s2 >= &s[len]) 8719880Swollman goto exit; 8819880Swollman } 8919880Swollman 9019880Swollman if (c >= ' ' && c < 0x7f && c != '\\') { 9119880Swollman *p++ = c; 9219880Swollman continue; 9319880Swollman } 9419880Swollman *p++ = '\\'; 9519880Swollman switch (c) { 9619880Swollman case '\\': 9719880Swollman *p++ = '\\'; 9819880Swollman break; 9919880Swollman case '\n': 10019880Swollman *p++= 'n'; 10119880Swollman break; 10219880Swollman case '\r': 10319880Swollman *p++= 'r'; 10419880Swollman break; 10519880Swollman case '\t': 10619880Swollman *p++ = 't'; 10719880Swollman break; 10819880Swollman case '\b': 10919880Swollman *p++ = 'b'; 11019880Swollman break; 11119880Swollman default: 11219880Swollman p += sprintf(p,"%o",c); 11319880Swollman break; 11419880Swollman } 11519880Swollman } 11619880Swollmanexit: 11719880Swollman *p = '\0'; 11819880Swollman return buf; 11919880Swollman} 12019880Swollman 12119880Swollman 12218316Swollman/* convert IP address to a string, but not into a single buffer 12318316Swollman */ 12418316Swollmanchar * 12518316Swollmannaddr_ntoa(naddr a) 12618316Swollman{ 12718316Swollman#define NUM_BUFS 4 12818316Swollman static int bufno; 12918316Swollman static struct { 13018316Swollman char str[16]; /* xxx.xxx.xxx.xxx\0 */ 13118316Swollman } bufs[NUM_BUFS]; 13218316Swollman char *s; 13318316Swollman struct in_addr addr; 13418316Swollman 13518316Swollman addr.s_addr = a; 13618316Swollman s = strcpy(bufs[bufno].str, inet_ntoa(addr)); 13718316Swollman bufno = (bufno+1) % NUM_BUFS; 13818316Swollman return s; 13918316Swollman#undef NUM_BUFS 14018316Swollman} 14118316Swollman 14218316Swollman 14346303Smarkmconst char * 14418316Swollmansaddr_ntoa(struct sockaddr *sa) 14518316Swollman{ 14618316Swollman return (sa == 0) ? "?" : naddr_ntoa(S_ADDR(sa)); 14718316Swollman} 14818316Swollman 14918316Swollman 15018316Swollmanstatic char * 15118316Swollmants(time_t secs) { 15218316Swollman static char s[20]; 15318316Swollman 15418316Swollman secs += epoch.tv_sec; 15518316Swollman#ifdef sgi 15618316Swollman (void)cftime(s, "%T", &secs); 15718316Swollman#else 15846303Smarkm memcpy(s, ctime(&secs)+11, 8); 15918316Swollman s[8] = '\0'; 16018316Swollman#endif 16118316Swollman return s; 16218316Swollman} 16318316Swollman 16418316Swollman 16518316Swollman/* On each event, display a time stamp. 16618316Swollman * This assumes that 'now' is update once for each event, and 16718316Swollman * that at least now.tv_usec changes. 16818316Swollman */ 16920339Swollmanstatic struct timeval lastlog_time; 17020339Swollman 17118316Swollmanvoid 17218316Swollmanlastlog(void) 17318316Swollman{ 17420339Swollman if (lastlog_time.tv_sec != now.tv_sec 17520339Swollman || lastlog_time.tv_usec != now.tv_usec) { 17618316Swollman (void)fprintf(ftrace, "-- %s --\n", ts(now.tv_sec)); 17720339Swollman lastlog_time = now; 17818316Swollman } 17918316Swollman} 18018316Swollman 18118316Swollman 18218316Swollmanstatic void 18346303Smarkmtmsg(const char *p, ...) 18418316Swollman{ 18518316Swollman va_list args; 18618316Swollman 18718316Swollman if (ftrace != 0) { 18818316Swollman lastlog(); 18918316Swollman va_start(args, p); 19018316Swollman vfprintf(ftrace, p, args); 19146303Smarkm (void)fputc('\n',ftrace); 19218316Swollman fflush(ftrace); 19318316Swollman } 19418316Swollman} 19518316Swollman 19618316Swollman 19746303Smarkmvoid 19846303Smarkmtrace_close(int zap_stdio) 19918316Swollman{ 20018316Swollman int fd; 20118316Swollman 20218316Swollman 20318316Swollman fflush(stdout); 20418316Swollman fflush(stderr); 20518316Swollman 20646303Smarkm if (ftrace != 0 && zap_stdio) { 20720339Swollman if (ftrace != stdout) 20820339Swollman fclose(ftrace); 20920339Swollman ftrace = 0; 21018316Swollman fd = open(_PATH_DEVNULL, O_RDWR); 21146303Smarkm if (isatty(STDIN_FILENO)) 21246303Smarkm (void)dup2(fd, STDIN_FILENO); 21346303Smarkm if (isatty(STDOUT_FILENO)) 21446303Smarkm (void)dup2(fd, STDOUT_FILENO); 21546303Smarkm if (isatty(STDERR_FILENO)) 21646303Smarkm (void)dup2(fd, STDERR_FILENO); 21718316Swollman (void)close(fd); 21818316Swollman } 21920339Swollman lastlog_time.tv_sec = 0; 22018316Swollman} 22118316Swollman 22218316Swollman 22318316Swollmanvoid 22418316Swollmantrace_flush(void) 22518316Swollman{ 22618316Swollman if (ftrace != 0) { 22718316Swollman fflush(ftrace); 22818316Swollman if (ferror(ftrace)) 22946303Smarkm trace_off("tracing off: %s", strerror(ferror(ftrace))); 23018316Swollman } 23118316Swollman} 23218316Swollman 23318316Swollman 23418316Swollmanvoid 23546303Smarkmtrace_off(const char *p, ...) 23618316Swollman{ 23718316Swollman va_list args; 23818316Swollman 23918316Swollman 24018316Swollman if (ftrace != 0) { 24118316Swollman lastlog(); 24218316Swollman va_start(args, p); 24318316Swollman vfprintf(ftrace, p, args); 24446303Smarkm (void)fputc('\n',ftrace); 24518316Swollman } 24646303Smarkm trace_close(file_trace); 24718316Swollman 24818316Swollman new_tracelevel = tracelevel = 0; 24918316Swollman} 25018316Swollman 25118316Swollman 25220339Swollman/* log a change in tracing 25320339Swollman */ 25418316Swollmanvoid 25546303Smarkmtracelevel_msg(const char *pat, 25620339Swollman int dump) /* -1=no dump, 0=default, 1=force */ 25718316Swollman{ 25846303Smarkm static const char *off_msgs[MAX_TRACELEVEL] = { 25920339Swollman "Tracing actions stopped", 26020339Swollman "Tracing packets stopped", 26120339Swollman "Tracing packet contents stopped", 26220339Swollman "Tracing kernel changes stopped", 26320339Swollman }; 26446303Smarkm static const char *on_msgs[MAX_TRACELEVEL] = { 26520339Swollman "Tracing actions started", 26620339Swollman "Tracing packets started", 26720339Swollman "Tracing packet contents started", 26820339Swollman "Tracing kernel changes started", 26920339Swollman }; 27020339Swollman u_int old_tracelevel = tracelevel; 27120339Swollman 27220339Swollman 27320339Swollman if (new_tracelevel < 0) 27420339Swollman new_tracelevel = 0; 27520339Swollman else if (new_tracelevel > MAX_TRACELEVEL) 27620339Swollman new_tracelevel = MAX_TRACELEVEL; 27720339Swollman 27820339Swollman if (new_tracelevel < tracelevel) { 27920339Swollman if (new_tracelevel <= 0) { 28020339Swollman trace_off(pat, off_msgs[0]); 28120339Swollman } else do { 28220339Swollman tmsg(pat, off_msgs[tracelevel]); 28320339Swollman } 28420339Swollman while (--tracelevel != new_tracelevel); 28520339Swollman 28620339Swollman } else if (new_tracelevel > tracelevel) { 28720339Swollman do { 28820339Swollman tmsg(pat, on_msgs[tracelevel++]); 28920339Swollman } while (tracelevel != new_tracelevel); 29020339Swollman } 29120339Swollman 29220339Swollman if (dump > 0 29320339Swollman || (dump == 0 && old_tracelevel == 0 && tracelevel != 0)) 29420339Swollman trace_dump(); 29520339Swollman} 29620339Swollman 29720339Swollman 29820339Swollmanvoid 29946303Smarkmset_tracefile(const char *filename, 30046303Smarkm const char *pat, 30120339Swollman int dump) /* -1=no dump, 0=default, 1=force */ 30220339Swollman{ 30318316Swollman struct stat stbuf; 30418316Swollman FILE *n_ftrace; 30546303Smarkm const char *fn; 30618316Swollman 30718316Swollman 30820339Swollman /* Allow a null filename to increase the level if the trace file 30920339Swollman * is already open or if coming from a trusted source, such as 31020339Swollman * a signal or the command line. 31118316Swollman */ 31220339Swollman if (filename == 0 || filename[0] == '\0') { 31320339Swollman filename = 0; 31420339Swollman if (ftrace == 0) { 31520339Swollman if (inittracename[0] == '\0') { 31620339Swollman msglog("missing trace file name"); 31720339Swollman return; 31820339Swollman } 31920339Swollman fn = inittracename; 32020339Swollman } else { 32120339Swollman fn = 0; 32218316Swollman } 32318316Swollman 32418316Swollman } else if (!strcmp(filename,"dump/../table")) { 32518316Swollman trace_dump(); 32618316Swollman return; 32718316Swollman 32818316Swollman } else { 32920339Swollman /* Allow the file specified with "-T file" to be reopened, 33020339Swollman * but require all other names specified over the net to 33120339Swollman * match the official path. The path can specify a directory 33220339Swollman * in which the file is to be created. 33320339Swollman */ 33420339Swollman if (strcmp(filename, inittracename) 33520339Swollman#ifdef _PATH_TRACE 33620339Swollman && (strncmp(filename, _PATH_TRACE, sizeof(_PATH_TRACE)-1) 33720339Swollman || strstr(filename,"../") 33820339Swollman || 0 > stat(_PATH_TRACE, &stbuf)) 33920339Swollman#endif 34020339Swollman ) { 34120339Swollman msglog("wrong trace file \"%s\"", filename); 34220339Swollman return; 34320339Swollman } 34420339Swollman 34520339Swollman /* If the new tracefile exists, it must be a regular file. 34620339Swollman */ 34746303Smarkm if (stat(filename, &stbuf) >= 0 && !S_ISREG(stbuf.st_mode)) { 34818316Swollman msglog("wrong type (%#x) of trace file \"%s\"", 34918316Swollman stbuf.st_mode, filename); 35018316Swollman return; 35118316Swollman } 35218316Swollman 35320339Swollman fn = filename; 35420339Swollman } 35520339Swollman 35620339Swollman if (fn != 0) { 35720339Swollman n_ftrace = fopen(fn, "a"); 35820339Swollman if (n_ftrace == 0) { 35920339Swollman msglog("failed to open trace file \"%s\" %s", 36020339Swollman fn, strerror(errno)); 36120339Swollman if (fn == inittracename) 36220339Swollman inittracename[0] = '\0'; 36318316Swollman return; 36418316Swollman } 36518316Swollman 36646303Smarkm tmsg("switch to trace file %s", fn); 36718316Swollman 36846303Smarkm trace_close(file_trace = 1); 36918316Swollman 37020339Swollman if (fn != savetracename) 37120339Swollman strncpy(savetracename, fn, sizeof(savetracename)-1); 37220339Swollman ftrace = n_ftrace; 37318316Swollman 37420339Swollman fflush(stdout); 37520339Swollman fflush(stderr); 37620339Swollman dup2(fileno(ftrace), STDOUT_FILENO); 37720339Swollman dup2(fileno(ftrace), STDERR_FILENO); 37820339Swollman } 37919880Swollman 38020339Swollman if (new_tracelevel == 0 || filename == 0) 38120339Swollman new_tracelevel++; 38220339Swollman tracelevel_msg(pat, dump != 0 ? dump : (filename != 0)); 38318316Swollman} 38418316Swollman 38518316Swollman 38618316Swollman/* ARGSUSED */ 38718316Swollmanvoid 38846303Smarkmsigtrace_on(int s UNUSED) 38918316Swollman{ 39018316Swollman new_tracelevel++; 39146303Smarkm sigtrace_pat = "SIGUSR1: %s"; 39218316Swollman} 39318316Swollman 39418316Swollman 39518316Swollman/* ARGSUSED */ 39618316Swollmanvoid 39746303Smarkmsigtrace_off(int s UNUSED) 39818316Swollman{ 39918316Swollman new_tracelevel--; 40046303Smarkm sigtrace_pat = "SIGUSR2: %s"; 40118316Swollman} 40218316Swollman 40318316Swollman 40420339Swollman/* Set tracing after a signal. 40518316Swollman */ 40618316Swollmanvoid 40720339Swollmanset_tracelevel(void) 40818316Swollman{ 40920339Swollman if (new_tracelevel == tracelevel) 41020339Swollman return; 41118316Swollman 41220339Swollman /* If tracing entirely off, and there was no tracefile specified 41320339Swollman * on the command line, then leave it off. 41420339Swollman */ 41520339Swollman if (new_tracelevel > tracelevel && ftrace == 0) { 41620339Swollman if (savetracename[0] != '\0') { 41720339Swollman set_tracefile(savetracename,sigtrace_pat,0); 41820339Swollman } else if (inittracename[0] != '\0') { 41920339Swollman set_tracefile(inittracename,sigtrace_pat,0); 42020339Swollman } else { 42120339Swollman new_tracelevel = 0; 42218316Swollman return; 42318316Swollman } 42420339Swollman } else { 42520339Swollman tracelevel_msg(sigtrace_pat, 0); 42618316Swollman } 42718316Swollman} 42818316Swollman 42918316Swollman 43018316Swollman/* display an address 43118316Swollman */ 43218316Swollmanchar * 43318316Swollmanaddrname(naddr addr, /* in network byte order */ 43418316Swollman naddr mask, 43518316Swollman int force) /* 0=show mask if nonstandard, */ 43618316Swollman{ /* 1=always show mask, 2=never */ 43718316Swollman#define NUM_BUFS 4 43818316Swollman static int bufno; 43918316Swollman static struct { 44018316Swollman char str[15+20]; 44118316Swollman } bufs[NUM_BUFS]; 44218316Swollman char *s, *sp; 44318316Swollman naddr dmask; 44418316Swollman int i; 44518316Swollman 44618316Swollman s = strcpy(bufs[bufno].str, naddr_ntoa(addr)); 44718316Swollman bufno = (bufno+1) % NUM_BUFS; 44818316Swollman 44918316Swollman if (force == 1 || (force == 0 && mask != std_mask(addr))) { 45018316Swollman sp = &s[strlen(s)]; 45118316Swollman 45218316Swollman dmask = mask & -mask; 45318316Swollman if (mask + dmask == 0) { 45418316Swollman for (i = 0; i != 32 && ((1<<i) & mask) == 0; i++) 45518316Swollman continue; 45618316Swollman (void)sprintf(sp, "/%d", 32-i); 45718316Swollman 45818316Swollman } else { 45918316Swollman (void)sprintf(sp, " (mask %#x)", (u_int)mask); 46018316Swollman } 46118316Swollman } 46218316Swollman 46318316Swollman return s; 46418316Swollman#undef NUM_BUFS 46518316Swollman} 46618316Swollman 46718316Swollman 46818316Swollman/* display a bit-field 46918316Swollman */ 47018316Swollmanstruct bits { 47146303Smarkm u_int bits_mask; 47246303Smarkm u_int bits_clear; 47346303Smarkm const char *bits_name; 47418316Swollman}; 47518316Swollman 47618316Swollmanstatic struct bits if_bits[] = { 47718316Swollman { IFF_LOOPBACK, 0, "LOOPBACK" }, 47818316Swollman { IFF_POINTOPOINT, 0, "PT-TO-PT" }, 47918316Swollman { 0, 0, 0} 48018316Swollman}; 48118316Swollman 48218316Swollmanstatic struct bits is_bits[] = { 48319880Swollman { IS_ALIAS, 0, "ALIAS" }, 48418316Swollman { IS_SUBNET, 0, "" }, 48519880Swollman { IS_REMOTE, (IS_NO_RDISC 48619880Swollman | IS_BCAST_RDISC), "REMOTE" }, 48718316Swollman { IS_PASSIVE, (IS_NO_RDISC 48818316Swollman | IS_NO_RIP 48918316Swollman | IS_NO_SUPER_AG 49018316Swollman | IS_PM_RDISC 49118316Swollman | IS_NO_AG), "PASSIVE" }, 49218316Swollman { IS_EXTERNAL, 0, "EXTERNAL" }, 49318316Swollman { IS_CHECKED, 0, "" }, 49418316Swollman { IS_ALL_HOSTS, 0, "" }, 49518316Swollman { IS_ALL_ROUTERS, 0, "" }, 49619880Swollman { IS_DISTRUST, 0, "DISTRUST" }, 49718316Swollman { IS_BROKE, IS_SICK, "BROKEN" }, 49818316Swollman { IS_SICK, 0, "SICK" }, 49919880Swollman { IS_DUP, 0, "DUPLICATE" }, 50020339Swollman { IS_REDIRECT_OK, 0, "REDIRECT_OK" }, 50118316Swollman { IS_NEED_NET_SYN, 0, "" }, 50218316Swollman { IS_NO_AG, IS_NO_SUPER_AG, "NO_AG" }, 50318316Swollman { IS_NO_SUPER_AG, 0, "NO_SUPER_AG" }, 50418316Swollman { (IS_NO_RIPV1_IN 50518316Swollman | IS_NO_RIPV2_IN 50618316Swollman | IS_NO_RIPV1_OUT 50718316Swollman | IS_NO_RIPV2_OUT), 0, "NO_RIP" }, 50818316Swollman { (IS_NO_RIPV1_IN 50918316Swollman | IS_NO_RIPV1_OUT), 0, "RIPV2" }, 51018316Swollman { IS_NO_RIPV1_IN, 0, "NO_RIPV1_IN" }, 51118316Swollman { IS_NO_RIPV2_IN, 0, "NO_RIPV2_IN" }, 51218316Swollman { IS_NO_RIPV1_OUT, 0, "NO_RIPV1_OUT" }, 51318316Swollman { IS_NO_RIPV2_OUT, 0, "NO_RIPV2_OUT" }, 51418316Swollman { (IS_NO_ADV_IN 51518316Swollman | IS_NO_SOL_OUT 51618316Swollman | IS_NO_ADV_OUT), IS_BCAST_RDISC, "NO_RDISC" }, 51718316Swollman { IS_NO_SOL_OUT, 0, "NO_SOLICIT" }, 51818316Swollman { IS_SOL_OUT, 0, "SEND_SOLICIT" }, 51918316Swollman { IS_NO_ADV_OUT, IS_BCAST_RDISC, "NO_RDISC_ADV" }, 52018316Swollman { IS_ADV_OUT, 0, "RDISC_ADV" }, 52118316Swollman { IS_BCAST_RDISC, 0, "BCAST_RDISC" }, 52219880Swollman { IS_PM_RDISC, 0, "" }, 52318316Swollman { 0, 0, "%#x"} 52418316Swollman}; 52518316Swollman 52618316Swollmanstatic struct bits rs_bits[] = { 52718316Swollman { RS_IF, 0, "IF" }, 52818316Swollman { RS_NET_INT, RS_NET_SYN, "NET_INT" }, 52918316Swollman { RS_NET_SYN, 0, "NET_SYN" }, 53018316Swollman { RS_SUBNET, 0, "" }, 53118316Swollman { RS_LOCAL, 0, "LOCAL" }, 53218316Swollman { RS_MHOME, 0, "MHOME" }, 53318316Swollman { RS_STATIC, 0, "STATIC" }, 53418316Swollman { RS_RDISC, 0, "RDISC" }, 53518316Swollman { 0, 0, "%#x"} 53618316Swollman}; 53718316Swollman 53818316Swollman 53918316Swollmanstatic void 54046303Smarkmtrace_bits(const struct bits *tbl, 54118316Swollman u_int field, 54218316Swollman int force) 54318316Swollman{ 54446303Smarkm u_int b; 54518316Swollman char c; 54618316Swollman 54718316Swollman if (force) { 54818316Swollman (void)putc('<', ftrace); 54918316Swollman c = 0; 55018316Swollman } else { 55118316Swollman c = '<'; 55218316Swollman } 55318316Swollman 55418316Swollman while (field != 0 55518316Swollman && (b = tbl->bits_mask) != 0) { 55618316Swollman if ((b & field) == b) { 55718316Swollman if (tbl->bits_name[0] != '\0') { 55818316Swollman if (c) 55918316Swollman (void)putc(c, ftrace); 56018316Swollman (void)fprintf(ftrace, "%s", tbl->bits_name); 56118316Swollman c = '|'; 56218316Swollman } 56318316Swollman if (0 == (field &= ~(b | tbl->bits_clear))) 56418316Swollman break; 56518316Swollman } 56618316Swollman tbl++; 56718316Swollman } 56818316Swollman if (field != 0 && tbl->bits_name != 0) { 56918316Swollman if (c) 57018316Swollman (void)putc(c, ftrace); 57118316Swollman (void)fprintf(ftrace, tbl->bits_name, field); 57218316Swollman c = '|'; 57318316Swollman } 57418316Swollman 57518316Swollman if (c != '<' || force) 57618316Swollman (void)fputs("> ", ftrace); 57718316Swollman} 57818316Swollman 57918316Swollman 58046303Smarkmchar * 58146303Smarkmrtname(naddr dst, 58246303Smarkm naddr mask, 58346303Smarkm naddr gate) 58418316Swollman{ 58518316Swollman static char buf[3*4+3+1+2+3 /* "xxx.xxx.xxx.xxx/xx-->" */ 58618316Swollman +3*4+3+1]; /* "xxx.xxx.xxx.xxx" */ 58718316Swollman int i; 58818316Swollman 58918316Swollman i = sprintf(buf, "%-16s-->", addrname(dst, mask, 0)); 59046303Smarkm (void)sprintf(&buf[i], "%-*s", 15+20-MAX(20,i), naddr_ntoa(gate)); 59118316Swollman return buf; 59218316Swollman} 59318316Swollman 59418316Swollman 59520339Swollmanstatic void 59620339Swollmanprint_rts(struct rt_spare *rts, 59720339Swollman int force_metric, /* -1=suppress, 0=default */ 59820339Swollman int force_ifp, /* -1=suppress, 0=default */ 59920339Swollman int force_router, /* -1=suppress, 0=default, 1=display */ 60020339Swollman int force_tag, /* -1=suppress, 0=default, 1=display */ 60120339Swollman int force_time) /* 0=suppress, 1=display */ 60220339Swollman{ 60346303Smarkm int i; 60446303Smarkm 60546303Smarkm 60620339Swollman if (force_metric >= 0) 60720339Swollman (void)fprintf(ftrace, "metric=%-2d ", rts->rts_metric); 60820339Swollman if (force_ifp >= 0) 60920339Swollman (void)fprintf(ftrace, "%s ", (rts->rts_ifp == 0 ? 61020339Swollman "if?" : rts->rts_ifp->int_name)); 61120339Swollman if (force_router > 0 61220339Swollman || (force_router == 0 && rts->rts_router != rts->rts_gate)) 61320339Swollman (void)fprintf(ftrace, "router=%s ", 61420339Swollman naddr_ntoa(rts->rts_router)); 61520339Swollman if (force_time > 0) 61620339Swollman (void)fprintf(ftrace, "%s ", ts(rts->rts_time)); 61720339Swollman if (force_tag > 0 61820339Swollman || (force_tag == 0 && rts->rts_tag != 0)) 61946303Smarkm (void)fprintf(ftrace, "tag=%#x ", ntohs(rts->rts_tag)); 62046303Smarkm if (rts->rts_de_ag != 0) { 62146303Smarkm for (i = 1; (u_int)(1 << i) <= rts->rts_de_ag; i++) 62246303Smarkm continue; 62346303Smarkm (void)fprintf(ftrace, "de_ag=%d ", i); 62446303Smarkm } 62546303Smarkm 62620339Swollman} 62720339Swollman 62820339Swollman 62918316Swollmanvoid 63046303Smarkmtrace_if(const char *act, 63146303Smarkm struct interface *ifp) 63218316Swollman{ 63318316Swollman if (!TRACEACTIONS || ftrace == 0) 63418316Swollman return; 63518316Swollman 63618316Swollman lastlog(); 63719880Swollman (void)fprintf(ftrace, "%-3s interface %-4s ", act, ifp->int_name); 63818316Swollman (void)fprintf(ftrace, "%-15s-->%-15s ", 63918316Swollman naddr_ntoa(ifp->int_addr), 64019880Swollman addrname(((ifp->int_if_flags & IFF_POINTOPOINT) 64119880Swollman ? ifp->int_dstaddr 64219880Swollman : htonl(ifp->int_net)), 64318316Swollman ifp->int_mask, 1)); 64418316Swollman if (ifp->int_metric != 0) 64518316Swollman (void)fprintf(ftrace, "metric=%d ", ifp->int_metric); 64619880Swollman if (!IS_RIP_OUT_OFF(ifp->int_state) 64719880Swollman && ifp->int_d_metric != 0) 64819880Swollman (void)fprintf(ftrace, "fake_default=%d ", ifp->int_d_metric); 64918316Swollman trace_bits(if_bits, ifp->int_if_flags, 0); 65018316Swollman trace_bits(is_bits, ifp->int_state, 0); 65118316Swollman (void)fputc('\n',ftrace); 65218316Swollman} 65318316Swollman 65418316Swollman 65518316Swollmanvoid 65618316Swollmantrace_upslot(struct rt_entry *rt, 65718316Swollman struct rt_spare *rts, 65846303Smarkm struct rt_spare *new) 65918316Swollman{ 66018316Swollman if (!TRACEACTIONS || ftrace == 0) 66118316Swollman return; 66220339Swollman 66346303Smarkm if (rts->rts_gate == new->rts_gate 66446303Smarkm && rts->rts_router == new->rts_router 66546303Smarkm && rts->rts_metric == new->rts_metric 66646303Smarkm && rts->rts_tag == new->rts_tag 66746303Smarkm && rts->rts_de_ag == new->rts_de_ag) 66818316Swollman return; 66918316Swollman 67018316Swollman lastlog(); 67146303Smarkm if (new->rts_gate == 0) { 67246303Smarkm (void)fprintf(ftrace, "Del #%d %-35s ", 67346303Smarkm (int)(rts - rt->rt_spares), 67446303Smarkm rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate)); 67546303Smarkm print_rts(rts, 0,0,0,0, 67646303Smarkm (rts != rt->rt_spares 67746303Smarkm || AGE_RT(rt->rt_state,new->rts_ifp))); 67846303Smarkm 67946303Smarkm } else if (rts->rts_gate != RIP_DEFAULT) { 68018316Swollman (void)fprintf(ftrace, "Chg #%d %-35s ", 68146303Smarkm (int)(rts - rt->rt_spares), 68246303Smarkm rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate)); 68320339Swollman print_rts(rts, 0,0, 68446303Smarkm rts->rts_gate != new->rts_gate, 68546303Smarkm rts->rts_tag != new->rts_tag, 68620339Swollman rts != rt->rt_spares || AGE_RT(rt->rt_state, 68720339Swollman rt->rt_ifp)); 68818316Swollman 68920339Swollman (void)fprintf(ftrace, "\n %19s%-16s ", "", 69046303Smarkm (new->rts_gate != rts->rts_gate 69146303Smarkm ? naddr_ntoa(new->rts_gate) : "")); 69246303Smarkm print_rts(new, 69346303Smarkm -(new->rts_metric == rts->rts_metric), 69446303Smarkm -(new->rts_ifp == rts->rts_ifp), 69520339Swollman 0, 69646303Smarkm rts->rts_tag != new->rts_tag, 69746303Smarkm (new->rts_time != rts->rts_time 69846303Smarkm && (rts != rt->rt_spares 69946303Smarkm || AGE_RT(rt->rt_state, new->rts_ifp)))); 70018316Swollman 70118316Swollman } else { 70218316Swollman (void)fprintf(ftrace, "Add #%d %-35s ", 70346303Smarkm (int)(rts - rt->rt_spares), 70446303Smarkm rtname(rt->rt_dst, rt->rt_mask, new->rts_gate)); 70546303Smarkm print_rts(new, 0,0,0,0, 70646303Smarkm (rts != rt->rt_spares 70746303Smarkm || AGE_RT(rt->rt_state,new->rts_ifp))); 70818316Swollman } 70920339Swollman (void)fputc('\n',ftrace); 71018316Swollman} 71118316Swollman 71218316Swollman 71346303Smarkm/* miscellaneous message checked by the caller 71418316Swollman */ 71518316Swollmanvoid 71646303Smarkmtrace_misc(const char *p, ...) 71718316Swollman{ 71818316Swollman va_list args; 71918316Swollman 72046303Smarkm if (ftrace == 0) 72118316Swollman return; 72218316Swollman 72318316Swollman lastlog(); 72418316Swollman va_start(args, p); 72518316Swollman vfprintf(ftrace, p, args); 72646303Smarkm (void)fputc('\n',ftrace); 72718316Swollman} 72818316Swollman 72918316Swollman 73018316Swollman/* display a message if tracing actions 73118316Swollman */ 73218316Swollmanvoid 73346303Smarkmtrace_act(const char *p, ...) 73418316Swollman{ 73518316Swollman va_list args; 73618316Swollman 73718316Swollman if (!TRACEACTIONS || ftrace == 0) 73818316Swollman return; 73918316Swollman 74018316Swollman lastlog(); 74118316Swollman va_start(args, p); 74218316Swollman vfprintf(ftrace, p, args); 74319880Swollman (void)fputc('\n',ftrace); 74418316Swollman} 74518316Swollman 74618316Swollman 74718316Swollman/* display a message if tracing packets 74818316Swollman */ 74918316Swollmanvoid 75046303Smarkmtrace_pkt(const char *p, ...) 75118316Swollman{ 75218316Swollman va_list args; 75318316Swollman 75418316Swollman if (!TRACEPACKETS || ftrace == 0) 75518316Swollman return; 75618316Swollman 75718316Swollman lastlog(); 75818316Swollman va_start(args, p); 75918316Swollman vfprintf(ftrace, p, args); 76019880Swollman (void)fputc('\n',ftrace); 76118316Swollman} 76218316Swollman 76318316Swollman 76418316Swollmanvoid 76518316Swollmantrace_change(struct rt_entry *rt, 76618316Swollman u_int state, 76746303Smarkm struct rt_spare *new, 76846303Smarkm const char *label) 76918316Swollman{ 77018316Swollman if (ftrace == 0) 77118316Swollman return; 77218316Swollman 77346303Smarkm if (rt->rt_metric == new->rts_metric 77446303Smarkm && rt->rt_gate == new->rts_gate 77546303Smarkm && rt->rt_router == new->rts_router 77618316Swollman && rt->rt_state == state 77746303Smarkm && rt->rt_tag == new->rts_tag 77846303Smarkm && rt->rt_de_ag == new->rts_de_ag) 77918316Swollman return; 78018316Swollman 78118316Swollman lastlog(); 78220339Swollman (void)fprintf(ftrace, "%s %-35s ", 78318316Swollman label, 78446303Smarkm rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate)); 78520339Swollman print_rts(rt->rt_spares, 78620339Swollman 0,0,0,0, AGE_RT(rt->rt_state, rt->rt_ifp)); 78718316Swollman trace_bits(rs_bits, rt->rt_state, rt->rt_state != state); 78818316Swollman 78920339Swollman (void)fprintf(ftrace, "\n%*s %19s%-16s ", 79046303Smarkm (int)strlen(label), "", "", 79146303Smarkm (rt->rt_gate != new->rts_gate 79246303Smarkm ? naddr_ntoa(new->rts_gate) : "")); 79346303Smarkm print_rts(new, 79446303Smarkm -(new->rts_metric == rt->rt_metric), 79546303Smarkm -(new->rts_ifp == rt->rt_ifp), 79620339Swollman 0, 79746303Smarkm rt->rt_tag != new->rts_tag, 79846303Smarkm (rt->rt_time != new->rts_time 79946303Smarkm && AGE_RT(rt->rt_state,new->rts_ifp))); 80018316Swollman if (rt->rt_state != state) 80118316Swollman trace_bits(rs_bits, state, 1); 80220339Swollman (void)fputc('\n',ftrace); 80318316Swollman} 80418316Swollman 80518316Swollman 80618316Swollmanvoid 80746303Smarkmtrace_add_del(const char * action, struct rt_entry *rt) 80818316Swollman{ 80918316Swollman if (ftrace == 0) 81018316Swollman return; 81118316Swollman 81218316Swollman lastlog(); 81320339Swollman (void)fprintf(ftrace, "%s %-35s ", 81418316Swollman action, 81546303Smarkm rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate)); 81620339Swollman print_rts(rt->rt_spares, 0,0,0,0,AGE_RT(rt->rt_state,rt->rt_ifp)); 81720339Swollman trace_bits(rs_bits, rt->rt_state, 0); 81820339Swollman (void)fputc('\n',ftrace); 81918316Swollman} 82018316Swollman 82118316Swollman 82218316Swollman/* ARGSUSED */ 82318316Swollmanstatic int 82418316Swollmanwalk_trace(struct radix_node *rn, 82546303Smarkm struct walkarg *w UNUSED) 82618316Swollman{ 82718316Swollman#define RT ((struct rt_entry *)rn) 82818316Swollman struct rt_spare *rts; 82946303Smarkm int i; 83018316Swollman 83146303Smarkm (void)fprintf(ftrace, " %-35s ", 83246303Smarkm rtname(RT->rt_dst, RT->rt_mask, RT->rt_gate)); 83346303Smarkm print_rts(&RT->rt_spares[0], 0,0,0,0, AGE_RT(RT->rt_state, RT->rt_ifp)); 83418316Swollman trace_bits(rs_bits, RT->rt_state, 0); 83520339Swollman if (RT->rt_poison_time >= now_garbage 83620339Swollman && RT->rt_poison_metric < RT->rt_metric) 83720339Swollman (void)fprintf(ftrace, "pm=%d@%s", 83846303Smarkm RT->rt_poison_metric, ts(RT->rt_poison_time)); 83918316Swollman 84018316Swollman rts = &RT->rt_spares[1]; 84118316Swollman for (i = 1; i < NUM_SPARES; i++, rts++) { 84220339Swollman if (rts->rts_gate != RIP_DEFAULT) { 84320339Swollman (void)fprintf(ftrace,"\n #%d%15s%-16s ", 84420339Swollman i, "", naddr_ntoa(rts->rts_gate)); 84520339Swollman print_rts(rts, 0,0,0,0,1); 84618316Swollman } 84718316Swollman } 84818316Swollman (void)fputc('\n',ftrace); 84918316Swollman 85018316Swollman return 0; 85118316Swollman} 85218316Swollman 85318316Swollman 85418316Swollmanstatic void 85518316Swollmantrace_dump(void) 85618316Swollman{ 85719880Swollman struct interface *ifp; 85819880Swollman 85918316Swollman if (ftrace == 0) 86018316Swollman return; 86118316Swollman lastlog(); 86218316Swollman 86320339Swollman (void)fputs("current daemon state:\n", ftrace); 86419880Swollman for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) 86519880Swollman trace_if("", ifp); 86618316Swollman (void)rn_walktree(rhead, walk_trace, 0); 86718316Swollman} 86818316Swollman 86918316Swollman 87018316Swollmanvoid 87146303Smarkmtrace_rip(const char *dir1, const char *dir2, 87218316Swollman struct sockaddr_in *who, 87318316Swollman struct interface *ifp, 87418316Swollman struct rip *msg, 87518316Swollman int size) /* total size of message */ 87618316Swollman{ 87718316Swollman struct netinfo *n, *lim; 87846303Smarkm# define NA ((struct netauth*)n) 87919880Swollman int i, seen_route; 88018316Swollman 88118316Swollman if (!TRACEPACKETS || ftrace == 0) 88218316Swollman return; 88318316Swollman 88418316Swollman lastlog(); 88518316Swollman if (msg->rip_cmd >= RIPCMD_MAX 88618316Swollman || msg->rip_vers == 0) { 88718316Swollman (void)fprintf(ftrace, "%s bad RIPv%d cmd=%d %s" 88818316Swollman " %s.%d size=%d\n", 88918316Swollman dir1, msg->rip_vers, msg->rip_cmd, dir2, 89018316Swollman naddr_ntoa(who->sin_addr.s_addr), 89118316Swollman ntohs(who->sin_port), 89218316Swollman size); 89318316Swollman return; 89418316Swollman } 89518316Swollman 89618316Swollman (void)fprintf(ftrace, "%s RIPv%d %s %s %s.%d%s%s\n", 89718316Swollman dir1, msg->rip_vers, ripcmds[msg->rip_cmd], dir2, 89818316Swollman naddr_ntoa(who->sin_addr.s_addr), ntohs(who->sin_port), 89918316Swollman ifp ? " via " : "", ifp ? ifp->int_name : ""); 90018316Swollman if (!TRACECONTENTS) 90118316Swollman return; 90218316Swollman 90319880Swollman seen_route = 0; 90418316Swollman switch (msg->rip_cmd) { 90518316Swollman case RIPCMD_REQUEST: 90618316Swollman case RIPCMD_RESPONSE: 90718316Swollman n = msg->rip_nets; 90818316Swollman lim = (struct netinfo *)((char*)msg + size); 90918316Swollman for (; n < lim; n++) { 91019880Swollman if (!seen_route 91119880Swollman && n->n_family == RIP_AF_UNSPEC 91218316Swollman && ntohl(n->n_metric) == HOPCNT_INFINITY 91319880Swollman && msg->rip_cmd == RIPCMD_REQUEST 91419880Swollman && (n+1 == lim 91519880Swollman || (n+2 == lim 91619880Swollman && (n+1)->n_family == RIP_AF_AUTH))) { 91718316Swollman (void)fputs("\tQUERY ", ftrace); 91818316Swollman if (n->n_dst != 0) 91918316Swollman (void)fprintf(ftrace, "%s ", 92018316Swollman naddr_ntoa(n->n_dst)); 92118316Swollman if (n->n_mask != 0) 92218316Swollman (void)fprintf(ftrace, "mask=%#x ", 92318316Swollman (u_int)ntohl(n->n_mask)); 92418316Swollman if (n->n_nhop != 0) 92519880Swollman (void)fprintf(ftrace, "nhop=%s ", 92618316Swollman naddr_ntoa(n->n_nhop)); 92718316Swollman if (n->n_tag != 0) 92819880Swollman (void)fprintf(ftrace, "tag=%#x ", 92918316Swollman ntohs(n->n_tag)); 93018316Swollman (void)fputc('\n',ftrace); 93118316Swollman continue; 93218316Swollman } 93318316Swollman 93418316Swollman if (n->n_family == RIP_AF_AUTH) { 93519880Swollman if (NA->a_type == RIP_AUTH_PW 93619880Swollman && n == msg->rip_nets) { 93719880Swollman (void)fprintf(ftrace, "\tPassword" 93819880Swollman " Authentication:" 93919880Swollman " \"%s\"\n", 94019880Swollman qstring(NA->au.au_pw, 94119880Swollman RIP_AUTH_PW_LEN)); 94219880Swollman continue; 94319880Swollman } 94419880Swollman 94519880Swollman if (NA->a_type == RIP_AUTH_MD5 94619880Swollman && n == msg->rip_nets) { 94719880Swollman (void)fprintf(ftrace, 94846303Smarkm "\tMD5 Auth" 94946303Smarkm " pkt_len=%d KeyID=%u" 95046303Smarkm " auth_len=%d" 95146303Smarkm " seqno=%#x" 95219880Swollman " rsvd=%#x,%#x\n", 95346303Smarkm ntohs(NA->au.a_md5.md5_pkt_len), 95446303Smarkm NA->au.a_md5.md5_keyid, 95546303Smarkm NA->au.a_md5.md5_auth_len, 95646303Smarkm (int)ntohl(NA->au.a_md5.md5_seqno), 95746303Smarkm (int)ntohs(NA->au.a_md5.rsvd[0]), 95846303Smarkm (int)ntohs(NA->au.a_md5.rsvd[1])); 95919880Swollman continue; 96019880Swollman } 96118316Swollman (void)fprintf(ftrace, 96246303Smarkm "\tAuthentication type %d: ", 96319880Swollman ntohs(NA->a_type)); 96418316Swollman for (i = 0; 96546303Smarkm i < (int)sizeof(NA->au.au_pw); 96618316Swollman i++) 96718316Swollman (void)fprintf(ftrace, "%02x ", 96819880Swollman NA->au.au_pw[i]); 96918316Swollman (void)fputc('\n',ftrace); 97018316Swollman continue; 97118316Swollman } 97218316Swollman 97319880Swollman seen_route = 1; 97418316Swollman if (n->n_family != RIP_AF_INET) { 97518316Swollman (void)fprintf(ftrace, 97619880Swollman "\t(af %d) %-18s mask=%#x ", 97718316Swollman ntohs(n->n_family), 97818316Swollman naddr_ntoa(n->n_dst), 97918316Swollman (u_int)ntohl(n->n_mask)); 98018316Swollman } else if (msg->rip_vers == RIPv1) { 98118316Swollman (void)fprintf(ftrace, "\t%-18s ", 98218316Swollman addrname(n->n_dst, 98318316Swollman ntohl(n->n_mask), 98418316Swollman n->n_mask==0 ? 2 : 1)); 98518316Swollman } else { 98618316Swollman (void)fprintf(ftrace, "\t%-18s ", 98718316Swollman addrname(n->n_dst, 98818316Swollman ntohl(n->n_mask), 98918316Swollman n->n_mask==0 ? 2 : 0)); 99018316Swollman } 99118316Swollman (void)fprintf(ftrace, "metric=%-2d ", 99218316Swollman (u_int)ntohl(n->n_metric)); 99318316Swollman if (n->n_nhop != 0) 99418316Swollman (void)fprintf(ftrace, " nhop=%s ", 99518316Swollman naddr_ntoa(n->n_nhop)); 99618316Swollman if (n->n_tag != 0) 99718316Swollman (void)fprintf(ftrace, "tag=%#x", 99818316Swollman ntohs(n->n_tag)); 99918316Swollman (void)fputc('\n',ftrace); 100018316Swollman } 100118316Swollman if (size != (char *)n - (char *)msg) 100218316Swollman (void)fprintf(ftrace, "truncated record, len %d\n", 100318316Swollman size); 100418316Swollman break; 100518316Swollman 100618316Swollman case RIPCMD_TRACEON: 100720339Swollman fprintf(ftrace, "\tfile=\"%.*s\"\n", size-4, 100820339Swollman msg->rip_tracefile); 100918316Swollman break; 101018316Swollman 101118316Swollman case RIPCMD_TRACEOFF: 101218316Swollman break; 101318316Swollman } 101418316Swollman} 1015