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(&lt);
                    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>