10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 30Sstevel@tonic-gate * Use is subject to license terms. 40Sstevel@tonic-gate * 50Sstevel@tonic-gate * Copyright (c) 1983, 1988, 1993 60Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 90Sstevel@tonic-gate * modification, are permitted provided that the following conditions 100Sstevel@tonic-gate * are met: 110Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 120Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 130Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 140Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 150Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 160Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 170Sstevel@tonic-gate * must display the following acknowledgment: 180Sstevel@tonic-gate * This product includes software developed by the University of 190Sstevel@tonic-gate * California, Berkeley and its contributors. 200Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors 210Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 220Sstevel@tonic-gate * without specific prior written permission. 230Sstevel@tonic-gate * 240Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 250Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 260Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 270Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 280Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 290Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 300Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 310Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 320Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 330Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 340Sstevel@tonic-gate * SUCH DAMAGE. 350Sstevel@tonic-gate * 360Sstevel@tonic-gate * $FreeBSD: src/sbin/routed/trace.c,v 1.6 2000/08/11 08:24:38 sheldonh Exp $ 370Sstevel@tonic-gate */ 380Sstevel@tonic-gate 390Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 400Sstevel@tonic-gate 410Sstevel@tonic-gate #include "defs.h" 420Sstevel@tonic-gate #include "pathnames.h" 430Sstevel@tonic-gate #include <signal.h> 440Sstevel@tonic-gate #include <sys/stat.h> 450Sstevel@tonic-gate #include <sys/signal.h> 460Sstevel@tonic-gate #include <strings.h> 470Sstevel@tonic-gate #include <fcntl.h> 480Sstevel@tonic-gate #include <protocols/routed.h> 490Sstevel@tonic-gate 500Sstevel@tonic-gate #define NRECORDS 50 /* size of circular trace buffer */ 510Sstevel@tonic-gate 520Sstevel@tonic-gate int tracelevel, new_tracelevel; 530Sstevel@tonic-gate FILE *ftrace = stdout; /* output trace file */ 540Sstevel@tonic-gate static const char *sigtrace_pat = "%s"; 550Sstevel@tonic-gate static char savetracename[MAXPATHLEN+1]; 560Sstevel@tonic-gate static char *ripcmds[RIPCMD_MAX] = 570Sstevel@tonic-gate {"#0", "REQUEST", "RESPONSE", "TRACEON", "TRACEOFF", "POLL", 580Sstevel@tonic-gate "POLLENTRY"}; 590Sstevel@tonic-gate char inittracename[MAXPATHLEN+1]; 600Sstevel@tonic-gate static boolean_t file_trace; /* 1=tracing to file, not stdout */ 610Sstevel@tonic-gate 620Sstevel@tonic-gate static void tmsg(const char *, ...); 630Sstevel@tonic-gate 640Sstevel@tonic-gate const char * 650Sstevel@tonic-gate rip_strerror(int err) 660Sstevel@tonic-gate { 670Sstevel@tonic-gate const char *cp = strerror(err); 680Sstevel@tonic-gate static char msgbuf[64]; 690Sstevel@tonic-gate 700Sstevel@tonic-gate if (cp == NULL) { 710Sstevel@tonic-gate if (err == 0) { 720Sstevel@tonic-gate cp = "success"; 730Sstevel@tonic-gate } else { 740Sstevel@tonic-gate (void) snprintf(msgbuf, sizeof (msgbuf), 750Sstevel@tonic-gate "unknown error %d", err); 760Sstevel@tonic-gate cp = msgbuf; 770Sstevel@tonic-gate } 780Sstevel@tonic-gate } 790Sstevel@tonic-gate return (cp); 800Sstevel@tonic-gate } 810Sstevel@tonic-gate 820Sstevel@tonic-gate /* convert IP address to a string, but not into a single buffer */ 830Sstevel@tonic-gate char * 840Sstevel@tonic-gate naddr_ntoa(in_addr_t a) 850Sstevel@tonic-gate { 860Sstevel@tonic-gate #define NUM_BUFS 4 870Sstevel@tonic-gate static int bufno; 880Sstevel@tonic-gate static struct { 890Sstevel@tonic-gate char str[INET_ADDRSTRLEN]; /* xxx.xxx.xxx.xxx\0 */ 900Sstevel@tonic-gate } bufs[NUM_BUFS]; 910Sstevel@tonic-gate char *s; 920Sstevel@tonic-gate struct in_addr addr; 930Sstevel@tonic-gate 940Sstevel@tonic-gate addr.s_addr = a; 950Sstevel@tonic-gate s = strcpy(bufs[bufno].str, inet_ntoa(addr)); 960Sstevel@tonic-gate bufno = (bufno+1) % NUM_BUFS; 970Sstevel@tonic-gate return (s); 980Sstevel@tonic-gate #undef NUM_BUFS 990Sstevel@tonic-gate } 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate const char * 1030Sstevel@tonic-gate saddr_ntoa(struct sockaddr_storage *ss) 1040Sstevel@tonic-gate { 1050Sstevel@tonic-gate return (ss == NULL) ? "?" : naddr_ntoa(S_ADDR(ss)); 1060Sstevel@tonic-gate } 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate static char * 1100Sstevel@tonic-gate ts(time_t secs) 1110Sstevel@tonic-gate { 1120Sstevel@tonic-gate static char s[20]; 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate secs += epoch.tv_sec; 1150Sstevel@tonic-gate (void) strftime(s, sizeof (s), "%T", localtime(&secs)); 1160Sstevel@tonic-gate return (s); 1170Sstevel@tonic-gate } 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate static char * 1200Sstevel@tonic-gate ts_full(struct timeval *tv) 1210Sstevel@tonic-gate { 1220Sstevel@tonic-gate static char s[32]; 1230Sstevel@tonic-gate time_t secs; 1240Sstevel@tonic-gate int len; 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate secs = tv->tv_sec + epoch.tv_sec; 1270Sstevel@tonic-gate (void) strftime(s, sizeof (s), "%Y/%m/%d %T", localtime(&secs)); 1280Sstevel@tonic-gate len = strlen(s); 1290Sstevel@tonic-gate (void) snprintf(s + len, sizeof (s) - len, ".%06ld", tv->tv_usec); 1300Sstevel@tonic-gate return (s); 1310Sstevel@tonic-gate } 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate /* 1340Sstevel@tonic-gate * On each event, display a time stamp. 1350Sstevel@tonic-gate * This assumes that 'now' is update once for each event, and 1360Sstevel@tonic-gate * that at least now.tv_usec changes. 1370Sstevel@tonic-gate */ 1380Sstevel@tonic-gate static struct timeval lastlog_time; 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate void 1410Sstevel@tonic-gate lastlog(void) 1420Sstevel@tonic-gate { 1430Sstevel@tonic-gate if (lastlog_time.tv_sec != now.tv_sec || 1440Sstevel@tonic-gate lastlog_time.tv_usec != now.tv_usec) { 1450Sstevel@tonic-gate (void) fprintf(ftrace, "-- %s --\n", ts_full(&now)); 1460Sstevel@tonic-gate lastlog_time = now; 1470Sstevel@tonic-gate } 1480Sstevel@tonic-gate } 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate static void 1520Sstevel@tonic-gate tmsg(const char *p, ...) 1530Sstevel@tonic-gate { 1540Sstevel@tonic-gate va_list args; 1550Sstevel@tonic-gate 1560Sstevel@tonic-gate if (ftrace != NULL) { 1570Sstevel@tonic-gate lastlog(); 1580Sstevel@tonic-gate va_start(args, p); 1590Sstevel@tonic-gate (void) vfprintf(ftrace, p, args); 1600Sstevel@tonic-gate (void) fputc('\n', ftrace); 1610Sstevel@tonic-gate (void) fflush(ftrace); 1620Sstevel@tonic-gate (void) va_end(args); 1630Sstevel@tonic-gate } 1640Sstevel@tonic-gate } 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate 1670Sstevel@tonic-gate void 1680Sstevel@tonic-gate trace_close(int zap_stdio) 1690Sstevel@tonic-gate { 1700Sstevel@tonic-gate int fd; 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate (void) fflush(stdout); 1740Sstevel@tonic-gate (void) fflush(stderr); 1750Sstevel@tonic-gate 1760Sstevel@tonic-gate if (ftrace != NULL && zap_stdio) { 1770Sstevel@tonic-gate if (ftrace != stdout) 1780Sstevel@tonic-gate (void) fclose(ftrace); 1790Sstevel@tonic-gate ftrace = NULL; 1800Sstevel@tonic-gate fd = open("/dev/null", O_RDWR); 1810Sstevel@tonic-gate if (isatty(STDIN_FILENO)) 1820Sstevel@tonic-gate (void) dup2(fd, STDIN_FILENO); 1830Sstevel@tonic-gate if (isatty(STDOUT_FILENO)) 1840Sstevel@tonic-gate (void) dup2(fd, STDOUT_FILENO); 1850Sstevel@tonic-gate if (isatty(STDERR_FILENO)) 1860Sstevel@tonic-gate (void) dup2(fd, STDERR_FILENO); 1870Sstevel@tonic-gate (void) close(fd); 1880Sstevel@tonic-gate } 1890Sstevel@tonic-gate lastlog_time.tv_sec = 0; 1900Sstevel@tonic-gate } 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate 1930Sstevel@tonic-gate void 1940Sstevel@tonic-gate trace_flush(void) 1950Sstevel@tonic-gate { 1960Sstevel@tonic-gate if (ftrace != NULL) { 1970Sstevel@tonic-gate (void) fflush(ftrace); 1980Sstevel@tonic-gate if (ferror(ftrace)) 1990Sstevel@tonic-gate trace_off("tracing off: %s", 2000Sstevel@tonic-gate rip_strerror(ferror(ftrace))); 2010Sstevel@tonic-gate } 2020Sstevel@tonic-gate } 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate 2050Sstevel@tonic-gate void 2060Sstevel@tonic-gate trace_off(const char *p, ...) 2070Sstevel@tonic-gate { 2080Sstevel@tonic-gate va_list args; 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate if (ftrace != NULL) { 2120Sstevel@tonic-gate lastlog(); 2130Sstevel@tonic-gate va_start(args, p); 2140Sstevel@tonic-gate (void) vfprintf(ftrace, p, args); 2150Sstevel@tonic-gate (void) fputc('\n', ftrace); 2160Sstevel@tonic-gate (void) va_end(args); 2170Sstevel@tonic-gate } 2180Sstevel@tonic-gate trace_close(file_trace); 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate new_tracelevel = tracelevel = 0; 2210Sstevel@tonic-gate } 2220Sstevel@tonic-gate 2230Sstevel@tonic-gate 2240Sstevel@tonic-gate /* log a change in tracing */ 2250Sstevel@tonic-gate void 2260Sstevel@tonic-gate tracelevel_msg(const char *pat, 2270Sstevel@tonic-gate int dump) /* -1=no dump, 0=default, 1=force */ 2280Sstevel@tonic-gate { 2290Sstevel@tonic-gate static const char *off_msgs[MAX_TRACELEVEL] = { 2300Sstevel@tonic-gate "Tracing actions stopped", 2310Sstevel@tonic-gate "Tracing packets stopped", 2320Sstevel@tonic-gate "Tracing packet contents stopped", 2330Sstevel@tonic-gate "Tracing kernel changes stopped", 2340Sstevel@tonic-gate "Tracing routing socket messages stopped", 2350Sstevel@tonic-gate }; 2360Sstevel@tonic-gate static const char *on_msgs[MAX_TRACELEVEL] = { 2370Sstevel@tonic-gate "Tracing actions started", 2380Sstevel@tonic-gate "Tracing packets started", 2390Sstevel@tonic-gate "Tracing packet contents started", 2400Sstevel@tonic-gate "Tracing kernel changes started", 2410Sstevel@tonic-gate "Tracing routing socket messages started", 2420Sstevel@tonic-gate }; 2430Sstevel@tonic-gate uint_t old_tracelevel = tracelevel; 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate if (new_tracelevel < 0) 2470Sstevel@tonic-gate new_tracelevel = 0; 2480Sstevel@tonic-gate else if (new_tracelevel > MAX_TRACELEVEL) 2490Sstevel@tonic-gate new_tracelevel = MAX_TRACELEVEL; 2500Sstevel@tonic-gate 2510Sstevel@tonic-gate if (new_tracelevel < tracelevel) { 2520Sstevel@tonic-gate if (new_tracelevel <= 0) { 2530Sstevel@tonic-gate trace_off(pat, off_msgs[0]); 2540Sstevel@tonic-gate } else { 2550Sstevel@tonic-gate do { 2560Sstevel@tonic-gate tmsg(pat, off_msgs[tracelevel]); 2570Sstevel@tonic-gate } while (--tracelevel != new_tracelevel); 2580Sstevel@tonic-gate } 2590Sstevel@tonic-gate 2600Sstevel@tonic-gate } else if (new_tracelevel > tracelevel) { 2610Sstevel@tonic-gate do { 2620Sstevel@tonic-gate tmsg(pat, on_msgs[tracelevel++]); 2630Sstevel@tonic-gate } while (tracelevel != new_tracelevel); 2640Sstevel@tonic-gate } 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate if (dump > 0 || 2670Sstevel@tonic-gate (dump == 0 && old_tracelevel == 0 && tracelevel != 0)) 2680Sstevel@tonic-gate trace_dump(); 2690Sstevel@tonic-gate } 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate void 2720Sstevel@tonic-gate set_tracefile(const char *filename, 2730Sstevel@tonic-gate const char *pat, 2740Sstevel@tonic-gate int dump) /* -1=no dump, 0=default, 1=force */ 2750Sstevel@tonic-gate { 2760Sstevel@tonic-gate struct stat stbuf; 2770Sstevel@tonic-gate struct stat stbuf2; 2780Sstevel@tonic-gate FILE *n_ftrace; 2790Sstevel@tonic-gate const char *fn; 2800Sstevel@tonic-gate int nfd; 2810Sstevel@tonic-gate boolean_t allow_create; 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate /* 2840Sstevel@tonic-gate * main() calls this routine with "dump == -1". All others 2850Sstevel@tonic-gate * call it with 0, so we take dump == -1 to mean "can create 2860Sstevel@tonic-gate * the file." 2870Sstevel@tonic-gate */ 2880Sstevel@tonic-gate allow_create = (dump == -1); 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate /* 2910Sstevel@tonic-gate * Allow a null filename to increase the level if the trace file 2920Sstevel@tonic-gate * is already open or if coming from a trusted source, such as 2930Sstevel@tonic-gate * a signal or the command line. 2940Sstevel@tonic-gate */ 2950Sstevel@tonic-gate if (filename == NULL || filename[0] == '\0') { 2960Sstevel@tonic-gate filename = NULL; 2970Sstevel@tonic-gate if (ftrace == NULL) { 2980Sstevel@tonic-gate if (inittracename[0] == '\0') { 2990Sstevel@tonic-gate msglog("missing trace file name"); 3000Sstevel@tonic-gate return; 3010Sstevel@tonic-gate } 3020Sstevel@tonic-gate fn = inittracename; 3030Sstevel@tonic-gate } else { 3040Sstevel@tonic-gate goto set_tracelevel; 3050Sstevel@tonic-gate } 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate } else if (strcmp(filename, "dump/../table") == 0) { 3080Sstevel@tonic-gate trace_dump(); 3090Sstevel@tonic-gate return; 3100Sstevel@tonic-gate 3110Sstevel@tonic-gate } else { 3120Sstevel@tonic-gate /* 3130Sstevel@tonic-gate * Allow the file specified with "-T file" to be reopened, 3140Sstevel@tonic-gate * but require all other names specified over the net to 3150Sstevel@tonic-gate * match the official path. The path can specify a directory 3160Sstevel@tonic-gate * in which the file is to be created. 3170Sstevel@tonic-gate */ 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate if (strcmp(filename, inittracename) != 0) { 3200Sstevel@tonic-gate if (strncmp(filename, PATH_TRACE, 3210Sstevel@tonic-gate sizeof (PATH_TRACE)-1) != 0 || 3220Sstevel@tonic-gate (strstr(filename, "../") != NULL)) { 3230Sstevel@tonic-gate msglog("wrong trace file \"%s\"", filename); 3240Sstevel@tonic-gate return; 3250Sstevel@tonic-gate } 3260Sstevel@tonic-gate if (stat(PATH_TRACE, &stbuf) == -1) { 3270Sstevel@tonic-gate fn = PATH_TRACE; 3280Sstevel@tonic-gate goto missing_file; 3290Sstevel@tonic-gate } 3300Sstevel@tonic-gate if (filename[sizeof (PATH_TRACE) - 1] != '\0' && 3310Sstevel@tonic-gate (filename[sizeof (PATH_TRACE) - 1] != '/' || 3320Sstevel@tonic-gate !S_ISDIR(stbuf.st_mode))) { 3330Sstevel@tonic-gate goto bad_file_type; 3340Sstevel@tonic-gate } 3350Sstevel@tonic-gate if (S_ISDIR(stbuf.st_mode)) 3360Sstevel@tonic-gate allow_create = _B_TRUE; 3370Sstevel@tonic-gate } 3380Sstevel@tonic-gate 3390Sstevel@tonic-gate fn = filename; 3400Sstevel@tonic-gate } 3410Sstevel@tonic-gate /* fn cannot be null here */ 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate /* If the new tracefile exists, it must be a regular file. */ 3440Sstevel@tonic-gate if (lstat(fn, &stbuf) == -1) { 3450Sstevel@tonic-gate if (!allow_create) 3460Sstevel@tonic-gate goto missing_file; 3470Sstevel@tonic-gate nfd = open(fn, O_CREAT|O_EXCL|O_WRONLY, 0644); 3480Sstevel@tonic-gate if (nfd != -1 && fstat(nfd, &stbuf) == -1) { 3490Sstevel@tonic-gate (void) close(nfd); 3500Sstevel@tonic-gate goto missing_file; 3510Sstevel@tonic-gate } 3520Sstevel@tonic-gate } else if (S_ISREG(stbuf.st_mode)) { 3530Sstevel@tonic-gate nfd = open(fn, O_APPEND|O_WRONLY, 0644); 3540Sstevel@tonic-gate } else { 3550Sstevel@tonic-gate goto bad_file_type; 3560Sstevel@tonic-gate } 3570Sstevel@tonic-gate 3580Sstevel@tonic-gate if (nfd == -1 || (n_ftrace = fdopen(nfd, "a")) == NULL) { 3590Sstevel@tonic-gate msglog("failed to open trace file \"%s\" %s", fn, 3600Sstevel@tonic-gate rip_strerror(errno)); 3610Sstevel@tonic-gate if (fn == inittracename) 3620Sstevel@tonic-gate inittracename[0] = '\0'; 3630Sstevel@tonic-gate if (nfd != -1) 3640Sstevel@tonic-gate (void) close(nfd); 3650Sstevel@tonic-gate return; 3660Sstevel@tonic-gate } 3670Sstevel@tonic-gate 3680Sstevel@tonic-gate if (fstat(nfd, &stbuf2) == -1 || !S_ISREG(stbuf2.st_mode) || 3690Sstevel@tonic-gate stbuf2.st_dev != stbuf.st_dev || stbuf2.st_ino != stbuf.st_ino) { 3700Sstevel@tonic-gate msglog("trace file \"%s\" moved", fn); 3710Sstevel@tonic-gate (void) fclose(n_ftrace); 3720Sstevel@tonic-gate return; 3730Sstevel@tonic-gate } 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate tmsg("switch to trace file %s", fn); 3760Sstevel@tonic-gate trace_close(file_trace = _B_TRUE); 3770Sstevel@tonic-gate (void) dup2(nfd, STDOUT_FILENO); 3780Sstevel@tonic-gate (void) dup2(nfd, STDERR_FILENO); 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate if (fn != savetracename) 3810Sstevel@tonic-gate (void) strlcpy(savetracename, fn, sizeof (savetracename) - 1); 3820Sstevel@tonic-gate ftrace = n_ftrace; 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate set_tracelevel: 3850Sstevel@tonic-gate if (new_tracelevel == 0 || filename == NULL) 3860Sstevel@tonic-gate new_tracelevel++; 3870Sstevel@tonic-gate tracelevel_msg(pat, dump != 0 ? dump : (filename != NULL)); 3880Sstevel@tonic-gate return; 3890Sstevel@tonic-gate 3900Sstevel@tonic-gate missing_file: 3910Sstevel@tonic-gate msglog("trace \"%s\" missing", fn); 3920Sstevel@tonic-gate return; 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate bad_file_type: 3950Sstevel@tonic-gate msglog("wrong type (%#x) of trace file \"%s\"", stbuf.st_mode, fn); 3960Sstevel@tonic-gate } 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate 3990Sstevel@tonic-gate /* ARGSUSED */ 4000Sstevel@tonic-gate void 4010Sstevel@tonic-gate sigtrace_more(int s) 4020Sstevel@tonic-gate { 4030Sstevel@tonic-gate new_tracelevel++; 4040Sstevel@tonic-gate sigtrace_pat = "SIGUSR1: %s"; 4050Sstevel@tonic-gate if (signal(s, sigtrace_more) == SIG_ERR) 4060Sstevel@tonic-gate msglog("signal: %s", rip_strerror(errno)); 4070Sstevel@tonic-gate } 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate /* ARGSUSED */ 4110Sstevel@tonic-gate void 4120Sstevel@tonic-gate sigtrace_less(int s) 4130Sstevel@tonic-gate { 4140Sstevel@tonic-gate new_tracelevel--; 4150Sstevel@tonic-gate sigtrace_pat = "SIGUSR2: %s"; 4160Sstevel@tonic-gate if (signal(s, sigtrace_less) == SIG_ERR) 4170Sstevel@tonic-gate msglog("signal: %s", rip_strerror(errno)); 4180Sstevel@tonic-gate } 4190Sstevel@tonic-gate 4200Sstevel@tonic-gate /* ARGSUSED */ 4210Sstevel@tonic-gate void 4220Sstevel@tonic-gate sigtrace_dump(int s) 4230Sstevel@tonic-gate { 4240Sstevel@tonic-gate trace_dump(); 4250Sstevel@tonic-gate if (signal(s, sigtrace_dump) == SIG_ERR) 4260Sstevel@tonic-gate msglog("signal: %s", rip_strerror(errno)); 4270Sstevel@tonic-gate } 4280Sstevel@tonic-gate 4290Sstevel@tonic-gate /* Set tracing after a signal. */ 4300Sstevel@tonic-gate void 4310Sstevel@tonic-gate set_tracelevel(void) 4320Sstevel@tonic-gate { 4330Sstevel@tonic-gate if (new_tracelevel == tracelevel) 4340Sstevel@tonic-gate return; 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate /* 4370Sstevel@tonic-gate * If tracing entirely off, and there was no tracefile specified 4380Sstevel@tonic-gate * on the command line, then leave it off. 4390Sstevel@tonic-gate */ 4400Sstevel@tonic-gate if (new_tracelevel > tracelevel && ftrace == NULL) { 4410Sstevel@tonic-gate if (savetracename[0] != '\0') { 4420Sstevel@tonic-gate set_tracefile(savetracename, sigtrace_pat, 0); 4430Sstevel@tonic-gate } else if (inittracename[0] != '\0') { 4440Sstevel@tonic-gate set_tracefile(inittracename, sigtrace_pat, 0); 4450Sstevel@tonic-gate } else { 4460Sstevel@tonic-gate new_tracelevel = 0; 4470Sstevel@tonic-gate return; 4480Sstevel@tonic-gate } 4490Sstevel@tonic-gate } else { 4500Sstevel@tonic-gate tracelevel_msg(sigtrace_pat, 0); 4510Sstevel@tonic-gate } 4520Sstevel@tonic-gate } 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate 4550Sstevel@tonic-gate /* display an address */ 4560Sstevel@tonic-gate char * 4570Sstevel@tonic-gate addrname(in_addr_t addr, /* in network byte order */ 4580Sstevel@tonic-gate in_addr_t mask, 4590Sstevel@tonic-gate int force) /* 0=show mask if nonstandard, */ 4600Sstevel@tonic-gate { /* 1=always show mask, 2=never */ 4610Sstevel@tonic-gate #define NUM_BUFS 4 4620Sstevel@tonic-gate static int bufno; 4630Sstevel@tonic-gate static struct { 4640Sstevel@tonic-gate /* 4650Sstevel@tonic-gate * this array can hold either of the following strings terminated 4660Sstevel@tonic-gate * by a null character: 4670Sstevel@tonic-gate * "xxx.xxx.xxx.xxx/xx" 4680Sstevel@tonic-gate * "xxx.xxx.xxx.xxx (mask xxx.xxx.xxx.xxx)" 4690Sstevel@tonic-gate * 4700Sstevel@tonic-gate */ 4710Sstevel@tonic-gate char str[2*INET_ADDRSTRLEN + sizeof (" (mask )")]; 4720Sstevel@tonic-gate } bufs[NUM_BUFS]; 4730Sstevel@tonic-gate char *s, *sp; 4740Sstevel@tonic-gate in_addr_t dmask; 4750Sstevel@tonic-gate int i, len; 4760Sstevel@tonic-gate struct in_addr tmp_addr; 4770Sstevel@tonic-gate 4780Sstevel@tonic-gate tmp_addr.s_addr = addr; 4790Sstevel@tonic-gate len = strlcpy(bufs[bufno].str, inet_ntoa(tmp_addr), 4800Sstevel@tonic-gate sizeof (bufs[bufno].str)); 4810Sstevel@tonic-gate s = bufs[bufno].str; 4820Sstevel@tonic-gate bufno = (bufno+1) % NUM_BUFS; 4830Sstevel@tonic-gate 4840Sstevel@tonic-gate if (force == 1 || (force == 0 && mask != std_mask(addr))) { 4850Sstevel@tonic-gate sp = &s[strlen(s)]; 4860Sstevel@tonic-gate 4870Sstevel@tonic-gate dmask = mask & -mask; 4880Sstevel@tonic-gate if (mask + dmask == 0) { 4890Sstevel@tonic-gate i = ffs(mask); 4900Sstevel@tonic-gate (void) snprintf(sp, 4910Sstevel@tonic-gate (sizeof (bufs[bufno].str) - len), "/%d", 4920Sstevel@tonic-gate (NBBY * sizeof (in_addr_t) + 1) - i); 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate } else { 4950Sstevel@tonic-gate (void) snprintf(sp, 4960Sstevel@tonic-gate (sizeof (bufs[bufno].str) - len), " (mask %s)", 4970Sstevel@tonic-gate naddr_ntoa(htonl(mask))); 4980Sstevel@tonic-gate } 4990Sstevel@tonic-gate } 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate return (s); 5020Sstevel@tonic-gate #undef NUM_BUFS 5030Sstevel@tonic-gate } 5040Sstevel@tonic-gate 5050Sstevel@tonic-gate 5060Sstevel@tonic-gate /* display a bit-field */ 5070Sstevel@tonic-gate struct or_bits { 5080Sstevel@tonic-gate uint8_t origin; 5090Sstevel@tonic-gate const char *origin_name; 5100Sstevel@tonic-gate }; 5110Sstevel@tonic-gate 5120Sstevel@tonic-gate static struct or_bits origin_bits[] = { 5130Sstevel@tonic-gate { RO_RIP, "RIP" }, 5140Sstevel@tonic-gate { RO_RDISC, "RDISC" }, 5150Sstevel@tonic-gate { RO_STATIC, "STATIC" }, 5160Sstevel@tonic-gate { RO_LOOPBCK, "LOOPBCK" }, 5170Sstevel@tonic-gate { RO_PTOPT, "PTOPT" }, 5180Sstevel@tonic-gate { RO_NET_SYN, "NET_SYN" }, 5190Sstevel@tonic-gate { RO_IF, "IF" }, 5200Sstevel@tonic-gate { RO_FILE, "FILE" }, 5210Sstevel@tonic-gate { RO_NONE, " " }, 5220Sstevel@tonic-gate { 0, NULL} 5230Sstevel@tonic-gate }; 5240Sstevel@tonic-gate 5250Sstevel@tonic-gate /* display a bit-field */ 5260Sstevel@tonic-gate struct bits { 527192Scarlsonj uint64_t bits_mask; 528192Scarlsonj uint64_t bits_clear; 529192Scarlsonj const char *bits_name; 5300Sstevel@tonic-gate }; 5310Sstevel@tonic-gate 5320Sstevel@tonic-gate static struct bits if_bits[] = { 5330Sstevel@tonic-gate { IFF_BROADCAST, 0, "BROADCAST" }, 5340Sstevel@tonic-gate { IFF_DEBUG, 0, "DEBUG" }, 5350Sstevel@tonic-gate { IFF_LOOPBACK, 0, "LOOPBACK" }, 5360Sstevel@tonic-gate { IFF_POINTOPOINT, 0, "POINTOPOINT" }, 5370Sstevel@tonic-gate { IFF_NOTRAILERS, 0, "NOTRAILERS" }, 5380Sstevel@tonic-gate { IFF_RUNNING, 0, "RUNNING" }, 5390Sstevel@tonic-gate { IFF_NOARP, 0, "NOARP" }, 5400Sstevel@tonic-gate { IFF_PROMISC, 0, "PROMISC" }, 5410Sstevel@tonic-gate { IFF_ALLMULTI, 0, "ALLMULTI" }, 5420Sstevel@tonic-gate { IFF_INTELLIGENT, 0, "INTELLIGENT" }, 5430Sstevel@tonic-gate { IFF_MULTICAST, 0, "MULTICAST" }, 5440Sstevel@tonic-gate { IFF_MULTI_BCAST, 0, "MULTI_BCAST" }, 5450Sstevel@tonic-gate { IFF_UNNUMBERED, 0, "UNNUMBERED" }, 5460Sstevel@tonic-gate { IFF_DHCPRUNNING, 0, "DHCP" }, 5470Sstevel@tonic-gate { IFF_PRIVATE, 0, "PRIVATE" }, 5480Sstevel@tonic-gate { IFF_NOXMIT, 0, "NOXMIT" }, 5490Sstevel@tonic-gate { IFF_NOLOCAL, 0, "NOLOCAL" }, 5500Sstevel@tonic-gate { IFF_DEPRECATED, 0, "DEPRECATED" }, 5510Sstevel@tonic-gate { IFF_ADDRCONF, 0, "ADDRCONF" }, 5520Sstevel@tonic-gate { IFF_ROUTER, 0, "ROUTER" }, 5530Sstevel@tonic-gate { IFF_NONUD, 0, "NONUD" }, 5540Sstevel@tonic-gate { IFF_ANYCAST, 0, "ANYCAST" }, 5550Sstevel@tonic-gate { IFF_NORTEXCH, 0, "NORTEXCH" }, 5560Sstevel@tonic-gate { IFF_IPV4, 0, "IPv4" }, 5570Sstevel@tonic-gate { IFF_IPV6, 0, "IPv6" }, 5580Sstevel@tonic-gate { IFF_MIPRUNNING, 0, "MIP" }, 5590Sstevel@tonic-gate { IFF_NOFAILOVER, 0, "NOFAILOVER" }, 5600Sstevel@tonic-gate { IFF_FAILED, 0, "FAILED" }, 5610Sstevel@tonic-gate { IFF_STANDBY, 0, "STANDBY" }, 5620Sstevel@tonic-gate { IFF_INACTIVE, 0, "INACTIVE" }, 5630Sstevel@tonic-gate { IFF_OFFLINE, 0, "OFFLINE" }, 5640Sstevel@tonic-gate { IFF_XRESOLV, 0, "XRESOLV" }, 5650Sstevel@tonic-gate { IFF_COS_ENABLED, 0, "CoS" }, 5660Sstevel@tonic-gate { IFF_PREFERRED, 0, "PREFERRED" }, 5670Sstevel@tonic-gate { IFF_TEMPORARY, 0, "TEMPORARY" }, 5680Sstevel@tonic-gate { IFF_FIXEDMTU, 0, "FIXEDMTU" }, 5690Sstevel@tonic-gate { IFF_VIRTUAL, 0, "VIRTUAL"}, 5700Sstevel@tonic-gate { 0, 0, NULL} 5710Sstevel@tonic-gate }; 5720Sstevel@tonic-gate 5730Sstevel@tonic-gate static struct bits is_bits[] = { 5740Sstevel@tonic-gate { IS_ALIAS, 0, "ALIAS" }, 5750Sstevel@tonic-gate { IS_SUBNET, 0, "" }, 5760Sstevel@tonic-gate { IS_REMOTE, (IS_NO_RDISC | 5770Sstevel@tonic-gate IS_BCAST_RDISC), "REMOTE" }, 5780Sstevel@tonic-gate { IS_PASSIVE, (IS_NO_RDISC | 5790Sstevel@tonic-gate IS_NO_RIP | 5800Sstevel@tonic-gate IS_NO_SUPER_AG | 5810Sstevel@tonic-gate IS_PM_RDISC | 5820Sstevel@tonic-gate IS_NO_AG), "PASSIVE" }, 5830Sstevel@tonic-gate { IS_EXTERNAL, 0, "EXTERNAL" }, 5840Sstevel@tonic-gate { IS_CHECKED, 0, "" }, 5850Sstevel@tonic-gate { IS_ALL_HOSTS, 0, "" }, 5860Sstevel@tonic-gate { IS_ALL_ROUTERS, 0, "" }, 5870Sstevel@tonic-gate { IS_DISTRUST, 0, "DISTRUST" }, 5880Sstevel@tonic-gate { IS_BROKE, IS_SICK, "BROKEN" }, 5890Sstevel@tonic-gate { IS_SICK, 0, "SICK" }, 5900Sstevel@tonic-gate { IS_DUP, 0, "DUPLICATE" }, 5910Sstevel@tonic-gate { IS_REDIRECT_OK, 0, "REDIRECT_OK" }, 5920Sstevel@tonic-gate { IS_NEED_NET_SYN, 0, "" }, 5930Sstevel@tonic-gate { IS_NO_AG, IS_NO_SUPER_AG, "NO_AG" }, 5940Sstevel@tonic-gate { IS_NO_SUPER_AG, 0, "NO_SUPER_AG" }, 5950Sstevel@tonic-gate { (IS_NO_RIPV1_IN | 5960Sstevel@tonic-gate IS_NO_RIPV2_IN | 5970Sstevel@tonic-gate IS_NO_RIPV1_OUT | 5980Sstevel@tonic-gate IS_NO_RIPV2_OUT), 0, "NO_RIP" }, 5990Sstevel@tonic-gate { (IS_NO_RIPV1_IN | 6000Sstevel@tonic-gate IS_NO_RIPV1_OUT), 0, "RIPV2" }, 6010Sstevel@tonic-gate { IS_NO_RIPV1_IN, 0, "NO_RIPV1_IN" }, 6020Sstevel@tonic-gate { IS_NO_RIPV2_IN, 0, "NO_RIPV2_IN" }, 6030Sstevel@tonic-gate { IS_NO_RIPV1_OUT, 0, "NO_RIPV1_OUT" }, 6040Sstevel@tonic-gate { IS_NO_RIPV2_OUT, 0, "NO_RIPV2_OUT" }, 6050Sstevel@tonic-gate { IS_NO_RIP_MCAST, 0, "NO_RIP_MCAST" }, 6060Sstevel@tonic-gate { (IS_NO_ADV_IN | 6070Sstevel@tonic-gate IS_NO_SOL_OUT | 6080Sstevel@tonic-gate IS_NO_ADV_OUT), IS_BCAST_RDISC, "NO_RDISC" }, 6090Sstevel@tonic-gate { IS_NO_SOL_OUT, 0, "NO_SOLICIT" }, 6100Sstevel@tonic-gate { IS_SOL_OUT, 0, "SEND_SOLICIT" }, 6110Sstevel@tonic-gate { IS_NO_ADV_OUT, IS_BCAST_RDISC, "NO_RDISC_ADV" }, 6120Sstevel@tonic-gate { IS_ADV_OUT, 0, "RDISC_ADV" }, 6130Sstevel@tonic-gate { IS_BCAST_RDISC, 0, "BCAST_RDISC" }, 6140Sstevel@tonic-gate { IS_PM_RDISC, 0, "" }, 6150Sstevel@tonic-gate { IS_NO_HOST, 0, "NO_HOST" }, 6160Sstevel@tonic-gate { IS_SUPPRESS_RDISC, 0, "SUPPRESS_RDISC" }, 6170Sstevel@tonic-gate { IS_FLUSH_RDISC, 0, "FLUSH_RDISC" }, 6180Sstevel@tonic-gate { 0, 0, NULL} 6190Sstevel@tonic-gate }; 6200Sstevel@tonic-gate 6210Sstevel@tonic-gate static struct bits rs_bits[] = { 6220Sstevel@tonic-gate { RS_IF, 0, "IF" }, 6230Sstevel@tonic-gate { RS_NET_INT, RS_NET_SYN, "NET_INT" }, 6240Sstevel@tonic-gate { RS_NET_SYN, 0, "NET_SYN" }, 6250Sstevel@tonic-gate { RS_SUBNET, 0, "" }, 6260Sstevel@tonic-gate { RS_LOCAL, 0, "LOCAL" }, 6270Sstevel@tonic-gate { RS_MHOME, 0, "MHOME" }, 6280Sstevel@tonic-gate { RS_STATIC, 0, "STATIC" }, 6290Sstevel@tonic-gate { RS_NOPROPAGATE, 0, "NOPROP" }, 6300Sstevel@tonic-gate { RS_BADIF, 0, "BADIF" }, 6310Sstevel@tonic-gate { 0, 0, NULL} 6320Sstevel@tonic-gate }; 6330Sstevel@tonic-gate 6340Sstevel@tonic-gate static struct bits ks_bits[] = { 6350Sstevel@tonic-gate { KS_NEW, 0, "NEW" }, 6360Sstevel@tonic-gate { KS_DELETE, 0, "DELETE" }, 6370Sstevel@tonic-gate { KS_ADD, 0, "ADD" }, 6380Sstevel@tonic-gate { KS_CHANGE, 0, "CHANGE" }, 6390Sstevel@tonic-gate { KS_DEL_ADD, 0, "DEL_ADD" }, 6400Sstevel@tonic-gate { KS_STATIC, 0, "STATIC" }, 6410Sstevel@tonic-gate { KS_GATEWAY, 0, "GATEWAY" }, 6420Sstevel@tonic-gate { KS_DYNAMIC, 0, "DYNAMIC" }, 6430Sstevel@tonic-gate { KS_DELETED, 0, "DELETED" }, 6440Sstevel@tonic-gate { KS_PRIVATE, 0, "PRIVATE" }, 6450Sstevel@tonic-gate { KS_CHECK, 0, "CHECK" }, 6460Sstevel@tonic-gate { KS_IF, 0, "IF" }, 6470Sstevel@tonic-gate { KS_PASSIVE, 0, "PASSIVE" }, 6480Sstevel@tonic-gate { KS_DEPRE_IF, 0, "DEPRE_IF" }, 6490Sstevel@tonic-gate { KS_FILE, 0, "FILE" }, 6500Sstevel@tonic-gate { 0, 0, NULL} 6510Sstevel@tonic-gate }; 6520Sstevel@tonic-gate 6530Sstevel@tonic-gate static void 6540Sstevel@tonic-gate trace_bits(const struct bits *tbl, 655192Scarlsonj uint64_t field, 6560Sstevel@tonic-gate boolean_t force) 6570Sstevel@tonic-gate { 658192Scarlsonj uint64_t b; 6590Sstevel@tonic-gate char c; 6600Sstevel@tonic-gate 6610Sstevel@tonic-gate if (force) { 6620Sstevel@tonic-gate (void) putc('<', ftrace); 6630Sstevel@tonic-gate c = '\0'; 6640Sstevel@tonic-gate } else { 6650Sstevel@tonic-gate c = '<'; 6660Sstevel@tonic-gate } 6670Sstevel@tonic-gate 6680Sstevel@tonic-gate while (field != 0 && 6690Sstevel@tonic-gate (b = tbl->bits_mask) != 0) { 6700Sstevel@tonic-gate if ((b & field) == b) { 6710Sstevel@tonic-gate if (tbl->bits_name[0] != '\0') { 6720Sstevel@tonic-gate if (c != '\0') 6730Sstevel@tonic-gate (void) putc(c, ftrace); 6740Sstevel@tonic-gate (void) fprintf(ftrace, "%s", tbl->bits_name); 6750Sstevel@tonic-gate c = '|'; 6760Sstevel@tonic-gate } 6770Sstevel@tonic-gate field &= ~(b | tbl->bits_clear); 6780Sstevel@tonic-gate } 6790Sstevel@tonic-gate tbl++; 6800Sstevel@tonic-gate } 6810Sstevel@tonic-gate if (field != 0) { 6820Sstevel@tonic-gate if (c != '\0') 6830Sstevel@tonic-gate (void) putc(c, ftrace); 684192Scarlsonj (void) fprintf(ftrace, "%#llx", field); 6850Sstevel@tonic-gate c = '|'; 6860Sstevel@tonic-gate } 6870Sstevel@tonic-gate 6880Sstevel@tonic-gate if (c != '<' || force) 6890Sstevel@tonic-gate (void) fputs("> ", ftrace); 6900Sstevel@tonic-gate } 6910Sstevel@tonic-gate 6920Sstevel@tonic-gate static char * 6930Sstevel@tonic-gate trace_string(const struct bits *tbl, uint_t field, boolean_t force) 6940Sstevel@tonic-gate { 6950Sstevel@tonic-gate const struct bits *tbp; 6960Sstevel@tonic-gate char *sbuf, *cp, chr; 6970Sstevel@tonic-gate size_t slen; 6980Sstevel@tonic-gate 6990Sstevel@tonic-gate /* minimum default string */ 7000Sstevel@tonic-gate slen = sizeof ("<0x12345678>"); 7010Sstevel@tonic-gate for (tbp = tbl; tbp->bits_mask != 0; tbp++) 7020Sstevel@tonic-gate if (tbp->bits_name[0] != '\0') 7030Sstevel@tonic-gate slen += strlen(tbp->bits_name) + 1; 7040Sstevel@tonic-gate if ((sbuf = malloc(slen)) == NULL) 7050Sstevel@tonic-gate return (NULL); 7060Sstevel@tonic-gate cp = sbuf; 7070Sstevel@tonic-gate 7080Sstevel@tonic-gate if (force) { 7090Sstevel@tonic-gate *cp++ = '<'; 7100Sstevel@tonic-gate chr = '\0'; 7110Sstevel@tonic-gate } else { 7120Sstevel@tonic-gate chr = '<'; 7130Sstevel@tonic-gate } 7140Sstevel@tonic-gate 7150Sstevel@tonic-gate while (field != 0 && tbl->bits_mask != 0) { 7160Sstevel@tonic-gate if ((tbl->bits_mask & field) == tbl->bits_mask) { 7170Sstevel@tonic-gate if (tbl->bits_name[0] != '\0') { 7180Sstevel@tonic-gate if (chr != '\0') 7190Sstevel@tonic-gate *cp++ = chr; 7200Sstevel@tonic-gate (void) strcpy(cp, tbl->bits_name); 7210Sstevel@tonic-gate cp += strlen(tbl->bits_name); 7220Sstevel@tonic-gate chr = '|'; 7230Sstevel@tonic-gate } 7240Sstevel@tonic-gate field &= ~(tbl->bits_mask | tbl->bits_clear); 7250Sstevel@tonic-gate } 7260Sstevel@tonic-gate tbl++; 7270Sstevel@tonic-gate } 7280Sstevel@tonic-gate if (field != 0) { 7290Sstevel@tonic-gate if (chr != '\0') 7300Sstevel@tonic-gate *cp++ = chr; 7310Sstevel@tonic-gate cp += sprintf(cp, "%#x", field); 7320Sstevel@tonic-gate chr = '|'; 7330Sstevel@tonic-gate } 7340Sstevel@tonic-gate 7350Sstevel@tonic-gate if (chr != '<' || force) 7360Sstevel@tonic-gate *cp++ = '>'; 7370Sstevel@tonic-gate *cp = '\0'; 7380Sstevel@tonic-gate return (sbuf); 7390Sstevel@tonic-gate } 7400Sstevel@tonic-gate 7410Sstevel@tonic-gate char * 7420Sstevel@tonic-gate if_bit_string(uint_t field, boolean_t force) 7430Sstevel@tonic-gate { 7440Sstevel@tonic-gate return (trace_string(if_bits, field, force)); 7450Sstevel@tonic-gate } 7460Sstevel@tonic-gate 7470Sstevel@tonic-gate char * 7480Sstevel@tonic-gate rtname(in_addr_t dst, 7490Sstevel@tonic-gate in_addr_t mask, 7500Sstevel@tonic-gate in_addr_t gate) 7510Sstevel@tonic-gate { 7520Sstevel@tonic-gate static char buf[sizeof ("xxx.xxx.xxx.xxx/xx-->xxx.xxx.xxx.xxx")]; 7530Sstevel@tonic-gate int i; 7540Sstevel@tonic-gate 7550Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%-16s-->", addrname(dst, mask, 0)); 7560Sstevel@tonic-gate i = strlen(buf); 7570Sstevel@tonic-gate (void) snprintf(&buf[i], (sizeof (buf) -i), "%-*s", 15+24-MAX(24, i), 7580Sstevel@tonic-gate naddr_ntoa(gate)); 7590Sstevel@tonic-gate return (buf); 7600Sstevel@tonic-gate } 7610Sstevel@tonic-gate 7620Sstevel@tonic-gate 7630Sstevel@tonic-gate static void 7640Sstevel@tonic-gate print_rts(struct rt_spare *rts, 7650Sstevel@tonic-gate int force_metric, /* -1=suppress, 0=default */ 7660Sstevel@tonic-gate int force_ifp, /* -1=suppress, 0=default */ 7670Sstevel@tonic-gate int force_router, /* -1=suppress, 0=default, 1=display */ 7680Sstevel@tonic-gate int force_tag, /* -1=suppress, 0=default, 1=display */ 7690Sstevel@tonic-gate int force_time) /* 0=suppress, 1=display */ 7700Sstevel@tonic-gate { 7710Sstevel@tonic-gate int i; 7720Sstevel@tonic-gate 7730Sstevel@tonic-gate if (force_metric >= 0) 7740Sstevel@tonic-gate (void) fprintf(ftrace, "metric=%-2d ", rts->rts_metric); 7750Sstevel@tonic-gate if (force_ifp >= 0) 7760Sstevel@tonic-gate (void) fprintf(ftrace, "%s ", (rts->rts_ifp == 0 ? 7770Sstevel@tonic-gate "if?" : rts->rts_ifp->int_name)); 7780Sstevel@tonic-gate if (force_router > 0 || 7790Sstevel@tonic-gate (force_router == 0 && rts->rts_router != rts->rts_gate)) 7800Sstevel@tonic-gate (void) fprintf(ftrace, "router=%s ", 7810Sstevel@tonic-gate naddr_ntoa(rts->rts_router)); 7820Sstevel@tonic-gate if (force_time > 0) 7830Sstevel@tonic-gate (void) fprintf(ftrace, "%s ", ts(rts->rts_time)); 7840Sstevel@tonic-gate if (force_tag > 0 || 7850Sstevel@tonic-gate (force_tag == 0 && rts->rts_tag != 0)) 7860Sstevel@tonic-gate (void) fprintf(ftrace, "tag=%#x ", ntohs(rts->rts_tag)); 7870Sstevel@tonic-gate if (rts->rts_de_ag != 0) { 7880Sstevel@tonic-gate for (i = 1; (uint_t)(1 << i) <= rts->rts_de_ag; i++) 7890Sstevel@tonic-gate continue; 7900Sstevel@tonic-gate (void) fprintf(ftrace, "de_ag=%d ", i); 7910Sstevel@tonic-gate } 7920Sstevel@tonic-gate (void) fprintf(ftrace, "flags 0x%x ", rts->rts_flags); 7930Sstevel@tonic-gate 7940Sstevel@tonic-gate } 7950Sstevel@tonic-gate 7960Sstevel@tonic-gate 7970Sstevel@tonic-gate static void 7980Sstevel@tonic-gate print_rtsorigin(const struct or_bits *tbl, uint8_t route_origin) 7990Sstevel@tonic-gate { 8000Sstevel@tonic-gate 8010Sstevel@tonic-gate uint8_t tblentry; 8020Sstevel@tonic-gate while ((tblentry = tbl->origin) != 0) { 8030Sstevel@tonic-gate if (tblentry == route_origin) { 8040Sstevel@tonic-gate (void) fprintf(ftrace, "origin=%s ", tbl->origin_name); 8050Sstevel@tonic-gate } 8060Sstevel@tonic-gate tbl++; 8070Sstevel@tonic-gate } 8080Sstevel@tonic-gate } 8090Sstevel@tonic-gate 8100Sstevel@tonic-gate 8110Sstevel@tonic-gate void 8120Sstevel@tonic-gate trace_if(const char *act, struct interface *ifp) 8130Sstevel@tonic-gate { 8140Sstevel@tonic-gate if (!TRACEACTIONS || ftrace == NULL) 8150Sstevel@tonic-gate return; 8160Sstevel@tonic-gate 8170Sstevel@tonic-gate lastlog(); 8180Sstevel@tonic-gate (void) fprintf(ftrace, "%-3s interface %-4s #%-3d ", act, 8190Sstevel@tonic-gate ifp->int_name, 8200Sstevel@tonic-gate ifp->int_phys != NULL ? ifp->int_phys->phyi_index : 0); 8210Sstevel@tonic-gate (void) fprintf(ftrace, "%-15s-->%-15s", 8220Sstevel@tonic-gate naddr_ntoa(ifp->int_addr), 8230Sstevel@tonic-gate addrname(((ifp->int_if_flags & IFF_POINTOPOINT) ? 8240Sstevel@tonic-gate ifp->int_dstaddr : htonl(ifp->int_net)), 8250Sstevel@tonic-gate ifp->int_mask, 1)); 8260Sstevel@tonic-gate if (ifp->int_metric != 0) 8270Sstevel@tonic-gate (void) fprintf(ftrace, " metric=%d", ifp->int_metric); 8280Sstevel@tonic-gate if (!IS_RIP_OUT_OFF(ifp->int_state) && 8290Sstevel@tonic-gate ifp->int_d_metric != 0) 8300Sstevel@tonic-gate (void) fprintf(ftrace, " fake_default=%d", ifp->int_d_metric); 8310Sstevel@tonic-gate (void) fputs("\n ", ftrace); 8320Sstevel@tonic-gate trace_bits(if_bits, ifp->int_if_flags, _B_FALSE); 8330Sstevel@tonic-gate trace_bits(is_bits, ifp->int_state, _B_FALSE); 8340Sstevel@tonic-gate (void) fputc('\n', ftrace); 8350Sstevel@tonic-gate } 8360Sstevel@tonic-gate 8370Sstevel@tonic-gate void 8380Sstevel@tonic-gate trace_khash(const struct khash *krt) 8390Sstevel@tonic-gate { 8400Sstevel@tonic-gate if (ftrace == NULL) 8410Sstevel@tonic-gate return; 8420Sstevel@tonic-gate 8430Sstevel@tonic-gate lastlog(); 8440Sstevel@tonic-gate (void) fprintf(ftrace, " %-15s-->%-15s metric=%d ", 8450Sstevel@tonic-gate addrname(krt->k_dst, krt->k_mask, 0), 8460Sstevel@tonic-gate naddr_ntoa(krt->k_gate), krt->k_metric); 8470Sstevel@tonic-gate if (krt->k_ifp != NULL) 8480Sstevel@tonic-gate (void) fprintf(ftrace, "ifp %s ", krt->k_ifp->int_name); 8490Sstevel@tonic-gate else 8500Sstevel@tonic-gate (void) fprintf(ftrace, "ifp NULL "); 8510Sstevel@tonic-gate (void) fprintf(ftrace, "%s ", ts(krt->k_keep)); 8520Sstevel@tonic-gate (void) fprintf(ftrace, "%s ", ts(krt->k_redirect_time)); 8530Sstevel@tonic-gate trace_bits(ks_bits, krt->k_state, _B_TRUE); 8540Sstevel@tonic-gate (void) fputc('\n', ftrace); 8550Sstevel@tonic-gate } 8560Sstevel@tonic-gate 8570Sstevel@tonic-gate void 8580Sstevel@tonic-gate trace_dr(const struct dr *drp) 8590Sstevel@tonic-gate { 8600Sstevel@tonic-gate if (ftrace == NULL) 8610Sstevel@tonic-gate return; 8620Sstevel@tonic-gate 8630Sstevel@tonic-gate lastlog(); 8640Sstevel@tonic-gate (void) fprintf(ftrace, " %-4s %-15s %s ", 8650Sstevel@tonic-gate drp->dr_ifp != NULL ? drp->dr_ifp->int_name : "?", 8660Sstevel@tonic-gate naddr_ntoa(drp->dr_gate), ts(drp->dr_ts)); 8670Sstevel@tonic-gate (void) fprintf(ftrace, "%s %d %u\n", ts(drp->dr_life), 8680Sstevel@tonic-gate SIGN_PREF(drp->dr_recv_pref), drp->dr_pref); 8690Sstevel@tonic-gate } 8700Sstevel@tonic-gate 8710Sstevel@tonic-gate void 8720Sstevel@tonic-gate trace_upslot(struct rt_entry *rt, 8730Sstevel@tonic-gate struct rt_spare *rts, 8740Sstevel@tonic-gate struct rt_spare *new) 8750Sstevel@tonic-gate { 8760Sstevel@tonic-gate if (!TRACEACTIONS || ftrace == NULL) 8770Sstevel@tonic-gate return; 8780Sstevel@tonic-gate 8790Sstevel@tonic-gate if (rts->rts_gate == new->rts_gate && 8800Sstevel@tonic-gate rts->rts_router == new->rts_router && 8810Sstevel@tonic-gate rts->rts_metric == new->rts_metric && 8820Sstevel@tonic-gate rts->rts_tag == new->rts_tag && 8830Sstevel@tonic-gate rts->rts_de_ag == new->rts_de_ag) 8840Sstevel@tonic-gate return; 8850Sstevel@tonic-gate 8860Sstevel@tonic-gate lastlog(); 8870Sstevel@tonic-gate if (new->rts_gate == 0) { 8880Sstevel@tonic-gate (void) fprintf(ftrace, "Del #%d %-35s ", 8890Sstevel@tonic-gate (int)(rts - rt->rt_spares), 8900Sstevel@tonic-gate rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate)); 8910Sstevel@tonic-gate print_rts(rts, 0, 0, 0, 0, 8920Sstevel@tonic-gate (rts != rt->rt_spares || 8930Sstevel@tonic-gate AGE_RT(rt->rt_state, rts->rts_origin, new->rts_ifp))); 8940Sstevel@tonic-gate 8950Sstevel@tonic-gate } else if (rts->rts_gate != RIP_DEFAULT) { 8960Sstevel@tonic-gate (void) fprintf(ftrace, "Chg #%d %-35s ", 8970Sstevel@tonic-gate (int)(rts - rt->rt_spares), 8980Sstevel@tonic-gate rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate)); 8990Sstevel@tonic-gate print_rts(rts, 0, 0, 9000Sstevel@tonic-gate rts->rts_gate != new->rts_gate, 9010Sstevel@tonic-gate rts->rts_tag != new->rts_tag, 9020Sstevel@tonic-gate rts != rt->rt_spares || AGE_RT(rt->rt_state, 9030Sstevel@tonic-gate rts->rts_origin, rt->rt_ifp)); 9040Sstevel@tonic-gate 9050Sstevel@tonic-gate (void) fprintf(ftrace, "\n %19s%-16s ", "", 9060Sstevel@tonic-gate (new->rts_gate != rts->rts_gate ? 9070Sstevel@tonic-gate naddr_ntoa(new->rts_gate) : "")); 9080Sstevel@tonic-gate print_rts(new, 9090Sstevel@tonic-gate ((new->rts_metric == rts->rts_metric) ? -1 : 0), 9100Sstevel@tonic-gate ((new->rts_ifp == rts->rts_ifp) ? -1 : 0), 9110Sstevel@tonic-gate 0, 9120Sstevel@tonic-gate rts->rts_tag != new->rts_tag, 9130Sstevel@tonic-gate (new->rts_time != rts->rts_time && 9140Sstevel@tonic-gate (rts != rt->rt_spares || 9150Sstevel@tonic-gate AGE_RT(rt->rt_state, new->rts_origin, new->rts_ifp)))); 9160Sstevel@tonic-gate 9170Sstevel@tonic-gate } else { 9180Sstevel@tonic-gate (void) fprintf(ftrace, "Add #%d %-35s ", 9190Sstevel@tonic-gate (int)(rts - rt->rt_spares), 9200Sstevel@tonic-gate rtname(rt->rt_dst, rt->rt_mask, new->rts_gate)); 9210Sstevel@tonic-gate print_rts(new, 0, 0, 0, 0, 9220Sstevel@tonic-gate (rts != rt->rt_spares || 9230Sstevel@tonic-gate AGE_RT(rt->rt_state, new->rts_origin, new->rts_ifp))); 9240Sstevel@tonic-gate } 9250Sstevel@tonic-gate (void) fputc('\n', ftrace); 9260Sstevel@tonic-gate } 9270Sstevel@tonic-gate 9280Sstevel@tonic-gate 9290Sstevel@tonic-gate /* miscellaneous message checked by the caller */ 9300Sstevel@tonic-gate void 9310Sstevel@tonic-gate trace_misc(const char *p, ...) 9320Sstevel@tonic-gate { 9330Sstevel@tonic-gate va_list args; 9340Sstevel@tonic-gate 9350Sstevel@tonic-gate if (ftrace == NULL) 9360Sstevel@tonic-gate return; 9370Sstevel@tonic-gate 9380Sstevel@tonic-gate lastlog(); 9390Sstevel@tonic-gate va_start(args, p); 9400Sstevel@tonic-gate (void) vfprintf(ftrace, p, args); 9410Sstevel@tonic-gate (void) fputc('\n', ftrace); 9420Sstevel@tonic-gate (void) va_end(args); 9430Sstevel@tonic-gate } 9440Sstevel@tonic-gate 9450Sstevel@tonic-gate 9460Sstevel@tonic-gate /* display a message if tracing actions */ 9470Sstevel@tonic-gate void 9480Sstevel@tonic-gate trace_act(const char *p, ...) 9490Sstevel@tonic-gate { 9500Sstevel@tonic-gate va_list args; 9510Sstevel@tonic-gate 9520Sstevel@tonic-gate if (!TRACEACTIONS || ftrace == NULL) 9530Sstevel@tonic-gate return; 9540Sstevel@tonic-gate 9550Sstevel@tonic-gate lastlog(); 9560Sstevel@tonic-gate va_start(args, p); 9570Sstevel@tonic-gate (void) vfprintf(ftrace, p, args); 9580Sstevel@tonic-gate (void) fputc('\n', ftrace); 9590Sstevel@tonic-gate (void) va_end(args); 9600Sstevel@tonic-gate } 9610Sstevel@tonic-gate 9620Sstevel@tonic-gate 9630Sstevel@tonic-gate /* display a message if tracing packets */ 9640Sstevel@tonic-gate void 9650Sstevel@tonic-gate trace_pkt(const char *p, ...) 9660Sstevel@tonic-gate { 9670Sstevel@tonic-gate va_list args; 9680Sstevel@tonic-gate 9690Sstevel@tonic-gate if (!TRACEPACKETS || ftrace == NULL) 9700Sstevel@tonic-gate return; 9710Sstevel@tonic-gate 9720Sstevel@tonic-gate lastlog(); 9730Sstevel@tonic-gate va_start(args, p); 9740Sstevel@tonic-gate (void) vfprintf(ftrace, p, args); 9750Sstevel@tonic-gate (void) fputc('\n', ftrace); 9760Sstevel@tonic-gate (void) va_end(args); 9770Sstevel@tonic-gate } 9780Sstevel@tonic-gate 9790Sstevel@tonic-gate 9800Sstevel@tonic-gate void 9810Sstevel@tonic-gate trace_change(struct rt_entry *rt, 9820Sstevel@tonic-gate uint16_t state, 9830Sstevel@tonic-gate struct rt_spare *new, 9840Sstevel@tonic-gate const char *label) 9850Sstevel@tonic-gate { 9860Sstevel@tonic-gate if (ftrace == NULL) 9870Sstevel@tonic-gate return; 9880Sstevel@tonic-gate 9890Sstevel@tonic-gate if (rt->rt_metric == new->rts_metric && 9900Sstevel@tonic-gate rt->rt_gate == new->rts_gate && 9910Sstevel@tonic-gate rt->rt_router == new->rts_router && 9920Sstevel@tonic-gate rt->rt_state == state && 9930Sstevel@tonic-gate rt->rt_tag == new->rts_tag && 9940Sstevel@tonic-gate rt->rt_de_ag == new->rts_de_ag) 9950Sstevel@tonic-gate return; 9960Sstevel@tonic-gate 9970Sstevel@tonic-gate lastlog(); 9980Sstevel@tonic-gate (void) fprintf(ftrace, "%s %-35s ", 9990Sstevel@tonic-gate label, 10000Sstevel@tonic-gate rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate)); 10010Sstevel@tonic-gate print_rts(rt->rt_spares, 10020Sstevel@tonic-gate 0, 0, 0, 0, AGE_RT(rt->rt_state, rt->rt_spares->rts_origin, 10030Sstevel@tonic-gate rt->rt_ifp)); 10040Sstevel@tonic-gate print_rtsorigin(origin_bits, rt->rt_spares->rts_origin); 10050Sstevel@tonic-gate trace_bits(rs_bits, rt->rt_state, rt->rt_state != state); 10060Sstevel@tonic-gate 10070Sstevel@tonic-gate (void) fprintf(ftrace, "\n%*s %19s%-16s ", 10080Sstevel@tonic-gate strlen(label), "", "", 10090Sstevel@tonic-gate (rt->rt_gate != new->rts_gate ? 10100Sstevel@tonic-gate naddr_ntoa(new->rts_gate) : "")); 10110Sstevel@tonic-gate print_rts(new, 10120Sstevel@tonic-gate ((new->rts_metric == rt->rt_metric) ? -1 : 0), 10130Sstevel@tonic-gate ((new->rts_ifp == rt->rt_ifp) ? -1 : 0), 10140Sstevel@tonic-gate 0, 10150Sstevel@tonic-gate rt->rt_tag != new->rts_tag, 10160Sstevel@tonic-gate (rt->rt_time != new->rts_time && 10170Sstevel@tonic-gate AGE_RT(rt->rt_state, new->rts_origin, new->rts_ifp))); 10180Sstevel@tonic-gate if (rt->rt_state != state) { 10190Sstevel@tonic-gate print_rtsorigin(origin_bits, new->rts_origin); 10200Sstevel@tonic-gate trace_bits(rs_bits, state, _B_TRUE); 10210Sstevel@tonic-gate } 10220Sstevel@tonic-gate (void) fputc('\n', ftrace); 10230Sstevel@tonic-gate } 10240Sstevel@tonic-gate 10250Sstevel@tonic-gate 10260Sstevel@tonic-gate void 10270Sstevel@tonic-gate trace_add_del(const char *action, struct rt_entry *rt) 10280Sstevel@tonic-gate { 10290Sstevel@tonic-gate if (ftrace == NULL) 10300Sstevel@tonic-gate return; 10310Sstevel@tonic-gate 10320Sstevel@tonic-gate lastlog(); 10330Sstevel@tonic-gate (void) fprintf(ftrace, "%s %-35s ", 10340Sstevel@tonic-gate action, 10350Sstevel@tonic-gate rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate)); 10360Sstevel@tonic-gate print_rts(rt->rt_spares, 0, 0, 0, 0, AGE_RT(rt->rt_state, 10370Sstevel@tonic-gate rt->rt_spares->rts_origin, rt->rt_ifp)); 10380Sstevel@tonic-gate print_rtsorigin(origin_bits, rt->rt_spares->rts_origin); 10390Sstevel@tonic-gate trace_bits(rs_bits, rt->rt_state, _B_FALSE); 10400Sstevel@tonic-gate (void) fputc('\n', ftrace); 10410Sstevel@tonic-gate } 10420Sstevel@tonic-gate 10430Sstevel@tonic-gate 10440Sstevel@tonic-gate /* ARGSUSED */ 10450Sstevel@tonic-gate static int 10460Sstevel@tonic-gate walk_trace(struct radix_node *rn, 10470Sstevel@tonic-gate void *w) 10480Sstevel@tonic-gate { 10490Sstevel@tonic-gate #define RT ((struct rt_entry *)rn) 10500Sstevel@tonic-gate struct rt_spare *rts; 10510Sstevel@tonic-gate int i; 10520Sstevel@tonic-gate 10530Sstevel@tonic-gate (void) fprintf(ftrace, " %-35s ", 10540Sstevel@tonic-gate rtname(RT->rt_dst, RT->rt_mask, RT->rt_gate)); 10550Sstevel@tonic-gate print_rts(&RT->rt_spares[0], 0, 0, 0, 0, 10560Sstevel@tonic-gate AGE_RT(RT->rt_state, RT->rt_spares[0].rts_origin, RT->rt_ifp)); 10570Sstevel@tonic-gate print_rtsorigin(origin_bits, RT->rt_spares[0].rts_origin); 10580Sstevel@tonic-gate trace_bits(rs_bits, RT->rt_state, _B_FALSE); 10590Sstevel@tonic-gate if (RT->rt_poison_time >= now_garbage && 10600Sstevel@tonic-gate RT->rt_poison_metric < RT->rt_metric) 10610Sstevel@tonic-gate (void) fprintf(ftrace, "pm=%d@%s", 10620Sstevel@tonic-gate RT->rt_poison_metric, ts(RT->rt_poison_time)); 1063*552Ssowmini (void) fprintf(ftrace, "%d spare slots", RT->rt_num_spares); 10640Sstevel@tonic-gate 10650Sstevel@tonic-gate rts = &RT->rt_spares[1]; 10660Sstevel@tonic-gate for (i = 1; i < RT->rt_num_spares; i++, rts++) { 10670Sstevel@tonic-gate if (rts->rts_gate != RIP_DEFAULT) { 10680Sstevel@tonic-gate (void) fprintf(ftrace, "\n #%d%15s%-16s ", 10690Sstevel@tonic-gate i, "", naddr_ntoa(rts->rts_gate)); 10700Sstevel@tonic-gate print_rts(rts, 0, 0, 0, 0, 1); 10710Sstevel@tonic-gate print_rtsorigin(origin_bits, rts->rts_origin); 10720Sstevel@tonic-gate } 10730Sstevel@tonic-gate } 10740Sstevel@tonic-gate (void) fputc('\n', ftrace); 10750Sstevel@tonic-gate 10760Sstevel@tonic-gate return (0); 10770Sstevel@tonic-gate } 10780Sstevel@tonic-gate 10790Sstevel@tonic-gate 10800Sstevel@tonic-gate void 10810Sstevel@tonic-gate trace_dump(void) 10820Sstevel@tonic-gate { 10830Sstevel@tonic-gate struct interface *ifp; 10840Sstevel@tonic-gate 10850Sstevel@tonic-gate if (ftrace == NULL) 10860Sstevel@tonic-gate return; 10870Sstevel@tonic-gate lastlog(); 10880Sstevel@tonic-gate 10890Sstevel@tonic-gate /* 10900Sstevel@tonic-gate * Warning: the rtquery.trace.* family of STC tests depend on 10910Sstevel@tonic-gate * the log file format here. If you need to change this next 10920Sstevel@tonic-gate * message, make sure that you change the TRACE_DUMP variable 10930Sstevel@tonic-gate * as well. 10940Sstevel@tonic-gate */ 10950Sstevel@tonic-gate (void) fputs("current daemon state:\n", ftrace); 10960Sstevel@tonic-gate for (ifp = ifnet; ifp != NULL; ifp = ifp->int_next) 10970Sstevel@tonic-gate trace_if("", ifp); 10980Sstevel@tonic-gate (void) fputs("Routes:\n", ftrace); 10990Sstevel@tonic-gate (void) rn_walktree(rhead, walk_trace, NULL); 11000Sstevel@tonic-gate (void) fputs("Kernel routes:\n", ftrace); 11010Sstevel@tonic-gate kern_dump(); 11020Sstevel@tonic-gate (void) fputs("Discovered routers:\n", ftrace); 11030Sstevel@tonic-gate rdisc_dump(); 11040Sstevel@tonic-gate } 11050Sstevel@tonic-gate 11060Sstevel@tonic-gate 11070Sstevel@tonic-gate void 11080Sstevel@tonic-gate trace_rip(const char *dir1, const char *dir2, 11090Sstevel@tonic-gate struct sockaddr_in *who, 11100Sstevel@tonic-gate struct interface *ifp, 11110Sstevel@tonic-gate struct rip *msg, 11120Sstevel@tonic-gate int size) /* total size of message */ 11130Sstevel@tonic-gate { 11140Sstevel@tonic-gate struct netinfo *n, *lim; 11150Sstevel@tonic-gate #define NA ((struct netauth *)n) 11160Sstevel@tonic-gate int i, seen_route; 11170Sstevel@tonic-gate struct in_addr tmp_mask; 11180Sstevel@tonic-gate 11190Sstevel@tonic-gate if (!TRACEPACKETS || ftrace == NULL) 11200Sstevel@tonic-gate return; 11210Sstevel@tonic-gate 11220Sstevel@tonic-gate lastlog(); 11230Sstevel@tonic-gate if (msg->rip_cmd >= RIPCMD_MAX || msg->rip_vers == 0) { 11240Sstevel@tonic-gate (void) fprintf(ftrace, "%s bad RIPv%d cmd=%d %s" 11250Sstevel@tonic-gate " %s.%d size=%d\n", 11260Sstevel@tonic-gate dir1, msg->rip_vers, msg->rip_cmd, dir2, 11270Sstevel@tonic-gate naddr_ntoa(who->sin_addr.s_addr), 11280Sstevel@tonic-gate ntohs(who->sin_port), 11290Sstevel@tonic-gate size); 11300Sstevel@tonic-gate return; 11310Sstevel@tonic-gate } 11320Sstevel@tonic-gate 11330Sstevel@tonic-gate (void) fprintf(ftrace, "%s RIPv%d %s %s %s.%d%s%s\n", 11340Sstevel@tonic-gate dir1, msg->rip_vers, ripcmds[msg->rip_cmd], dir2, 11350Sstevel@tonic-gate naddr_ntoa(who->sin_addr.s_addr), ntohs(who->sin_port), 11360Sstevel@tonic-gate ifp ? " via " : "", ifp ? ifp->int_name : ""); 11370Sstevel@tonic-gate if (!TRACECONTENTS) 11380Sstevel@tonic-gate return; 11390Sstevel@tonic-gate 11400Sstevel@tonic-gate seen_route = 0; 11410Sstevel@tonic-gate switch (msg->rip_cmd) { 11420Sstevel@tonic-gate case RIPCMD_REQUEST: 11430Sstevel@tonic-gate case RIPCMD_RESPONSE: 11440Sstevel@tonic-gate 11450Sstevel@tonic-gate n = msg->rip_nets; 11460Sstevel@tonic-gate tmp_mask.s_addr = n->n_mask; 11470Sstevel@tonic-gate lim = n + (size - 4) / sizeof (struct netinfo); 11480Sstevel@tonic-gate for (; n < lim; n++) { 11490Sstevel@tonic-gate if (!seen_route && 11500Sstevel@tonic-gate n->n_family == RIP_AF_UNSPEC && 11510Sstevel@tonic-gate ntohl(n->n_metric) == HOPCNT_INFINITY && 11520Sstevel@tonic-gate msg->rip_cmd == RIPCMD_REQUEST && 11530Sstevel@tonic-gate (n+1 == lim || 11540Sstevel@tonic-gate (n+2 == lim && 11550Sstevel@tonic-gate (n+1)->n_family == RIP_AF_AUTH))) { 11560Sstevel@tonic-gate (void) fputs("\tQUERY ", ftrace); 11570Sstevel@tonic-gate if (n->n_dst != 0) 11580Sstevel@tonic-gate (void) fprintf(ftrace, "%s ", 11590Sstevel@tonic-gate naddr_ntoa(n->n_dst)); 11600Sstevel@tonic-gate if (n->n_mask != 0) 11610Sstevel@tonic-gate (void) fprintf(ftrace, "mask=%s ", 11620Sstevel@tonic-gate inet_ntoa(tmp_mask)); 11630Sstevel@tonic-gate if (n->n_nhop != 0) 11640Sstevel@tonic-gate (void) fprintf(ftrace, "nhop=%s ", 11650Sstevel@tonic-gate naddr_ntoa(n->n_nhop)); 11660Sstevel@tonic-gate if (n->n_tag != 0) 11670Sstevel@tonic-gate (void) fprintf(ftrace, "tag=%#x ", 11680Sstevel@tonic-gate ntohs(n->n_tag)); 11690Sstevel@tonic-gate (void) fputc('\n', ftrace); 11700Sstevel@tonic-gate continue; 11710Sstevel@tonic-gate } 11720Sstevel@tonic-gate 11730Sstevel@tonic-gate if (n->n_family == RIP_AF_AUTH) { 11740Sstevel@tonic-gate if (NA->a_type == RIP_AUTH_PW && 11750Sstevel@tonic-gate n == msg->rip_nets) { 11760Sstevel@tonic-gate (void) fprintf(ftrace, "\tPassword" 11770Sstevel@tonic-gate " Authentication:" 11780Sstevel@tonic-gate " \"%s\"\n", 11790Sstevel@tonic-gate qstring(NA->au.au_pw, 11800Sstevel@tonic-gate RIP_AUTH_PW_LEN)); 11810Sstevel@tonic-gate continue; 11820Sstevel@tonic-gate } 11830Sstevel@tonic-gate 11840Sstevel@tonic-gate if (NA->a_type == RIP_AUTH_MD5 && 11850Sstevel@tonic-gate n == msg->rip_nets) { 11860Sstevel@tonic-gate (void) fprintf(ftrace, 11870Sstevel@tonic-gate "\tMD5 Auth" 11880Sstevel@tonic-gate " pkt_len=%d KeyID=%u" 11890Sstevel@tonic-gate " auth_len=%d" 11900Sstevel@tonic-gate " seqno=%#lx" 11910Sstevel@tonic-gate " rsvd=%#x,%#x\n", 11920Sstevel@tonic-gate ntohs(NA->au.a_md5.md5_pkt_len), 11930Sstevel@tonic-gate NA->au.a_md5.md5_keyid, 11940Sstevel@tonic-gate NA->au.a_md5.md5_auth_len, 11950Sstevel@tonic-gate (unsigned long)ntohl(NA->au.a_md5. 11960Sstevel@tonic-gate md5_seqno), 11970Sstevel@tonic-gate ntohs(NA->au.a_md5.rsvd[0]), 11980Sstevel@tonic-gate ntohs(NA->au.a_md5.rsvd[1])); 11990Sstevel@tonic-gate continue; 12000Sstevel@tonic-gate } 12010Sstevel@tonic-gate (void) fprintf(ftrace, 12020Sstevel@tonic-gate "\tAuthentication type %d: ", 12030Sstevel@tonic-gate ntohs(NA->a_type)); 12040Sstevel@tonic-gate for (i = 0; i < (int)sizeof (NA->au.au_pw); 12050Sstevel@tonic-gate i++) 12060Sstevel@tonic-gate (void) fprintf(ftrace, "%02x ", 12070Sstevel@tonic-gate NA->au.au_pw[i]); 12080Sstevel@tonic-gate (void) fputc('\n', ftrace); 12090Sstevel@tonic-gate continue; 12100Sstevel@tonic-gate } 12110Sstevel@tonic-gate 12120Sstevel@tonic-gate seen_route = 1; 12130Sstevel@tonic-gate if (n->n_family != RIP_AF_INET) { 12140Sstevel@tonic-gate (void) fprintf(ftrace, 12150Sstevel@tonic-gate "\t(af %d) %-18s mask=%s ", 12160Sstevel@tonic-gate ntohs(n->n_family), 12170Sstevel@tonic-gate naddr_ntoa(n->n_dst), 12180Sstevel@tonic-gate inet_ntoa(tmp_mask)); 12190Sstevel@tonic-gate } else if (msg->rip_vers == RIPv1) { 12200Sstevel@tonic-gate (void) fprintf(ftrace, "\t%-18s ", 12210Sstevel@tonic-gate addrname(n->n_dst, 12220Sstevel@tonic-gate ntohl(n->n_mask), 12230Sstevel@tonic-gate n->n_mask == 0 ? 2 : 1)); 12240Sstevel@tonic-gate } else { 12250Sstevel@tonic-gate (void) fprintf(ftrace, "\t%-18s ", 12260Sstevel@tonic-gate addrname(n->n_dst, 12270Sstevel@tonic-gate ntohl(n->n_mask), 12280Sstevel@tonic-gate n->n_mask == 0 ? 2 : 0)); 12290Sstevel@tonic-gate } 12300Sstevel@tonic-gate (void) fprintf(ftrace, "metric=%-2lu ", 12310Sstevel@tonic-gate (unsigned long)ntohl(n->n_metric)); 12320Sstevel@tonic-gate if (n->n_nhop != 0) 12330Sstevel@tonic-gate (void) fprintf(ftrace, " nhop=%s ", 12340Sstevel@tonic-gate naddr_ntoa(n->n_nhop)); 12350Sstevel@tonic-gate if (n->n_tag != 0) 12360Sstevel@tonic-gate (void) fprintf(ftrace, "tag=%#x", 12370Sstevel@tonic-gate ntohs(n->n_tag)); 12380Sstevel@tonic-gate (void) fputc('\n', ftrace); 12390Sstevel@tonic-gate } 12400Sstevel@tonic-gate if (size != (char *)n - (char *)msg) 12410Sstevel@tonic-gate (void) fprintf(ftrace, "truncated record, len %d\n", 12420Sstevel@tonic-gate size); 12430Sstevel@tonic-gate break; 12440Sstevel@tonic-gate 12450Sstevel@tonic-gate case RIPCMD_TRACEON: 12460Sstevel@tonic-gate (void) fprintf(ftrace, "\tfile=\"%.*s\"\n", size-4, 12470Sstevel@tonic-gate msg->rip_tracefile); 12480Sstevel@tonic-gate break; 12490Sstevel@tonic-gate 12500Sstevel@tonic-gate case RIPCMD_TRACEOFF: 12510Sstevel@tonic-gate break; 12520Sstevel@tonic-gate } 12530Sstevel@tonic-gate } 1254