1 /* $NetBSD: trace.c,v 1.14 1996/08/10 01:30:15 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1983, 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #if !defined(lint) && !defined(sgi) 37 #if 0 38 static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93"; 39 #else 40 static char rcsid[] = "$NetBSD: trace.c,v 1.14 1996/08/10 01:30:15 thorpej Exp $"; 41 #endif 42 #endif /* not lint */ 43 44 #define RIPCMDS 45 #include "defs.h" 46 #include "pathnames.h" 47 #include <sys/stat.h> 48 #include <sys/signal.h> 49 #include <fcntl.h> 50 51 52 #ifdef sgi 53 /* use *stat64 for files on large filesystems */ 54 #define stat stat64 55 #endif 56 57 #define NRECORDS 50 /* size of circular trace buffer */ 58 59 u_int tracelevel, new_tracelevel; 60 FILE *ftrace = stdout; /* output trace file */ 61 static char *tracelevel_pat = "%s\n"; 62 63 char savetracename[MAXPATHLEN+1]; 64 65 66 /* convert IP address to a string, but not into a single buffer 67 */ 68 char * 69 naddr_ntoa(naddr a) 70 { 71 #define NUM_BUFS 4 72 static int i; 73 static struct { 74 char str[16]; /* xxx.xxx.xxx.xxx\0 */ 75 } bufs[NUM_BUFS]; 76 struct in_addr addr; 77 char *s; 78 79 addr.s_addr = a; 80 s = strcpy(bufs[i].str, inet_ntoa(addr)); 81 i = (i+1) % NUM_BUFS; 82 return s; 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 (stat(filename, &stbuf) >= 0) { 211 if (!trusted) { 212 msglog("trace file \"%s\" already exists"); 213 return; 214 } 215 if ((stbuf.st_mode & S_IFMT) != S_IFREG) { 216 msglog("wrong type (%#x) of trace file \"%s\"", 217 stbuf.st_mode, filename); 218 return; 219 } 220 221 if (!trusted 222 && strcmp(filename, savetracename) 223 && strncmp(filename, _PATH_TRACE, sizeof(_PATH_TRACE)-1)) { 224 msglog("wrong directory for trace file: \"%s\"", 225 filename); 226 return; 227 } 228 } 229 230 n_ftrace = fopen(filename, "a"); 231 if (n_ftrace == 0) { 232 msglog("failed to open trace file \"%s\" %s", 233 filename, strerror(errno)); 234 return; 235 } 236 237 tmsg("switch to trace file %s\n", filename); 238 trace_close(); 239 if (filename != savetracename) 240 strncpy(savetracename, filename, sizeof(savetracename)-1); 241 ftrace = n_ftrace; 242 243 fflush(stdout); 244 fflush(stderr); 245 dup2(fileno(ftrace), STDOUT_FILENO); 246 dup2(fileno(ftrace), STDERR_FILENO); 247 248 if (new_tracelevel == 0) 249 new_tracelevel = 1; 250 set_tracelevel(); 251 } 252 253 254 /* ARGSUSED */ 255 void 256 sigtrace_on(int s) 257 { 258 new_tracelevel++; 259 tracelevel_pat = "SIGUSR1: %s\n"; 260 } 261 262 263 /* ARGSUSED */ 264 void 265 sigtrace_off(int s) 266 { 267 new_tracelevel--; 268 tracelevel_pat = "SIGUSR2: %s\n"; 269 } 270 271 272 /* Move to next higher level of tracing when -t option processed or 273 * SIGUSR1 is received. Successive levels are: 274 * actions 275 * actions + packets 276 * actions + packets + contents 277 */ 278 void 279 set_tracelevel(void) 280 { 281 static char *off_msgs[MAX_TRACELEVEL] = { 282 "Tracing actions stopped", 283 "Tracing packets stopped", 284 "Tracing packet contents stopped", 285 }; 286 static char *on_msgs[MAX_TRACELEVEL] = { 287 "Tracing actions started", 288 "Tracing packets started", 289 "Tracing packet contents started", 290 }; 291 292 293 if (new_tracelevel > MAX_TRACELEVEL) { 294 new_tracelevel = MAX_TRACELEVEL; 295 if (new_tracelevel == tracelevel) { 296 tmsg(tracelevel_pat, on_msgs[tracelevel-1]); 297 return; 298 } 299 } 300 while (new_tracelevel != tracelevel) { 301 if (new_tracelevel < tracelevel) { 302 if (--tracelevel == 0) 303 trace_off(tracelevel_pat, off_msgs[0]); 304 else 305 tmsg(tracelevel_pat, off_msgs[tracelevel]); 306 } else { 307 if (ftrace == 0) { 308 if (savetracename[0] != '\0') 309 trace_on(savetracename, 1); 310 else 311 ftrace = stdout; 312 } 313 tmsg(tracelevel_pat, on_msgs[tracelevel++]); 314 } 315 } 316 tracelevel_pat = "%s\n"; 317 } 318 319 320 /* display an address 321 */ 322 char * 323 addrname(naddr addr, /* in network byte order */ 324 naddr mask, 325 int force) /* 0=show mask if nonstandard, */ 326 { /* 1=always show mask, 2=never */ 327 static char s[15+20]; 328 char *sp; 329 naddr dmask; 330 int i; 331 332 (void)strcpy(s, naddr_ntoa(addr)); 333 334 if (force == 1 || (force == 0 && mask != std_mask(addr))) { 335 sp = &s[strlen(s)]; 336 337 dmask = mask & -mask; 338 if (mask + dmask == 0) { 339 for (i = 0; i != 32 && ((1<<i) & mask) == 0; i++) 340 continue; 341 (void)sprintf(sp, "/%d", 32-i); 342 343 } else { 344 (void)sprintf(sp, " (mask %#x)", mask); 345 } 346 } 347 348 return s; 349 } 350 351 352 /* display a bit-field 353 */ 354 struct bits { 355 int bits_mask; 356 int bits_clear; 357 char *bits_name; 358 }; 359 360 static struct bits if_bits[] = { 361 { IFF_LOOPBACK, 0, "LOOPBACK" }, 362 { IFF_POINTOPOINT, 0, "PT-TO-PT" }, 363 { 0, 0, 0} 364 }; 365 366 static struct bits is_bits[] = { 367 { IS_SUBNET, 0, "" }, 368 { IS_REMOTE, 0, "REMOTE" }, 369 { IS_PASSIVE, (IS_NO_RDISC 370 | IS_BCAST_RDISC 371 | IS_NO_RIP 372 | IS_NO_SUPER_AG 373 | IS_PM_RDISC 374 | IS_NO_AG), "PASSIVE" }, 375 { IS_EXTERNAL, 0, "EXTERNAL" }, 376 { IS_CHECKED, 0, "" }, 377 { IS_ALL_HOSTS, 0, "" }, 378 { IS_ALL_ROUTERS, 0, "" }, 379 { IS_RIP_QUERIED, 0, "" }, 380 { IS_BROKE, IS_SICK, "BROKEN" }, 381 { IS_SICK, 0, "SICK" }, 382 { IS_ACTIVE, 0, "ACTIVE" }, 383 { IS_NEED_NET_SYN, 0, "" }, 384 { IS_NO_AG, IS_NO_SUPER_AG, "NO_AG" }, 385 { IS_NO_SUPER_AG, 0, "NO_SUPER_AG" }, 386 { (IS_NO_RIPV1_IN 387 | IS_NO_RIPV2_IN 388 | IS_NO_RIPV1_OUT 389 | IS_NO_RIPV2_OUT), 0, "NO_RIP" }, 390 { (IS_NO_RIPV1_IN 391 | IS_NO_RIPV1_OUT), 0, "RIPV2" }, 392 { IS_NO_RIPV1_IN, 0, "NO_RIPV1_IN" }, 393 { IS_NO_RIPV2_IN, 0, "NO_RIPV2_IN" }, 394 { IS_NO_RIPV1_OUT, 0, "NO_RIPV1_OUT" }, 395 { IS_NO_RIPV2_OUT, 0, "NO_RIPV2_OUT" }, 396 { (IS_NO_ADV_IN 397 | IS_NO_SOL_OUT 398 | IS_NO_ADV_OUT), IS_BCAST_RDISC, "NO_RDISC" }, 399 { IS_NO_SOL_OUT, 0, "NO_SOLICIT" }, 400 { IS_SOL_OUT, 0, "SEND_SOLICIT" }, 401 { IS_NO_ADV_OUT, IS_BCAST_RDISC, "NO_RDISC_ADV" }, 402 { IS_ADV_OUT, 0, "RDISC_ADV" }, 403 { IS_BCAST_RDISC, 0, "BCAST_RDISC" }, 404 { IS_PM_RDISC, 0, "PM_RDISC" }, 405 { 0, 0, "%#x"} 406 }; 407 408 static struct bits rs_bits[] = { 409 { RS_IF, 0, "IF" }, 410 { RS_NET_INT, RS_NET_SYN, "NET_INT" }, 411 { RS_NET_SYN, 0, "NET_SYN" }, 412 { RS_SUBNET, 0, "" }, 413 { RS_LOCAL, 0, "LOCAL" }, 414 { RS_MHOME, 0, "MHOME" }, 415 { RS_STATIC, 0, "STATIC" }, 416 { RS_RDISC, 0, "RDISC" }, 417 { 0, 0, "%#x"} 418 }; 419 420 421 static void 422 trace_bits(struct bits *tbl, 423 u_int field, 424 int force) 425 { 426 int b; 427 char c; 428 429 if (force) { 430 (void)putc('<', ftrace); 431 c = 0; 432 } else { 433 c = '<'; 434 } 435 436 while (field != 0 437 && (b = tbl->bits_mask) != 0) { 438 if ((b & field) == b) { 439 if (tbl->bits_name[0] != '\0') { 440 if (c) 441 (void)putc(c, ftrace); 442 (void)fprintf(ftrace, "%s", tbl->bits_name); 443 c = '|'; 444 } 445 if (0 == (field &= ~(b | tbl->bits_clear))) 446 break; 447 } 448 tbl++; 449 } 450 if (field != 0 && tbl->bits_name != 0) { 451 if (c) 452 (void)putc(c, ftrace); 453 (void)fprintf(ftrace, tbl->bits_name, field); 454 c = '|'; 455 } 456 457 if (c != '<' || force) 458 (void)fputs("> ", ftrace); 459 } 460 461 462 static char * 463 trace_pair(naddr dst, 464 naddr mask, 465 char *gate) 466 { 467 static char buf[3*4+3+1+2+3 /* "xxx.xxx.xxx.xxx/xx-->" */ 468 +3*4+3+1]; /* "xxx.xxx.xxx.xxx" */ 469 int i; 470 471 i = sprintf(buf, "%-16s-->", addrname(dst, mask, 0)); 472 (void)sprintf(&buf[i], "%-*s", 15+20-MAX(20,i), gate); 473 return buf; 474 } 475 476 477 void 478 trace_if(char *act, 479 struct interface *ifp) 480 { 481 if (!TRACEACTIONS || ftrace == 0) 482 return; 483 484 lastlog(); 485 (void)fprintf(ftrace, "%s interface %-4s ", act, ifp->int_name); 486 (void)fprintf(ftrace, "%-15s --> %s ", 487 naddr_ntoa(ifp->int_addr), 488 ((ifp->int_if_flags & IFF_POINTOPOINT) 489 ? naddr_ntoa(ifp->int_dstaddr) 490 : addrname(htonl(ifp->int_net), ifp->int_mask, 0))); 491 (void)fprintf(ftrace, "metric=%d ", ifp->int_metric); 492 trace_bits(if_bits, ifp->int_if_flags, 0); 493 trace_bits(is_bits, ifp->int_state, 0); 494 (void)fputc('\n',ftrace); 495 } 496 497 498 void 499 trace_upslot(struct rt_entry *rt, 500 struct rt_spare *rts, 501 naddr gate, 502 naddr router, 503 struct interface *ifp, 504 int metric, 505 u_short tag, 506 time_t new_time) 507 { 508 if (!TRACEACTIONS || ftrace == 0) 509 return; 510 if (rts->rts_gate == gate 511 && rts->rts_router == router 512 && rts->rts_metric == metric 513 && rts->rts_tag == tag) 514 return; 515 516 lastlog(); 517 if (rts->rts_gate != RIP_DEFAULT) { 518 (void)fprintf(ftrace, "Chg #%d %-35s ", 519 rts - rt->rt_spares, 520 trace_pair(rt->rt_dst, rt->rt_mask, 521 naddr_ntoa(rts->rts_gate))); 522 if (rts->rts_gate != rts->rts_gate) 523 (void)fprintf(ftrace, "router=%s ", 524 naddr_ntoa(rts->rts_gate)); 525 if (rts->rts_tag != 0) 526 (void)fprintf(ftrace, "tag=%#x ", rts->rts_tag); 527 (void)fprintf(ftrace, "metric=%-2d ", rts->rts_metric); 528 if (rts->rts_ifp != 0) 529 (void)fprintf(ftrace, "%s ", 530 rts->rts_ifp->int_name); 531 (void)fprintf(ftrace, "%s\n", ts(rts->rts_time)); 532 533 (void)fprintf(ftrace, " %19s%-16s ", 534 "", 535 gate != rts->rts_gate ? naddr_ntoa(gate) : ""); 536 if (gate != router) 537 (void)fprintf(ftrace,"router=%s ",naddr_ntoa(router)); 538 if (tag != rts->rts_tag) 539 (void)fprintf(ftrace, "tag=%#x ", tag); 540 if (metric != rts->rts_metric) 541 (void)fprintf(ftrace, "metric=%-2d ", metric); 542 if (ifp != rts->rts_ifp && ifp != 0 ) 543 (void)fprintf(ftrace, "%s ", ifp->int_name); 544 (void)fprintf(ftrace, "%s\n", 545 new_time != rts->rts_time ? ts(new_time) : ""); 546 547 } else { 548 (void)fprintf(ftrace, "Add #%d %-35s ", 549 rts - rt->rt_spares, 550 trace_pair(rt->rt_dst, rt->rt_mask, 551 naddr_ntoa(gate))); 552 if (gate != router) 553 (void)fprintf(ftrace, "router=%s ", naddr_ntoa(gate)); 554 if (tag != 0) 555 (void)fprintf(ftrace, "tag=%#x ", tag); 556 (void)fprintf(ftrace, "metric=%-2d ", metric); 557 if (ifp != 0) 558 (void)fprintf(ftrace, "%s ", ifp->int_name); 559 (void)fprintf(ftrace, "%s\n", ts(new_time)); 560 } 561 } 562 563 564 /* display a message if tracing actions 565 */ 566 void 567 trace_act(char *p, ...) 568 { 569 va_list args; 570 571 if (!TRACEACTIONS || ftrace == 0) 572 return; 573 574 lastlog(); 575 va_start(args, p); 576 vfprintf(ftrace, p, args); 577 } 578 579 580 /* display a message if tracing packets 581 */ 582 void 583 trace_pkt(char *p, ...) 584 { 585 va_list args; 586 587 if (!TRACEPACKETS || ftrace == 0) 588 return; 589 590 lastlog(); 591 va_start(args, p); 592 vfprintf(ftrace, p, args); 593 } 594 595 596 void 597 trace_change(struct rt_entry *rt, 598 u_int state, 599 naddr gate, /* forward packets here */ 600 naddr router, /* on the authority of this router */ 601 int metric, 602 u_short tag, 603 struct interface *ifp, 604 time_t new_time, 605 char *label) 606 { 607 if (ftrace == 0) 608 return; 609 610 if (rt->rt_metric == metric 611 && rt->rt_gate == gate 612 && rt->rt_router == router 613 && rt->rt_state == state 614 && rt->rt_tag == tag) 615 return; 616 617 lastlog(); 618 (void)fprintf(ftrace, "%s %-35s metric=%-2d ", 619 label, 620 trace_pair(rt->rt_dst, rt->rt_mask, 621 naddr_ntoa(rt->rt_gate)), 622 rt->rt_metric); 623 if (rt->rt_router != rt->rt_gate) 624 (void)fprintf(ftrace, "router=%s ", 625 naddr_ntoa(rt->rt_router)); 626 if (rt->rt_tag != 0) 627 (void)fprintf(ftrace, "tag=%#x ", rt->rt_tag); 628 trace_bits(rs_bits, rt->rt_state, rt->rt_state != state); 629 (void)fprintf(ftrace, "%s ", 630 rt->rt_ifp == 0 ? "?" : rt->rt_ifp->int_name); 631 (void)fprintf(ftrace, "%s\n", 632 AGE_RT(rt, rt->rt_ifp) ? ts(rt->rt_time) : ""); 633 634 (void)fprintf(ftrace, "%*s %19s%-16s ", 635 strlen(label), "", "", 636 rt->rt_gate != gate ? naddr_ntoa(gate) : ""); 637 if (rt->rt_metric != metric) 638 (void)fprintf(ftrace, "metric=%-2d ", metric); 639 if (router != gate) 640 (void)fprintf(ftrace, "router=%s ", naddr_ntoa(router)); 641 if (rt->rt_tag != tag) 642 (void)fprintf(ftrace, "tag=%#x ", tag); 643 if (rt->rt_state != state) 644 trace_bits(rs_bits, state, 1); 645 if (rt->rt_ifp != ifp) 646 (void)fprintf(ftrace, "%s ", 647 ifp != 0 ? ifp->int_name : "?"); 648 (void)fprintf(ftrace, "%s\n", 649 ((rt->rt_time == new_time || !AGE_RT(rt, ifp)) 650 ? "" : ts(new_time))); 651 } 652 653 654 void 655 trace_add_del(char * action, struct rt_entry *rt) 656 { 657 u_int state = rt->rt_state; 658 659 if (ftrace == 0) 660 return; 661 662 lastlog(); 663 (void)fprintf(ftrace, "%s %-35s metric=%-2d ", 664 action, 665 trace_pair(rt->rt_dst, rt->rt_mask, 666 naddr_ntoa(rt->rt_gate)), 667 rt->rt_metric); 668 if (rt->rt_router != rt->rt_gate) 669 (void)fprintf(ftrace, "router=%s ", 670 naddr_ntoa(rt->rt_router)); 671 if (rt->rt_tag != 0) 672 (void)fprintf(ftrace, "tag=%#x ", rt->rt_tag); 673 trace_bits(rs_bits, state, 0); 674 (void)fprintf(ftrace, "%s ", 675 rt->rt_ifp != 0 ? rt->rt_ifp->int_name : "?"); 676 (void)fprintf(ftrace, "%s\n", ts(rt->rt_time)); 677 } 678 679 680 void 681 trace_rip(char *dir1, char *dir2, 682 struct sockaddr_in *who, 683 struct interface *ifp, 684 struct rip *msg, 685 int size) /* total size of message */ 686 { 687 struct netinfo *n, *lim; 688 struct netauth *a; 689 int i; 690 691 if (!TRACEPACKETS || ftrace == 0) 692 return; 693 694 lastlog(); 695 if (msg->rip_cmd >= RIPCMD_MAX 696 || msg->rip_vers == 0) { 697 (void)fprintf(ftrace, 698 "%s bad RIPv%d cmd=%d %s %s.%d size=%d msg=%#lx\n", 699 dir1, msg->rip_vers, msg->rip_cmd, dir2, 700 naddr_ntoa(who->sin_addr.s_addr), 701 ntohs(who->sin_port), size, (unsigned long)msg); 702 return; 703 } 704 705 (void)fprintf(ftrace, "%s RIPv%d %s %s %s.%d%s%s\n", 706 dir1, msg->rip_vers, ripcmds[msg->rip_cmd], dir2, 707 naddr_ntoa(who->sin_addr.s_addr), ntohs(who->sin_port), 708 ifp ? " via " : "", ifp ? ifp->int_name : ""); 709 if (!TRACECONTENTS) 710 return; 711 712 switch (msg->rip_cmd) { 713 case RIPCMD_REQUEST: 714 case RIPCMD_RESPONSE: 715 n = msg->rip_nets; 716 lim = (struct netinfo *)((char*)msg + size); 717 for (; n < lim; n++) { 718 if (n->n_family == RIP_AF_UNSPEC 719 && ntohl(n->n_metric) == HOPCNT_INFINITY 720 && n+1 == lim 721 && n == msg->rip_nets 722 && msg->rip_cmd == RIPCMD_REQUEST) { 723 (void)fputs("\tQUERY ", ftrace); 724 if (n->n_dst != 0) 725 (void)fprintf(ftrace, "%s ", 726 naddr_ntoa(n->n_dst)); 727 if (n->n_mask != 0) 728 (void)fprintf(ftrace, "mask=%#x ", 729 ntohl(n->n_mask)); 730 if (n->n_nhop != 0) 731 (void)fprintf(ftrace, " nhop=%s ", 732 naddr_ntoa(n->n_nhop)); 733 if (n->n_tag != 0) 734 (void)fprintf(ftrace, "tag=%#x", 735 n->n_tag); 736 (void)fputc('\n',ftrace); 737 continue; 738 } 739 740 if (n->n_family == RIP_AF_AUTH) { 741 a = (struct netauth*)n; 742 (void)fprintf(ftrace, 743 "\tAuthentication type %d: ", 744 ntohs(a->a_type)); 745 for (i = 0; 746 i < sizeof(a->au.au_pw); 747 i++) 748 (void)fprintf(ftrace, "%02x ", 749 a->au.au_pw[i]); 750 (void)fputc('\n',ftrace); 751 continue; 752 } 753 754 if (n->n_family != RIP_AF_INET) { 755 (void)fprintf(ftrace, 756 "\t(af %d) %-18s mask=%#x", 757 ntohs(n->n_family), 758 naddr_ntoa(n->n_dst), 759 ntohl(n->n_mask)); 760 } else if (msg->rip_vers == RIPv1) { 761 (void)fprintf(ftrace, "\t%-18s ", 762 addrname(n->n_dst, 763 ntohl(n->n_mask), 764 n->n_mask==0 ? 2 : 1)); 765 } else { 766 (void)fprintf(ftrace, "\t%-18s ", 767 addrname(n->n_dst, 768 ntohl(n->n_mask), 769 n->n_mask==0 ? 2 : 0)); 770 } 771 (void)fprintf(ftrace, "metric=%-2d ", 772 ntohl(n->n_metric)); 773 if (n->n_nhop != 0) 774 (void)fprintf(ftrace, " nhop=%s ", 775 naddr_ntoa(n->n_nhop)); 776 if (n->n_tag != 0) 777 (void)fprintf(ftrace, "tag=%#x", 778 n->n_tag); 779 (void)fputc('\n',ftrace); 780 } 781 if (size != (char *)n - (char *)msg) 782 (void)fprintf(ftrace, "truncated record, len %d\n", 783 size); 784 break; 785 786 case RIPCMD_TRACEON: 787 fprintf(ftrace, "\tfile=%*s\n", size-4, msg->rip_tracefile); 788 break; 789 790 case RIPCMD_TRACEOFF: 791 break; 792 } 793 } 794