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: releng/11.0/sbin/routed/trace.c 299825 2016-05-15 03:04:21Z pfg $ 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: releng/11.0/sbin/routed/trace.c 299825 2016-05-15 03:04:21Z pfg $"); 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 5420339Swollmanint tracelevel, new_tracelevel; 5581604SpeterFILE *ftrace; /* output trace file */ 5646303Smarkmstatic const char *sigtrace_pat = "%s"; 57118582Simpstatic char savetracename[PATH_MAX]; 58118582Simpchar inittracename[PATH_MAX]; 59190715Sphkstatic int file_trace; /* 1=tracing to file, not stdout */ 6018316Swollman 6118316Swollmanstatic void trace_dump(void); 6246303Smarkmstatic void tmsg(const char *, ...) PATTRIB(1,2); 6318316Swollman 6418316Swollman 6519880Swollman/* convert string to printable characters 6619880Swollman */ 6719880Swollmanstatic char * 6819880Swollmanqstring(u_char *s, int len) 6919880Swollman{ 7019880Swollman static char buf[8*20+1]; 7119880Swollman char *p; 7219880Swollman u_char *s2, c; 7319880Swollman 7419880Swollman 7519880Swollman for (p = buf; len != 0 && p < &buf[sizeof(buf)-1]; len--) { 7619880Swollman c = *s++; 7719880Swollman if (c == '\0') { 7819880Swollman for (s2 = s+1; s2 < &s[len]; s2++) { 7919880Swollman if (*s2 != '\0') 8019880Swollman break; 8119880Swollman } 8219880Swollman if (s2 >= &s[len]) 8319880Swollman goto exit; 8419880Swollman } 8519880Swollman 8619880Swollman if (c >= ' ' && c < 0x7f && c != '\\') { 8719880Swollman *p++ = c; 8819880Swollman continue; 8919880Swollman } 9019880Swollman *p++ = '\\'; 9119880Swollman switch (c) { 9219880Swollman case '\\': 9319880Swollman *p++ = '\\'; 9419880Swollman break; 9519880Swollman case '\n': 9619880Swollman *p++= 'n'; 9719880Swollman break; 9819880Swollman case '\r': 9919880Swollman *p++= 'r'; 10019880Swollman break; 10119880Swollman case '\t': 10219880Swollman *p++ = 't'; 10319880Swollman break; 10419880Swollman case '\b': 10519880Swollman *p++ = 'b'; 10619880Swollman break; 10719880Swollman default: 10819880Swollman p += sprintf(p,"%o",c); 10919880Swollman break; 11019880Swollman } 11119880Swollman } 11219880Swollmanexit: 11319880Swollman *p = '\0'; 11419880Swollman return buf; 11519880Swollman} 11619880Swollman 11719880Swollman 11818316Swollman/* convert IP address to a string, but not into a single buffer 11918316Swollman */ 12018316Swollmanchar * 12118316Swollmannaddr_ntoa(naddr a) 12218316Swollman{ 12318316Swollman#define NUM_BUFS 4 12418316Swollman static int bufno; 12518316Swollman static struct { 12618316Swollman char str[16]; /* xxx.xxx.xxx.xxx\0 */ 12718316Swollman } bufs[NUM_BUFS]; 12818316Swollman char *s; 12918316Swollman struct in_addr addr; 13018316Swollman 13118316Swollman addr.s_addr = a; 13218316Swollman s = strcpy(bufs[bufno].str, inet_ntoa(addr)); 13318316Swollman bufno = (bufno+1) % NUM_BUFS; 13418316Swollman return s; 13518316Swollman#undef NUM_BUFS 13618316Swollman} 13718316Swollman 13818316Swollman 13946303Smarkmconst char * 14018316Swollmansaddr_ntoa(struct sockaddr *sa) 14118316Swollman{ 142299768Spfg return (sa == NULL) ? "?" : naddr_ntoa(S_ADDR(sa)); 14318316Swollman} 14418316Swollman 14518316Swollman 14618316Swollmanstatic char * 14718316Swollmants(time_t secs) { 14818316Swollman static char s[20]; 14918316Swollman 15018316Swollman secs += epoch.tv_sec; 15118316Swollman#ifdef sgi 15218316Swollman (void)cftime(s, "%T", &secs); 15318316Swollman#else 15446303Smarkm memcpy(s, ctime(&secs)+11, 8); 15518316Swollman s[8] = '\0'; 15618316Swollman#endif 15718316Swollman return s; 15818316Swollman} 15918316Swollman 16018316Swollman 16118316Swollman/* On each event, display a time stamp. 16218316Swollman * This assumes that 'now' is update once for each event, and 16318316Swollman * that at least now.tv_usec changes. 16418316Swollman */ 16520339Swollmanstatic struct timeval lastlog_time; 16620339Swollman 16718316Swollmanvoid 16818316Swollmanlastlog(void) 16918316Swollman{ 17020339Swollman if (lastlog_time.tv_sec != now.tv_sec 17120339Swollman || lastlog_time.tv_usec != now.tv_usec) { 17218316Swollman (void)fprintf(ftrace, "-- %s --\n", ts(now.tv_sec)); 17320339Swollman lastlog_time = now; 17418316Swollman } 17518316Swollman} 17618316Swollman 17718316Swollman 17818316Swollmanstatic void 17946303Smarkmtmsg(const char *p, ...) 18018316Swollman{ 18118316Swollman va_list args; 18218316Swollman 183299768Spfg if (ftrace != NULL) { 18418316Swollman lastlog(); 18518316Swollman va_start(args, p); 18618316Swollman vfprintf(ftrace, p, args); 187126250Sbms va_end(args); 18846303Smarkm (void)fputc('\n',ftrace); 18918316Swollman fflush(ftrace); 19018316Swollman } 19118316Swollman} 19218316Swollman 19318316Swollman 19446303Smarkmvoid 19546303Smarkmtrace_close(int zap_stdio) 19618316Swollman{ 19718316Swollman int fd; 19818316Swollman 19918316Swollman 20018316Swollman fflush(stdout); 20118316Swollman fflush(stderr); 20218316Swollman 203299768Spfg if (ftrace != NULL && zap_stdio) { 20420339Swollman if (ftrace != stdout) 20520339Swollman fclose(ftrace); 206299768Spfg ftrace = NULL; 20718316Swollman fd = open(_PATH_DEVNULL, O_RDWR); 208299825Spfg if (fd < 0) 209299825Spfg return; 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{ 225299768Spfg if (ftrace != NULL) { 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 239299768Spfg if (ftrace != NULL) { 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{ 258190718Sphk static const char * const off_msgs[MAX_TRACELEVEL] = { 25920339Swollman "Tracing actions stopped", 26020339Swollman "Tracing packets stopped", 26120339Swollman "Tracing packet contents stopped", 26220339Swollman "Tracing kernel changes stopped", 26320339Swollman }; 264190718Sphk static const char * const 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 */ 312299768Spfg if (filename == NULL || filename[0] == '\0') { 313299768Spfg filename = NULL; 314299768Spfg if (ftrace == NULL) { 31520339Swollman if (inittracename[0] == '\0') { 31620339Swollman msglog("missing trace file name"); 31720339Swollman return; 31820339Swollman } 31920339Swollman fn = inittracename; 32020339Swollman } else { 321299768Spfg fn = NULL; 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 356299768Spfg if (fn != NULL) { 35720339Swollman n_ftrace = fopen(fn, "a"); 358299768Spfg if (n_ftrace == NULL) { 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 380299768Spfg if (new_tracelevel == 0 || filename == NULL) 38120339Swollman new_tracelevel++; 382299768Spfg tracelevel_msg(pat, dump != 0 ? dump : (filename != NULL)); 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 */ 415299768Spfg if (new_tracelevel > tracelevel && ftrace == NULL) { 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; 444299825Spfg size_t l; 44518316Swollman int i; 44618316Swollman 447299825Spfg strlcpy(bufs[bufno].str, naddr_ntoa(addr), sizeof(bufs[bufno].str)); 448299825Spfg s = bufs[bufno].str; 449299825Spfg l = sizeof(bufs[bufno].str); 45018316Swollman bufno = (bufno+1) % NUM_BUFS; 45118316Swollman 45218316Swollman if (force == 1 || (force == 0 && mask != std_mask(addr))) { 45318316Swollman sp = &s[strlen(s)]; 45418316Swollman 45518316Swollman dmask = mask & -mask; 45618316Swollman if (mask + dmask == 0) { 45718316Swollman for (i = 0; i != 32 && ((1<<i) & mask) == 0; i++) 45818316Swollman continue; 459299825Spfg (void)snprintf(sp, s + l - sp, "/%d", 32-i); 46018316Swollman 46118316Swollman } else { 462299825Spfg (void)snprintf(sp, s + l - sp, " (mask %#x)", 463299825Spfg (u_int)mask); 46418316Swollman } 46518316Swollman } 46618316Swollman 46718316Swollman return s; 46818316Swollman#undef NUM_BUFS 46918316Swollman} 47018316Swollman 47118316Swollman 47218316Swollman/* display a bit-field 47318316Swollman */ 47418316Swollmanstruct bits { 47546303Smarkm u_int bits_mask; 47646303Smarkm u_int bits_clear; 47746303Smarkm const char *bits_name; 47818316Swollman}; 47918316Swollman 480190718Sphkstatic const struct bits if_bits[] = { 48118316Swollman { IFF_LOOPBACK, 0, "LOOPBACK" }, 48218316Swollman { IFF_POINTOPOINT, 0, "PT-TO-PT" }, 48318316Swollman { 0, 0, 0} 48418316Swollman}; 48518316Swollman 486190718Sphkstatic const struct bits is_bits[] = { 48719880Swollman { IS_ALIAS, 0, "ALIAS" }, 48818316Swollman { IS_SUBNET, 0, "" }, 48919880Swollman { IS_REMOTE, (IS_NO_RDISC 49019880Swollman | IS_BCAST_RDISC), "REMOTE" }, 49118316Swollman { IS_PASSIVE, (IS_NO_RDISC 49218316Swollman | IS_NO_RIP 49318316Swollman | IS_NO_SUPER_AG 49418316Swollman | IS_PM_RDISC 49518316Swollman | IS_NO_AG), "PASSIVE" }, 49618316Swollman { IS_EXTERNAL, 0, "EXTERNAL" }, 49718316Swollman { IS_CHECKED, 0, "" }, 49818316Swollman { IS_ALL_HOSTS, 0, "" }, 49918316Swollman { IS_ALL_ROUTERS, 0, "" }, 50019880Swollman { IS_DISTRUST, 0, "DISTRUST" }, 50118316Swollman { IS_BROKE, IS_SICK, "BROKEN" }, 50218316Swollman { IS_SICK, 0, "SICK" }, 50319880Swollman { IS_DUP, 0, "DUPLICATE" }, 50420339Swollman { IS_REDIRECT_OK, 0, "REDIRECT_OK" }, 50518316Swollman { IS_NEED_NET_SYN, 0, "" }, 50618316Swollman { IS_NO_AG, IS_NO_SUPER_AG, "NO_AG" }, 50718316Swollman { IS_NO_SUPER_AG, 0, "NO_SUPER_AG" }, 50818316Swollman { (IS_NO_RIPV1_IN 50918316Swollman | IS_NO_RIPV2_IN 51018316Swollman | IS_NO_RIPV1_OUT 51118316Swollman | IS_NO_RIPV2_OUT), 0, "NO_RIP" }, 51218316Swollman { (IS_NO_RIPV1_IN 51318316Swollman | IS_NO_RIPV1_OUT), 0, "RIPV2" }, 51418316Swollman { IS_NO_RIPV1_IN, 0, "NO_RIPV1_IN" }, 51518316Swollman { IS_NO_RIPV2_IN, 0, "NO_RIPV2_IN" }, 51618316Swollman { IS_NO_RIPV1_OUT, 0, "NO_RIPV1_OUT" }, 51718316Swollman { IS_NO_RIPV2_OUT, 0, "NO_RIPV2_OUT" }, 51818316Swollman { (IS_NO_ADV_IN 51918316Swollman | IS_NO_SOL_OUT 52018316Swollman | IS_NO_ADV_OUT), IS_BCAST_RDISC, "NO_RDISC" }, 52118316Swollman { IS_NO_SOL_OUT, 0, "NO_SOLICIT" }, 52218316Swollman { IS_SOL_OUT, 0, "SEND_SOLICIT" }, 52318316Swollman { IS_NO_ADV_OUT, IS_BCAST_RDISC, "NO_RDISC_ADV" }, 52418316Swollman { IS_ADV_OUT, 0, "RDISC_ADV" }, 52518316Swollman { IS_BCAST_RDISC, 0, "BCAST_RDISC" }, 52619880Swollman { IS_PM_RDISC, 0, "" }, 52718316Swollman { 0, 0, "%#x"} 52818316Swollman}; 52918316Swollman 530190718Sphkstatic const struct bits rs_bits[] = { 53118316Swollman { RS_IF, 0, "IF" }, 53218316Swollman { RS_NET_INT, RS_NET_SYN, "NET_INT" }, 53318316Swollman { RS_NET_SYN, 0, "NET_SYN" }, 53418316Swollman { RS_SUBNET, 0, "" }, 53518316Swollman { RS_LOCAL, 0, "LOCAL" }, 53618316Swollman { RS_MHOME, 0, "MHOME" }, 53718316Swollman { RS_STATIC, 0, "STATIC" }, 53818316Swollman { RS_RDISC, 0, "RDISC" }, 53918316Swollman { 0, 0, "%#x"} 54018316Swollman}; 54118316Swollman 54218316Swollman 54318316Swollmanstatic void 54446303Smarkmtrace_bits(const struct bits *tbl, 54518316Swollman u_int field, 54618316Swollman int force) 54718316Swollman{ 54846303Smarkm u_int b; 54918316Swollman char c; 55018316Swollman 55118316Swollman if (force) { 55218316Swollman (void)putc('<', ftrace); 55318316Swollman c = 0; 55418316Swollman } else { 55518316Swollman c = '<'; 55618316Swollman } 55718316Swollman 55818316Swollman while (field != 0 55918316Swollman && (b = tbl->bits_mask) != 0) { 56018316Swollman if ((b & field) == b) { 56118316Swollman if (tbl->bits_name[0] != '\0') { 56218316Swollman if (c) 56318316Swollman (void)putc(c, ftrace); 56418316Swollman (void)fprintf(ftrace, "%s", tbl->bits_name); 56518316Swollman c = '|'; 56618316Swollman } 56718316Swollman if (0 == (field &= ~(b | tbl->bits_clear))) 56818316Swollman break; 56918316Swollman } 57018316Swollman tbl++; 57118316Swollman } 572299768Spfg if (field != 0 && tbl->bits_name != NULL) { 57318316Swollman if (c) 57418316Swollman (void)putc(c, ftrace); 57518316Swollman (void)fprintf(ftrace, tbl->bits_name, field); 57618316Swollman c = '|'; 57718316Swollman } 57818316Swollman 57918316Swollman if (c != '<' || force) 58018316Swollman (void)fputs("> ", ftrace); 58118316Swollman} 58218316Swollman 58318316Swollman 58446303Smarkmchar * 58546303Smarkmrtname(naddr dst, 58646303Smarkm naddr mask, 58746303Smarkm naddr gate) 58818316Swollman{ 58918316Swollman static char buf[3*4+3+1+2+3 /* "xxx.xxx.xxx.xxx/xx-->" */ 59018316Swollman +3*4+3+1]; /* "xxx.xxx.xxx.xxx" */ 59118316Swollman int i; 59218316Swollman 59318316Swollman i = sprintf(buf, "%-16s-->", addrname(dst, mask, 0)); 59446303Smarkm (void)sprintf(&buf[i], "%-*s", 15+20-MAX(20,i), naddr_ntoa(gate)); 59518316Swollman return buf; 59618316Swollman} 59718316Swollman 59818316Swollman 59920339Swollmanstatic void 60020339Swollmanprint_rts(struct rt_spare *rts, 60120339Swollman int force_metric, /* -1=suppress, 0=default */ 60220339Swollman int force_ifp, /* -1=suppress, 0=default */ 60320339Swollman int force_router, /* -1=suppress, 0=default, 1=display */ 60420339Swollman int force_tag, /* -1=suppress, 0=default, 1=display */ 60520339Swollman int force_time) /* 0=suppress, 1=display */ 60620339Swollman{ 60746303Smarkm int i; 60846303Smarkm 60946303Smarkm 61020339Swollman if (force_metric >= 0) 61120339Swollman (void)fprintf(ftrace, "metric=%-2d ", rts->rts_metric); 61220339Swollman if (force_ifp >= 0) 613299768Spfg (void)fprintf(ftrace, "%s ", (rts->rts_ifp == NULL ? 61420339Swollman "if?" : rts->rts_ifp->int_name)); 61520339Swollman if (force_router > 0 61620339Swollman || (force_router == 0 && rts->rts_router != rts->rts_gate)) 61720339Swollman (void)fprintf(ftrace, "router=%s ", 61820339Swollman naddr_ntoa(rts->rts_router)); 61920339Swollman if (force_time > 0) 62020339Swollman (void)fprintf(ftrace, "%s ", ts(rts->rts_time)); 62120339Swollman if (force_tag > 0 62220339Swollman || (force_tag == 0 && rts->rts_tag != 0)) 62346303Smarkm (void)fprintf(ftrace, "tag=%#x ", ntohs(rts->rts_tag)); 62446303Smarkm if (rts->rts_de_ag != 0) { 62546303Smarkm for (i = 1; (u_int)(1 << i) <= rts->rts_de_ag; i++) 62646303Smarkm continue; 62746303Smarkm (void)fprintf(ftrace, "de_ag=%d ", i); 62846303Smarkm } 62946303Smarkm 63020339Swollman} 63120339Swollman 63220339Swollman 63318316Swollmanvoid 63446303Smarkmtrace_if(const char *act, 63546303Smarkm struct interface *ifp) 63618316Swollman{ 637299768Spfg if (!TRACEACTIONS || ftrace == NULL) 63818316Swollman return; 63918316Swollman 64018316Swollman lastlog(); 64119880Swollman (void)fprintf(ftrace, "%-3s interface %-4s ", act, ifp->int_name); 64218316Swollman (void)fprintf(ftrace, "%-15s-->%-15s ", 64318316Swollman naddr_ntoa(ifp->int_addr), 64419880Swollman addrname(((ifp->int_if_flags & IFF_POINTOPOINT) 64519880Swollman ? ifp->int_dstaddr 64619880Swollman : htonl(ifp->int_net)), 64718316Swollman ifp->int_mask, 1)); 64818316Swollman if (ifp->int_metric != 0) 64918316Swollman (void)fprintf(ftrace, "metric=%d ", ifp->int_metric); 650126250Sbms if (ifp->int_adj_inmetric != 0) 651126250Sbms (void)fprintf(ftrace, "adj_inmetric=%u ", 652126250Sbms ifp->int_adj_inmetric); 653126250Sbms if (ifp->int_adj_outmetric != 0) 654126250Sbms (void)fprintf(ftrace, "adj_outmetric=%u ", 655126250Sbms ifp->int_adj_outmetric); 65619880Swollman if (!IS_RIP_OUT_OFF(ifp->int_state) 65719880Swollman && ifp->int_d_metric != 0) 658126250Sbms (void)fprintf(ftrace, "fake_default=%u ", ifp->int_d_metric); 65918316Swollman trace_bits(if_bits, ifp->int_if_flags, 0); 66018316Swollman trace_bits(is_bits, ifp->int_state, 0); 66118316Swollman (void)fputc('\n',ftrace); 66218316Swollman} 66318316Swollman 66418316Swollman 66518316Swollmanvoid 66618316Swollmantrace_upslot(struct rt_entry *rt, 66718316Swollman struct rt_spare *rts, 66846303Smarkm struct rt_spare *new) 66918316Swollman{ 670299768Spfg if (!TRACEACTIONS || ftrace == NULL) 67118316Swollman return; 67220339Swollman 67346303Smarkm if (rts->rts_gate == new->rts_gate 67446303Smarkm && rts->rts_router == new->rts_router 67546303Smarkm && rts->rts_metric == new->rts_metric 67646303Smarkm && rts->rts_tag == new->rts_tag 67746303Smarkm && rts->rts_de_ag == new->rts_de_ag) 67818316Swollman return; 67918316Swollman 68018316Swollman lastlog(); 68146303Smarkm if (new->rts_gate == 0) { 68246303Smarkm (void)fprintf(ftrace, "Del #%d %-35s ", 68346303Smarkm (int)(rts - rt->rt_spares), 68446303Smarkm rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate)); 68546303Smarkm print_rts(rts, 0,0,0,0, 68646303Smarkm (rts != rt->rt_spares 68746303Smarkm || AGE_RT(rt->rt_state,new->rts_ifp))); 68846303Smarkm 68946303Smarkm } else if (rts->rts_gate != RIP_DEFAULT) { 69018316Swollman (void)fprintf(ftrace, "Chg #%d %-35s ", 69146303Smarkm (int)(rts - rt->rt_spares), 69246303Smarkm rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate)); 69320339Swollman print_rts(rts, 0,0, 69446303Smarkm rts->rts_gate != new->rts_gate, 69546303Smarkm rts->rts_tag != new->rts_tag, 69620339Swollman rts != rt->rt_spares || AGE_RT(rt->rt_state, 69720339Swollman rt->rt_ifp)); 69818316Swollman 69920339Swollman (void)fprintf(ftrace, "\n %19s%-16s ", "", 70046303Smarkm (new->rts_gate != rts->rts_gate 70146303Smarkm ? naddr_ntoa(new->rts_gate) : "")); 70246303Smarkm print_rts(new, 70346303Smarkm -(new->rts_metric == rts->rts_metric), 70446303Smarkm -(new->rts_ifp == rts->rts_ifp), 70520339Swollman 0, 70646303Smarkm rts->rts_tag != new->rts_tag, 70746303Smarkm (new->rts_time != rts->rts_time 70846303Smarkm && (rts != rt->rt_spares 70946303Smarkm || AGE_RT(rt->rt_state, new->rts_ifp)))); 71018316Swollman 71118316Swollman } else { 71218316Swollman (void)fprintf(ftrace, "Add #%d %-35s ", 71346303Smarkm (int)(rts - rt->rt_spares), 71446303Smarkm rtname(rt->rt_dst, rt->rt_mask, new->rts_gate)); 71546303Smarkm print_rts(new, 0,0,0,0, 71646303Smarkm (rts != rt->rt_spares 71746303Smarkm || AGE_RT(rt->rt_state,new->rts_ifp))); 71818316Swollman } 71920339Swollman (void)fputc('\n',ftrace); 72018316Swollman} 72118316Swollman 72218316Swollman 72346303Smarkm/* miscellaneous message checked by the caller 72418316Swollman */ 72518316Swollmanvoid 72646303Smarkmtrace_misc(const char *p, ...) 72718316Swollman{ 72818316Swollman va_list args; 72918316Swollman 730299768Spfg if (ftrace == NULL) 73118316Swollman return; 73218316Swollman 73318316Swollman lastlog(); 73418316Swollman va_start(args, p); 73518316Swollman vfprintf(ftrace, p, args); 736126250Sbms va_end(args); 73746303Smarkm (void)fputc('\n',ftrace); 73818316Swollman} 73918316Swollman 74018316Swollman 74118316Swollman/* display a message if tracing actions 74218316Swollman */ 74318316Swollmanvoid 74446303Smarkmtrace_act(const char *p, ...) 74518316Swollman{ 74618316Swollman va_list args; 74718316Swollman 748299768Spfg if (!TRACEACTIONS || ftrace == NULL) 74918316Swollman return; 75018316Swollman 75118316Swollman lastlog(); 75218316Swollman va_start(args, p); 75318316Swollman vfprintf(ftrace, p, args); 754126250Sbms va_end(args); 75519880Swollman (void)fputc('\n',ftrace); 75618316Swollman} 75718316Swollman 75818316Swollman 75918316Swollman/* display a message if tracing packets 76018316Swollman */ 76118316Swollmanvoid 76246303Smarkmtrace_pkt(const char *p, ...) 76318316Swollman{ 76418316Swollman va_list args; 76518316Swollman 766299768Spfg if (!TRACEPACKETS || ftrace == NULL) 76718316Swollman return; 76818316Swollman 76918316Swollman lastlog(); 77018316Swollman va_start(args, p); 77118316Swollman vfprintf(ftrace, p, args); 772126250Sbms va_end(args); 77319880Swollman (void)fputc('\n',ftrace); 77418316Swollman} 77518316Swollman 77618316Swollman 77718316Swollmanvoid 77818316Swollmantrace_change(struct rt_entry *rt, 77918316Swollman u_int state, 78046303Smarkm struct rt_spare *new, 78146303Smarkm const char *label) 78218316Swollman{ 783299768Spfg if (ftrace == NULL) 78418316Swollman return; 78518316Swollman 78646303Smarkm if (rt->rt_metric == new->rts_metric 78746303Smarkm && rt->rt_gate == new->rts_gate 78846303Smarkm && rt->rt_router == new->rts_router 78918316Swollman && rt->rt_state == state 79046303Smarkm && rt->rt_tag == new->rts_tag 79146303Smarkm && rt->rt_de_ag == new->rts_de_ag) 79218316Swollman return; 79318316Swollman 79418316Swollman lastlog(); 79520339Swollman (void)fprintf(ftrace, "%s %-35s ", 79618316Swollman label, 79746303Smarkm rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate)); 79820339Swollman print_rts(rt->rt_spares, 79920339Swollman 0,0,0,0, AGE_RT(rt->rt_state, rt->rt_ifp)); 80018316Swollman trace_bits(rs_bits, rt->rt_state, rt->rt_state != state); 80118316Swollman 80220339Swollman (void)fprintf(ftrace, "\n%*s %19s%-16s ", 80346303Smarkm (int)strlen(label), "", "", 80446303Smarkm (rt->rt_gate != new->rts_gate 80546303Smarkm ? naddr_ntoa(new->rts_gate) : "")); 80646303Smarkm print_rts(new, 80746303Smarkm -(new->rts_metric == rt->rt_metric), 80846303Smarkm -(new->rts_ifp == rt->rt_ifp), 80920339Swollman 0, 81046303Smarkm rt->rt_tag != new->rts_tag, 81146303Smarkm (rt->rt_time != new->rts_time 81246303Smarkm && AGE_RT(rt->rt_state,new->rts_ifp))); 81318316Swollman if (rt->rt_state != state) 81418316Swollman trace_bits(rs_bits, state, 1); 81520339Swollman (void)fputc('\n',ftrace); 81618316Swollman} 81718316Swollman 81818316Swollman 81918316Swollmanvoid 82046303Smarkmtrace_add_del(const char * action, struct rt_entry *rt) 82118316Swollman{ 822299768Spfg if (ftrace == NULL) 82318316Swollman return; 82418316Swollman 82518316Swollman lastlog(); 82620339Swollman (void)fprintf(ftrace, "%s %-35s ", 82718316Swollman action, 82846303Smarkm rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate)); 82920339Swollman print_rts(rt->rt_spares, 0,0,0,0,AGE_RT(rt->rt_state,rt->rt_ifp)); 83020339Swollman trace_bits(rs_bits, rt->rt_state, 0); 83120339Swollman (void)fputc('\n',ftrace); 83218316Swollman} 83318316Swollman 83418316Swollman 83518316Swollman/* ARGSUSED */ 83618316Swollmanstatic int 83718316Swollmanwalk_trace(struct radix_node *rn, 83846303Smarkm struct walkarg *w UNUSED) 83918316Swollman{ 84018316Swollman#define RT ((struct rt_entry *)rn) 84118316Swollman struct rt_spare *rts; 84246303Smarkm int i; 84318316Swollman 84446303Smarkm (void)fprintf(ftrace, " %-35s ", 84546303Smarkm rtname(RT->rt_dst, RT->rt_mask, RT->rt_gate)); 84646303Smarkm print_rts(&RT->rt_spares[0], 0,0,0,0, AGE_RT(RT->rt_state, RT->rt_ifp)); 84718316Swollman trace_bits(rs_bits, RT->rt_state, 0); 84820339Swollman if (RT->rt_poison_time >= now_garbage 84920339Swollman && RT->rt_poison_metric < RT->rt_metric) 85020339Swollman (void)fprintf(ftrace, "pm=%d@%s", 85146303Smarkm RT->rt_poison_metric, ts(RT->rt_poison_time)); 85218316Swollman 85318316Swollman rts = &RT->rt_spares[1]; 85418316Swollman for (i = 1; i < NUM_SPARES; i++, rts++) { 85520339Swollman if (rts->rts_gate != RIP_DEFAULT) { 85620339Swollman (void)fprintf(ftrace,"\n #%d%15s%-16s ", 85720339Swollman i, "", naddr_ntoa(rts->rts_gate)); 85820339Swollman print_rts(rts, 0,0,0,0,1); 85918316Swollman } 86018316Swollman } 86118316Swollman (void)fputc('\n',ftrace); 86218316Swollman 86318316Swollman return 0; 86418316Swollman} 86518316Swollman 86618316Swollman 86718316Swollmanstatic void 86818316Swollmantrace_dump(void) 86918316Swollman{ 87019880Swollman struct interface *ifp; 87119880Swollman 872299768Spfg if (ftrace == NULL) 87318316Swollman return; 87418316Swollman lastlog(); 87518316Swollman 87620339Swollman (void)fputs("current daemon state:\n", ftrace); 877190711Sphk LIST_FOREACH(ifp, &ifnet, int_list) 87819880Swollman trace_if("", ifp); 87918316Swollman (void)rn_walktree(rhead, walk_trace, 0); 88018316Swollman} 88118316Swollman 88218316Swollman 88318316Swollmanvoid 88446303Smarkmtrace_rip(const char *dir1, const char *dir2, 88518316Swollman struct sockaddr_in *who, 88618316Swollman struct interface *ifp, 88718316Swollman struct rip *msg, 88818316Swollman int size) /* total size of message */ 88918316Swollman{ 89018316Swollman struct netinfo *n, *lim; 89146303Smarkm# define NA ((struct netauth*)n) 89219880Swollman int i, seen_route; 89318316Swollman 894299768Spfg if (!TRACEPACKETS || ftrace == NULL) 89518316Swollman return; 89618316Swollman 89718316Swollman lastlog(); 89818316Swollman if (msg->rip_cmd >= RIPCMD_MAX 89918316Swollman || msg->rip_vers == 0) { 90018316Swollman (void)fprintf(ftrace, "%s bad RIPv%d cmd=%d %s" 90118316Swollman " %s.%d size=%d\n", 90218316Swollman dir1, msg->rip_vers, msg->rip_cmd, dir2, 90318316Swollman naddr_ntoa(who->sin_addr.s_addr), 90418316Swollman ntohs(who->sin_port), 90518316Swollman size); 90618316Swollman return; 90718316Swollman } 90818316Swollman 90918316Swollman (void)fprintf(ftrace, "%s RIPv%d %s %s %s.%d%s%s\n", 91018316Swollman dir1, msg->rip_vers, ripcmds[msg->rip_cmd], dir2, 91118316Swollman naddr_ntoa(who->sin_addr.s_addr), ntohs(who->sin_port), 91218316Swollman ifp ? " via " : "", ifp ? ifp->int_name : ""); 91318316Swollman if (!TRACECONTENTS) 91418316Swollman return; 91518316Swollman 91619880Swollman seen_route = 0; 91718316Swollman switch (msg->rip_cmd) { 91818316Swollman case RIPCMD_REQUEST: 91918316Swollman case RIPCMD_RESPONSE: 92018316Swollman n = msg->rip_nets; 92118316Swollman lim = (struct netinfo *)((char*)msg + size); 92218316Swollman for (; n < lim; n++) { 92319880Swollman if (!seen_route 92419880Swollman && n->n_family == RIP_AF_UNSPEC 92518316Swollman && ntohl(n->n_metric) == HOPCNT_INFINITY 92619880Swollman && msg->rip_cmd == RIPCMD_REQUEST 92719880Swollman && (n+1 == lim 92819880Swollman || (n+2 == lim 92919880Swollman && (n+1)->n_family == RIP_AF_AUTH))) { 93018316Swollman (void)fputs("\tQUERY ", ftrace); 93118316Swollman if (n->n_dst != 0) 93218316Swollman (void)fprintf(ftrace, "%s ", 93318316Swollman naddr_ntoa(n->n_dst)); 93418316Swollman if (n->n_mask != 0) 93518316Swollman (void)fprintf(ftrace, "mask=%#x ", 93618316Swollman (u_int)ntohl(n->n_mask)); 93718316Swollman if (n->n_nhop != 0) 93819880Swollman (void)fprintf(ftrace, "nhop=%s ", 93918316Swollman naddr_ntoa(n->n_nhop)); 94018316Swollman if (n->n_tag != 0) 94119880Swollman (void)fprintf(ftrace, "tag=%#x ", 94218316Swollman ntohs(n->n_tag)); 94318316Swollman (void)fputc('\n',ftrace); 94418316Swollman continue; 94518316Swollman } 94618316Swollman 94718316Swollman if (n->n_family == RIP_AF_AUTH) { 94819880Swollman if (NA->a_type == RIP_AUTH_PW 94919880Swollman && n == msg->rip_nets) { 95019880Swollman (void)fprintf(ftrace, "\tPassword" 95119880Swollman " Authentication:" 95219880Swollman " \"%s\"\n", 95319880Swollman qstring(NA->au.au_pw, 95419880Swollman RIP_AUTH_PW_LEN)); 95519880Swollman continue; 95619880Swollman } 95719880Swollman 95819880Swollman if (NA->a_type == RIP_AUTH_MD5 95919880Swollman && n == msg->rip_nets) { 96019880Swollman (void)fprintf(ftrace, 96146303Smarkm "\tMD5 Auth" 96246303Smarkm " pkt_len=%d KeyID=%u" 96346303Smarkm " auth_len=%d" 96446303Smarkm " seqno=%#x" 96519880Swollman " rsvd=%#x,%#x\n", 96646303Smarkm ntohs(NA->au.a_md5.md5_pkt_len), 96746303Smarkm NA->au.a_md5.md5_keyid, 96846303Smarkm NA->au.a_md5.md5_auth_len, 96946303Smarkm (int)ntohl(NA->au.a_md5.md5_seqno), 97046303Smarkm (int)ntohs(NA->au.a_md5.rsvd[0]), 97146303Smarkm (int)ntohs(NA->au.a_md5.rsvd[1])); 97219880Swollman continue; 97319880Swollman } 97418316Swollman (void)fprintf(ftrace, 97546303Smarkm "\tAuthentication type %d: ", 97619880Swollman ntohs(NA->a_type)); 97718316Swollman for (i = 0; 97846303Smarkm i < (int)sizeof(NA->au.au_pw); 97918316Swollman i++) 98018316Swollman (void)fprintf(ftrace, "%02x ", 98119880Swollman NA->au.au_pw[i]); 98218316Swollman (void)fputc('\n',ftrace); 98318316Swollman continue; 98418316Swollman } 98518316Swollman 98619880Swollman seen_route = 1; 98718316Swollman if (n->n_family != RIP_AF_INET) { 98818316Swollman (void)fprintf(ftrace, 98919880Swollman "\t(af %d) %-18s mask=%#x ", 99018316Swollman ntohs(n->n_family), 99118316Swollman naddr_ntoa(n->n_dst), 99218316Swollman (u_int)ntohl(n->n_mask)); 99318316Swollman } else if (msg->rip_vers == RIPv1) { 99418316Swollman (void)fprintf(ftrace, "\t%-18s ", 99518316Swollman addrname(n->n_dst, 99618316Swollman ntohl(n->n_mask), 99718316Swollman n->n_mask==0 ? 2 : 1)); 99818316Swollman } else { 99918316Swollman (void)fprintf(ftrace, "\t%-18s ", 100018316Swollman addrname(n->n_dst, 100118316Swollman ntohl(n->n_mask), 100218316Swollman n->n_mask==0 ? 2 : 0)); 100318316Swollman } 100418316Swollman (void)fprintf(ftrace, "metric=%-2d ", 100518316Swollman (u_int)ntohl(n->n_metric)); 100618316Swollman if (n->n_nhop != 0) 100718316Swollman (void)fprintf(ftrace, " nhop=%s ", 100818316Swollman naddr_ntoa(n->n_nhop)); 100918316Swollman if (n->n_tag != 0) 101018316Swollman (void)fprintf(ftrace, "tag=%#x", 101118316Swollman ntohs(n->n_tag)); 101218316Swollman (void)fputc('\n',ftrace); 101318316Swollman } 101418316Swollman if (size != (char *)n - (char *)msg) 101518316Swollman (void)fprintf(ftrace, "truncated record, len %d\n", 101618316Swollman size); 101718316Swollman break; 101818316Swollman 101918316Swollman case RIPCMD_TRACEON: 102020339Swollman fprintf(ftrace, "\tfile=\"%.*s\"\n", size-4, 102120339Swollman msg->rip_tracefile); 102218316Swollman break; 102318316Swollman 102418316Swollman case RIPCMD_TRACEOFF: 102518316Swollman break; 102618316Swollman } 102718316Swollman} 1028