trace.c revision 190715
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 * 4. Neither the name of the University nor the names of its contributors 1418316Swollman * may be used to endorse or promote products derived from this software 1518316Swollman * without specific prior written permission. 1618316Swollman * 1718316Swollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1818316Swollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1918316Swollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2018316Swollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2118316Swollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2218316Swollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2318316Swollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2418316Swollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2518316Swollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2618316Swollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2718316Swollman * SUCH DAMAGE. 2846303Smarkm * 2950476Speter * $FreeBSD: head/sbin/routed/trace.c 190715 2009-04-05 15:55:09Z phk $ 3018316Swollman */ 3118316Swollman 3218316Swollman#define RIPCMDS 3318316Swollman#include "defs.h" 3418316Swollman#include "pathnames.h" 3518316Swollman#include <sys/stat.h> 3646303Smarkm#include <sys/signal.h> 3718316Swollman#include <fcntl.h> 3818316Swollman 39126250Sbms#ifdef __NetBSD__ 4046303Smarkm__RCSID("$NetBSD$"); 41126250Sbms#elif defined(__FreeBSD__) 42126250Sbms__RCSID("$FreeBSD: head/sbin/routed/trace.c 190715 2009-04-05 15:55:09Z phk $"); 43126250Sbms#else 44126250Sbms__RCSID("$Revision: 2.27 $"); 45126250Sbms#ident "$Revision: 2.27 $" 4646303Smarkm#endif 4746303Smarkm 4846303Smarkm 4918316Swollman#ifdef sgi 50102231Strhodes/* use *stat64 for files on large file systems */ 5118316Swollman#define stat stat64 5218316Swollman#endif 5318316Swollman 5418316Swollman#define NRECORDS 50 /* size of circular trace buffer */ 5518316Swollman 5620339Swollmanint tracelevel, new_tracelevel; 5781604SpeterFILE *ftrace; /* output trace file */ 5846303Smarkmstatic const char *sigtrace_pat = "%s"; 59118582Simpstatic char savetracename[PATH_MAX]; 60118582Simpchar inittracename[PATH_MAX]; 61190715Sphkstatic int file_trace; /* 1=tracing to file, not stdout */ 6218316Swollman 6318316Swollmanstatic void trace_dump(void); 6446303Smarkmstatic void tmsg(const char *, ...) PATTRIB(1,2); 6518316Swollman 6618316Swollman 6719880Swollman/* convert string to printable characters 6819880Swollman */ 6919880Swollmanstatic char * 7019880Swollmanqstring(u_char *s, int len) 7119880Swollman{ 7219880Swollman static char buf[8*20+1]; 7319880Swollman char *p; 7419880Swollman u_char *s2, c; 7519880Swollman 7619880Swollman 7719880Swollman for (p = buf; len != 0 && p < &buf[sizeof(buf)-1]; len--) { 7819880Swollman c = *s++; 7919880Swollman if (c == '\0') { 8019880Swollman for (s2 = s+1; s2 < &s[len]; s2++) { 8119880Swollman if (*s2 != '\0') 8219880Swollman break; 8319880Swollman } 8419880Swollman if (s2 >= &s[len]) 8519880Swollman goto exit; 8619880Swollman } 8719880Swollman 8819880Swollman if (c >= ' ' && c < 0x7f && c != '\\') { 8919880Swollman *p++ = c; 9019880Swollman continue; 9119880Swollman } 9219880Swollman *p++ = '\\'; 9319880Swollman switch (c) { 9419880Swollman case '\\': 9519880Swollman *p++ = '\\'; 9619880Swollman break; 9719880Swollman case '\n': 9819880Swollman *p++= 'n'; 9919880Swollman break; 10019880Swollman case '\r': 10119880Swollman *p++= 'r'; 10219880Swollman break; 10319880Swollman case '\t': 10419880Swollman *p++ = 't'; 10519880Swollman break; 10619880Swollman case '\b': 10719880Swollman *p++ = 'b'; 10819880Swollman break; 10919880Swollman default: 11019880Swollman p += sprintf(p,"%o",c); 11119880Swollman break; 11219880Swollman } 11319880Swollman } 11419880Swollmanexit: 11519880Swollman *p = '\0'; 11619880Swollman return buf; 11719880Swollman} 11819880Swollman 11919880Swollman 12018316Swollman/* convert IP address to a string, but not into a single buffer 12118316Swollman */ 12218316Swollmanchar * 12318316Swollmannaddr_ntoa(naddr a) 12418316Swollman{ 12518316Swollman#define NUM_BUFS 4 12618316Swollman static int bufno; 12718316Swollman static struct { 12818316Swollman char str[16]; /* xxx.xxx.xxx.xxx\0 */ 12918316Swollman } bufs[NUM_BUFS]; 13018316Swollman char *s; 13118316Swollman struct in_addr addr; 13218316Swollman 13318316Swollman addr.s_addr = a; 13418316Swollman s = strcpy(bufs[bufno].str, inet_ntoa(addr)); 13518316Swollman bufno = (bufno+1) % NUM_BUFS; 13618316Swollman return s; 13718316Swollman#undef NUM_BUFS 13818316Swollman} 13918316Swollman 14018316Swollman 14146303Smarkmconst char * 14218316Swollmansaddr_ntoa(struct sockaddr *sa) 14318316Swollman{ 14418316Swollman return (sa == 0) ? "?" : naddr_ntoa(S_ADDR(sa)); 14518316Swollman} 14618316Swollman 14718316Swollman 14818316Swollmanstatic char * 14918316Swollmants(time_t secs) { 15018316Swollman static char s[20]; 15118316Swollman 15218316Swollman secs += epoch.tv_sec; 15318316Swollman#ifdef sgi 15418316Swollman (void)cftime(s, "%T", &secs); 15518316Swollman#else 15646303Smarkm memcpy(s, ctime(&secs)+11, 8); 15718316Swollman s[8] = '\0'; 15818316Swollman#endif 15918316Swollman return s; 16018316Swollman} 16118316Swollman 16218316Swollman 16318316Swollman/* On each event, display a time stamp. 16418316Swollman * This assumes that 'now' is update once for each event, and 16518316Swollman * that at least now.tv_usec changes. 16618316Swollman */ 16720339Swollmanstatic struct timeval lastlog_time; 16820339Swollman 16918316Swollmanvoid 17018316Swollmanlastlog(void) 17118316Swollman{ 17220339Swollman if (lastlog_time.tv_sec != now.tv_sec 17320339Swollman || lastlog_time.tv_usec != now.tv_usec) { 17418316Swollman (void)fprintf(ftrace, "-- %s --\n", ts(now.tv_sec)); 17520339Swollman lastlog_time = now; 17618316Swollman } 17718316Swollman} 17818316Swollman 17918316Swollman 18018316Swollmanstatic void 18146303Smarkmtmsg(const char *p, ...) 18218316Swollman{ 18318316Swollman va_list args; 18418316Swollman 18518316Swollman if (ftrace != 0) { 18618316Swollman lastlog(); 18718316Swollman va_start(args, p); 18818316Swollman vfprintf(ftrace, p, args); 189126250Sbms va_end(args); 19046303Smarkm (void)fputc('\n',ftrace); 19118316Swollman fflush(ftrace); 19218316Swollman } 19318316Swollman} 19418316Swollman 19518316Swollman 19646303Smarkmvoid 19746303Smarkmtrace_close(int zap_stdio) 19818316Swollman{ 19918316Swollman int fd; 20018316Swollman 20118316Swollman 20218316Swollman fflush(stdout); 20318316Swollman fflush(stderr); 20418316Swollman 20546303Smarkm if (ftrace != 0 && zap_stdio) { 20620339Swollman if (ftrace != stdout) 20720339Swollman fclose(ftrace); 20820339Swollman ftrace = 0; 20918316Swollman fd = open(_PATH_DEVNULL, O_RDWR); 21046303Smarkm if (isatty(STDIN_FILENO)) 21146303Smarkm (void)dup2(fd, STDIN_FILENO); 21246303Smarkm if (isatty(STDOUT_FILENO)) 21346303Smarkm (void)dup2(fd, STDOUT_FILENO); 21446303Smarkm if (isatty(STDERR_FILENO)) 21546303Smarkm (void)dup2(fd, STDERR_FILENO); 21618316Swollman (void)close(fd); 21718316Swollman } 21820339Swollman lastlog_time.tv_sec = 0; 21918316Swollman} 22018316Swollman 22118316Swollman 22218316Swollmanvoid 22318316Swollmantrace_flush(void) 22418316Swollman{ 22518316Swollman if (ftrace != 0) { 22618316Swollman fflush(ftrace); 22718316Swollman if (ferror(ftrace)) 22846303Smarkm trace_off("tracing off: %s", strerror(ferror(ftrace))); 22918316Swollman } 23018316Swollman} 23118316Swollman 23218316Swollman 23318316Swollmanvoid 23446303Smarkmtrace_off(const char *p, ...) 23518316Swollman{ 23618316Swollman va_list args; 23718316Swollman 23818316Swollman 23918316Swollman if (ftrace != 0) { 24018316Swollman lastlog(); 24118316Swollman va_start(args, p); 24218316Swollman vfprintf(ftrace, p, args); 243126250Sbms va_end(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); 646126250Sbms if (ifp->int_adj_inmetric != 0) 647126250Sbms (void)fprintf(ftrace, "adj_inmetric=%u ", 648126250Sbms ifp->int_adj_inmetric); 649126250Sbms if (ifp->int_adj_outmetric != 0) 650126250Sbms (void)fprintf(ftrace, "adj_outmetric=%u ", 651126250Sbms ifp->int_adj_outmetric); 65219880Swollman if (!IS_RIP_OUT_OFF(ifp->int_state) 65319880Swollman && ifp->int_d_metric != 0) 654126250Sbms (void)fprintf(ftrace, "fake_default=%u ", ifp->int_d_metric); 65518316Swollman trace_bits(if_bits, ifp->int_if_flags, 0); 65618316Swollman trace_bits(is_bits, ifp->int_state, 0); 65718316Swollman (void)fputc('\n',ftrace); 65818316Swollman} 65918316Swollman 66018316Swollman 66118316Swollmanvoid 66218316Swollmantrace_upslot(struct rt_entry *rt, 66318316Swollman struct rt_spare *rts, 66446303Smarkm struct rt_spare *new) 66518316Swollman{ 66618316Swollman if (!TRACEACTIONS || ftrace == 0) 66718316Swollman return; 66820339Swollman 66946303Smarkm if (rts->rts_gate == new->rts_gate 67046303Smarkm && rts->rts_router == new->rts_router 67146303Smarkm && rts->rts_metric == new->rts_metric 67246303Smarkm && rts->rts_tag == new->rts_tag 67346303Smarkm && rts->rts_de_ag == new->rts_de_ag) 67418316Swollman return; 67518316Swollman 67618316Swollman lastlog(); 67746303Smarkm if (new->rts_gate == 0) { 67846303Smarkm (void)fprintf(ftrace, "Del #%d %-35s ", 67946303Smarkm (int)(rts - rt->rt_spares), 68046303Smarkm rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate)); 68146303Smarkm print_rts(rts, 0,0,0,0, 68246303Smarkm (rts != rt->rt_spares 68346303Smarkm || AGE_RT(rt->rt_state,new->rts_ifp))); 68446303Smarkm 68546303Smarkm } else if (rts->rts_gate != RIP_DEFAULT) { 68618316Swollman (void)fprintf(ftrace, "Chg #%d %-35s ", 68746303Smarkm (int)(rts - rt->rt_spares), 68846303Smarkm rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate)); 68920339Swollman print_rts(rts, 0,0, 69046303Smarkm rts->rts_gate != new->rts_gate, 69146303Smarkm rts->rts_tag != new->rts_tag, 69220339Swollman rts != rt->rt_spares || AGE_RT(rt->rt_state, 69320339Swollman rt->rt_ifp)); 69418316Swollman 69520339Swollman (void)fprintf(ftrace, "\n %19s%-16s ", "", 69646303Smarkm (new->rts_gate != rts->rts_gate 69746303Smarkm ? naddr_ntoa(new->rts_gate) : "")); 69846303Smarkm print_rts(new, 69946303Smarkm -(new->rts_metric == rts->rts_metric), 70046303Smarkm -(new->rts_ifp == rts->rts_ifp), 70120339Swollman 0, 70246303Smarkm rts->rts_tag != new->rts_tag, 70346303Smarkm (new->rts_time != rts->rts_time 70446303Smarkm && (rts != rt->rt_spares 70546303Smarkm || AGE_RT(rt->rt_state, new->rts_ifp)))); 70618316Swollman 70718316Swollman } else { 70818316Swollman (void)fprintf(ftrace, "Add #%d %-35s ", 70946303Smarkm (int)(rts - rt->rt_spares), 71046303Smarkm rtname(rt->rt_dst, rt->rt_mask, new->rts_gate)); 71146303Smarkm print_rts(new, 0,0,0,0, 71246303Smarkm (rts != rt->rt_spares 71346303Smarkm || AGE_RT(rt->rt_state,new->rts_ifp))); 71418316Swollman } 71520339Swollman (void)fputc('\n',ftrace); 71618316Swollman} 71718316Swollman 71818316Swollman 71946303Smarkm/* miscellaneous message checked by the caller 72018316Swollman */ 72118316Swollmanvoid 72246303Smarkmtrace_misc(const char *p, ...) 72318316Swollman{ 72418316Swollman va_list args; 72518316Swollman 72646303Smarkm if (ftrace == 0) 72718316Swollman return; 72818316Swollman 72918316Swollman lastlog(); 73018316Swollman va_start(args, p); 73118316Swollman vfprintf(ftrace, p, args); 732126250Sbms va_end(args); 73346303Smarkm (void)fputc('\n',ftrace); 73418316Swollman} 73518316Swollman 73618316Swollman 73718316Swollman/* display a message if tracing actions 73818316Swollman */ 73918316Swollmanvoid 74046303Smarkmtrace_act(const char *p, ...) 74118316Swollman{ 74218316Swollman va_list args; 74318316Swollman 74418316Swollman if (!TRACEACTIONS || ftrace == 0) 74518316Swollman return; 74618316Swollman 74718316Swollman lastlog(); 74818316Swollman va_start(args, p); 74918316Swollman vfprintf(ftrace, p, args); 750126250Sbms va_end(args); 75119880Swollman (void)fputc('\n',ftrace); 75218316Swollman} 75318316Swollman 75418316Swollman 75518316Swollman/* display a message if tracing packets 75618316Swollman */ 75718316Swollmanvoid 75846303Smarkmtrace_pkt(const char *p, ...) 75918316Swollman{ 76018316Swollman va_list args; 76118316Swollman 76218316Swollman if (!TRACEPACKETS || ftrace == 0) 76318316Swollman return; 76418316Swollman 76518316Swollman lastlog(); 76618316Swollman va_start(args, p); 76718316Swollman vfprintf(ftrace, p, args); 768126250Sbms va_end(args); 76919880Swollman (void)fputc('\n',ftrace); 77018316Swollman} 77118316Swollman 77218316Swollman 77318316Swollmanvoid 77418316Swollmantrace_change(struct rt_entry *rt, 77518316Swollman u_int state, 77646303Smarkm struct rt_spare *new, 77746303Smarkm const char *label) 77818316Swollman{ 77918316Swollman if (ftrace == 0) 78018316Swollman return; 78118316Swollman 78246303Smarkm if (rt->rt_metric == new->rts_metric 78346303Smarkm && rt->rt_gate == new->rts_gate 78446303Smarkm && rt->rt_router == new->rts_router 78518316Swollman && rt->rt_state == state 78646303Smarkm && rt->rt_tag == new->rts_tag 78746303Smarkm && rt->rt_de_ag == new->rts_de_ag) 78818316Swollman return; 78918316Swollman 79018316Swollman lastlog(); 79120339Swollman (void)fprintf(ftrace, "%s %-35s ", 79218316Swollman label, 79346303Smarkm rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate)); 79420339Swollman print_rts(rt->rt_spares, 79520339Swollman 0,0,0,0, AGE_RT(rt->rt_state, rt->rt_ifp)); 79618316Swollman trace_bits(rs_bits, rt->rt_state, rt->rt_state != state); 79718316Swollman 79820339Swollman (void)fprintf(ftrace, "\n%*s %19s%-16s ", 79946303Smarkm (int)strlen(label), "", "", 80046303Smarkm (rt->rt_gate != new->rts_gate 80146303Smarkm ? naddr_ntoa(new->rts_gate) : "")); 80246303Smarkm print_rts(new, 80346303Smarkm -(new->rts_metric == rt->rt_metric), 80446303Smarkm -(new->rts_ifp == rt->rt_ifp), 80520339Swollman 0, 80646303Smarkm rt->rt_tag != new->rts_tag, 80746303Smarkm (rt->rt_time != new->rts_time 80846303Smarkm && AGE_RT(rt->rt_state,new->rts_ifp))); 80918316Swollman if (rt->rt_state != state) 81018316Swollman trace_bits(rs_bits, state, 1); 81120339Swollman (void)fputc('\n',ftrace); 81218316Swollman} 81318316Swollman 81418316Swollman 81518316Swollmanvoid 81646303Smarkmtrace_add_del(const char * action, struct rt_entry *rt) 81718316Swollman{ 81818316Swollman if (ftrace == 0) 81918316Swollman return; 82018316Swollman 82118316Swollman lastlog(); 82220339Swollman (void)fprintf(ftrace, "%s %-35s ", 82318316Swollman action, 82446303Smarkm rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate)); 82520339Swollman print_rts(rt->rt_spares, 0,0,0,0,AGE_RT(rt->rt_state,rt->rt_ifp)); 82620339Swollman trace_bits(rs_bits, rt->rt_state, 0); 82720339Swollman (void)fputc('\n',ftrace); 82818316Swollman} 82918316Swollman 83018316Swollman 83118316Swollman/* ARGSUSED */ 83218316Swollmanstatic int 83318316Swollmanwalk_trace(struct radix_node *rn, 83446303Smarkm struct walkarg *w UNUSED) 83518316Swollman{ 83618316Swollman#define RT ((struct rt_entry *)rn) 83718316Swollman struct rt_spare *rts; 83846303Smarkm int i; 83918316Swollman 84046303Smarkm (void)fprintf(ftrace, " %-35s ", 84146303Smarkm rtname(RT->rt_dst, RT->rt_mask, RT->rt_gate)); 84246303Smarkm print_rts(&RT->rt_spares[0], 0,0,0,0, AGE_RT(RT->rt_state, RT->rt_ifp)); 84318316Swollman trace_bits(rs_bits, RT->rt_state, 0); 84420339Swollman if (RT->rt_poison_time >= now_garbage 84520339Swollman && RT->rt_poison_metric < RT->rt_metric) 84620339Swollman (void)fprintf(ftrace, "pm=%d@%s", 84746303Smarkm RT->rt_poison_metric, ts(RT->rt_poison_time)); 84818316Swollman 84918316Swollman rts = &RT->rt_spares[1]; 85018316Swollman for (i = 1; i < NUM_SPARES; i++, rts++) { 85120339Swollman if (rts->rts_gate != RIP_DEFAULT) { 85220339Swollman (void)fprintf(ftrace,"\n #%d%15s%-16s ", 85320339Swollman i, "", naddr_ntoa(rts->rts_gate)); 85420339Swollman print_rts(rts, 0,0,0,0,1); 85518316Swollman } 85618316Swollman } 85718316Swollman (void)fputc('\n',ftrace); 85818316Swollman 85918316Swollman return 0; 86018316Swollman} 86118316Swollman 86218316Swollman 86318316Swollmanstatic void 86418316Swollmantrace_dump(void) 86518316Swollman{ 86619880Swollman struct interface *ifp; 86719880Swollman 86818316Swollman if (ftrace == 0) 86918316Swollman return; 87018316Swollman lastlog(); 87118316Swollman 87220339Swollman (void)fputs("current daemon state:\n", ftrace); 873190711Sphk LIST_FOREACH(ifp, &ifnet, int_list) 87419880Swollman trace_if("", ifp); 87518316Swollman (void)rn_walktree(rhead, walk_trace, 0); 87618316Swollman} 87718316Swollman 87818316Swollman 87918316Swollmanvoid 88046303Smarkmtrace_rip(const char *dir1, const char *dir2, 88118316Swollman struct sockaddr_in *who, 88218316Swollman struct interface *ifp, 88318316Swollman struct rip *msg, 88418316Swollman int size) /* total size of message */ 88518316Swollman{ 88618316Swollman struct netinfo *n, *lim; 88746303Smarkm# define NA ((struct netauth*)n) 88819880Swollman int i, seen_route; 88918316Swollman 89018316Swollman if (!TRACEPACKETS || ftrace == 0) 89118316Swollman return; 89218316Swollman 89318316Swollman lastlog(); 89418316Swollman if (msg->rip_cmd >= RIPCMD_MAX 89518316Swollman || msg->rip_vers == 0) { 89618316Swollman (void)fprintf(ftrace, "%s bad RIPv%d cmd=%d %s" 89718316Swollman " %s.%d size=%d\n", 89818316Swollman dir1, msg->rip_vers, msg->rip_cmd, dir2, 89918316Swollman naddr_ntoa(who->sin_addr.s_addr), 90018316Swollman ntohs(who->sin_port), 90118316Swollman size); 90218316Swollman return; 90318316Swollman } 90418316Swollman 90518316Swollman (void)fprintf(ftrace, "%s RIPv%d %s %s %s.%d%s%s\n", 90618316Swollman dir1, msg->rip_vers, ripcmds[msg->rip_cmd], dir2, 90718316Swollman naddr_ntoa(who->sin_addr.s_addr), ntohs(who->sin_port), 90818316Swollman ifp ? " via " : "", ifp ? ifp->int_name : ""); 90918316Swollman if (!TRACECONTENTS) 91018316Swollman return; 91118316Swollman 91219880Swollman seen_route = 0; 91318316Swollman switch (msg->rip_cmd) { 91418316Swollman case RIPCMD_REQUEST: 91518316Swollman case RIPCMD_RESPONSE: 91618316Swollman n = msg->rip_nets; 91718316Swollman lim = (struct netinfo *)((char*)msg + size); 91818316Swollman for (; n < lim; n++) { 91919880Swollman if (!seen_route 92019880Swollman && n->n_family == RIP_AF_UNSPEC 92118316Swollman && ntohl(n->n_metric) == HOPCNT_INFINITY 92219880Swollman && msg->rip_cmd == RIPCMD_REQUEST 92319880Swollman && (n+1 == lim 92419880Swollman || (n+2 == lim 92519880Swollman && (n+1)->n_family == RIP_AF_AUTH))) { 92618316Swollman (void)fputs("\tQUERY ", ftrace); 92718316Swollman if (n->n_dst != 0) 92818316Swollman (void)fprintf(ftrace, "%s ", 92918316Swollman naddr_ntoa(n->n_dst)); 93018316Swollman if (n->n_mask != 0) 93118316Swollman (void)fprintf(ftrace, "mask=%#x ", 93218316Swollman (u_int)ntohl(n->n_mask)); 93318316Swollman if (n->n_nhop != 0) 93419880Swollman (void)fprintf(ftrace, "nhop=%s ", 93518316Swollman naddr_ntoa(n->n_nhop)); 93618316Swollman if (n->n_tag != 0) 93719880Swollman (void)fprintf(ftrace, "tag=%#x ", 93818316Swollman ntohs(n->n_tag)); 93918316Swollman (void)fputc('\n',ftrace); 94018316Swollman continue; 94118316Swollman } 94218316Swollman 94318316Swollman if (n->n_family == RIP_AF_AUTH) { 94419880Swollman if (NA->a_type == RIP_AUTH_PW 94519880Swollman && n == msg->rip_nets) { 94619880Swollman (void)fprintf(ftrace, "\tPassword" 94719880Swollman " Authentication:" 94819880Swollman " \"%s\"\n", 94919880Swollman qstring(NA->au.au_pw, 95019880Swollman RIP_AUTH_PW_LEN)); 95119880Swollman continue; 95219880Swollman } 95319880Swollman 95419880Swollman if (NA->a_type == RIP_AUTH_MD5 95519880Swollman && n == msg->rip_nets) { 95619880Swollman (void)fprintf(ftrace, 95746303Smarkm "\tMD5 Auth" 95846303Smarkm " pkt_len=%d KeyID=%u" 95946303Smarkm " auth_len=%d" 96046303Smarkm " seqno=%#x" 96119880Swollman " rsvd=%#x,%#x\n", 96246303Smarkm ntohs(NA->au.a_md5.md5_pkt_len), 96346303Smarkm NA->au.a_md5.md5_keyid, 96446303Smarkm NA->au.a_md5.md5_auth_len, 96546303Smarkm (int)ntohl(NA->au.a_md5.md5_seqno), 96646303Smarkm (int)ntohs(NA->au.a_md5.rsvd[0]), 96746303Smarkm (int)ntohs(NA->au.a_md5.rsvd[1])); 96819880Swollman continue; 96919880Swollman } 97018316Swollman (void)fprintf(ftrace, 97146303Smarkm "\tAuthentication type %d: ", 97219880Swollman ntohs(NA->a_type)); 97318316Swollman for (i = 0; 97446303Smarkm i < (int)sizeof(NA->au.au_pw); 97518316Swollman i++) 97618316Swollman (void)fprintf(ftrace, "%02x ", 97719880Swollman NA->au.au_pw[i]); 97818316Swollman (void)fputc('\n',ftrace); 97918316Swollman continue; 98018316Swollman } 98118316Swollman 98219880Swollman seen_route = 1; 98318316Swollman if (n->n_family != RIP_AF_INET) { 98418316Swollman (void)fprintf(ftrace, 98519880Swollman "\t(af %d) %-18s mask=%#x ", 98618316Swollman ntohs(n->n_family), 98718316Swollman naddr_ntoa(n->n_dst), 98818316Swollman (u_int)ntohl(n->n_mask)); 98918316Swollman } else if (msg->rip_vers == RIPv1) { 99018316Swollman (void)fprintf(ftrace, "\t%-18s ", 99118316Swollman addrname(n->n_dst, 99218316Swollman ntohl(n->n_mask), 99318316Swollman n->n_mask==0 ? 2 : 1)); 99418316Swollman } else { 99518316Swollman (void)fprintf(ftrace, "\t%-18s ", 99618316Swollman addrname(n->n_dst, 99718316Swollman ntohl(n->n_mask), 99818316Swollman n->n_mask==0 ? 2 : 0)); 99918316Swollman } 100018316Swollman (void)fprintf(ftrace, "metric=%-2d ", 100118316Swollman (u_int)ntohl(n->n_metric)); 100218316Swollman if (n->n_nhop != 0) 100318316Swollman (void)fprintf(ftrace, " nhop=%s ", 100418316Swollman naddr_ntoa(n->n_nhop)); 100518316Swollman if (n->n_tag != 0) 100618316Swollman (void)fprintf(ftrace, "tag=%#x", 100718316Swollman ntohs(n->n_tag)); 100818316Swollman (void)fputc('\n',ftrace); 100918316Swollman } 101018316Swollman if (size != (char *)n - (char *)msg) 101118316Swollman (void)fprintf(ftrace, "truncated record, len %d\n", 101218316Swollman size); 101318316Swollman break; 101418316Swollman 101518316Swollman case RIPCMD_TRACEON: 101620339Swollman fprintf(ftrace, "\tfile=\"%.*s\"\n", size-4, 101720339Swollman msg->rip_tracefile); 101818316Swollman break; 101918316Swollman 102018316Swollman case RIPCMD_TRACEOFF: 102118316Swollman break; 102218316Swollman } 102318316Swollman} 1024