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/10.3/sbin/routed/trace.c 190718 2009-04-05 17:33:07Z 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: releng/10.3/sbin/routed/trace.c 190718 2009-04-05 17:33:07Z 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 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{ 14218316Swollman return (sa == 0) ? "?" : 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 18318316Swollman if (ftrace != 0) { 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 20346303Smarkm if (ftrace != 0 && zap_stdio) { 20420339Swollman if (ftrace != stdout) 20520339Swollman fclose(ftrace); 20620339Swollman ftrace = 0; 20718316Swollman fd = open(_PATH_DEVNULL, O_RDWR); 20846303Smarkm if (isatty(STDIN_FILENO)) 20946303Smarkm (void)dup2(fd, STDIN_FILENO); 21046303Smarkm if (isatty(STDOUT_FILENO)) 21146303Smarkm (void)dup2(fd, STDOUT_FILENO); 21246303Smarkm if (isatty(STDERR_FILENO)) 21346303Smarkm (void)dup2(fd, STDERR_FILENO); 21418316Swollman (void)close(fd); 21518316Swollman } 21620339Swollman lastlog_time.tv_sec = 0; 21718316Swollman} 21818316Swollman 21918316Swollman 22018316Swollmanvoid 22118316Swollmantrace_flush(void) 22218316Swollman{ 22318316Swollman if (ftrace != 0) { 22418316Swollman fflush(ftrace); 22518316Swollman if (ferror(ftrace)) 22646303Smarkm trace_off("tracing off: %s", strerror(ferror(ftrace))); 22718316Swollman } 22818316Swollman} 22918316Swollman 23018316Swollman 23118316Swollmanvoid 23246303Smarkmtrace_off(const char *p, ...) 23318316Swollman{ 23418316Swollman va_list args; 23518316Swollman 23618316Swollman 23718316Swollman if (ftrace != 0) { 23818316Swollman lastlog(); 23918316Swollman va_start(args, p); 24018316Swollman vfprintf(ftrace, p, args); 241126250Sbms va_end(args); 24246303Smarkm (void)fputc('\n',ftrace); 24318316Swollman } 24446303Smarkm trace_close(file_trace); 24518316Swollman 24618316Swollman new_tracelevel = tracelevel = 0; 24718316Swollman} 24818316Swollman 24918316Swollman 25020339Swollman/* log a change in tracing 25120339Swollman */ 25218316Swollmanvoid 25346303Smarkmtracelevel_msg(const char *pat, 25420339Swollman int dump) /* -1=no dump, 0=default, 1=force */ 25518316Swollman{ 256190718Sphk static const char * const off_msgs[MAX_TRACELEVEL] = { 25720339Swollman "Tracing actions stopped", 25820339Swollman "Tracing packets stopped", 25920339Swollman "Tracing packet contents stopped", 26020339Swollman "Tracing kernel changes stopped", 26120339Swollman }; 262190718Sphk static const char * const on_msgs[MAX_TRACELEVEL] = { 26320339Swollman "Tracing actions started", 26420339Swollman "Tracing packets started", 26520339Swollman "Tracing packet contents started", 26620339Swollman "Tracing kernel changes started", 26720339Swollman }; 26820339Swollman u_int old_tracelevel = tracelevel; 26920339Swollman 27020339Swollman 27120339Swollman if (new_tracelevel < 0) 27220339Swollman new_tracelevel = 0; 27320339Swollman else if (new_tracelevel > MAX_TRACELEVEL) 27420339Swollman new_tracelevel = MAX_TRACELEVEL; 27520339Swollman 27620339Swollman if (new_tracelevel < tracelevel) { 27720339Swollman if (new_tracelevel <= 0) { 27820339Swollman trace_off(pat, off_msgs[0]); 27920339Swollman } else do { 28020339Swollman tmsg(pat, off_msgs[tracelevel]); 28120339Swollman } 28220339Swollman while (--tracelevel != new_tracelevel); 28320339Swollman 28420339Swollman } else if (new_tracelevel > tracelevel) { 28520339Swollman do { 28620339Swollman tmsg(pat, on_msgs[tracelevel++]); 28720339Swollman } while (tracelevel != new_tracelevel); 28820339Swollman } 28920339Swollman 29020339Swollman if (dump > 0 29120339Swollman || (dump == 0 && old_tracelevel == 0 && tracelevel != 0)) 29220339Swollman trace_dump(); 29320339Swollman} 29420339Swollman 29520339Swollman 29620339Swollmanvoid 29746303Smarkmset_tracefile(const char *filename, 29846303Smarkm const char *pat, 29920339Swollman int dump) /* -1=no dump, 0=default, 1=force */ 30020339Swollman{ 30118316Swollman struct stat stbuf; 30218316Swollman FILE *n_ftrace; 30346303Smarkm const char *fn; 30418316Swollman 30518316Swollman 30620339Swollman /* Allow a null filename to increase the level if the trace file 30720339Swollman * is already open or if coming from a trusted source, such as 30820339Swollman * a signal or the command line. 30918316Swollman */ 31020339Swollman if (filename == 0 || filename[0] == '\0') { 31120339Swollman filename = 0; 31220339Swollman if (ftrace == 0) { 31320339Swollman if (inittracename[0] == '\0') { 31420339Swollman msglog("missing trace file name"); 31520339Swollman return; 31620339Swollman } 31720339Swollman fn = inittracename; 31820339Swollman } else { 31920339Swollman fn = 0; 32018316Swollman } 32118316Swollman 32218316Swollman } else if (!strcmp(filename,"dump/../table")) { 32318316Swollman trace_dump(); 32418316Swollman return; 32518316Swollman 32618316Swollman } else { 32720339Swollman /* Allow the file specified with "-T file" to be reopened, 32820339Swollman * but require all other names specified over the net to 32920339Swollman * match the official path. The path can specify a directory 33020339Swollman * in which the file is to be created. 33120339Swollman */ 33220339Swollman if (strcmp(filename, inittracename) 33320339Swollman#ifdef _PATH_TRACE 33420339Swollman && (strncmp(filename, _PATH_TRACE, sizeof(_PATH_TRACE)-1) 33520339Swollman || strstr(filename,"../") 33620339Swollman || 0 > stat(_PATH_TRACE, &stbuf)) 33720339Swollman#endif 33820339Swollman ) { 33920339Swollman msglog("wrong trace file \"%s\"", filename); 34020339Swollman return; 34120339Swollman } 34220339Swollman 34320339Swollman /* If the new tracefile exists, it must be a regular file. 34420339Swollman */ 34546303Smarkm if (stat(filename, &stbuf) >= 0 && !S_ISREG(stbuf.st_mode)) { 34618316Swollman msglog("wrong type (%#x) of trace file \"%s\"", 34718316Swollman stbuf.st_mode, filename); 34818316Swollman return; 34918316Swollman } 35018316Swollman 35120339Swollman fn = filename; 35220339Swollman } 35320339Swollman 35420339Swollman if (fn != 0) { 35520339Swollman n_ftrace = fopen(fn, "a"); 35620339Swollman if (n_ftrace == 0) { 35720339Swollman msglog("failed to open trace file \"%s\" %s", 35820339Swollman fn, strerror(errno)); 35920339Swollman if (fn == inittracename) 36020339Swollman inittracename[0] = '\0'; 36118316Swollman return; 36218316Swollman } 36318316Swollman 36446303Smarkm tmsg("switch to trace file %s", fn); 36518316Swollman 36646303Smarkm trace_close(file_trace = 1); 36718316Swollman 36820339Swollman if (fn != savetracename) 36920339Swollman strncpy(savetracename, fn, sizeof(savetracename)-1); 37020339Swollman ftrace = n_ftrace; 37118316Swollman 37220339Swollman fflush(stdout); 37320339Swollman fflush(stderr); 37420339Swollman dup2(fileno(ftrace), STDOUT_FILENO); 37520339Swollman dup2(fileno(ftrace), STDERR_FILENO); 37620339Swollman } 37719880Swollman 37820339Swollman if (new_tracelevel == 0 || filename == 0) 37920339Swollman new_tracelevel++; 38020339Swollman tracelevel_msg(pat, dump != 0 ? dump : (filename != 0)); 38118316Swollman} 38218316Swollman 38318316Swollman 38418316Swollman/* ARGSUSED */ 38518316Swollmanvoid 38646303Smarkmsigtrace_on(int s UNUSED) 38718316Swollman{ 38818316Swollman new_tracelevel++; 38946303Smarkm sigtrace_pat = "SIGUSR1: %s"; 39018316Swollman} 39118316Swollman 39218316Swollman 39318316Swollman/* ARGSUSED */ 39418316Swollmanvoid 39546303Smarkmsigtrace_off(int s UNUSED) 39618316Swollman{ 39718316Swollman new_tracelevel--; 39846303Smarkm sigtrace_pat = "SIGUSR2: %s"; 39918316Swollman} 40018316Swollman 40118316Swollman 40220339Swollman/* Set tracing after a signal. 40318316Swollman */ 40418316Swollmanvoid 40520339Swollmanset_tracelevel(void) 40618316Swollman{ 40720339Swollman if (new_tracelevel == tracelevel) 40820339Swollman return; 40918316Swollman 41020339Swollman /* If tracing entirely off, and there was no tracefile specified 41120339Swollman * on the command line, then leave it off. 41220339Swollman */ 41320339Swollman if (new_tracelevel > tracelevel && ftrace == 0) { 41420339Swollman if (savetracename[0] != '\0') { 41520339Swollman set_tracefile(savetracename,sigtrace_pat,0); 41620339Swollman } else if (inittracename[0] != '\0') { 41720339Swollman set_tracefile(inittracename,sigtrace_pat,0); 41820339Swollman } else { 41920339Swollman new_tracelevel = 0; 42018316Swollman return; 42118316Swollman } 42220339Swollman } else { 42320339Swollman tracelevel_msg(sigtrace_pat, 0); 42418316Swollman } 42518316Swollman} 42618316Swollman 42718316Swollman 42818316Swollman/* display an address 42918316Swollman */ 43018316Swollmanchar * 43118316Swollmanaddrname(naddr addr, /* in network byte order */ 43218316Swollman naddr mask, 43318316Swollman int force) /* 0=show mask if nonstandard, */ 43418316Swollman{ /* 1=always show mask, 2=never */ 43518316Swollman#define NUM_BUFS 4 43618316Swollman static int bufno; 43718316Swollman static struct { 43818316Swollman char str[15+20]; 43918316Swollman } bufs[NUM_BUFS]; 44018316Swollman char *s, *sp; 44118316Swollman naddr dmask; 44218316Swollman int i; 44318316Swollman 44418316Swollman s = strcpy(bufs[bufno].str, naddr_ntoa(addr)); 44518316Swollman bufno = (bufno+1) % NUM_BUFS; 44618316Swollman 44718316Swollman if (force == 1 || (force == 0 && mask != std_mask(addr))) { 44818316Swollman sp = &s[strlen(s)]; 44918316Swollman 45018316Swollman dmask = mask & -mask; 45118316Swollman if (mask + dmask == 0) { 45218316Swollman for (i = 0; i != 32 && ((1<<i) & mask) == 0; i++) 45318316Swollman continue; 45418316Swollman (void)sprintf(sp, "/%d", 32-i); 45518316Swollman 45618316Swollman } else { 45718316Swollman (void)sprintf(sp, " (mask %#x)", (u_int)mask); 45818316Swollman } 45918316Swollman } 46018316Swollman 46118316Swollman return s; 46218316Swollman#undef NUM_BUFS 46318316Swollman} 46418316Swollman 46518316Swollman 46618316Swollman/* display a bit-field 46718316Swollman */ 46818316Swollmanstruct bits { 46946303Smarkm u_int bits_mask; 47046303Smarkm u_int bits_clear; 47146303Smarkm const char *bits_name; 47218316Swollman}; 47318316Swollman 474190718Sphkstatic const struct bits if_bits[] = { 47518316Swollman { IFF_LOOPBACK, 0, "LOOPBACK" }, 47618316Swollman { IFF_POINTOPOINT, 0, "PT-TO-PT" }, 47718316Swollman { 0, 0, 0} 47818316Swollman}; 47918316Swollman 480190718Sphkstatic const struct bits is_bits[] = { 48119880Swollman { IS_ALIAS, 0, "ALIAS" }, 48218316Swollman { IS_SUBNET, 0, "" }, 48319880Swollman { IS_REMOTE, (IS_NO_RDISC 48419880Swollman | IS_BCAST_RDISC), "REMOTE" }, 48518316Swollman { IS_PASSIVE, (IS_NO_RDISC 48618316Swollman | IS_NO_RIP 48718316Swollman | IS_NO_SUPER_AG 48818316Swollman | IS_PM_RDISC 48918316Swollman | IS_NO_AG), "PASSIVE" }, 49018316Swollman { IS_EXTERNAL, 0, "EXTERNAL" }, 49118316Swollman { IS_CHECKED, 0, "" }, 49218316Swollman { IS_ALL_HOSTS, 0, "" }, 49318316Swollman { IS_ALL_ROUTERS, 0, "" }, 49419880Swollman { IS_DISTRUST, 0, "DISTRUST" }, 49518316Swollman { IS_BROKE, IS_SICK, "BROKEN" }, 49618316Swollman { IS_SICK, 0, "SICK" }, 49719880Swollman { IS_DUP, 0, "DUPLICATE" }, 49820339Swollman { IS_REDIRECT_OK, 0, "REDIRECT_OK" }, 49918316Swollman { IS_NEED_NET_SYN, 0, "" }, 50018316Swollman { IS_NO_AG, IS_NO_SUPER_AG, "NO_AG" }, 50118316Swollman { IS_NO_SUPER_AG, 0, "NO_SUPER_AG" }, 50218316Swollman { (IS_NO_RIPV1_IN 50318316Swollman | IS_NO_RIPV2_IN 50418316Swollman | IS_NO_RIPV1_OUT 50518316Swollman | IS_NO_RIPV2_OUT), 0, "NO_RIP" }, 50618316Swollman { (IS_NO_RIPV1_IN 50718316Swollman | IS_NO_RIPV1_OUT), 0, "RIPV2" }, 50818316Swollman { IS_NO_RIPV1_IN, 0, "NO_RIPV1_IN" }, 50918316Swollman { IS_NO_RIPV2_IN, 0, "NO_RIPV2_IN" }, 51018316Swollman { IS_NO_RIPV1_OUT, 0, "NO_RIPV1_OUT" }, 51118316Swollman { IS_NO_RIPV2_OUT, 0, "NO_RIPV2_OUT" }, 51218316Swollman { (IS_NO_ADV_IN 51318316Swollman | IS_NO_SOL_OUT 51418316Swollman | IS_NO_ADV_OUT), IS_BCAST_RDISC, "NO_RDISC" }, 51518316Swollman { IS_NO_SOL_OUT, 0, "NO_SOLICIT" }, 51618316Swollman { IS_SOL_OUT, 0, "SEND_SOLICIT" }, 51718316Swollman { IS_NO_ADV_OUT, IS_BCAST_RDISC, "NO_RDISC_ADV" }, 51818316Swollman { IS_ADV_OUT, 0, "RDISC_ADV" }, 51918316Swollman { IS_BCAST_RDISC, 0, "BCAST_RDISC" }, 52019880Swollman { IS_PM_RDISC, 0, "" }, 52118316Swollman { 0, 0, "%#x"} 52218316Swollman}; 52318316Swollman 524190718Sphkstatic const struct bits rs_bits[] = { 52518316Swollman { RS_IF, 0, "IF" }, 52618316Swollman { RS_NET_INT, RS_NET_SYN, "NET_INT" }, 52718316Swollman { RS_NET_SYN, 0, "NET_SYN" }, 52818316Swollman { RS_SUBNET, 0, "" }, 52918316Swollman { RS_LOCAL, 0, "LOCAL" }, 53018316Swollman { RS_MHOME, 0, "MHOME" }, 53118316Swollman { RS_STATIC, 0, "STATIC" }, 53218316Swollman { RS_RDISC, 0, "RDISC" }, 53318316Swollman { 0, 0, "%#x"} 53418316Swollman}; 53518316Swollman 53618316Swollman 53718316Swollmanstatic void 53846303Smarkmtrace_bits(const struct bits *tbl, 53918316Swollman u_int field, 54018316Swollman int force) 54118316Swollman{ 54246303Smarkm u_int b; 54318316Swollman char c; 54418316Swollman 54518316Swollman if (force) { 54618316Swollman (void)putc('<', ftrace); 54718316Swollman c = 0; 54818316Swollman } else { 54918316Swollman c = '<'; 55018316Swollman } 55118316Swollman 55218316Swollman while (field != 0 55318316Swollman && (b = tbl->bits_mask) != 0) { 55418316Swollman if ((b & field) == b) { 55518316Swollman if (tbl->bits_name[0] != '\0') { 55618316Swollman if (c) 55718316Swollman (void)putc(c, ftrace); 55818316Swollman (void)fprintf(ftrace, "%s", tbl->bits_name); 55918316Swollman c = '|'; 56018316Swollman } 56118316Swollman if (0 == (field &= ~(b | tbl->bits_clear))) 56218316Swollman break; 56318316Swollman } 56418316Swollman tbl++; 56518316Swollman } 56618316Swollman if (field != 0 && tbl->bits_name != 0) { 56718316Swollman if (c) 56818316Swollman (void)putc(c, ftrace); 56918316Swollman (void)fprintf(ftrace, tbl->bits_name, field); 57018316Swollman c = '|'; 57118316Swollman } 57218316Swollman 57318316Swollman if (c != '<' || force) 57418316Swollman (void)fputs("> ", ftrace); 57518316Swollman} 57618316Swollman 57718316Swollman 57846303Smarkmchar * 57946303Smarkmrtname(naddr dst, 58046303Smarkm naddr mask, 58146303Smarkm naddr gate) 58218316Swollman{ 58318316Swollman static char buf[3*4+3+1+2+3 /* "xxx.xxx.xxx.xxx/xx-->" */ 58418316Swollman +3*4+3+1]; /* "xxx.xxx.xxx.xxx" */ 58518316Swollman int i; 58618316Swollman 58718316Swollman i = sprintf(buf, "%-16s-->", addrname(dst, mask, 0)); 58846303Smarkm (void)sprintf(&buf[i], "%-*s", 15+20-MAX(20,i), naddr_ntoa(gate)); 58918316Swollman return buf; 59018316Swollman} 59118316Swollman 59218316Swollman 59320339Swollmanstatic void 59420339Swollmanprint_rts(struct rt_spare *rts, 59520339Swollman int force_metric, /* -1=suppress, 0=default */ 59620339Swollman int force_ifp, /* -1=suppress, 0=default */ 59720339Swollman int force_router, /* -1=suppress, 0=default, 1=display */ 59820339Swollman int force_tag, /* -1=suppress, 0=default, 1=display */ 59920339Swollman int force_time) /* 0=suppress, 1=display */ 60020339Swollman{ 60146303Smarkm int i; 60246303Smarkm 60346303Smarkm 60420339Swollman if (force_metric >= 0) 60520339Swollman (void)fprintf(ftrace, "metric=%-2d ", rts->rts_metric); 60620339Swollman if (force_ifp >= 0) 60720339Swollman (void)fprintf(ftrace, "%s ", (rts->rts_ifp == 0 ? 60820339Swollman "if?" : rts->rts_ifp->int_name)); 60920339Swollman if (force_router > 0 61020339Swollman || (force_router == 0 && rts->rts_router != rts->rts_gate)) 61120339Swollman (void)fprintf(ftrace, "router=%s ", 61220339Swollman naddr_ntoa(rts->rts_router)); 61320339Swollman if (force_time > 0) 61420339Swollman (void)fprintf(ftrace, "%s ", ts(rts->rts_time)); 61520339Swollman if (force_tag > 0 61620339Swollman || (force_tag == 0 && rts->rts_tag != 0)) 61746303Smarkm (void)fprintf(ftrace, "tag=%#x ", ntohs(rts->rts_tag)); 61846303Smarkm if (rts->rts_de_ag != 0) { 61946303Smarkm for (i = 1; (u_int)(1 << i) <= rts->rts_de_ag; i++) 62046303Smarkm continue; 62146303Smarkm (void)fprintf(ftrace, "de_ag=%d ", i); 62246303Smarkm } 62346303Smarkm 62420339Swollman} 62520339Swollman 62620339Swollman 62718316Swollmanvoid 62846303Smarkmtrace_if(const char *act, 62946303Smarkm struct interface *ifp) 63018316Swollman{ 63118316Swollman if (!TRACEACTIONS || ftrace == 0) 63218316Swollman return; 63318316Swollman 63418316Swollman lastlog(); 63519880Swollman (void)fprintf(ftrace, "%-3s interface %-4s ", act, ifp->int_name); 63618316Swollman (void)fprintf(ftrace, "%-15s-->%-15s ", 63718316Swollman naddr_ntoa(ifp->int_addr), 63819880Swollman addrname(((ifp->int_if_flags & IFF_POINTOPOINT) 63919880Swollman ? ifp->int_dstaddr 64019880Swollman : htonl(ifp->int_net)), 64118316Swollman ifp->int_mask, 1)); 64218316Swollman if (ifp->int_metric != 0) 64318316Swollman (void)fprintf(ftrace, "metric=%d ", ifp->int_metric); 644126250Sbms if (ifp->int_adj_inmetric != 0) 645126250Sbms (void)fprintf(ftrace, "adj_inmetric=%u ", 646126250Sbms ifp->int_adj_inmetric); 647126250Sbms if (ifp->int_adj_outmetric != 0) 648126250Sbms (void)fprintf(ftrace, "adj_outmetric=%u ", 649126250Sbms ifp->int_adj_outmetric); 65019880Swollman if (!IS_RIP_OUT_OFF(ifp->int_state) 65119880Swollman && ifp->int_d_metric != 0) 652126250Sbms (void)fprintf(ftrace, "fake_default=%u ", ifp->int_d_metric); 65318316Swollman trace_bits(if_bits, ifp->int_if_flags, 0); 65418316Swollman trace_bits(is_bits, ifp->int_state, 0); 65518316Swollman (void)fputc('\n',ftrace); 65618316Swollman} 65718316Swollman 65818316Swollman 65918316Swollmanvoid 66018316Swollmantrace_upslot(struct rt_entry *rt, 66118316Swollman struct rt_spare *rts, 66246303Smarkm struct rt_spare *new) 66318316Swollman{ 66418316Swollman if (!TRACEACTIONS || ftrace == 0) 66518316Swollman return; 66620339Swollman 66746303Smarkm if (rts->rts_gate == new->rts_gate 66846303Smarkm && rts->rts_router == new->rts_router 66946303Smarkm && rts->rts_metric == new->rts_metric 67046303Smarkm && rts->rts_tag == new->rts_tag 67146303Smarkm && rts->rts_de_ag == new->rts_de_ag) 67218316Swollman return; 67318316Swollman 67418316Swollman lastlog(); 67546303Smarkm if (new->rts_gate == 0) { 67646303Smarkm (void)fprintf(ftrace, "Del #%d %-35s ", 67746303Smarkm (int)(rts - rt->rt_spares), 67846303Smarkm rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate)); 67946303Smarkm print_rts(rts, 0,0,0,0, 68046303Smarkm (rts != rt->rt_spares 68146303Smarkm || AGE_RT(rt->rt_state,new->rts_ifp))); 68246303Smarkm 68346303Smarkm } else if (rts->rts_gate != RIP_DEFAULT) { 68418316Swollman (void)fprintf(ftrace, "Chg #%d %-35s ", 68546303Smarkm (int)(rts - rt->rt_spares), 68646303Smarkm rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate)); 68720339Swollman print_rts(rts, 0,0, 68846303Smarkm rts->rts_gate != new->rts_gate, 68946303Smarkm rts->rts_tag != new->rts_tag, 69020339Swollman rts != rt->rt_spares || AGE_RT(rt->rt_state, 69120339Swollman rt->rt_ifp)); 69218316Swollman 69320339Swollman (void)fprintf(ftrace, "\n %19s%-16s ", "", 69446303Smarkm (new->rts_gate != rts->rts_gate 69546303Smarkm ? naddr_ntoa(new->rts_gate) : "")); 69646303Smarkm print_rts(new, 69746303Smarkm -(new->rts_metric == rts->rts_metric), 69846303Smarkm -(new->rts_ifp == rts->rts_ifp), 69920339Swollman 0, 70046303Smarkm rts->rts_tag != new->rts_tag, 70146303Smarkm (new->rts_time != rts->rts_time 70246303Smarkm && (rts != rt->rt_spares 70346303Smarkm || AGE_RT(rt->rt_state, new->rts_ifp)))); 70418316Swollman 70518316Swollman } else { 70618316Swollman (void)fprintf(ftrace, "Add #%d %-35s ", 70746303Smarkm (int)(rts - rt->rt_spares), 70846303Smarkm rtname(rt->rt_dst, rt->rt_mask, new->rts_gate)); 70946303Smarkm print_rts(new, 0,0,0,0, 71046303Smarkm (rts != rt->rt_spares 71146303Smarkm || AGE_RT(rt->rt_state,new->rts_ifp))); 71218316Swollman } 71320339Swollman (void)fputc('\n',ftrace); 71418316Swollman} 71518316Swollman 71618316Swollman 71746303Smarkm/* miscellaneous message checked by the caller 71818316Swollman */ 71918316Swollmanvoid 72046303Smarkmtrace_misc(const char *p, ...) 72118316Swollman{ 72218316Swollman va_list args; 72318316Swollman 72446303Smarkm if (ftrace == 0) 72518316Swollman return; 72618316Swollman 72718316Swollman lastlog(); 72818316Swollman va_start(args, p); 72918316Swollman vfprintf(ftrace, p, args); 730126250Sbms va_end(args); 73146303Smarkm (void)fputc('\n',ftrace); 73218316Swollman} 73318316Swollman 73418316Swollman 73518316Swollman/* display a message if tracing actions 73618316Swollman */ 73718316Swollmanvoid 73846303Smarkmtrace_act(const char *p, ...) 73918316Swollman{ 74018316Swollman va_list args; 74118316Swollman 74218316Swollman if (!TRACEACTIONS || ftrace == 0) 74318316Swollman return; 74418316Swollman 74518316Swollman lastlog(); 74618316Swollman va_start(args, p); 74718316Swollman vfprintf(ftrace, p, args); 748126250Sbms va_end(args); 74919880Swollman (void)fputc('\n',ftrace); 75018316Swollman} 75118316Swollman 75218316Swollman 75318316Swollman/* display a message if tracing packets 75418316Swollman */ 75518316Swollmanvoid 75646303Smarkmtrace_pkt(const char *p, ...) 75718316Swollman{ 75818316Swollman va_list args; 75918316Swollman 76018316Swollman if (!TRACEPACKETS || ftrace == 0) 76118316Swollman return; 76218316Swollman 76318316Swollman lastlog(); 76418316Swollman va_start(args, p); 76518316Swollman vfprintf(ftrace, p, args); 766126250Sbms va_end(args); 76719880Swollman (void)fputc('\n',ftrace); 76818316Swollman} 76918316Swollman 77018316Swollman 77118316Swollmanvoid 77218316Swollmantrace_change(struct rt_entry *rt, 77318316Swollman u_int state, 77446303Smarkm struct rt_spare *new, 77546303Smarkm const char *label) 77618316Swollman{ 77718316Swollman if (ftrace == 0) 77818316Swollman return; 77918316Swollman 78046303Smarkm if (rt->rt_metric == new->rts_metric 78146303Smarkm && rt->rt_gate == new->rts_gate 78246303Smarkm && rt->rt_router == new->rts_router 78318316Swollman && rt->rt_state == state 78446303Smarkm && rt->rt_tag == new->rts_tag 78546303Smarkm && rt->rt_de_ag == new->rts_de_ag) 78618316Swollman return; 78718316Swollman 78818316Swollman lastlog(); 78920339Swollman (void)fprintf(ftrace, "%s %-35s ", 79018316Swollman label, 79146303Smarkm rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate)); 79220339Swollman print_rts(rt->rt_spares, 79320339Swollman 0,0,0,0, AGE_RT(rt->rt_state, rt->rt_ifp)); 79418316Swollman trace_bits(rs_bits, rt->rt_state, rt->rt_state != state); 79518316Swollman 79620339Swollman (void)fprintf(ftrace, "\n%*s %19s%-16s ", 79746303Smarkm (int)strlen(label), "", "", 79846303Smarkm (rt->rt_gate != new->rts_gate 79946303Smarkm ? naddr_ntoa(new->rts_gate) : "")); 80046303Smarkm print_rts(new, 80146303Smarkm -(new->rts_metric == rt->rt_metric), 80246303Smarkm -(new->rts_ifp == rt->rt_ifp), 80320339Swollman 0, 80446303Smarkm rt->rt_tag != new->rts_tag, 80546303Smarkm (rt->rt_time != new->rts_time 80646303Smarkm && AGE_RT(rt->rt_state,new->rts_ifp))); 80718316Swollman if (rt->rt_state != state) 80818316Swollman trace_bits(rs_bits, state, 1); 80920339Swollman (void)fputc('\n',ftrace); 81018316Swollman} 81118316Swollman 81218316Swollman 81318316Swollmanvoid 81446303Smarkmtrace_add_del(const char * action, struct rt_entry *rt) 81518316Swollman{ 81618316Swollman if (ftrace == 0) 81718316Swollman return; 81818316Swollman 81918316Swollman lastlog(); 82020339Swollman (void)fprintf(ftrace, "%s %-35s ", 82118316Swollman action, 82246303Smarkm rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate)); 82320339Swollman print_rts(rt->rt_spares, 0,0,0,0,AGE_RT(rt->rt_state,rt->rt_ifp)); 82420339Swollman trace_bits(rs_bits, rt->rt_state, 0); 82520339Swollman (void)fputc('\n',ftrace); 82618316Swollman} 82718316Swollman 82818316Swollman 82918316Swollman/* ARGSUSED */ 83018316Swollmanstatic int 83118316Swollmanwalk_trace(struct radix_node *rn, 83246303Smarkm struct walkarg *w UNUSED) 83318316Swollman{ 83418316Swollman#define RT ((struct rt_entry *)rn) 83518316Swollman struct rt_spare *rts; 83646303Smarkm int i; 83718316Swollman 83846303Smarkm (void)fprintf(ftrace, " %-35s ", 83946303Smarkm rtname(RT->rt_dst, RT->rt_mask, RT->rt_gate)); 84046303Smarkm print_rts(&RT->rt_spares[0], 0,0,0,0, AGE_RT(RT->rt_state, RT->rt_ifp)); 84118316Swollman trace_bits(rs_bits, RT->rt_state, 0); 84220339Swollman if (RT->rt_poison_time >= now_garbage 84320339Swollman && RT->rt_poison_metric < RT->rt_metric) 84420339Swollman (void)fprintf(ftrace, "pm=%d@%s", 84546303Smarkm RT->rt_poison_metric, ts(RT->rt_poison_time)); 84618316Swollman 84718316Swollman rts = &RT->rt_spares[1]; 84818316Swollman for (i = 1; i < NUM_SPARES; i++, rts++) { 84920339Swollman if (rts->rts_gate != RIP_DEFAULT) { 85020339Swollman (void)fprintf(ftrace,"\n #%d%15s%-16s ", 85120339Swollman i, "", naddr_ntoa(rts->rts_gate)); 85220339Swollman print_rts(rts, 0,0,0,0,1); 85318316Swollman } 85418316Swollman } 85518316Swollman (void)fputc('\n',ftrace); 85618316Swollman 85718316Swollman return 0; 85818316Swollman} 85918316Swollman 86018316Swollman 86118316Swollmanstatic void 86218316Swollmantrace_dump(void) 86318316Swollman{ 86419880Swollman struct interface *ifp; 86519880Swollman 86618316Swollman if (ftrace == 0) 86718316Swollman return; 86818316Swollman lastlog(); 86918316Swollman 87020339Swollman (void)fputs("current daemon state:\n", ftrace); 871190711Sphk LIST_FOREACH(ifp, &ifnet, int_list) 87219880Swollman trace_if("", ifp); 87318316Swollman (void)rn_walktree(rhead, walk_trace, 0); 87418316Swollman} 87518316Swollman 87618316Swollman 87718316Swollmanvoid 87846303Smarkmtrace_rip(const char *dir1, const char *dir2, 87918316Swollman struct sockaddr_in *who, 88018316Swollman struct interface *ifp, 88118316Swollman struct rip *msg, 88218316Swollman int size) /* total size of message */ 88318316Swollman{ 88418316Swollman struct netinfo *n, *lim; 88546303Smarkm# define NA ((struct netauth*)n) 88619880Swollman int i, seen_route; 88718316Swollman 88818316Swollman if (!TRACEPACKETS || ftrace == 0) 88918316Swollman return; 89018316Swollman 89118316Swollman lastlog(); 89218316Swollman if (msg->rip_cmd >= RIPCMD_MAX 89318316Swollman || msg->rip_vers == 0) { 89418316Swollman (void)fprintf(ftrace, "%s bad RIPv%d cmd=%d %s" 89518316Swollman " %s.%d size=%d\n", 89618316Swollman dir1, msg->rip_vers, msg->rip_cmd, dir2, 89718316Swollman naddr_ntoa(who->sin_addr.s_addr), 89818316Swollman ntohs(who->sin_port), 89918316Swollman size); 90018316Swollman return; 90118316Swollman } 90218316Swollman 90318316Swollman (void)fprintf(ftrace, "%s RIPv%d %s %s %s.%d%s%s\n", 90418316Swollman dir1, msg->rip_vers, ripcmds[msg->rip_cmd], dir2, 90518316Swollman naddr_ntoa(who->sin_addr.s_addr), ntohs(who->sin_port), 90618316Swollman ifp ? " via " : "", ifp ? ifp->int_name : ""); 90718316Swollman if (!TRACECONTENTS) 90818316Swollman return; 90918316Swollman 91019880Swollman seen_route = 0; 91118316Swollman switch (msg->rip_cmd) { 91218316Swollman case RIPCMD_REQUEST: 91318316Swollman case RIPCMD_RESPONSE: 91418316Swollman n = msg->rip_nets; 91518316Swollman lim = (struct netinfo *)((char*)msg + size); 91618316Swollman for (; n < lim; n++) { 91719880Swollman if (!seen_route 91819880Swollman && n->n_family == RIP_AF_UNSPEC 91918316Swollman && ntohl(n->n_metric) == HOPCNT_INFINITY 92019880Swollman && msg->rip_cmd == RIPCMD_REQUEST 92119880Swollman && (n+1 == lim 92219880Swollman || (n+2 == lim 92319880Swollman && (n+1)->n_family == RIP_AF_AUTH))) { 92418316Swollman (void)fputs("\tQUERY ", ftrace); 92518316Swollman if (n->n_dst != 0) 92618316Swollman (void)fprintf(ftrace, "%s ", 92718316Swollman naddr_ntoa(n->n_dst)); 92818316Swollman if (n->n_mask != 0) 92918316Swollman (void)fprintf(ftrace, "mask=%#x ", 93018316Swollman (u_int)ntohl(n->n_mask)); 93118316Swollman if (n->n_nhop != 0) 93219880Swollman (void)fprintf(ftrace, "nhop=%s ", 93318316Swollman naddr_ntoa(n->n_nhop)); 93418316Swollman if (n->n_tag != 0) 93519880Swollman (void)fprintf(ftrace, "tag=%#x ", 93618316Swollman ntohs(n->n_tag)); 93718316Swollman (void)fputc('\n',ftrace); 93818316Swollman continue; 93918316Swollman } 94018316Swollman 94118316Swollman if (n->n_family == RIP_AF_AUTH) { 94219880Swollman if (NA->a_type == RIP_AUTH_PW 94319880Swollman && n == msg->rip_nets) { 94419880Swollman (void)fprintf(ftrace, "\tPassword" 94519880Swollman " Authentication:" 94619880Swollman " \"%s\"\n", 94719880Swollman qstring(NA->au.au_pw, 94819880Swollman RIP_AUTH_PW_LEN)); 94919880Swollman continue; 95019880Swollman } 95119880Swollman 95219880Swollman if (NA->a_type == RIP_AUTH_MD5 95319880Swollman && n == msg->rip_nets) { 95419880Swollman (void)fprintf(ftrace, 95546303Smarkm "\tMD5 Auth" 95646303Smarkm " pkt_len=%d KeyID=%u" 95746303Smarkm " auth_len=%d" 95846303Smarkm " seqno=%#x" 95919880Swollman " rsvd=%#x,%#x\n", 96046303Smarkm ntohs(NA->au.a_md5.md5_pkt_len), 96146303Smarkm NA->au.a_md5.md5_keyid, 96246303Smarkm NA->au.a_md5.md5_auth_len, 96346303Smarkm (int)ntohl(NA->au.a_md5.md5_seqno), 96446303Smarkm (int)ntohs(NA->au.a_md5.rsvd[0]), 96546303Smarkm (int)ntohs(NA->au.a_md5.rsvd[1])); 96619880Swollman continue; 96719880Swollman } 96818316Swollman (void)fprintf(ftrace, 96946303Smarkm "\tAuthentication type %d: ", 97019880Swollman ntohs(NA->a_type)); 97118316Swollman for (i = 0; 97246303Smarkm i < (int)sizeof(NA->au.au_pw); 97318316Swollman i++) 97418316Swollman (void)fprintf(ftrace, "%02x ", 97519880Swollman NA->au.au_pw[i]); 97618316Swollman (void)fputc('\n',ftrace); 97718316Swollman continue; 97818316Swollman } 97918316Swollman 98019880Swollman seen_route = 1; 98118316Swollman if (n->n_family != RIP_AF_INET) { 98218316Swollman (void)fprintf(ftrace, 98319880Swollman "\t(af %d) %-18s mask=%#x ", 98418316Swollman ntohs(n->n_family), 98518316Swollman naddr_ntoa(n->n_dst), 98618316Swollman (u_int)ntohl(n->n_mask)); 98718316Swollman } else if (msg->rip_vers == RIPv1) { 98818316Swollman (void)fprintf(ftrace, "\t%-18s ", 98918316Swollman addrname(n->n_dst, 99018316Swollman ntohl(n->n_mask), 99118316Swollman n->n_mask==0 ? 2 : 1)); 99218316Swollman } else { 99318316Swollman (void)fprintf(ftrace, "\t%-18s ", 99418316Swollman addrname(n->n_dst, 99518316Swollman ntohl(n->n_mask), 99618316Swollman n->n_mask==0 ? 2 : 0)); 99718316Swollman } 99818316Swollman (void)fprintf(ftrace, "metric=%-2d ", 99918316Swollman (u_int)ntohl(n->n_metric)); 100018316Swollman if (n->n_nhop != 0) 100118316Swollman (void)fprintf(ftrace, " nhop=%s ", 100218316Swollman naddr_ntoa(n->n_nhop)); 100318316Swollman if (n->n_tag != 0) 100418316Swollman (void)fprintf(ftrace, "tag=%#x", 100518316Swollman ntohs(n->n_tag)); 100618316Swollman (void)fputc('\n',ftrace); 100718316Swollman } 100818316Swollman if (size != (char *)n - (char *)msg) 100918316Swollman (void)fprintf(ftrace, "truncated record, len %d\n", 101018316Swollman size); 101118316Swollman break; 101218316Swollman 101318316Swollman case RIPCMD_TRACEON: 101420339Swollman fprintf(ftrace, "\tfile=\"%.*s\"\n", size-4, 101520339Swollman msg->rip_tracefile); 101618316Swollman break; 101718316Swollman 101818316Swollman case RIPCMD_TRACEOFF: 101918316Swollman break; 102018316Swollman } 102118316Swollman} 1022