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