trace.c revision 1.1.1.4 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: trace.c,v 1.1.1.4 1996/09/24 15:11:45 christos Exp $";
38 #endif
39 #ident "$Revision: 1.1.1.4 $"
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