Annotation of embedaddon/pimd/debug.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (c) 1998-2001
3: * University of Southern California/Information Sciences Institute.
4: * All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: * 3. Neither the name of the project nor the names of its contributors
15: * may be used to endorse or promote products derived from this software
16: * without specific prior written permission.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
19: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
22: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28: * SUCH DAMAGE.
29: */
30: /*
31: * $Id: debug.c,v 1.22 2001/11/28 00:13:50 pavlin Exp $
32: */
33: /*
34: * Part of this program has been derived from mrouted.
35: * The mrouted program is covered by the license in the accompanying file
36: * named "LICENSE.mrouted".
37: *
38: * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
39: * Leland Stanford Junior University.
40: *
41: */
42:
43: #define SYSLOG_NAMES
44: #include "defs.h"
45:
46: #include <stdarg.h>
47: #include <stdio.h>
48:
49: #define MAX_MSG_SIZE 64 /* Max for dump_frame() */
50:
51: int log_nmsgs = 0;
52: int loglevel = LOG_NOTICE;
53: unsigned long debug = 0x00000000; /* If (long) is smaller than
54: * 4 bytes, then we are in
55: * trouble.
56: */
57: static char dumpfilename[] = _PATH_PIMD_DUMP;
58: static char cachefilename[] = _PATH_PIMD_CACHE; /* TODO: notused */
59:
60:
61: char *packet_kind(int proto, int type, int code)
62: {
63: static char unknown[60];
64:
65: switch (proto) {
66: case IPPROTO_IGMP:
67: switch (type) {
68: case IGMP_MEMBERSHIP_QUERY: return "IGMP Membership Query ";
69: case IGMP_V1_MEMBERSHIP_REPORT: return "IGMP v1 Membership Report";
70: case IGMP_V2_MEMBERSHIP_REPORT: return "IGMP v2 Membership Report";
71: case IGMP_V3_MEMBERSHIP_REPORT: return "IGMP v3 Membership Report";
72: case IGMP_V2_LEAVE_GROUP: return "IGMP Leave message ";
73: case IGMP_DVMRP:
74: switch (code) {
75: case DVMRP_PROBE: return "DVMRP Neighbor Probe ";
76: case DVMRP_REPORT: return "DVMRP Route Report ";
77: case DVMRP_ASK_NEIGHBORS: return "DVMRP Neighbor Request ";
78: case DVMRP_NEIGHBORS: return "DVMRP Neighbor List ";
79: case DVMRP_ASK_NEIGHBORS2: return "DVMRP Neighbor request 2 ";
80: case DVMRP_NEIGHBORS2: return "DVMRP Neighbor list 2 ";
81: case DVMRP_PRUNE: return "DVMRP Prune message ";
82: case DVMRP_GRAFT: return "DVMRP Graft message ";
83: case DVMRP_GRAFT_ACK: return "DVMRP Graft message ack ";
84: case DVMRP_INFO_REQUEST: return "DVMRP Info Request ";
85: case DVMRP_INFO_REPLY: return "DVMRP Info Reply ";
86: default:
87: snprintf(unknown, sizeof(unknown), "UNKNOWN DVMRP message code = %3d ", code);
88: return unknown;
89: }
90:
91: case IGMP_PIM:
92: /* The old style (PIM v1) encapsulation of PIM messages
93: * inside IGMP messages.
94: */
95: /* PIM v1 is not implemented but we just inform that a message
96: * has arrived.
97: */
98: switch (code) {
99: case PIM_V1_QUERY: return "PIM v1 Router-Query ";
100: case PIM_V1_REGISTER: return "PIM v1 Register ";
101: case PIM_V1_REGISTER_STOP: return "PIM v1 Register-Stop ";
102: case PIM_V1_JOIN_PRUNE: return "PIM v1 Join/Prune ";
103: case PIM_V1_RP_REACHABILITY:
104: return "PIM v1 RP-Reachability ";
105:
106: case PIM_V1_ASSERT: return "PIM v1 Assert ";
107: case PIM_V1_GRAFT: return "PIM v1 Graft ";
108: case PIM_V1_GRAFT_ACK: return "PIM v1 Graft_Ack ";
109: default:
110: snprintf(unknown, sizeof(unknown), "UNKNOWN PIM v1 message type =%3d ", code);
111: return unknown;
112: }
113:
114: case IGMP_MTRACE: return "IGMP trace query ";
115: case IGMP_MTRACE_RESP: return "IGMP trace reply ";
116: default:
117: snprintf(unknown, sizeof (unknown), "UNKNOWN IGMP message: type = 0x%02x, code = 0x%02x ", type, code);
118: return unknown;
119: }
120:
121: case IPPROTO_PIM: /* PIM v2 */
122: switch (type) {
123: case PIM_V2_HELLO: return "PIM v2 Hello ";
124: case PIM_V2_REGISTER: return "PIM v2 Register ";
125: case PIM_V2_REGISTER_STOP: return "PIM v2 Register_Stop ";
126: case PIM_V2_JOIN_PRUNE: return "PIM v2 Join/Prune ";
127: case PIM_V2_BOOTSTRAP: return "PIM v2 Bootstrap ";
128: case PIM_V2_ASSERT: return "PIM v2 Assert ";
129: case PIM_V2_GRAFT: return "PIM-DM v2 Graft ";
130: case PIM_V2_GRAFT_ACK: return "PIM-DM v2 Graft_Ack ";
131: case PIM_V2_CAND_RP_ADV: return "PIM v2 Cand. RP Adv. ";
132: default:
133: snprintf(unknown, sizeof(unknown), "UNKNOWN PIM v2 message type =%3d ", type);
134: return unknown;
135: }
136:
137: default:
138: snprintf(unknown, sizeof(unknown), "UNKNOWN proto =%3d ", proto);
139: return unknown;
140: }
141: }
142:
143:
144: /*
145: * Used for debugging particular type of messages.
146: */
147: int debug_kind(int proto, int type, int code)
148: {
149: switch (proto) {
150: case IPPROTO_IGMP:
151: switch (type) {
152: case IGMP_MEMBERSHIP_QUERY: return DEBUG_IGMP;
153: case IGMP_V1_MEMBERSHIP_REPORT: return DEBUG_IGMP;
154: case IGMP_V2_MEMBERSHIP_REPORT: return DEBUG_IGMP;
155: case IGMP_V3_MEMBERSHIP_REPORT: return DEBUG_IGMP;
156: case IGMP_V2_LEAVE_GROUP: return DEBUG_IGMP;
157: case IGMP_DVMRP:
158: switch (code) {
159: case DVMRP_PROBE: return DEBUG_DVMRP_PEER;
160: case DVMRP_REPORT: return DEBUG_DVMRP_ROUTE;
161: case DVMRP_ASK_NEIGHBORS: return 0;
162: case DVMRP_NEIGHBORS: return 0;
163: case DVMRP_ASK_NEIGHBORS2: return 0;
164: case DVMRP_NEIGHBORS2: return 0;
165: case DVMRP_PRUNE: return DEBUG_DVMRP_PRUNE;
166: case DVMRP_GRAFT: return DEBUG_DVMRP_PRUNE;
167: case DVMRP_GRAFT_ACK: return DEBUG_DVMRP_PRUNE;
168: case DVMRP_INFO_REQUEST: return 0;
169: case DVMRP_INFO_REPLY: return 0;
170: default: return 0;
171: }
172:
173: case IGMP_PIM:
174: /* PIM v1 is not implemented */
175: switch (code) {
176: case PIM_V1_QUERY: return DEBUG_PIM;
177: case PIM_V1_REGISTER: return DEBUG_PIM;
178: case PIM_V1_REGISTER_STOP: return DEBUG_PIM;
179: case PIM_V1_JOIN_PRUNE: return DEBUG_PIM;
180: case PIM_V1_RP_REACHABILITY: return DEBUG_PIM;
181: case PIM_V1_ASSERT: return DEBUG_PIM;
182: case PIM_V1_GRAFT: return DEBUG_PIM;
183: case PIM_V1_GRAFT_ACK: return DEBUG_PIM;
184: default: return DEBUG_PIM;
185: }
186:
187: case IGMP_MTRACE: return DEBUG_TRACE;
188: case IGMP_MTRACE_RESP: return DEBUG_TRACE;
189: default: return DEBUG_IGMP;
190: }
191:
192: case IPPROTO_PIM: /* PIM v2 */
193: /* TODO: modify? */
194: switch (type) {
195: case PIM_V2_HELLO: return DEBUG_PIM;
196: case PIM_V2_REGISTER: return DEBUG_PIM_REGISTER;
197: case PIM_V2_REGISTER_STOP: return DEBUG_PIM_REGISTER;
198: case PIM_V2_JOIN_PRUNE: return DEBUG_PIM;
199: case PIM_V2_BOOTSTRAP: return DEBUG_PIM_BOOTSTRAP;
200: case PIM_V2_ASSERT: return DEBUG_PIM;
201: case PIM_V2_GRAFT: return DEBUG_PIM;
202: case PIM_V2_GRAFT_ACK: return DEBUG_PIM;
203: case PIM_V2_CAND_RP_ADV: return DEBUG_PIM_CAND_RP;
204: default: return DEBUG_PIM;
205: }
206:
207: default: return 0;
208: }
209:
210: return 0;
211: }
212:
213:
214: /*
215: * Some messages are more important than others. This routine
216: * determines the logging level at which to log a send error (often
217: * "No route to host"). This is important when there is asymmetric
218: * reachability and someone is trying to, i.e., mrinfo me periodically.
219: */
220: int
221: log_level(int proto, int type, int code)
222: {
223: switch (proto) {
224: case IPPROTO_IGMP:
225: switch (type) {
226: case IGMP_MTRACE_RESP:
227: return LOG_INFO;
228:
229: case IGMP_DVMRP:
230: switch (code) {
231: case DVMRP_NEIGHBORS:
232: case DVMRP_NEIGHBORS2:
233: return LOG_INFO;
234: }
235: return LOG_WARNING;
236:
237: case IGMP_PIM:
238: /* PIM v1 */
239: switch (code) {
240: default:
241: return LOG_INFO;
242: }
243: return LOG_WARNING;
244:
245: default:
246: return LOG_WARNING;
247: }
248:
249: case IPPROTO_PIM:
250: /* PIM v2 */
251: switch (type) {
252: default:
253: return LOG_INFO;
254: }
255: return LOG_WARNING;
256:
257: default:
258: return LOG_WARNING;
259: }
260: return LOG_WARNING;
261: }
262:
263:
264: /*
265: * Dump internal data structures to a file.
266: */
267: void fdump(int i __attribute__((unused)))
268: {
269: FILE *fp;
270:
271: fp = fopen(dumpfilename, "w");
272: if (fp) {
273: dump_vifs(fp);
274: dump_pim_mrt(fp);
275: fclose(fp);
276: }
277: }
278:
279: /* TODO: dummy, to be used in the future. */
280: /*
281: * Dump local cache contents to a file.
282: */
283: void cdump(int i __attribute__((unused)))
284: {
285: FILE *fp;
286:
287: fp = fopen(cachefilename, "w");
288: if (fp) {
289: /* XXX: TODO: implement it:
290: dump_cache(fp);
291: */
292: fclose(fp);
293: }
294: }
295:
296: /*
297: 1 2 3 4 5 6 7 8
298: 012345678901234567890123456789012345678901234567890123456789012345678901234567890
299: Virtual Interface Table
300: Vif Local-Address Subnet Thresh Flags Neighbors
301: 0 10.0.3.1 10.0.3/24 1 DR NO-NBR
302: 1 172.16.12.254 172.16.12/24 1 DR PIM 172.16.12.2
303: 172.16.12.3
304: 2 192.168.122.147 register_vif0 1
305: */
306: void dump_vifs(FILE *fp)
307: {
308: vifi_t vifi;
309: struct uvif *v;
310: pim_nbr_entry_t *n;
311: int width;
312: int i;
313: struct listaddr *group, *source;
314:
315: fprintf(fp, "Virtual Interface Table ======================================================\n");
316: fprintf(fp, "Vif Local Address Subnet Thresh Flags Neighbors\n");
317: fprintf(fp, "--- --------------- ------------------ ------ --------- -----------------\n");
318:
319: for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
320: int down = 0;
321:
322: fprintf(fp, "%3u %-15s ", vifi, inet_fmt(v->uv_lcl_addr, s1, sizeof(s1)));
323:
324: if (v->uv_flags & VIFF_REGISTER)
325: fprintf(fp, "%-18s ", v->uv_name);
326: else
327: fprintf(fp,"%-18.18s ", netname(v->uv_subnet, v->uv_subnetmask));
328:
329: fprintf(fp, "%6u ", v->uv_threshold);
330:
331: /* TODO: XXX: Print VIFF_TUNNEL? */
332: width = 0;
333: if (v->uv_flags & VIFF_DISABLED) {
334: fprintf(fp, " DISABLED");
335: down = 1;
336: }
337: if (v->uv_flags & VIFF_DOWN) {
338: fprintf(fp, " DOWN");
339: down = 1;
340: }
341:
342: if (v->uv_flags & VIFF_DR) {
343: fprintf(fp, " DR");
344: width += 3;
345: }
346: if (v->uv_flags & VIFF_PIM_NBR) {
347: fprintf(fp, " PIM");
348: width += 4;
349: }
350: if (v->uv_flags & VIFF_DVMRP_NBR) {
351: fprintf(fp, " DVMRP");
352: width += 6;
353: }
354: if (v->uv_flags & VIFF_NONBRS) {
355: fprintf(fp, " NO-NBR");
356: width += 6;
357: }
358:
359: n = v->uv_pim_neighbors;
360: if (!down && n) {
361: for (i = width; i <= 11; i++)
362: fprintf(fp, " ");
363: fprintf(fp, "%-15s\n", inet_fmt(n->address, s1, sizeof(s1)));
364: for (n = n->next; n; n = n->next)
365: fprintf(fp, "%61s%-15s\n", "", inet_fmt(n->address, s1, sizeof(s1)));
366: } else {
367: fprintf(fp, "\n");
368: }
369: }
370:
371: fprintf(fp, "\n");
372:
373: /* Dump groups and sources */
374: fprintf(fp, " %-3s %-15s %-20s", "Vif", "SSM Group", "Sources");
375: for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) {
376: for (group = v->uv_groups; group != NULL; group = group->al_next) {
377: if (IN_PIM_SSM_RANGE(group->al_addr)) {
378: fprintf(fp, "\n %3u %-15s ", vifi, inet_fmt(group->al_addr, s1, sizeof(s1)));
379: for (source = group->al_sources; source != NULL; source = source->al_next) {
380: fprintf(fp, "%s ", inet_fmt(source->al_addr, s1, sizeof(s1)));
381: }
382: }
383: }
384: }
385:
386: fprintf(fp, "\n\n");
387: }
388:
389: int loglvl(char *level)
390: {
391: int i;
392:
393: for (i = 0; prioritynames[i].c_name; i++) {
394: if (string_match(prioritynames[i].c_name, level))
395: return prioritynames[i].c_val;
396: }
397:
398: return atoi(level);
399: }
400:
401: /*
402: * Log errors and other messages to the system log daemon and to stderr,
403: * according to the severity of the message and the current debug level.
404: * For errors of severity LOG_ERR or worse, terminate the program.
405: */
406: void logit(int severity, int syserr, const char *format, ...)
407: {
408: va_list ap;
409: char msg[211];
410: struct timeval now;
411: struct tm *thyme;
412: time_t lt;
413:
414: va_start(ap, format);
415: vsnprintf(msg, sizeof(msg), format, ap);
416: va_end(ap);
417:
418: /*
419: * Log to stderr if we haven't forked yet and it's a warning or
420: * worse, or if we're debugging.
421: */
422: if (haveterminal && (debug || severity <= LOG_WARNING)) {
423: gettimeofday(&now, NULL);
424: lt = now.tv_sec;
425: thyme = localtime(<);
426:
427: if (!debug)
428: fprintf(stderr, "%s: ", __progname);
429:
430: fprintf(stderr, "%02d:%02d:%02d.%03ld %s", thyme->tm_hour, thyme->tm_min,
431: thyme->tm_sec, (long int)(now.tv_usec / 1000), msg);
432:
433: if (syserr) {
434: errno = syserr;
435: fprintf(stderr, ": %m");
436: }
437: fprintf(stderr, "\n");
438: }
439:
440: /*
441: * Always log things that are worse than warnings, no matter what
442: * the log_nmsgs rate limiter says.
443: *
444: * Only count things at the defined loglevel or worse in the rate limiter
445: * and exclude debugging (since if you put daemon.debug in syslog.conf
446: * you probably actually want to log the debugging messages so they
447: * shouldn't be rate-limited)
448: */
449: if ((severity < LOG_WARNING) || (log_nmsgs < LOG_MAX_MSGS)) {
450: if ((severity <= loglevel) && (severity != LOG_DEBUG))
451: log_nmsgs++;
452:
453: if (syserr) {
454: errno = syserr;
455: syslog(severity, "%s: %m", msg);
456: } else {
457: syslog(severity, "%s", msg);
458: }
459: }
460:
461: #ifndef CONTINUE_ON_ERROR
462: if (severity <= LOG_ERR)
463: exit(-1); /* Exit status: 255 */
464: #endif /* CONTINUE_ON_ERROR */
465: }
466:
467:
468: /*
469: * Hex dump a control frame to the log, MAX 64 bytes length
470: */
471: void dump_frame(char *desc, void *dump, size_t len)
472: {
473: unsigned int length, i = 0;
474: unsigned char *data = (unsigned char *)dump;
475: char buf[80] = "";
476: char tmp[10];
477:
478: length = len;
479: if (length > MAX_MSG_SIZE)
480: length = MAX_MSG_SIZE;
481:
482: if (desc)
483: logit(LOG_DEBUG, 0, "%s", desc);
484:
485: while (i < length) {
486: if (!(i % 16))
487: snprintf(buf, sizeof(buf), "%03X: ", i);
488:
489: snprintf(tmp, sizeof(tmp), "%02X ", data[i++]);
490: strlcat(buf, tmp, sizeof(buf));
491:
492: if (i > 0 && !(i % 16))
493: logit(LOG_DEBUG, 0, "%s", buf);
494: else if (i > 0 && !(i % 8))
495: strlcat(buf, ":: ", sizeof(buf));
496: }
497: logit(LOG_DEBUG, 0, "%s", buf);
498: }
499:
500:
501: static void dump_route(FILE *fp, mrtentry_t *r)
502: {
503: vifi_t vifi;
504: char oifs[(sizeof(vifbitmap_t)<<3)+1];
505: char joined_oifs[(sizeof(vifbitmap_t)<<3)+1];
506: char pruned_oifs[(sizeof(vifbitmap_t)<<3)+1];
507: char leaves_oifs[(sizeof(vifbitmap_t)<<3)+1];
508: char asserted_oifs[(sizeof(vifbitmap_t)<<3)+1];
509: char incoming_iif[(sizeof(vifbitmap_t)<<3)+1];
510:
511: for (vifi = 0; vifi < numvifs; vifi++) {
512: oifs[vifi] =
513: VIFM_ISSET(vifi, r->oifs) ? 'o' : '.';
514: joined_oifs[vifi] =
515: VIFM_ISSET(vifi, r->joined_oifs) ? 'j' : '.';
516: pruned_oifs[vifi] =
517: VIFM_ISSET(vifi, r->pruned_oifs) ? 'p' : '.';
518: leaves_oifs[vifi] =
519: VIFM_ISSET(vifi, r->leaves) ? 'l' : '.';
520: asserted_oifs[vifi] =
521: VIFM_ISSET(vifi, r->asserted_oifs) ? 'a' : '.';
522: incoming_iif[vifi] = '.';
523: }
524: oifs[vifi] = 0x0; /* End of string */
525: joined_oifs[vifi] = 0x0;
526: pruned_oifs[vifi] = 0x0;
527: leaves_oifs[vifi] = 0x0;
528: asserted_oifs[vifi] = 0x0;
529: incoming_iif[vifi] = 0x0;
530: incoming_iif[r->incoming] = 'I';
531:
532: /* TODO: don't need some of the flags */
533: if (r->flags & MRTF_SPT) fprintf(fp, " SPT");
534: if (r->flags & MRTF_WC) fprintf(fp, " WC");
535: if (r->flags & MRTF_RP) fprintf(fp, " RP");
536: if (r->flags & MRTF_REGISTER) fprintf(fp, " REG");
537: if (r->flags & MRTF_IIF_REGISTER) fprintf(fp, " IIF_REG");
538: if (r->flags & MRTF_NULL_OIF) fprintf(fp, " NULL_OIF");
539: if (r->flags & MRTF_KERNEL_CACHE) fprintf(fp, " CACHE");
540: if (r->flags & MRTF_ASSERTED) fprintf(fp, " ASSERTED");
541: if (r->flags & MRTF_REG_SUPP) fprintf(fp, " REG_SUPP");
542: if (r->flags & MRTF_SG) fprintf(fp, " SG");
543: if (r->flags & MRTF_PMBR) fprintf(fp, " PMBR");
544: fprintf(fp, "\n");
545:
546: fprintf(fp, "Joined oifs: %-20s\n", joined_oifs);
547: fprintf(fp, "Pruned oifs: %-20s\n", pruned_oifs);
548: fprintf(fp, "Leaves oifs: %-20s\n", leaves_oifs);
549: fprintf(fp, "Asserted oifs: %-20s\n", asserted_oifs);
550: fprintf(fp, "Outgoing oifs: %-20s\n", oifs);
551: fprintf(fp, "Incoming : %-20s\n", incoming_iif);
552:
553: fprintf(fp, "\nTIMERS: Entry JP RS Assert VIFS:");
554: for (vifi = 0; vifi < numvifs; vifi++)
555: fprintf(fp, " %d", vifi);
556: fprintf(fp, "\n %5d %4d %4d %6d ",
557: r->timer, r->jp_timer, r->rs_timer, r->assert_timer);
558: for (vifi = 0; vifi < numvifs; vifi++)
559: fprintf(fp, " %2d", r->vif_timers[vifi]);
560: fprintf(fp, "\n");
561: }
562:
563: void dump_pim_mrt(FILE *fp)
564: {
565: grpentry_t *g;
566: mrtentry_t *r;
567: u_int number_of_cache_mirrors = 0;
568: u_int number_of_groups = 0;
569: cand_rp_t *rp;
570: kernel_cache_t *kc;
571:
572: fprintf(fp, "Multicast Routing Table ======================================================\n");
573:
574: /* TODO: remove the dummy 0.0.0.0 group (first in the chain) */
575: for (g = grplist->next; g; g = g->next) {
576: number_of_groups++;
577:
578: r = g->grp_route;
579: if (r) {
580: if (r->flags & MRTF_KERNEL_CACHE) {
581: for (kc = r->kernel_cache; kc; kc = kc->next)
582: number_of_cache_mirrors++;
583: }
584:
585: /* Print the (*,G) routing info */
586: fprintf(fp, "----------------------------------- (*,G) ------------------------------------\n");
587: fprintf(fp, "Source Group RP Address Flags\n");
588: fprintf(fp, "--------------- --------------- --------------- ---------------------------\n");
589: fprintf(fp, "%-15s ", "INADDR_ANY");
590: fprintf(fp, "%-15s ", inet_fmt(g->group, s1, sizeof(s1)));
591: fprintf(fp, "%-15s ", IN_PIM_SSM_RANGE(g->group) ? "SSM" :
592: (g->active_rp_grp ? inet_fmt(g->rpaddr, s2, sizeof(s2)) : "NULL"));
593:
594: dump_route(fp, r);
595: }
596:
597: /* Print all (S,G) routing info */
598: fprintf(fp, "----------------------------------- (S,G) ------------------------------------\n");
599: for (r = g->mrtlink; r; r = r->grpnext) {
600: if (r->flags & MRTF_KERNEL_CACHE)
601: number_of_cache_mirrors++;
602:
603: /* Print the routing info */
604: fprintf(fp, "Source Group RP Address Flags\n");
605: fprintf(fp, "--------------- --------------- --------------- ---------------------------\n");
606: fprintf(fp, "%-15s ", inet_fmt(r->source->address, s1, sizeof(s1)));
607: fprintf(fp, "%-15s ", inet_fmt(g->group, s2, sizeof(s2)));
608: fprintf(fp, "%-15s ", IN_PIM_SSM_RANGE(g->group) ? "SSM" :
609: (g->active_rp_grp ? inet_fmt(g->rpaddr, s2, sizeof(s2)) : "NULL"));
610:
611: dump_route(fp, r);
612: }
613: }/* for all groups */
614:
615: /* Print the (*,*,R) routing entries */
616: fprintf(fp, "--------------------------------- (*,*,G) ------------------------------------\n");
617: for (rp = cand_rp_list; rp; rp = rp->next) {
618: r = rp->rpentry->mrtlink;
619: if (r) {
620: if (r->flags & MRTF_KERNEL_CACHE) {
621: for (kc = r->kernel_cache; kc; kc = kc->next)
622: number_of_cache_mirrors++;
623: }
624:
625: /* Print the (*,*,RP) routing info */
626: fprintf(fp, "Source Group RP Address Flags\n");
627: fprintf(fp, "--------------- --------------- --------------- ---------------------------\n");
628: fprintf(fp, "%-15s ", inet_fmt(r->source->address, s1, sizeof(s1)));
629: fprintf(fp, "%-15s ", "INADDR_ANY");
630: fprintf(fp, "%-15s ", "");
631:
632: dump_route(fp, r);
633: }
634: } /* For all (*,*,RP) */
635:
636: fprintf(fp, "Number of Groups: %u\n", number_of_groups);
637: fprintf(fp, "Number of Cache MIRRORs: %u\n", number_of_cache_mirrors);
638: fprintf(fp, "------------------------------------------------------------------------------\n\n");
639: }
640:
641: static void dump_rpgrp(FILE *fp, rp_grp_entry_t *rpgrp, int indent)
642: {
643: grp_mask_t *grp = rpgrp->group;
644:
645: if (indent)
646: fprintf(fp, " ");
647:
648: fprintf(fp, "%-18.18s %-8u %-8u\n",
649: netname(grp->group_addr, grp->group_mask),
650: rpgrp->priority, rpgrp->holdtime);
651: }
652:
653: /*
654: * Dumps the local Cand-RP-set
655: */
656: int dump_rp_set(FILE *fp)
657: {
658: cand_rp_t *rp;
659: rp_grp_entry_t *rpgrp;
660:
661: fprintf(fp, "Candidate Rendezvous-Point Set ===============================================\n");
662: fprintf(fp, "RP address Incoming Group Prefix Priority Holdtime\n");
663: fprintf(fp, "--------------- -------- ------------------ -------- ---------------------\n");
664: for (rp = cand_rp_list; rp; rp = rp->next) {
665: fprintf(fp, "%-15s %-8d ",
666: inet_fmt(rp->rpentry->address, s1, sizeof(s1)),
667: rp->rpentry->incoming);
668:
669: rpgrp = rp->rp_grp_next;
670: if (rpgrp) {
671: dump_rpgrp(fp, rpgrp, 0);
672:
673: for (rpgrp = rpgrp->rp_grp_next; rpgrp; rpgrp = rpgrp->rp_grp_next)
674: dump_rpgrp(fp, rpgrp, 1);
675: }
676: }
677:
678: fprintf(fp, "------------------------------------------------------------------------------\n");
679: fprintf(fp, "Current BSR address: %s\n\n", inet_fmt(curr_bsr_address, s1, sizeof(s1)));
680:
681: return TRUE;
682: }
683:
684: /**
685: * Local Variables:
686: * version-control: t
687: * indent-tabs-mode: t
688: * c-file-style: "ellemtel"
689: * c-basic-offset: 4
690: * End:
691: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>