1 1.33 maya /* $NetBSD: trace.c,v 1.33 2017/10/02 11:02:19 maya Exp $ */ 2 1.10 cgd 3 1.1 cgd /* 4 1.5 mycroft * Copyright (c) 1983, 1988, 1993 5 1.5 mycroft * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * Redistribution and use in source and binary forms, with or without 8 1.1 cgd * modification, are permitted provided that the following conditions 9 1.1 cgd * are met: 10 1.1 cgd * 1. Redistributions of source code must retain the above copyright 11 1.1 cgd * notice, this list of conditions and the following disclaimer. 12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cgd * notice, this list of conditions and the following disclaimer in the 14 1.1 cgd * documentation and/or other materials provided with the distribution. 15 1.1 cgd * 3. All advertising materials mentioning features or use of this software 16 1.22 christos * must display the following acknowledgment: 17 1.1 cgd * This product includes software developed by the University of 18 1.1 cgd * California, Berkeley and its contributors. 19 1.1 cgd * 4. Neither the name of the University nor the names of its contributors 20 1.1 cgd * may be used to endorse or promote products derived from this software 21 1.1 cgd * without specific prior written permission. 22 1.1 cgd * 23 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 1.1 cgd * SUCH DAMAGE. 34 1.1 cgd */ 35 1.1 cgd 36 1.1 cgd #define RIPCMDS 37 1.1 cgd #include "defs.h" 38 1.14 thorpej #include "pathnames.h" 39 1.1 cgd #include <sys/stat.h> 40 1.14 thorpej #include <sys/signal.h> 41 1.1 cgd #include <fcntl.h> 42 1.14 thorpej 43 1.25 christos #ifdef __NetBSD__ 44 1.33 maya __RCSID("$NetBSD: trace.c,v 1.33 2017/10/02 11:02:19 maya Exp $"); 45 1.25 christos #elif defined(__FreeBSD__) 46 1.25 christos __RCSID("$FreeBSD$"); 47 1.25 christos #else 48 1.27 christos __RCSID("Revision: 2.27 "); 49 1.27 christos #ident "Revision: 2.27 " 50 1.25 christos #endif 51 1.14 thorpej 52 1.1 cgd #define NRECORDS 50 /* size of circular trace buffer */ 53 1.14 thorpej 54 1.16 christos int tracelevel, new_tracelevel; 55 1.14 thorpej FILE *ftrace = stdout; /* output trace file */ 56 1.23 christos static const char *sigtrace_pat = "%s"; 57 1.16 christos static char savetracename[MAXPATHLEN+1]; 58 1.16 christos char inittracename[MAXPATHLEN+1]; 59 1.16 christos int file_trace; /* 1=tracing to file, not stdout */ 60 1.14 thorpej 61 1.16 christos static void trace_dump(void); 62 1.23 christos static void tmsg(const char *, ...) PATTRIB(1,2); 63 1.16 christos 64 1.16 christos 65 1.16 christos /* convert string to printable characters 66 1.16 christos */ 67 1.16 christos static char * 68 1.16 christos qstring(u_char *s, int len) 69 1.16 christos { 70 1.16 christos static char buf[8*20+1]; 71 1.16 christos char *p; 72 1.16 christos u_char *s2, c; 73 1.29 itojun int n; 74 1.16 christos 75 1.16 christos for (p = buf; len != 0 && p < &buf[sizeof(buf)-1]; len--) { 76 1.16 christos c = *s++; 77 1.16 christos if (c == '\0') { 78 1.16 christos for (s2 = s+1; s2 < &s[len]; s2++) { 79 1.16 christos if (*s2 != '\0') 80 1.16 christos break; 81 1.16 christos } 82 1.16 christos if (s2 >= &s[len]) 83 1.16 christos goto exit; 84 1.16 christos } 85 1.14 thorpej 86 1.16 christos if (c >= ' ' && c < 0x7f && c != '\\') { 87 1.16 christos *p++ = c; 88 1.16 christos continue; 89 1.16 christos } 90 1.16 christos *p++ = '\\'; 91 1.16 christos switch (c) { 92 1.16 christos case '\\': 93 1.16 christos *p++ = '\\'; 94 1.16 christos break; 95 1.16 christos case '\n': 96 1.16 christos *p++= 'n'; 97 1.16 christos break; 98 1.16 christos case '\r': 99 1.16 christos *p++= 'r'; 100 1.16 christos break; 101 1.16 christos case '\t': 102 1.16 christos *p++ = 't'; 103 1.16 christos break; 104 1.16 christos case '\b': 105 1.16 christos *p++ = 'b'; 106 1.16 christos break; 107 1.16 christos default: 108 1.29 itojun n = snprintf(p, sizeof(buf) - (p - buf), "%o", c); 109 1.29 itojun if (n <= 0) 110 1.29 itojun goto exit; 111 1.29 itojun p += n; 112 1.16 christos break; 113 1.16 christos } 114 1.16 christos } 115 1.16 christos exit: 116 1.16 christos *p = '\0'; 117 1.16 christos return buf; 118 1.16 christos } 119 1.15 christos 120 1.14 thorpej 121 1.14 thorpej /* convert IP address to a string, but not into a single buffer 122 1.14 thorpej */ 123 1.14 thorpej char * 124 1.14 thorpej naddr_ntoa(naddr a) 125 1.14 thorpej { 126 1.14 thorpej #define NUM_BUFS 4 127 1.15 christos static int bufno; 128 1.14 thorpej static struct { 129 1.14 thorpej char str[16]; /* xxx.xxx.xxx.xxx\0 */ 130 1.14 thorpej } bufs[NUM_BUFS]; 131 1.15 christos char *s; 132 1.14 thorpej struct in_addr addr; 133 1.14 thorpej 134 1.14 thorpej addr.s_addr = a; 135 1.28 itojun strlcpy(bufs[bufno].str, inet_ntoa(addr), sizeof(bufs[bufno].str)); 136 1.28 itojun s = bufs[bufno].str; 137 1.15 christos bufno = (bufno+1) % NUM_BUFS; 138 1.14 thorpej return s; 139 1.15 christos #undef NUM_BUFS 140 1.14 thorpej } 141 1.14 thorpej 142 1.14 thorpej 143 1.23 christos const char * 144 1.30 christos saddr_ntoa(const struct sockaddr *sa) 145 1.14 thorpej { 146 1.14 thorpej return (sa == 0) ? "?" : naddr_ntoa(S_ADDR(sa)); 147 1.14 thorpej } 148 1.14 thorpej 149 1.14 thorpej 150 1.14 thorpej static char * 151 1.14 thorpej ts(time_t secs) { 152 1.14 thorpej static char s[20]; 153 1.14 thorpej 154 1.14 thorpej secs += epoch.tv_sec; 155 1.22 christos memcpy(s, ctime(&secs)+11, 8); 156 1.14 thorpej s[8] = '\0'; 157 1.33 maya 158 1.14 thorpej return s; 159 1.14 thorpej } 160 1.1 cgd 161 1.7 cgd 162 1.14 thorpej /* On each event, display a time stamp. 163 1.14 thorpej * This assumes that 'now' is update once for each event, and 164 1.14 thorpej * that at least now.tv_usec changes. 165 1.14 thorpej */ 166 1.16 christos static struct timeval lastlog_time; 167 1.16 christos 168 1.7 cgd void 169 1.14 thorpej lastlog(void) 170 1.1 cgd { 171 1.16 christos if (lastlog_time.tv_sec != now.tv_sec 172 1.16 christos || lastlog_time.tv_usec != now.tv_usec) { 173 1.14 thorpej (void)fprintf(ftrace, "-- %s --\n", ts(now.tv_sec)); 174 1.16 christos lastlog_time = now; 175 1.14 thorpej } 176 1.1 cgd } 177 1.1 cgd 178 1.14 thorpej 179 1.14 thorpej static void 180 1.23 christos tmsg(const char *p, ...) 181 1.1 cgd { 182 1.14 thorpej va_list args; 183 1.1 cgd 184 1.14 thorpej if (ftrace != 0) { 185 1.14 thorpej lastlog(); 186 1.14 thorpej va_start(args, p); 187 1.14 thorpej vfprintf(ftrace, p, args); 188 1.26 wiz va_end(args); 189 1.16 christos (void)fputc('\n',ftrace); 190 1.14 thorpej fflush(ftrace); 191 1.1 cgd } 192 1.1 cgd } 193 1.1 cgd 194 1.14 thorpej 195 1.21 thorpej void 196 1.21 thorpej trace_close(int zap_stdio) 197 1.1 cgd { 198 1.14 thorpej int fd; 199 1.14 thorpej 200 1.14 thorpej 201 1.14 thorpej fflush(stdout); 202 1.14 thorpej fflush(stderr); 203 1.1 cgd 204 1.21 thorpej if (ftrace != 0 && zap_stdio) { 205 1.16 christos if (ftrace != stdout) 206 1.16 christos fclose(ftrace); 207 1.16 christos ftrace = 0; 208 1.14 thorpej fd = open(_PATH_DEVNULL, O_RDWR); 209 1.31 christos if (fd == -1) 210 1.31 christos return; 211 1.21 thorpej if (isatty(STDIN_FILENO)) 212 1.21 thorpej (void)dup2(fd, STDIN_FILENO); 213 1.21 thorpej if (isatty(STDOUT_FILENO)) 214 1.21 thorpej (void)dup2(fd, STDOUT_FILENO); 215 1.21 thorpej if (isatty(STDERR_FILENO)) 216 1.21 thorpej (void)dup2(fd, STDERR_FILENO); 217 1.14 thorpej (void)close(fd); 218 1.14 thorpej } 219 1.16 christos lastlog_time.tv_sec = 0; 220 1.1 cgd } 221 1.1 cgd 222 1.14 thorpej 223 1.7 cgd void 224 1.14 thorpej trace_flush(void) 225 1.1 cgd { 226 1.14 thorpej if (ftrace != 0) { 227 1.1 cgd fflush(ftrace); 228 1.14 thorpej if (ferror(ftrace)) 229 1.23 christos trace_off("tracing off: %s", strerror(ferror(ftrace))); 230 1.1 cgd } 231 1.1 cgd } 232 1.1 cgd 233 1.14 thorpej 234 1.1 cgd void 235 1.23 christos trace_off(const char *p, ...) 236 1.1 cgd { 237 1.14 thorpej va_list args; 238 1.1 cgd 239 1.14 thorpej 240 1.14 thorpej if (ftrace != 0) { 241 1.14 thorpej lastlog(); 242 1.14 thorpej va_start(args, p); 243 1.14 thorpej vfprintf(ftrace, p, args); 244 1.26 wiz va_end(args); 245 1.16 christos (void)fputc('\n',ftrace); 246 1.14 thorpej } 247 1.21 thorpej trace_close(file_trace); 248 1.14 thorpej 249 1.14 thorpej new_tracelevel = tracelevel = 0; 250 1.1 cgd } 251 1.1 cgd 252 1.14 thorpej 253 1.16 christos /* log a change in tracing 254 1.16 christos */ 255 1.7 cgd void 256 1.23 christos tracelevel_msg(const char *pat, 257 1.16 christos int dump) /* -1=no dump, 0=default, 1=force */ 258 1.16 christos { 259 1.23 christos static const char *off_msgs[MAX_TRACELEVEL] = { 260 1.16 christos "Tracing actions stopped", 261 1.16 christos "Tracing packets stopped", 262 1.16 christos "Tracing packet contents stopped", 263 1.16 christos "Tracing kernel changes stopped", 264 1.16 christos }; 265 1.23 christos static const char *on_msgs[MAX_TRACELEVEL] = { 266 1.16 christos "Tracing actions started", 267 1.16 christos "Tracing packets started", 268 1.16 christos "Tracing packet contents started", 269 1.16 christos "Tracing kernel changes started", 270 1.16 christos }; 271 1.16 christos u_int old_tracelevel = tracelevel; 272 1.16 christos 273 1.16 christos 274 1.16 christos if (new_tracelevel < 0) 275 1.16 christos new_tracelevel = 0; 276 1.16 christos else if (new_tracelevel > MAX_TRACELEVEL) 277 1.16 christos new_tracelevel = MAX_TRACELEVEL; 278 1.16 christos 279 1.16 christos if (new_tracelevel < tracelevel) { 280 1.16 christos if (new_tracelevel <= 0) { 281 1.16 christos trace_off(pat, off_msgs[0]); 282 1.16 christos } else do { 283 1.16 christos tmsg(pat, off_msgs[tracelevel]); 284 1.16 christos } 285 1.16 christos while (--tracelevel != new_tracelevel); 286 1.16 christos 287 1.16 christos } else if (new_tracelevel > tracelevel) { 288 1.16 christos do { 289 1.16 christos tmsg(pat, on_msgs[tracelevel++]); 290 1.16 christos } while (tracelevel != new_tracelevel); 291 1.16 christos } 292 1.16 christos 293 1.16 christos if (dump > 0 294 1.16 christos || (dump == 0 && old_tracelevel == 0 && tracelevel != 0)) 295 1.16 christos trace_dump(); 296 1.16 christos } 297 1.16 christos 298 1.16 christos 299 1.16 christos void 300 1.23 christos set_tracefile(const char *filename, 301 1.23 christos const char *pat, 302 1.16 christos int dump) /* -1=no dump, 0=default, 1=force */ 303 1.1 cgd { 304 1.14 thorpej struct stat stbuf; 305 1.14 thorpej FILE *n_ftrace; 306 1.23 christos const char *fn; 307 1.1 cgd 308 1.14 thorpej 309 1.16 christos /* Allow a null filename to increase the level if the trace file 310 1.16 christos * is already open or if coming from a trusted source, such as 311 1.16 christos * a signal or the command line. 312 1.14 thorpej */ 313 1.16 christos if (filename == 0 || filename[0] == '\0') { 314 1.16 christos filename = 0; 315 1.16 christos if (ftrace == 0) { 316 1.16 christos if (inittracename[0] == '\0') { 317 1.16 christos msglog("missing trace file name"); 318 1.16 christos return; 319 1.16 christos } 320 1.16 christos fn = inittracename; 321 1.16 christos } else { 322 1.16 christos fn = 0; 323 1.14 thorpej } 324 1.14 thorpej 325 1.15 christos } else if (!strcmp(filename,"dump/../table")) { 326 1.15 christos trace_dump(); 327 1.15 christos return; 328 1.15 christos 329 1.15 christos } else { 330 1.16 christos /* Allow the file specified with "-T file" to be reopened, 331 1.16 christos * but require all other names specified over the net to 332 1.16 christos * match the official path. The path can specify a directory 333 1.16 christos * in which the file is to be created. 334 1.16 christos */ 335 1.16 christos if (strcmp(filename, inittracename) 336 1.16 christos #ifdef _PATH_TRACE 337 1.16 christos && (strncmp(filename, _PATH_TRACE, sizeof(_PATH_TRACE)-1) 338 1.16 christos || strstr(filename,"../") 339 1.16 christos || 0 > stat(_PATH_TRACE, &stbuf)) 340 1.16 christos #endif 341 1.16 christos ) { 342 1.16 christos msglog("wrong trace file \"%s\"", filename); 343 1.16 christos return; 344 1.16 christos } 345 1.16 christos 346 1.16 christos /* If the new tracefile exists, it must be a regular file. 347 1.16 christos */ 348 1.20 mycroft if (stat(filename, &stbuf) >= 0 && !S_ISREG(stbuf.st_mode)) { 349 1.14 thorpej msglog("wrong type (%#x) of trace file \"%s\"", 350 1.14 thorpej stbuf.st_mode, filename); 351 1.14 thorpej return; 352 1.14 thorpej } 353 1.14 thorpej 354 1.16 christos fn = filename; 355 1.16 christos } 356 1.16 christos 357 1.16 christos if (fn != 0) { 358 1.16 christos n_ftrace = fopen(fn, "a"); 359 1.16 christos if (n_ftrace == 0) { 360 1.16 christos msglog("failed to open trace file \"%s\" %s", 361 1.16 christos fn, strerror(errno)); 362 1.16 christos if (fn == inittracename) 363 1.16 christos inittracename[0] = '\0'; 364 1.14 thorpej return; 365 1.14 thorpej } 366 1.14 thorpej 367 1.16 christos tmsg("switch to trace file %s", fn); 368 1.16 christos 369 1.21 thorpej trace_close(file_trace = 1); 370 1.14 thorpej 371 1.16 christos if (fn != savetracename) 372 1.28 itojun strlcpy(savetracename, fn, sizeof(savetracename)); 373 1.16 christos ftrace = n_ftrace; 374 1.14 thorpej 375 1.16 christos fflush(stdout); 376 1.16 christos fflush(stderr); 377 1.16 christos dup2(fileno(ftrace), STDOUT_FILENO); 378 1.16 christos dup2(fileno(ftrace), STDERR_FILENO); 379 1.16 christos } 380 1.14 thorpej 381 1.16 christos if (new_tracelevel == 0 || filename == 0) 382 1.16 christos new_tracelevel++; 383 1.16 christos tracelevel_msg(pat, dump != 0 ? dump : (filename != 0)); 384 1.14 thorpej } 385 1.14 thorpej 386 1.14 thorpej 387 1.14 thorpej /* ARGSUSED */ 388 1.14 thorpej void 389 1.23 christos sigtrace_on(int s UNUSED) 390 1.14 thorpej { 391 1.14 thorpej new_tracelevel++; 392 1.16 christos sigtrace_pat = "SIGUSR1: %s"; 393 1.1 cgd } 394 1.1 cgd 395 1.14 thorpej 396 1.14 thorpej /* ARGSUSED */ 397 1.7 cgd void 398 1.23 christos sigtrace_off(int s UNUSED) 399 1.14 thorpej { 400 1.14 thorpej new_tracelevel--; 401 1.16 christos sigtrace_pat = "SIGUSR2: %s"; 402 1.1 cgd } 403 1.1 cgd 404 1.14 thorpej 405 1.16 christos /* Set tracing after a signal. 406 1.14 thorpej */ 407 1.7 cgd void 408 1.14 thorpej set_tracelevel(void) 409 1.14 thorpej { 410 1.16 christos if (new_tracelevel == tracelevel) 411 1.16 christos return; 412 1.14 thorpej 413 1.16 christos /* If tracing entirely off, and there was no tracefile specified 414 1.16 christos * on the command line, then leave it off. 415 1.16 christos */ 416 1.16 christos if (new_tracelevel > tracelevel && ftrace == 0) { 417 1.16 christos if (savetracename[0] != '\0') { 418 1.16 christos set_tracefile(savetracename,sigtrace_pat,0); 419 1.16 christos } else if (inittracename[0] != '\0') { 420 1.16 christos set_tracefile(inittracename,sigtrace_pat,0); 421 1.16 christos } else { 422 1.16 christos new_tracelevel = 0; 423 1.14 thorpej return; 424 1.1 cgd } 425 1.16 christos } else { 426 1.16 christos tracelevel_msg(sigtrace_pat, 0); 427 1.1 cgd } 428 1.14 thorpej } 429 1.14 thorpej 430 1.14 thorpej 431 1.14 thorpej /* display an address 432 1.14 thorpej */ 433 1.14 thorpej char * 434 1.14 thorpej addrname(naddr addr, /* in network byte order */ 435 1.14 thorpej naddr mask, 436 1.14 thorpej int force) /* 0=show mask if nonstandard, */ 437 1.14 thorpej { /* 1=always show mask, 2=never */ 438 1.15 christos #define NUM_BUFS 4 439 1.15 christos static int bufno; 440 1.15 christos static struct { 441 1.15 christos char str[15+20]; 442 1.15 christos } bufs[NUM_BUFS]; 443 1.15 christos char *s, *sp; 444 1.14 thorpej naddr dmask; 445 1.28 itojun size_t l; 446 1.14 thorpej int i; 447 1.14 thorpej 448 1.28 itojun strlcpy(bufs[bufno].str, naddr_ntoa(addr), sizeof(bufs[bufno].str)); 449 1.28 itojun s = bufs[bufno].str; 450 1.28 itojun l = sizeof(bufs[bufno].str); 451 1.15 christos bufno = (bufno+1) % NUM_BUFS; 452 1.14 thorpej 453 1.14 thorpej if (force == 1 || (force == 0 && mask != std_mask(addr))) { 454 1.14 thorpej sp = &s[strlen(s)]; 455 1.14 thorpej 456 1.14 thorpej dmask = mask & -mask; 457 1.14 thorpej if (mask + dmask == 0) { 458 1.14 thorpej for (i = 0; i != 32 && ((1<<i) & mask) == 0; i++) 459 1.14 thorpej continue; 460 1.28 itojun (void)snprintf(sp, s + l - sp, "/%d", 32-i); 461 1.14 thorpej 462 1.14 thorpej } else { 463 1.28 itojun (void)snprintf(sp, s + l - sp, " (mask %#x)", 464 1.28 itojun (u_int)mask); 465 1.14 thorpej } 466 1.14 thorpej } 467 1.14 thorpej 468 1.14 thorpej return s; 469 1.15 christos #undef NUM_BUFS 470 1.14 thorpej } 471 1.14 thorpej 472 1.14 thorpej 473 1.14 thorpej /* display a bit-field 474 1.14 thorpej */ 475 1.14 thorpej struct bits { 476 1.23 christos u_int bits_mask; 477 1.23 christos u_int bits_clear; 478 1.23 christos const char *bits_name; 479 1.14 thorpej }; 480 1.14 thorpej 481 1.14 thorpej static struct bits if_bits[] = { 482 1.14 thorpej { IFF_LOOPBACK, 0, "LOOPBACK" }, 483 1.14 thorpej { IFF_POINTOPOINT, 0, "PT-TO-PT" }, 484 1.14 thorpej { 0, 0, 0} 485 1.14 thorpej }; 486 1.14 thorpej 487 1.14 thorpej static struct bits is_bits[] = { 488 1.16 christos { IS_ALIAS, 0, "ALIAS" }, 489 1.14 thorpej { IS_SUBNET, 0, "" }, 490 1.16 christos { IS_REMOTE, (IS_NO_RDISC 491 1.16 christos | IS_BCAST_RDISC), "REMOTE" }, 492 1.14 thorpej { IS_PASSIVE, (IS_NO_RDISC 493 1.14 thorpej | IS_NO_RIP 494 1.14 thorpej | IS_NO_SUPER_AG 495 1.14 thorpej | IS_PM_RDISC 496 1.14 thorpej | IS_NO_AG), "PASSIVE" }, 497 1.14 thorpej { IS_EXTERNAL, 0, "EXTERNAL" }, 498 1.14 thorpej { IS_CHECKED, 0, "" }, 499 1.14 thorpej { IS_ALL_HOSTS, 0, "" }, 500 1.14 thorpej { IS_ALL_ROUTERS, 0, "" }, 501 1.16 christos { IS_DISTRUST, 0, "DISTRUST" }, 502 1.14 thorpej { IS_BROKE, IS_SICK, "BROKEN" }, 503 1.14 thorpej { IS_SICK, 0, "SICK" }, 504 1.16 christos { IS_DUP, 0, "DUPLICATE" }, 505 1.16 christos { IS_REDIRECT_OK, 0, "REDIRECT_OK" }, 506 1.14 thorpej { IS_NEED_NET_SYN, 0, "" }, 507 1.14 thorpej { IS_NO_AG, IS_NO_SUPER_AG, "NO_AG" }, 508 1.14 thorpej { IS_NO_SUPER_AG, 0, "NO_SUPER_AG" }, 509 1.14 thorpej { (IS_NO_RIPV1_IN 510 1.14 thorpej | IS_NO_RIPV2_IN 511 1.14 thorpej | IS_NO_RIPV1_OUT 512 1.14 thorpej | IS_NO_RIPV2_OUT), 0, "NO_RIP" }, 513 1.14 thorpej { (IS_NO_RIPV1_IN 514 1.14 thorpej | IS_NO_RIPV1_OUT), 0, "RIPV2" }, 515 1.14 thorpej { IS_NO_RIPV1_IN, 0, "NO_RIPV1_IN" }, 516 1.14 thorpej { IS_NO_RIPV2_IN, 0, "NO_RIPV2_IN" }, 517 1.14 thorpej { IS_NO_RIPV1_OUT, 0, "NO_RIPV1_OUT" }, 518 1.14 thorpej { IS_NO_RIPV2_OUT, 0, "NO_RIPV2_OUT" }, 519 1.14 thorpej { (IS_NO_ADV_IN 520 1.14 thorpej | IS_NO_SOL_OUT 521 1.14 thorpej | IS_NO_ADV_OUT), IS_BCAST_RDISC, "NO_RDISC" }, 522 1.14 thorpej { IS_NO_SOL_OUT, 0, "NO_SOLICIT" }, 523 1.14 thorpej { IS_SOL_OUT, 0, "SEND_SOLICIT" }, 524 1.14 thorpej { IS_NO_ADV_OUT, IS_BCAST_RDISC, "NO_RDISC_ADV" }, 525 1.14 thorpej { IS_ADV_OUT, 0, "RDISC_ADV" }, 526 1.14 thorpej { IS_BCAST_RDISC, 0, "BCAST_RDISC" }, 527 1.16 christos { IS_PM_RDISC, 0, "" }, 528 1.14 thorpej { 0, 0, "%#x"} 529 1.14 thorpej }; 530 1.14 thorpej 531 1.14 thorpej static struct bits rs_bits[] = { 532 1.14 thorpej { RS_IF, 0, "IF" }, 533 1.14 thorpej { RS_NET_INT, RS_NET_SYN, "NET_INT" }, 534 1.14 thorpej { RS_NET_SYN, 0, "NET_SYN" }, 535 1.14 thorpej { RS_SUBNET, 0, "" }, 536 1.14 thorpej { RS_LOCAL, 0, "LOCAL" }, 537 1.14 thorpej { RS_MHOME, 0, "MHOME" }, 538 1.14 thorpej { RS_STATIC, 0, "STATIC" }, 539 1.14 thorpej { RS_RDISC, 0, "RDISC" }, 540 1.14 thorpej { 0, 0, "%#x"} 541 1.14 thorpej }; 542 1.14 thorpej 543 1.14 thorpej 544 1.14 thorpej static void 545 1.23 christos trace_bits(const struct bits *tbl, 546 1.14 thorpej u_int field, 547 1.14 thorpej int force) 548 1.14 thorpej { 549 1.23 christos u_int b; 550 1.14 thorpej char c; 551 1.14 thorpej 552 1.14 thorpej if (force) { 553 1.14 thorpej (void)putc('<', ftrace); 554 1.14 thorpej c = 0; 555 1.14 thorpej } else { 556 1.14 thorpej c = '<'; 557 1.14 thorpej } 558 1.14 thorpej 559 1.14 thorpej while (field != 0 560 1.14 thorpej && (b = tbl->bits_mask) != 0) { 561 1.14 thorpej if ((b & field) == b) { 562 1.14 thorpej if (tbl->bits_name[0] != '\0') { 563 1.14 thorpej if (c) 564 1.14 thorpej (void)putc(c, ftrace); 565 1.14 thorpej (void)fprintf(ftrace, "%s", tbl->bits_name); 566 1.14 thorpej c = '|'; 567 1.14 thorpej } 568 1.14 thorpej if (0 == (field &= ~(b | tbl->bits_clear))) 569 1.14 thorpej break; 570 1.14 thorpej } 571 1.14 thorpej tbl++; 572 1.14 thorpej } 573 1.14 thorpej if (field != 0 && tbl->bits_name != 0) { 574 1.14 thorpej if (c) 575 1.14 thorpej (void)putc(c, ftrace); 576 1.14 thorpej (void)fprintf(ftrace, tbl->bits_name, field); 577 1.14 thorpej c = '|'; 578 1.14 thorpej } 579 1.14 thorpej 580 1.14 thorpej if (c != '<' || force) 581 1.14 thorpej (void)fputs("> ", ftrace); 582 1.14 thorpej } 583 1.14 thorpej 584 1.14 thorpej 585 1.16 christos char * 586 1.16 christos rtname(naddr dst, 587 1.16 christos naddr mask, 588 1.16 christos naddr gate) 589 1.14 thorpej { 590 1.14 thorpej static char buf[3*4+3+1+2+3 /* "xxx.xxx.xxx.xxx/xx-->" */ 591 1.14 thorpej +3*4+3+1]; /* "xxx.xxx.xxx.xxx" */ 592 1.14 thorpej int i; 593 1.14 thorpej 594 1.28 itojun i = snprintf(buf, sizeof(buf), "%-16s-->", addrname(dst, mask, 0)); 595 1.32 lukem if (i < 0 || (size_t)i >= sizeof(buf)) 596 1.28 itojun return buf; 597 1.28 itojun (void)snprintf(&buf[i], sizeof(buf) - i, "%-*s", 15+20-MAX(20, i), 598 1.28 itojun naddr_ntoa(gate)); 599 1.14 thorpej return buf; 600 1.14 thorpej } 601 1.14 thorpej 602 1.14 thorpej 603 1.16 christos static void 604 1.16 christos print_rts(struct rt_spare *rts, 605 1.16 christos int force_metric, /* -1=suppress, 0=default */ 606 1.16 christos int force_ifp, /* -1=suppress, 0=default */ 607 1.16 christos int force_router, /* -1=suppress, 0=default, 1=display */ 608 1.16 christos int force_tag, /* -1=suppress, 0=default, 1=display */ 609 1.16 christos int force_time) /* 0=suppress, 1=display */ 610 1.16 christos { 611 1.21 thorpej int i; 612 1.21 thorpej 613 1.21 thorpej 614 1.16 christos if (force_metric >= 0) 615 1.16 christos (void)fprintf(ftrace, "metric=%-2d ", rts->rts_metric); 616 1.16 christos if (force_ifp >= 0) 617 1.16 christos (void)fprintf(ftrace, "%s ", (rts->rts_ifp == 0 ? 618 1.16 christos "if?" : rts->rts_ifp->int_name)); 619 1.16 christos if (force_router > 0 620 1.16 christos || (force_router == 0 && rts->rts_router != rts->rts_gate)) 621 1.16 christos (void)fprintf(ftrace, "router=%s ", 622 1.16 christos naddr_ntoa(rts->rts_router)); 623 1.16 christos if (force_time > 0) 624 1.16 christos (void)fprintf(ftrace, "%s ", ts(rts->rts_time)); 625 1.16 christos if (force_tag > 0 626 1.16 christos || (force_tag == 0 && rts->rts_tag != 0)) 627 1.21 thorpej (void)fprintf(ftrace, "tag=%#x ", ntohs(rts->rts_tag)); 628 1.21 thorpej if (rts->rts_de_ag != 0) { 629 1.23 christos for (i = 1; (u_int)(1 << i) <= rts->rts_de_ag; i++) 630 1.21 thorpej continue; 631 1.21 thorpej (void)fprintf(ftrace, "de_ag=%d ", i); 632 1.21 thorpej } 633 1.21 thorpej 634 1.16 christos } 635 1.16 christos 636 1.16 christos 637 1.14 thorpej void 638 1.23 christos trace_if(const char *act, 639 1.23 christos struct interface *ifp) 640 1.14 thorpej { 641 1.14 thorpej if (!TRACEACTIONS || ftrace == 0) 642 1.14 thorpej return; 643 1.14 thorpej 644 1.14 thorpej lastlog(); 645 1.16 christos (void)fprintf(ftrace, "%-3s interface %-4s ", act, ifp->int_name); 646 1.15 christos (void)fprintf(ftrace, "%-15s-->%-15s ", 647 1.14 thorpej naddr_ntoa(ifp->int_addr), 648 1.16 christos addrname(((ifp->int_if_flags & IFF_POINTOPOINT) 649 1.16 christos ? ifp->int_dstaddr 650 1.16 christos : htonl(ifp->int_net)), 651 1.15 christos ifp->int_mask, 1)); 652 1.15 christos if (ifp->int_metric != 0) 653 1.15 christos (void)fprintf(ftrace, "metric=%d ", ifp->int_metric); 654 1.27 christos if (ifp->int_adj_inmetric != 0) 655 1.27 christos (void)fprintf(ftrace, "adj_inmetric=%u ", 656 1.27 christos ifp->int_adj_inmetric); 657 1.27 christos if (ifp->int_adj_outmetric != 0) 658 1.27 christos (void)fprintf(ftrace, "adj_outmetric=%u ", 659 1.27 christos ifp->int_adj_outmetric); 660 1.16 christos if (!IS_RIP_OUT_OFF(ifp->int_state) 661 1.16 christos && ifp->int_d_metric != 0) 662 1.27 christos (void)fprintf(ftrace, "fake_default=%u ", ifp->int_d_metric); 663 1.14 thorpej trace_bits(if_bits, ifp->int_if_flags, 0); 664 1.14 thorpej trace_bits(is_bits, ifp->int_state, 0); 665 1.14 thorpej (void)fputc('\n',ftrace); 666 1.14 thorpej } 667 1.14 thorpej 668 1.14 thorpej 669 1.14 thorpej void 670 1.14 thorpej trace_upslot(struct rt_entry *rt, 671 1.14 thorpej struct rt_spare *rts, 672 1.21 thorpej struct rt_spare *new) 673 1.14 thorpej { 674 1.14 thorpej if (!TRACEACTIONS || ftrace == 0) 675 1.14 thorpej return; 676 1.16 christos 677 1.21 thorpej if (rts->rts_gate == new->rts_gate 678 1.21 thorpej && rts->rts_router == new->rts_router 679 1.21 thorpej && rts->rts_metric == new->rts_metric 680 1.21 thorpej && rts->rts_tag == new->rts_tag 681 1.21 thorpej && rts->rts_de_ag == new->rts_de_ag) 682 1.14 thorpej return; 683 1.14 thorpej 684 1.14 thorpej lastlog(); 685 1.21 thorpej if (new->rts_gate == 0) { 686 1.16 christos (void)fprintf(ftrace, "Del #%d %-35s ", 687 1.19 mrg (int)(rts - rt->rt_spares), 688 1.16 christos rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate)); 689 1.21 thorpej print_rts(rts, 0,0,0,0, 690 1.21 thorpej (rts != rt->rt_spares 691 1.21 thorpej || AGE_RT(rt->rt_state,new->rts_ifp))); 692 1.16 christos 693 1.16 christos } else if (rts->rts_gate != RIP_DEFAULT) { 694 1.14 thorpej (void)fprintf(ftrace, "Chg #%d %-35s ", 695 1.19 mrg (int)(rts - rt->rt_spares), 696 1.16 christos rtname(rt->rt_dst, rt->rt_mask, rts->rts_gate)); 697 1.16 christos print_rts(rts, 0,0, 698 1.21 thorpej rts->rts_gate != new->rts_gate, 699 1.21 thorpej rts->rts_tag != new->rts_tag, 700 1.16 christos rts != rt->rt_spares || AGE_RT(rt->rt_state, 701 1.16 christos rt->rt_ifp)); 702 1.14 thorpej 703 1.16 christos (void)fprintf(ftrace, "\n %19s%-16s ", "", 704 1.21 thorpej (new->rts_gate != rts->rts_gate 705 1.21 thorpej ? naddr_ntoa(new->rts_gate) : "")); 706 1.21 thorpej print_rts(new, 707 1.21 thorpej -(new->rts_metric == rts->rts_metric), 708 1.21 thorpej -(new->rts_ifp == rts->rts_ifp), 709 1.16 christos 0, 710 1.21 thorpej rts->rts_tag != new->rts_tag, 711 1.21 thorpej (new->rts_time != rts->rts_time 712 1.21 thorpej && (rts != rt->rt_spares 713 1.21 thorpej || AGE_RT(rt->rt_state, new->rts_ifp)))); 714 1.14 thorpej 715 1.14 thorpej } else { 716 1.14 thorpej (void)fprintf(ftrace, "Add #%d %-35s ", 717 1.19 mrg (int)(rts - rt->rt_spares), 718 1.21 thorpej rtname(rt->rt_dst, rt->rt_mask, new->rts_gate)); 719 1.21 thorpej print_rts(new, 0,0,0,0, 720 1.21 thorpej (rts != rt->rt_spares 721 1.21 thorpej || AGE_RT(rt->rt_state,new->rts_ifp))); 722 1.14 thorpej } 723 1.16 christos (void)fputc('\n',ftrace); 724 1.1 cgd } 725 1.1 cgd 726 1.14 thorpej 727 1.21 thorpej /* miscellaneous message checked by the caller 728 1.15 christos */ 729 1.15 christos void 730 1.23 christos trace_misc(const char *p, ...) 731 1.15 christos { 732 1.15 christos va_list args; 733 1.15 christos 734 1.21 thorpej if (ftrace == 0) 735 1.15 christos return; 736 1.15 christos 737 1.15 christos lastlog(); 738 1.15 christos va_start(args, p); 739 1.15 christos vfprintf(ftrace, p, args); 740 1.26 wiz va_end(args); 741 1.16 christos (void)fputc('\n',ftrace); 742 1.15 christos } 743 1.15 christos 744 1.15 christos 745 1.14 thorpej /* display a message if tracing actions 746 1.14 thorpej */ 747 1.14 thorpej void 748 1.23 christos trace_act(const char *p, ...) 749 1.14 thorpej { 750 1.14 thorpej va_list args; 751 1.14 thorpej 752 1.14 thorpej if (!TRACEACTIONS || ftrace == 0) 753 1.14 thorpej return; 754 1.14 thorpej 755 1.14 thorpej lastlog(); 756 1.14 thorpej va_start(args, p); 757 1.14 thorpej vfprintf(ftrace, p, args); 758 1.26 wiz va_end(args); 759 1.16 christos (void)fputc('\n',ftrace); 760 1.14 thorpej } 761 1.14 thorpej 762 1.14 thorpej 763 1.14 thorpej /* display a message if tracing packets 764 1.14 thorpej */ 765 1.7 cgd void 766 1.23 christos trace_pkt(const char *p, ...) 767 1.1 cgd { 768 1.14 thorpej va_list args; 769 1.1 cgd 770 1.14 thorpej if (!TRACEPACKETS || ftrace == 0) 771 1.1 cgd return; 772 1.14 thorpej 773 1.14 thorpej lastlog(); 774 1.14 thorpej va_start(args, p); 775 1.14 thorpej vfprintf(ftrace, p, args); 776 1.26 wiz va_end(args); 777 1.16 christos (void)fputc('\n',ftrace); 778 1.1 cgd } 779 1.1 cgd 780 1.14 thorpej 781 1.7 cgd void 782 1.14 thorpej trace_change(struct rt_entry *rt, 783 1.14 thorpej u_int state, 784 1.21 thorpej struct rt_spare *new, 785 1.23 christos const char *label) 786 1.1 cgd { 787 1.14 thorpej if (ftrace == 0) 788 1.14 thorpej return; 789 1.14 thorpej 790 1.21 thorpej if (rt->rt_metric == new->rts_metric 791 1.21 thorpej && rt->rt_gate == new->rts_gate 792 1.21 thorpej && rt->rt_router == new->rts_router 793 1.14 thorpej && rt->rt_state == state 794 1.21 thorpej && rt->rt_tag == new->rts_tag 795 1.21 thorpej && rt->rt_de_ag == new->rts_de_ag) 796 1.14 thorpej return; 797 1.14 thorpej 798 1.14 thorpej lastlog(); 799 1.16 christos (void)fprintf(ftrace, "%s %-35s ", 800 1.14 thorpej label, 801 1.16 christos rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate)); 802 1.16 christos print_rts(rt->rt_spares, 803 1.16 christos 0,0,0,0, AGE_RT(rt->rt_state, rt->rt_ifp)); 804 1.14 thorpej trace_bits(rs_bits, rt->rt_state, rt->rt_state != state); 805 1.14 thorpej 806 1.16 christos (void)fprintf(ftrace, "\n%*s %19s%-16s ", 807 1.19 mrg (int)strlen(label), "", "", 808 1.21 thorpej (rt->rt_gate != new->rts_gate 809 1.21 thorpej ? naddr_ntoa(new->rts_gate) : "")); 810 1.21 thorpej print_rts(new, 811 1.21 thorpej -(new->rts_metric == rt->rt_metric), 812 1.21 thorpej -(new->rts_ifp == rt->rt_ifp), 813 1.16 christos 0, 814 1.21 thorpej rt->rt_tag != new->rts_tag, 815 1.21 thorpej (rt->rt_time != new->rts_time 816 1.21 thorpej && AGE_RT(rt->rt_state,new->rts_ifp))); 817 1.14 thorpej if (rt->rt_state != state) 818 1.14 thorpej trace_bits(rs_bits, state, 1); 819 1.16 christos (void)fputc('\n',ftrace); 820 1.1 cgd } 821 1.1 cgd 822 1.14 thorpej 823 1.7 cgd void 824 1.23 christos trace_add_del(const char * action, struct rt_entry *rt) 825 1.1 cgd { 826 1.14 thorpej if (ftrace == 0) 827 1.1 cgd return; 828 1.14 thorpej 829 1.14 thorpej lastlog(); 830 1.16 christos (void)fprintf(ftrace, "%s %-35s ", 831 1.14 thorpej action, 832 1.16 christos rtname(rt->rt_dst, rt->rt_mask, rt->rt_gate)); 833 1.16 christos print_rts(rt->rt_spares, 0,0,0,0,AGE_RT(rt->rt_state,rt->rt_ifp)); 834 1.16 christos trace_bits(rs_bits, rt->rt_state, 0); 835 1.16 christos (void)fputc('\n',ftrace); 836 1.1 cgd } 837 1.1 cgd 838 1.14 thorpej 839 1.15 christos /* ARGSUSED */ 840 1.15 christos static int 841 1.15 christos walk_trace(struct radix_node *rn, 842 1.23 christos struct walkarg *w UNUSED) 843 1.15 christos { 844 1.15 christos #define RT ((struct rt_entry *)rn) 845 1.15 christos struct rt_spare *rts; 846 1.23 christos int i; 847 1.15 christos 848 1.16 christos (void)fprintf(ftrace, " %-35s ", 849 1.16 christos rtname(RT->rt_dst, RT->rt_mask, RT->rt_gate)); 850 1.23 christos print_rts(&RT->rt_spares[0], 0,0,0,0, AGE_RT(RT->rt_state, RT->rt_ifp)); 851 1.15 christos trace_bits(rs_bits, RT->rt_state, 0); 852 1.16 christos if (RT->rt_poison_time >= now_garbage 853 1.16 christos && RT->rt_poison_metric < RT->rt_metric) 854 1.16 christos (void)fprintf(ftrace, "pm=%d@%s", 855 1.16 christos RT->rt_poison_metric, ts(RT->rt_poison_time)); 856 1.15 christos 857 1.15 christos rts = &RT->rt_spares[1]; 858 1.15 christos for (i = 1; i < NUM_SPARES; i++, rts++) { 859 1.16 christos if (rts->rts_gate != RIP_DEFAULT) { 860 1.16 christos (void)fprintf(ftrace,"\n #%d%15s%-16s ", 861 1.16 christos i, "", naddr_ntoa(rts->rts_gate)); 862 1.16 christos print_rts(rts, 0,0,0,0,1); 863 1.15 christos } 864 1.15 christos } 865 1.15 christos (void)fputc('\n',ftrace); 866 1.15 christos 867 1.15 christos return 0; 868 1.15 christos } 869 1.15 christos 870 1.15 christos 871 1.15 christos static void 872 1.15 christos trace_dump(void) 873 1.15 christos { 874 1.16 christos struct interface *ifp; 875 1.16 christos 876 1.15 christos if (ftrace == 0) 877 1.15 christos return; 878 1.15 christos lastlog(); 879 1.15 christos 880 1.16 christos (void)fputs("current daemon state:\n", ftrace); 881 1.16 christos for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) 882 1.16 christos trace_if("", ifp); 883 1.15 christos (void)rn_walktree(rhead, walk_trace, 0); 884 1.15 christos } 885 1.15 christos 886 1.15 christos 887 1.7 cgd void 888 1.23 christos trace_rip(const char *dir1, const char *dir2, 889 1.14 thorpej struct sockaddr_in *who, 890 1.14 thorpej struct interface *ifp, 891 1.14 thorpej struct rip *msg, 892 1.14 thorpej int size) /* total size of message */ 893 1.1 cgd { 894 1.14 thorpej struct netinfo *n, *lim; 895 1.22 christos # define NA ((struct netauth*)n) 896 1.16 christos int i, seen_route; 897 1.1 cgd 898 1.14 thorpej if (!TRACEPACKETS || ftrace == 0) 899 1.1 cgd return; 900 1.14 thorpej 901 1.14 thorpej lastlog(); 902 1.14 thorpej if (msg->rip_cmd >= RIPCMD_MAX 903 1.14 thorpej || msg->rip_vers == 0) { 904 1.15 christos (void)fprintf(ftrace, "%s bad RIPv%d cmd=%d %s" 905 1.15 christos " %s.%d size=%d\n", 906 1.15 christos dir1, msg->rip_vers, msg->rip_cmd, dir2, 907 1.15 christos naddr_ntoa(who->sin_addr.s_addr), 908 1.15 christos ntohs(who->sin_port), 909 1.15 christos size); 910 1.1 cgd return; 911 1.1 cgd } 912 1.14 thorpej 913 1.14 thorpej (void)fprintf(ftrace, "%s RIPv%d %s %s %s.%d%s%s\n", 914 1.14 thorpej dir1, msg->rip_vers, ripcmds[msg->rip_cmd], dir2, 915 1.14 thorpej naddr_ntoa(who->sin_addr.s_addr), ntohs(who->sin_port), 916 1.14 thorpej ifp ? " via " : "", ifp ? ifp->int_name : ""); 917 1.14 thorpej if (!TRACECONTENTS) 918 1.1 cgd return; 919 1.14 thorpej 920 1.16 christos seen_route = 0; 921 1.1 cgd switch (msg->rip_cmd) { 922 1.1 cgd case RIPCMD_REQUEST: 923 1.1 cgd case RIPCMD_RESPONSE: 924 1.1 cgd n = msg->rip_nets; 925 1.14 thorpej lim = (struct netinfo *)((char*)msg + size); 926 1.14 thorpej for (; n < lim; n++) { 927 1.16 christos if (!seen_route 928 1.16 christos && n->n_family == RIP_AF_UNSPEC 929 1.14 thorpej && ntohl(n->n_metric) == HOPCNT_INFINITY 930 1.16 christos && msg->rip_cmd == RIPCMD_REQUEST 931 1.16 christos && (n+1 == lim 932 1.16 christos || (n+2 == lim 933 1.16 christos && (n+1)->n_family == RIP_AF_AUTH))) { 934 1.14 thorpej (void)fputs("\tQUERY ", ftrace); 935 1.14 thorpej if (n->n_dst != 0) 936 1.14 thorpej (void)fprintf(ftrace, "%s ", 937 1.14 thorpej naddr_ntoa(n->n_dst)); 938 1.14 thorpej if (n->n_mask != 0) 939 1.14 thorpej (void)fprintf(ftrace, "mask=%#x ", 940 1.15 christos (u_int)ntohl(n->n_mask)); 941 1.14 thorpej if (n->n_nhop != 0) 942 1.16 christos (void)fprintf(ftrace, "nhop=%s ", 943 1.14 thorpej naddr_ntoa(n->n_nhop)); 944 1.14 thorpej if (n->n_tag != 0) 945 1.16 christos (void)fprintf(ftrace, "tag=%#x ", 946 1.15 christos ntohs(n->n_tag)); 947 1.14 thorpej (void)fputc('\n',ftrace); 948 1.14 thorpej continue; 949 1.1 cgd } 950 1.1 cgd 951 1.14 thorpej if (n->n_family == RIP_AF_AUTH) { 952 1.16 christos if (NA->a_type == RIP_AUTH_PW 953 1.16 christos && n == msg->rip_nets) { 954 1.16 christos (void)fprintf(ftrace, "\tPassword" 955 1.16 christos " Authentication:" 956 1.16 christos " \"%s\"\n", 957 1.16 christos qstring(NA->au.au_pw, 958 1.16 christos RIP_AUTH_PW_LEN)); 959 1.16 christos continue; 960 1.16 christos } 961 1.16 christos 962 1.16 christos if (NA->a_type == RIP_AUTH_MD5 963 1.16 christos && n == msg->rip_nets) { 964 1.16 christos (void)fprintf(ftrace, 965 1.22 christos "\tMD5 Auth" 966 1.22 christos " pkt_len=%d KeyID=%u" 967 1.22 christos " auth_len=%d" 968 1.22 christos " seqno=%#x" 969 1.16 christos " rsvd=%#x,%#x\n", 970 1.24 christos ntohs(NA->au.a_md5.md5_pkt_len), 971 1.24 christos NA->au.a_md5.md5_keyid, 972 1.24 christos NA->au.a_md5.md5_auth_len, 973 1.24 christos (int)ntohl(NA->au.a_md5.md5_seqno), 974 1.24 christos (int)ntohs(NA->au.a_md5.rsvd[0]), 975 1.24 christos (int)ntohs(NA->au.a_md5.rsvd[1])); 976 1.16 christos continue; 977 1.16 christos } 978 1.14 thorpej (void)fprintf(ftrace, 979 1.22 christos "\tAuthentication type %d: ", 980 1.16 christos ntohs(NA->a_type)); 981 1.14 thorpej for (i = 0; 982 1.23 christos i < (int)sizeof(NA->au.au_pw); 983 1.14 thorpej i++) 984 1.14 thorpej (void)fprintf(ftrace, "%02x ", 985 1.16 christos NA->au.au_pw[i]); 986 1.14 thorpej (void)fputc('\n',ftrace); 987 1.14 thorpej continue; 988 1.14 thorpej } 989 1.1 cgd 990 1.16 christos seen_route = 1; 991 1.14 thorpej if (n->n_family != RIP_AF_INET) { 992 1.14 thorpej (void)fprintf(ftrace, 993 1.16 christos "\t(af %d) %-18s mask=%#x ", 994 1.14 thorpej ntohs(n->n_family), 995 1.14 thorpej naddr_ntoa(n->n_dst), 996 1.15 christos (u_int)ntohl(n->n_mask)); 997 1.14 thorpej } else if (msg->rip_vers == RIPv1) { 998 1.14 thorpej (void)fprintf(ftrace, "\t%-18s ", 999 1.14 thorpej addrname(n->n_dst, 1000 1.14 thorpej ntohl(n->n_mask), 1001 1.14 thorpej n->n_mask==0 ? 2 : 1)); 1002 1.14 thorpej } else { 1003 1.14 thorpej (void)fprintf(ftrace, "\t%-18s ", 1004 1.14 thorpej addrname(n->n_dst, 1005 1.14 thorpej ntohl(n->n_mask), 1006 1.14 thorpej n->n_mask==0 ? 2 : 0)); 1007 1.1 cgd } 1008 1.14 thorpej (void)fprintf(ftrace, "metric=%-2d ", 1009 1.15 christos (u_int)ntohl(n->n_metric)); 1010 1.14 thorpej if (n->n_nhop != 0) 1011 1.14 thorpej (void)fprintf(ftrace, " nhop=%s ", 1012 1.14 thorpej naddr_ntoa(n->n_nhop)); 1013 1.14 thorpej if (n->n_tag != 0) 1014 1.14 thorpej (void)fprintf(ftrace, "tag=%#x", 1015 1.15 christos ntohs(n->n_tag)); 1016 1.14 thorpej (void)fputc('\n',ftrace); 1017 1.1 cgd } 1018 1.14 thorpej if (size != (char *)n - (char *)msg) 1019 1.14 thorpej (void)fprintf(ftrace, "truncated record, len %d\n", 1020 1.14 thorpej size); 1021 1.1 cgd break; 1022 1.1 cgd 1023 1.1 cgd case RIPCMD_TRACEON: 1024 1.16 christos fprintf(ftrace, "\tfile=\"%.*s\"\n", size-4, 1025 1.16 christos msg->rip_tracefile); 1026 1.1 cgd break; 1027 1.1 cgd 1028 1.1 cgd case RIPCMD_TRACEOFF: 1029 1.1 cgd break; 1030 1.1 cgd } 1031 1.1 cgd } 1032