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