trace.c revision 1.1.1.3 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)
35 static char sccsid[] = "@(#)trace.c 8.1 (Berkeley) 6/5/93";
36 #endif /* not lint */
37
38 #ident "$Revision: 1.1.1.3 $"
39
40 #define RIPCMDS
41 #include "defs.h"
42 #include "pathnames.h"
43 #include <sys/stat.h>
44 #include <sys/signal.h>
45 #include <fcntl.h>
46
47
48 #ifdef sgi
49 /* use *stat64 for files on large filesystems */
50 #define stat stat64
51 #endif
52
53 #define NRECORDS 50 /* size of circular trace buffer */
54
55 u_int tracelevel, new_tracelevel;
56 FILE *ftrace = stdout; /* output trace file */
57 static char *tracelevel_pat = "%s\n";
58
59 char savetracename[MAXPATHLEN+1];
60
61
62 /* convert IP address to a string, but not into a single buffer
63 */
64 char *
65 naddr_ntoa(naddr a)
66 {
67 #define NUM_BUFS 4
68 static int i;
69 static struct {
70 char str[16]; /* xxx.xxx.xxx.xxx\0 */
71 } bufs[NUM_BUFS];
72 struct in_addr addr;
73 char *s;
74
75 addr.s_addr = a;
76 s = strcpy(bufs[i].str, inet_ntoa(addr));
77 i = (i+1) % NUM_BUFS;
78 return s;
79 }
80
81
82 char *
83 saddr_ntoa(struct sockaddr *sa)
84 {
85 return (sa == 0) ? "?" : naddr_ntoa(S_ADDR(sa));
86 }
87
88
89 static char *
90 ts(time_t secs) {
91 static char s[20];
92
93 secs += epoch.tv_sec;
94 #ifdef sgi
95 (void)cftime(s, "%T", &secs);
96 #else
97 bcopy(ctime(&secs)+11, s, 8);
98 s[8] = '\0';
99 #endif
100 return s;
101 }
102
103
104 /* On each event, display a time stamp.
105 * This assumes that 'now' is update once for each event, and
106 * that at least now.tv_usec changes.
107 */
108 void
109 lastlog(void)
110 {
111 static struct timeval last;
112
113 if (last.tv_sec != now.tv_sec
114 || last.tv_usec != now.tv_usec) {
115 (void)fprintf(ftrace, "-- %s --\n", ts(now.tv_sec));
116 last = now;
117 }
118 }
119
120
121 static void
122 tmsg(char *p, ...)
123 {
124 va_list args;
125
126 if (ftrace != 0) {
127 lastlog();
128 va_start(args, p);
129 vfprintf(ftrace, p, args);
130 fflush(ftrace);
131 }
132 }
133
134
135 static 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
157 trace_flush(void)
158 {
159 if (ftrace != 0) {
160 fflush(ftrace);
161 if (ferror(ftrace))
162 trace_off("tracing off: ", strerror(ferror(ftrace)));
163 }
164 }
165
166
167 void
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 }
179 trace_close();
180
181 new_tracelevel = tracelevel = 0;
182 }
183
184
185 void
186 trace_on(char *filename,
187 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 (stat(filename, &stbuf) >= 0) {
207 if (!trusted) {
208 msglog("trace file \"%s\" already exists");
209 return;
210 }
211 if ((stbuf.st_mode & S_IFMT) != S_IFREG) {
212 msglog("wrong type (%#x) of trace file \"%s\"",
213 stbuf.st_mode, filename);
214 return;
215 }
216
217 if (!trusted
218 && strcmp(filename, savetracename)
219 && strncmp(filename, _PATH_TRACE, sizeof(_PATH_TRACE)-1)) {
220 msglog("wrong directory for trace file: \"%s\"",
221 filename);
222 return;
223 }
224 }
225
226 n_ftrace = fopen(filename, "a");
227 if (n_ftrace == 0) {
228 msglog("failed to open trace file \"%s\" %s",
229 filename, strerror(errno));
230 return;
231 }
232
233 tmsg("switch to trace file %s\n", filename);
234 trace_close();
235 if (filename != savetracename)
236 strncpy(savetracename, filename, sizeof(savetracename)-1);
237 ftrace = n_ftrace;
238
239 fflush(stdout);
240 fflush(stderr);
241 dup2(fileno(ftrace), STDOUT_FILENO);
242 dup2(fileno(ftrace), STDERR_FILENO);
243
244 if (new_tracelevel == 0)
245 new_tracelevel = 1;
246 set_tracelevel();
247 }
248
249
250 /* ARGSUSED */
251 void
252 sigtrace_on(int s)
253 {
254 new_tracelevel++;
255 tracelevel_pat = "SIGUSR1: %s\n";
256 }
257
258
259 /* ARGSUSED */
260 void
261 sigtrace_off(int s)
262 {
263 new_tracelevel--;
264 tracelevel_pat = "SIGUSR2: %s\n";
265 }
266
267
268 /* Move to next higher level of tracing when -t option processed or
269 * SIGUSR1 is received. Successive levels are:
270 * actions
271 * actions + packets
272 * actions + packets + contents
273 */
274 void
275 set_tracelevel(void)
276 {
277 static char *off_msgs[MAX_TRACELEVEL] = {
278 "Tracing actions stopped",
279 "Tracing packets stopped",
280 "Tracing packet contents stopped",
281 };
282 static char *on_msgs[MAX_TRACELEVEL] = {
283 "Tracing actions started",
284 "Tracing packets started",
285 "Tracing packet contents started",
286 };
287
288
289 if (new_tracelevel > MAX_TRACELEVEL) {
290 new_tracelevel = MAX_TRACELEVEL;
291 if (new_tracelevel == tracelevel) {
292 tmsg(tracelevel_pat, on_msgs[tracelevel-1]);
293 return;
294 }
295 }
296 while (new_tracelevel != tracelevel) {
297 if (new_tracelevel < tracelevel) {
298 if (--tracelevel == 0)
299 trace_off(tracelevel_pat, off_msgs[0]);
300 else
301 tmsg(tracelevel_pat, off_msgs[tracelevel]);
302 } else {
303 if (ftrace == 0) {
304 if (savetracename[0] != '\0')
305 trace_on(savetracename, 1);
306 else
307 ftrace = stdout;
308 }
309 tmsg(tracelevel_pat, on_msgs[tracelevel++]);
310 }
311 }
312 tracelevel_pat = "%s\n";
313 }
314
315
316 /* display an address
317 */
318 char *
319 addrname(naddr addr, /* in network byte order */
320 naddr mask,
321 int force) /* 0=show mask if nonstandard, */
322 { /* 1=always show mask, 2=never */
323 static char s[15+20];
324 char *sp;
325 naddr dmask;
326 int i;
327
328 (void)strcpy(s, naddr_ntoa(addr));
329
330 if (force == 1 || (force == 0 && mask != std_mask(addr))) {
331 sp = &s[strlen(s)];
332
333 dmask = mask & -mask;
334 if (mask + dmask == 0) {
335 for (i = 0; i != 32 && ((1<<i) & mask) == 0; i++)
336 continue;
337 (void)sprintf(sp, "/%d", 32-i);
338
339 } else {
340 (void)sprintf(sp, " (mask %#x)", mask);
341 }
342 }
343
344 return s;
345 }
346
347
348 /* display a bit-field
349 */
350 struct bits {
351 int bits_mask;
352 int bits_clear;
353 char *bits_name;
354 };
355
356 static struct bits if_bits[] = {
357 { IFF_LOOPBACK, 0, "LOOPBACK" },
358 { IFF_POINTOPOINT, 0, "PT-TO-PT" },
359 { 0, 0, 0}
360 };
361
362 static struct bits is_bits[] = {
363 { IS_SUBNET, 0, "" },
364 { IS_REMOTE, 0, "REMOTE" },
365 { IS_PASSIVE, (IS_NO_RDISC
366 | IS_BCAST_RDISC
367 | IS_NO_RIP
368 | IS_NO_SUPER_AG
369 | IS_PM_RDISC
370 | IS_NO_AG), "PASSIVE" },
371 { IS_EXTERNAL, 0, "EXTERNAL" },
372 { IS_CHECKED, 0, "" },
373 { IS_ALL_HOSTS, 0, "" },
374 { IS_ALL_ROUTERS, 0, "" },
375 { IS_RIP_QUERIED, 0, "" },
376 { IS_BROKE, IS_SICK, "BROKEN" },
377 { IS_SICK, 0, "SICK" },
378 { IS_ACTIVE, 0, "ACTIVE" },
379 { IS_NEED_NET_SYN, 0, "" },
380 { IS_NO_AG, IS_NO_SUPER_AG, "NO_AG" },
381 { IS_NO_SUPER_AG, 0, "NO_SUPER_AG" },
382 { (IS_NO_RIPV1_IN
383 | IS_NO_RIPV2_IN
384 | IS_NO_RIPV1_OUT
385 | IS_NO_RIPV2_OUT), 0, "NO_RIP" },
386 { (IS_NO_RIPV1_IN
387 | IS_NO_RIPV1_OUT), 0, "RIPV2" },
388 { IS_NO_RIPV1_IN, 0, "NO_RIPV1_IN" },
389 { IS_NO_RIPV2_IN, 0, "NO_RIPV2_IN" },
390 { IS_NO_RIPV1_OUT, 0, "NO_RIPV1_OUT" },
391 { IS_NO_RIPV2_OUT, 0, "NO_RIPV2_OUT" },
392 { (IS_NO_ADV_IN
393 | IS_NO_SOL_OUT
394 | IS_NO_ADV_OUT), IS_BCAST_RDISC, "NO_RDISC" },
395 { IS_NO_SOL_OUT, 0, "NO_SOLICIT" },
396 { IS_SOL_OUT, 0, "SEND_SOLICIT" },
397 { IS_NO_ADV_OUT, IS_BCAST_RDISC, "NO_RDISC_ADV" },
398 { IS_ADV_OUT, 0, "RDISC_ADV" },
399 { IS_BCAST_RDISC, 0, "BCAST_RDISC" },
400 { IS_PM_RDISC, 0, "PM_RDISC" },
401 { 0, 0, "%#x"}
402 };
403
404 static struct bits rs_bits[] = {
405 { RS_IF, 0, "IF" },
406 { RS_NET_INT, RS_NET_SYN, "NET_INT" },
407 { RS_NET_SYN, 0, "NET_SYN" },
408 { RS_SUBNET, 0, "" },
409 { RS_LOCAL, 0, "LOCAL" },
410 { RS_MHOME, 0, "MHOME" },
411 { RS_STATIC, 0, "STATIC" },
412 { RS_RDISC, 0, "RDISC" },
413 { 0, 0, "%#x"}
414 };
415
416
417 static void
418 trace_bits(struct bits *tbl,
419 u_int field,
420 int force)
421 {
422 int b;
423 char c;
424
425 if (force) {
426 (void)putc('<', ftrace);
427 c = 0;
428 } else {
429 c = '<';
430 }
431
432 while (field != 0
433 && (b = tbl->bits_mask) != 0) {
434 if ((b & field) == b) {
435 if (tbl->bits_name[0] != '\0') {
436 if (c)
437 (void)putc(c, ftrace);
438 (void)fprintf(ftrace, "%s", tbl->bits_name);
439 c = '|';
440 }
441 if (0 == (field &= ~(b | tbl->bits_clear)))
442 break;
443 }
444 tbl++;
445 }
446 if (field != 0 && tbl->bits_name != 0) {
447 if (c)
448 (void)putc(c, ftrace);
449 (void)fprintf(ftrace, tbl->bits_name, field);
450 c = '|';
451 }
452
453 if (c != '<' || force)
454 (void)fputs("> ", ftrace);
455 }
456
457
458 static char *
459 trace_pair(naddr dst,
460 naddr mask,
461 char *gate)
462 {
463 static char buf[3*4+3+1+2+3 /* "xxx.xxx.xxx.xxx/xx-->" */
464 +3*4+3+1]; /* "xxx.xxx.xxx.xxx" */
465 int i;
466
467 i = sprintf(buf, "%-16s-->", addrname(dst, mask, 0));
468 (void)sprintf(&buf[i], "%-*s", 15+20-MAX(20,i), gate);
469 return buf;
470 }
471
472
473 void
474 trace_if(char *act,
475 struct interface *ifp)
476 {
477 if (!TRACEACTIONS || ftrace == 0)
478 return;
479
480 lastlog();
481 (void)fprintf(ftrace, "%s interface %-4s ", act, ifp->int_name);
482 (void)fprintf(ftrace, "%-15s --> %s ",
483 naddr_ntoa(ifp->int_addr),
484 ((ifp->int_if_flags & IFF_POINTOPOINT)
485 ? naddr_ntoa(ifp->int_dstaddr)
486 : addrname(htonl(ifp->int_net), ifp->int_mask, 0)));
487 (void)fprintf(ftrace, "metric=%d ", ifp->int_metric);
488 trace_bits(if_bits, ifp->int_if_flags, 0);
489 trace_bits(is_bits, ifp->int_state, 0);
490 (void)fputc('\n',ftrace);
491 }
492
493
494 void
495 trace_upslot(struct rt_entry *rt,
496 struct rt_spare *rts,
497 naddr gate,
498 naddr router,
499 struct interface *ifp,
500 int metric,
501 u_short tag,
502 time_t new_time)
503 {
504 if (!TRACEACTIONS || ftrace == 0)
505 return;
506 if (rts->rts_gate == gate
507 && rts->rts_router == router
508 && rts->rts_metric == metric
509 && rts->rts_tag == tag)
510 return;
511
512 lastlog();
513 if (rts->rts_gate != RIP_DEFAULT) {
514 (void)fprintf(ftrace, "Chg #%d %-35s ",
515 rts - rt->rt_spares,
516 trace_pair(rt->rt_dst, rt->rt_mask,
517 naddr_ntoa(rts->rts_gate)));
518 if (rts->rts_gate != rts->rts_gate)
519 (void)fprintf(ftrace, "router=%s ",
520 naddr_ntoa(rts->rts_gate));
521 if (rts->rts_tag != 0)
522 (void)fprintf(ftrace, "tag=%#x ", rts->rts_tag);
523 (void)fprintf(ftrace, "metric=%-2d ", rts->rts_metric);
524 if (rts->rts_ifp != 0)
525 (void)fprintf(ftrace, "%s ",
526 rts->rts_ifp->int_name);
527 (void)fprintf(ftrace, "%s\n", ts(rts->rts_time));
528
529 (void)fprintf(ftrace, " %19s%-16s ",
530 "",
531 gate != rts->rts_gate ? naddr_ntoa(gate) : "");
532 if (gate != router)
533 (void)fprintf(ftrace,"router=%s ",naddr_ntoa(router));
534 if (tag != rts->rts_tag)
535 (void)fprintf(ftrace, "tag=%#x ", tag);
536 if (metric != rts->rts_metric)
537 (void)fprintf(ftrace, "metric=%-2d ", metric);
538 if (ifp != rts->rts_ifp && ifp != 0 )
539 (void)fprintf(ftrace, "%s ", ifp->int_name);
540 (void)fprintf(ftrace, "%s\n",
541 new_time != rts->rts_time ? ts(new_time) : "");
542
543 } else {
544 (void)fprintf(ftrace, "Add #%d %-35s ",
545 rts - rt->rt_spares,
546 trace_pair(rt->rt_dst, rt->rt_mask,
547 naddr_ntoa(gate)));
548 if (gate != router)
549 (void)fprintf(ftrace, "router=%s ", naddr_ntoa(gate));
550 if (tag != 0)
551 (void)fprintf(ftrace, "tag=%#x ", tag);
552 (void)fprintf(ftrace, "metric=%-2d ", metric);
553 if (ifp != 0)
554 (void)fprintf(ftrace, "%s ", ifp->int_name);
555 (void)fprintf(ftrace, "%s\n", ts(new_time));
556 }
557 }
558
559
560 /* display a message if tracing actions
561 */
562 void
563 trace_act(char *p, ...)
564 {
565 va_list args;
566
567 if (!TRACEACTIONS || ftrace == 0)
568 return;
569
570 lastlog();
571 va_start(args, p);
572 vfprintf(ftrace, p, args);
573 }
574
575
576 /* display a message if tracing packets
577 */
578 void
579 trace_pkt(char *p, ...)
580 {
581 va_list args;
582
583 if (!TRACEPACKETS || ftrace == 0)
584 return;
585
586 lastlog();
587 va_start(args, p);
588 vfprintf(ftrace, p, args);
589 }
590
591
592 void
593 trace_change(struct rt_entry *rt,
594 u_int state,
595 naddr gate, /* forward packets here */
596 naddr router, /* on the authority of this router */
597 int metric,
598 u_short tag,
599 struct interface *ifp,
600 time_t new_time,
601 char *label)
602 {
603 if (ftrace == 0)
604 return;
605
606 if (rt->rt_metric == metric
607 && rt->rt_gate == gate
608 && rt->rt_router == router
609 && rt->rt_state == state
610 && rt->rt_tag == tag)
611 return;
612
613 lastlog();
614 (void)fprintf(ftrace, "%s %-35s metric=%-2d ",
615 label,
616 trace_pair(rt->rt_dst, rt->rt_mask,
617 naddr_ntoa(rt->rt_gate)),
618 rt->rt_metric);
619 if (rt->rt_router != rt->rt_gate)
620 (void)fprintf(ftrace, "router=%s ",
621 naddr_ntoa(rt->rt_router));
622 if (rt->rt_tag != 0)
623 (void)fprintf(ftrace, "tag=%#x ", rt->rt_tag);
624 trace_bits(rs_bits, rt->rt_state, rt->rt_state != state);
625 (void)fprintf(ftrace, "%s ",
626 rt->rt_ifp == 0 ? "?" : rt->rt_ifp->int_name);
627 (void)fprintf(ftrace, "%s\n",
628 AGE_RT(rt, rt->rt_ifp) ? ts(rt->rt_time) : "");
629
630 (void)fprintf(ftrace, "%*s %19s%-16s ",
631 strlen(label), "", "",
632 rt->rt_gate != gate ? naddr_ntoa(gate) : "");
633 if (rt->rt_metric != metric)
634 (void)fprintf(ftrace, "metric=%-2d ", metric);
635 if (router != gate)
636 (void)fprintf(ftrace, "router=%s ", naddr_ntoa(router));
637 if (rt->rt_tag != tag)
638 (void)fprintf(ftrace, "tag=%#x ", tag);
639 if (rt->rt_state != state)
640 trace_bits(rs_bits, state, 1);
641 if (rt->rt_ifp != ifp)
642 (void)fprintf(ftrace, "%s ",
643 ifp != 0 ? ifp->int_name : "?");
644 (void)fprintf(ftrace, "%s\n",
645 ((rt->rt_time == new_time || !AGE_RT(rt, ifp))
646 ? "" : ts(new_time)));
647 }
648
649
650 void
651 trace_add_del(char * action, struct rt_entry *rt)
652 {
653 u_int state = rt->rt_state;
654
655 if (ftrace == 0)
656 return;
657
658 lastlog();
659 (void)fprintf(ftrace, "%s %-35s metric=%-2d ",
660 action,
661 trace_pair(rt->rt_dst, rt->rt_mask,
662 naddr_ntoa(rt->rt_gate)),
663 rt->rt_metric);
664 if (rt->rt_router != rt->rt_gate)
665 (void)fprintf(ftrace, "router=%s ",
666 naddr_ntoa(rt->rt_router));
667 if (rt->rt_tag != 0)
668 (void)fprintf(ftrace, "tag=%#x ", rt->rt_tag);
669 trace_bits(rs_bits, state, 0);
670 (void)fprintf(ftrace, "%s ",
671 rt->rt_ifp != 0 ? rt->rt_ifp->int_name : "?");
672 (void)fprintf(ftrace, "%s\n", ts(rt->rt_time));
673 }
674
675
676 void
677 trace_rip(char *dir1, char *dir2,
678 struct sockaddr_in *who,
679 struct interface *ifp,
680 struct rip *msg,
681 int size) /* total size of message */
682 {
683 struct netinfo *n, *lim;
684 struct netauth *a;
685 int i;
686
687 if (!TRACEPACKETS || ftrace == 0)
688 return;
689
690 lastlog();
691 if (msg->rip_cmd >= RIPCMD_MAX
692 || msg->rip_vers == 0) {
693 (void)fprintf(ftrace, "%s bad RIPv%d cmd=%d %s %s.%d%s%s"
694 " size=%d msg=%#x\n",
695 dir1, msg->rip_vers, msg->rip_cmd, dir2,
696 naddr_ntoa(who->sin_addr.s_addr),
697 ntohs(who->sin_port),
698 size, msg);
699 return;
700 }
701
702 (void)fprintf(ftrace, "%s RIPv%d %s %s %s.%d%s%s\n",
703 dir1, msg->rip_vers, ripcmds[msg->rip_cmd], dir2,
704 naddr_ntoa(who->sin_addr.s_addr), ntohs(who->sin_port),
705 ifp ? " via " : "", ifp ? ifp->int_name : "");
706 if (!TRACECONTENTS)
707 return;
708
709 switch (msg->rip_cmd) {
710 case RIPCMD_REQUEST:
711 case RIPCMD_RESPONSE:
712 n = msg->rip_nets;
713 lim = (struct netinfo *)((char*)msg + size);
714 for (; n < lim; n++) {
715 if (n->n_family == RIP_AF_UNSPEC
716 && ntohl(n->n_metric) == HOPCNT_INFINITY
717 && n+1 == lim
718 && n == msg->rip_nets
719 && msg->rip_cmd == RIPCMD_REQUEST) {
720 (void)fputs("\tQUERY ", ftrace);
721 if (n->n_dst != 0)
722 (void)fprintf(ftrace, "%s ",
723 naddr_ntoa(n->n_dst));
724 if (n->n_mask != 0)
725 (void)fprintf(ftrace, "mask=%#x ",
726 ntohl(n->n_mask));
727 if (n->n_nhop != 0)
728 (void)fprintf(ftrace, " nhop=%s ",
729 naddr_ntoa(n->n_nhop));
730 if (n->n_tag != 0)
731 (void)fprintf(ftrace, "tag=%#x",
732 n->n_tag);
733 (void)fputc('\n',ftrace);
734 continue;
735 }
736
737 if (n->n_family == RIP_AF_AUTH) {
738 a = (struct netauth*)n;
739 (void)fprintf(ftrace,
740 "\tAuthentication type %d: ",
741 ntohs(a->a_type));
742 for (i = 0;
743 i < sizeof(a->au.au_pw);
744 i++)
745 (void)fprintf(ftrace, "%02x ",
746 a->au.au_pw[i]);
747 (void)fputc('\n',ftrace);
748 continue;
749 }
750
751 if (n->n_family != RIP_AF_INET) {
752 (void)fprintf(ftrace,
753 "\t(af %d) %-18s mask=%#x",
754 ntohs(n->n_family),
755 naddr_ntoa(n->n_dst),
756 ntohl(n->n_mask));
757 } else if (msg->rip_vers == RIPv1) {
758 (void)fprintf(ftrace, "\t%-18s ",
759 addrname(n->n_dst,
760 ntohl(n->n_mask),
761 n->n_mask==0 ? 2 : 1));
762 } else {
763 (void)fprintf(ftrace, "\t%-18s ",
764 addrname(n->n_dst,
765 ntohl(n->n_mask),
766 n->n_mask==0 ? 2 : 0));
767 }
768 (void)fprintf(ftrace, "metric=%-2d ",
769 ntohl(n->n_metric));
770 if (n->n_nhop != 0)
771 (void)fprintf(ftrace, " nhop=%s ",
772 naddr_ntoa(n->n_nhop));
773 if (n->n_tag != 0)
774 (void)fprintf(ftrace, "tag=%#x",
775 n->n_tag);
776 (void)fputc('\n',ftrace);
777 }
778 if (size != (char *)n - (char *)msg)
779 (void)fprintf(ftrace, "truncated record, len %d\n",
780 size);
781 break;
782
783 case RIPCMD_TRACEON:
784 fprintf(ftrace, "\tfile=%*s\n", size-4, msg->rip_tracefile);
785 break;
786
787 case RIPCMD_TRACEOFF:
788 break;
789 }
790 }
791