Annotation of embedaddon/pimdd/trace.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  *  Copyright (c) 1998 by the University of Southern California.
                      3:  *  All rights reserved.
                      4:  *
                      5:  *  Permission to use, copy, modify, and distribute this software and
                      6:  *  its documentation in source and binary forms for lawful
                      7:  *  non-commercial purposes and without fee is hereby granted, provided
                      8:  *  that the above copyright notice appear in all copies and that both
                      9:  *  the copyright notice and this permission notice appear in supporting
                     10:  *  documentation, and that any documentation, advertising materials,
                     11:  *  and other materials related to such distribution and use acknowledge
                     12:  *  that the software was developed by the University of Southern
                     13:  *  California and/or Information Sciences Institute.
                     14:  *  The name of the University of Southern California may not
                     15:  *  be used to endorse or promote products derived from this software
                     16:  *  without specific prior written permission.
                     17:  *
                     18:  *  THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY REPRESENTATIONS
                     19:  *  ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  THIS SOFTWARE IS
                     20:  *  PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
                     21:  *  INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     22:  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND 
                     23:  *  NON-INFRINGEMENT.
                     24:  *
                     25:  *  IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
                     26:  *  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
                     27:  *  TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH,
                     28:  *  THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     29:  *
                     30:  *  Other copyrights might apply to parts of this software and are so
                     31:  *  noted when applicable.
                     32:  */
                     33: /*
                     34:  *  Questions concerning this software should be directed to 
                     35:  *  Pavlin Ivanov Radoslavov (pavlin@catarina.usc.edu)
                     36:  *
                     37:  *  $Id: trace.c,v 1.3 1998/06/01 22:27:15 kurtw Exp $
                     38:  */
                     39: /*
                     40:  * Part of this program has been derived from mrouted.
                     41:  * The mrouted program is covered by the license in the accompanying file
                     42:  * named "LICENSE.mrouted".
                     43:  *
                     44:  * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
                     45:  * Leland Stanford Junior University.
                     46:  *
                     47:  */
                     48: 
                     49: 
                     50: #include "defs.h"
                     51: #include "trace.h"
                     52: 
                     53: 
                     54: /* TODO */
                     55: /*
                     56:  * Traceroute function which returns traceroute replies to the requesting
                     57:  * router. Also forwards the request to downstream routers.
                     58:  */
                     59: void
                     60: accept_mtrace(src, dst, group, data, no, datalen)
                     61:     u_int32 src;
                     62:     u_int32 dst;
                     63:     u_int32 group;
                     64:     char *data;
                     65:     u_int no;   /* promoted u_char */
                     66:     int datalen;
                     67: {
                     68:     u_char type;
                     69:     mrtentry_t *mrt;
                     70:     struct tr_query *qry;
                     71:     struct tr_resp  *resp;
                     72:     int vifi;
                     73:     char *p;
                     74:     int rcount;
                     75:     int errcode = TR_NO_ERR;
                     76:     int resptype;
                     77:     struct timeval tp;
                     78:     struct sioc_vif_req v_req;
                     79:     u_int32 parent_address;
                     80: 
                     81:     /* Remember qid across invocations */
                     82:     static u_int32 oqid = 0;
                     83: 
                     84:     /* timestamp the request/response */
                     85:     gettimeofday(&tp, 0);
                     86: 
                     87:     /*
                     88:      * Check if it is a query or a response
                     89:      */
                     90:     if (datalen == QLEN) {
                     91:        type = QUERY;
                     92:        IF_DEBUG(DEBUG_TRACE)
                     93:            log(LOG_DEBUG, 0, "Initial traceroute query rcvd from %s to %s",
                     94:                inet_fmt(src, s1), inet_fmt(dst, s2));
                     95:     }
                     96:     else if ((datalen - QLEN) % RLEN == 0) {
                     97:        type = RESP;
                     98:        IF_DEBUG(DEBUG_TRACE)
                     99:            log(LOG_DEBUG, 0, "In-transit traceroute query rcvd from %s to %s",
                    100:                inet_fmt(src, s1), inet_fmt(dst, s2));
                    101:        if (IN_MULTICAST(ntohl(dst))) {
                    102:            IF_DEBUG(DEBUG_TRACE)
                    103:                log(LOG_DEBUG, 0, "Dropping multicast response");
                    104:            return;
                    105:        }
                    106:     }
                    107:     else {
                    108:        log(LOG_WARNING, 0, "%s from %s to %s",
                    109:            "Non decipherable traceroute request recieved",
                    110:            inet_fmt(src, s1), inet_fmt(dst, s2));
                    111:        return;
                    112:     }
                    113: 
                    114:     qry = (struct tr_query *)data;
                    115: 
                    116:     /*
                    117:      * if it is a packet with all reports filled, drop it
                    118:      */
                    119:     if ((rcount = (datalen - QLEN)/RLEN) == no) {
                    120:        IF_DEBUG(DEBUG_TRACE)
                    121:            log(LOG_DEBUG, 0, "packet with all reports filled in");
                    122:        return;
                    123:     }
                    124: 
                    125:     IF_DEBUG(DEBUG_TRACE) {
                    126:        log(LOG_DEBUG, 0, "s: %s g: %s d: %s ", inet_fmt(qry->tr_src, s1),
                    127:            inet_fmt(group, s2), inet_fmt(qry->tr_dst, s3));
                    128:        log(LOG_DEBUG, 0, "rttl: %d rd: %s", qry->tr_rttl,
                    129:            inet_fmt(qry->tr_raddr, s1));
                    130:        log(LOG_DEBUG, 0, "rcount:%d, qid:%06x", rcount, qry->tr_qid);
                    131:     }
                    132: 
                    133:     /* determine the routing table entry for this traceroute */
                    134:     mrt = find_route(qry->tr_src, group, MRTF_SG | MRTF_WC | MRTF_PMBR,
                    135:                     DONT_CREATE);
                    136:     IF_DEBUG(DEBUG_TRACE)
                    137:        if (mrt != (mrtentry_t *)NULL) {
                    138:            if (mrt->upstream != (pim_nbr_entry_t *)NULL)
                    139:                parent_address = mrt->upstream->address;
                    140:            else
                    141:                parent_address = INADDR_ANY;
                    142:            log(LOG_DEBUG, 0, "mrt parent vif: %d rtr: %s metric: %d",
                    143:                mrt->incoming, inet_fmt(parent_address, s1), mrt->metric);
                    144: /* TODO
                    145:            log(LOG_DEBUG, 0, "mrt origin %s",
                    146:                RT_FMT(rt, s1));
                    147:                */
                    148:        } else
                    149:            log(LOG_DEBUG, 0, "...no route");
                    150:     
                    151:     /*
                    152:      * Query type packet - check if rte exists 
                    153:      * Check if the query destination is a vif connected to me.
                    154:      * and if so, whether I should start response back
                    155:      */
                    156:     if (type == QUERY) {
                    157:        if (oqid == qry->tr_qid) {
                    158:            /*
                    159:             * If the multicast router is a member of the group being
                    160:             * queried, and the query is multicasted, then the router can
                    161:             * recieve multiple copies of the same query.  If we have already
                    162:             * replied to this traceroute, just ignore it this time.
                    163:             *
                    164:             * This is not a total solution, but since if this fails you
                    165:             * only get N copies, N <= the number of interfaces on the router,
                    166:             * it is not fatal.
                    167:             */
                    168:            IF_DEBUG(DEBUG_TRACE)
                    169:                log(LOG_DEBUG, 0, "ignoring duplicate traceroute packet");
                    170:            return;
                    171:        }
                    172: 
                    173:        if (mrt == (mrtentry_t *)NULL) {
                    174:            IF_DEBUG(DEBUG_TRACE)
                    175:                log(LOG_DEBUG, 0, "Mcast traceroute: no route entry %s",
                    176:                    inet_fmt(qry->tr_src, s1));
                    177:            if (IN_MULTICAST(ntohl(dst)))
                    178:                return;
                    179:        }
                    180:        vifi = find_vif_direct(qry->tr_dst);
                    181:        
                    182:        if (vifi == NO_VIF) {
                    183:            /* The traceroute destination is not on one of my subnet vifs. */
                    184:            IF_DEBUG(DEBUG_TRACE)
                    185:                log(LOG_DEBUG, 0, "Destination %s not an interface",
                    186:                    inet_fmt(qry->tr_dst, s1));
                    187:            if (IN_MULTICAST(ntohl(dst)))
                    188:                return;
                    189:            errcode = TR_WRONG_IF;
                    190:        } else if (mrt != (mrtentry_t *)NULL && !VIFM_ISSET(vifi, mrt->oifs)) {
                    191:            IF_DEBUG(DEBUG_TRACE)
                    192:                log(LOG_DEBUG, 0,
                    193:                    "Destination %s not on forwarding tree for src %s",
                    194:                    inet_fmt(qry->tr_dst, s1), inet_fmt(qry->tr_src, s2));
                    195:            if (IN_MULTICAST(ntohl(dst)))
                    196:                return;
                    197:            errcode = TR_WRONG_IF;
                    198:        }
                    199:     }
                    200:     else {
                    201:        /*
                    202:         * determine which interface the packet came in on
                    203:         * RESP packets travel hop-by-hop so this either traversed
                    204:         * a tunnel or came from a directly attached mrouter.
                    205:         */
                    206:        if ((vifi = find_vif_direct(src)) == NO_VIF) {
                    207:            IF_DEBUG(DEBUG_TRACE)
                    208:                log(LOG_DEBUG, 0, "Wrong interface for packet");
                    209:            errcode = TR_WRONG_IF;
                    210:        }
                    211:     }   
                    212:     
                    213:     /* Now that we've decided to send a response, save the qid */
                    214:     oqid = qry->tr_qid;
                    215: 
                    216:     IF_DEBUG(DEBUG_TRACE)
                    217:        log(LOG_DEBUG, 0, "Sending traceroute response");
                    218:     
                    219:     /* copy the packet to the sending buffer */
                    220:     p = igmp_send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN;
                    221:     
                    222:     bcopy(data, p, datalen);
                    223:     
                    224:     p += datalen;
                    225:     
                    226:     /*
                    227:      * If there is no room to insert our reply, coopt the previous hop
                    228:      * error indication to relay this fact.
                    229:      */
                    230:     if (p + sizeof(struct tr_resp) > igmp_send_buf + RECV_BUF_SIZE) {
                    231:        resp = (struct tr_resp *)p - 1;
                    232:        resp->tr_rflags = TR_NO_SPACE;
                    233:        mrt = NULL;
                    234:        goto sendit;
                    235:     }
                    236: 
                    237:     /*
                    238:      * fill in initial response fields
                    239:      */
                    240:     resp = (struct tr_resp *)p;
                    241:     bzero(resp, sizeof(struct tr_resp));
                    242:     datalen += RLEN;
                    243: 
                    244:     resp->tr_qarr    = htonl(((tp.tv_sec + JAN_1970) << 16) + 
                    245:                             ((tp.tv_usec << 10) / 15625));
                    246: 
                    247:     resp->tr_rproto  = PROTO_PIM;
                    248:     resp->tr_outaddr = (vifi == NO_VIF) ? dst : uvifs[vifi].uv_lcl_addr;
                    249:     resp->tr_fttl    = (vifi == NO_VIF) ? 0 : uvifs[vifi].uv_threshold;
                    250:     resp->tr_rflags  = errcode;
                    251: 
                    252:     /*
                    253:      * obtain # of packets out on interface
                    254:      */
                    255:     v_req.vifi = vifi;
                    256:     if (vifi != NO_VIF && ioctl(udp_socket, SIOCGETVIFCNT, (char *)&v_req) >= 0)
                    257:        resp->tr_vifout  =  htonl(v_req.ocount);
                    258:     else
                    259:        resp->tr_vifout  =  0xffffffff;
                    260: 
                    261:     /*
                    262:      * fill in scoping & pruning information
                    263:      */
                    264: /* TODO */
                    265: #if 0
                    266:     if (mrt != (mrtentry_t *)NULL)
                    267:        for (gt = rt->rt_groups; gt; gt = gt->gt_next) {
                    268:            if (gt->gt_mcastgrp >= group)
                    269:                break;
                    270:        }
                    271:     else
                    272:        gt = NULL;
                    273: 
                    274:     if (gt && gt->gt_mcastgrp == group) {
                    275:        struct stable *st;
                    276: 
                    277:        for (st = gt->gt_srctbl; st; st = st->st_next)
                    278:            if (qry->tr_src == st->st_origin)
                    279:                break;
                    280: 
                    281:        sg_req.src.s_addr = qry->tr_src;
                    282:        sg_req.grp.s_addr = group;
                    283:        if (st && st->st_ctime != 0 &&
                    284:            ioctl(udp_socket, SIOCGETSGCNT, (char *)&sg_req) >= 0)
                    285:            resp->tr_pktcnt = htonl(sg_req.pktcnt + st->st_savpkt);
                    286:        else
                    287:            resp->tr_pktcnt = htonl(st ? st->st_savpkt : 0xffffffff);
                    288: 
                    289:        if (VIFM_ISSET(vifi, gt->gt_scope))
                    290:            resp->tr_rflags = TR_SCOPED;
                    291:        else if (gt->gt_prsent_timer)
                    292:            resp->tr_rflags = TR_PRUNED;
                    293:        else if (!VIFM_ISSET(vifi, gt->gt_grpmems))
                    294:            if (VIFM_ISSET(vifi, rt->rt_children) &&
                    295:                NBRM_ISSETMASK(uvifs[vifi].uv_nbrmap, rt->rt_subordinates)) /*XXX*/
                    296:                resp->tr_rflags = TR_OPRUNED;
                    297:            else
                    298:                resp->tr_rflags = TR_NO_FWD;
                    299:     } else {
                    300:        if (scoped_addr(vifi, group))
                    301:            resp->tr_rflags = TR_SCOPED;
                    302:        else if (rt && !VIFM_ISSET(vifi, rt->rt_children))
                    303:            resp->tr_rflags = TR_NO_FWD;
                    304:     }
                    305: #endif /* 0 */
                    306: 
                    307:     /*
                    308:      *  if no rte exists, set NO_RTE error
                    309:      */
                    310:     if (mrt == (mrtentry_t *)NULL) {
                    311:        src = dst;              /* the dst address of resp. pkt */
                    312:        resp->tr_inaddr   = 0;
                    313:        resp->tr_rflags   = TR_NO_RTE;
                    314:        resp->tr_rmtaddr  = 0;
                    315:     } else {
                    316:        /* get # of packets in on interface */
                    317:        v_req.vifi = mrt->incoming;
                    318:        if (ioctl(udp_socket, SIOCGETVIFCNT, (char *)&v_req) >= 0)
                    319:            resp->tr_vifin = htonl(v_req.icount);
                    320:        else
                    321:            resp->tr_vifin = 0xffffffff;
                    322: 
                    323: /* TODO
                    324:        MASK_TO_VAL(rt->rt_originmask, resp->tr_smask);
                    325:        */
                    326:        src = uvifs[mrt->incoming].uv_lcl_addr;
                    327:        resp->tr_inaddr = src;
                    328:        if (mrt->upstream != (pim_nbr_entry_t *)NULL)
                    329:            parent_address = mrt->upstream->address;
                    330:        else
                    331:            parent_address = INADDR_ANY;
                    332: 
                    333:        resp->tr_rmtaddr = parent_address;
                    334:        if (!VIFM_ISSET(vifi, mrt->oifs)) {
                    335:            IF_DEBUG(DEBUG_TRACE)
                    336:                log(LOG_DEBUG, 0, "Destination %s not on forwarding tree for src %s",
                    337:                    inet_fmt(qry->tr_dst, s1), inet_fmt(qry->tr_src, s2));
                    338:            resp->tr_rflags = TR_WRONG_IF;
                    339:        }
                    340: #if 0
                    341:        if (rt->rt_metric >= UNREACHABLE) {
                    342:            resp->tr_rflags = TR_NO_RTE;
                    343:            /* Hack to send reply directly */
                    344:            rt = NULL;
                    345:        }
                    346: #endif /* 0 */
                    347:     }
                    348: 
                    349: sendit:
                    350:     /*
                    351:      * if metric is 1 or no. of reports is 1, send response to requestor
                    352:      * else send to upstream router.  If the upstream router can't handle
                    353:      * mtrace, set an error code and send to requestor anyway.
                    354:      */
                    355:     IF_DEBUG(DEBUG_TRACE)
                    356:        log(LOG_DEBUG, 0, "rcount:%d, no:%d", rcount, no);
                    357: 
                    358:     if ((rcount + 1 == no) || (mrt == NULL) || (mrt->metric == 1)) {
                    359:        resptype = IGMP_MTRACE_RESP;
                    360:        dst = qry->tr_raddr;
                    361:     } else
                    362: /* TODO */
                    363:     {
                    364: #if 0
                    365:        if (!can_mtrace(rt->rt_parent, rt->rt_gateway)) {
                    366:            dst = qry->tr_raddr;
                    367:            resp->tr_rflags = TR_OLD_ROUTER;
                    368:            resptype = IGMP_MTRACE_RESP;
                    369:        } else {
                    370: #endif /* 0 */
                    371:        if (mrt->upstream != (pim_nbr_entry_t *)NULL)
                    372:            parent_address = mrt->upstream->address;
                    373:        else
                    374:            parent_address = INADDR_ANY;
                    375:            dst = parent_address;
                    376:            resptype = IGMP_MTRACE;
                    377:        }
                    378: 
                    379:     if (IN_MULTICAST(ntohl(dst))) {
                    380:        /*
                    381:         * Send the reply on a known multicast capable vif.
                    382:         * If we don't have one, we can't source any multicasts anyway.
                    383:         */
                    384:        if (phys_vif != -1) {
                    385:            IF_DEBUG(DEBUG_TRACE)
                    386:                log(LOG_DEBUG, 0, "Sending reply to %s from %s",
                    387:                    inet_fmt(dst, s1),
                    388:                    inet_fmt(uvifs[phys_vif].uv_lcl_addr, s2));
                    389:            k_set_ttl(igmp_socket, qry->tr_rttl);
                    390:            send_igmp(igmp_send_buf, uvifs[phys_vif].uv_lcl_addr, dst,
                    391:                      resptype, no, group, datalen);
                    392:            k_set_ttl(igmp_socket, 1);
                    393:        } else
                    394:            log(LOG_INFO, 0, "No enabled phyints -- %s",
                    395:                "dropping traceroute reply");
                    396:     } else {
                    397:        IF_DEBUG(DEBUG_TRACE)
                    398:            log(LOG_DEBUG, 0, "Sending %s to %s from %s",
                    399:                resptype == IGMP_MTRACE_RESP ?  "reply" : "request on",
                    400:                inet_fmt(dst, s1), inet_fmt(src, s2));
                    401:        
                    402:        send_igmp(igmp_send_buf, src, dst, resptype, no, group, datalen);
                    403:     }
                    404:     return;
                    405: }
                    406: 
                    407: 
                    408: /*
                    409:  * accept_neighbor_request() supports some old DVMRP messages from mrinfo.
                    410:  * Haven't tested it, because I have only the new mrinfo.
                    411:  */
                    412: void
                    413: accept_neighbor_request(src, dst)
                    414:     u_int32 src;
                    415:     u_int32 dst;
                    416: {
                    417:     vifi_t vifi;
                    418:     struct uvif *v;
                    419:     u_char *p, *ncount;
                    420: /*    struct listaddr *la; */
                    421:     pim_nbr_entry_t *pim_nbr;
                    422:     int datalen;
                    423:     u_int32 temp_addr, them = src;
                    424: 
                    425: #define PUT_ADDR(a)     temp_addr = ntohl(a); \
                    426:                         *p++ = temp_addr >> 24; \
                    427:                         *p++ = (temp_addr >> 16) & 0xFF; \
                    428:                         *p++ = (temp_addr >> 8) & 0xFF; \
                    429:                         *p++ = temp_addr & 0xFF;
                    430: 
                    431:     p = (u_char *) (igmp_send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN);
                    432:     datalen = 0;
                    433: 
                    434:     for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) {
                    435:         if (v->uv_flags & VIFF_DISABLED)
                    436:             continue;
                    437:        
                    438:         ncount = 0;
                    439:        
                    440:        /* TODO: XXX: if we are PMBR, then check the DVMRP interfaces too */
                    441:         for (pim_nbr = v->uv_pim_neighbors; pim_nbr != (pim_nbr_entry_t *)NULL;
                    442:             pim_nbr = pim_nbr->next) {
                    443:             /* Make sure that there's room for this neighbor... */
                    444:             if (datalen + (ncount == 0 ? 4 + 3 + 4 : 4) > MAX_DVMRP_DATA_LEN) {
                    445:                 send_igmp(igmp_send_buf, INADDR_ANY, them, IGMP_DVMRP,
                    446:                          DVMRP_NEIGHBORS, htonl(PIMD_LEVEL), datalen);
                    447:                 p = (u_char *) (igmp_send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN);
                    448:                 datalen = 0;
                    449:                 ncount = 0;
                    450:             }
                    451: 
                    452:             /* Put out the header for this neighbor list... */
                    453:             if (ncount == 0) {
                    454:                 PUT_ADDR(v->uv_lcl_addr);
                    455:                 *p++ = v->uv_metric;
                    456:                 *p++ = v->uv_threshold;
                    457:                 ncount = p;
                    458:                 *p++ = 0;
                    459:                 datalen += 4 + 3;
                    460:             }
                    461: 
                    462:             PUT_ADDR(pim_nbr->address);
                    463:             datalen += 4;
                    464:             (*ncount)++;
                    465:         }
                    466:     }
                    467: 
                    468:     if (datalen != 0)
                    469:         send_igmp(igmp_send_buf, INADDR_ANY, them, IGMP_DVMRP, DVMRP_NEIGHBORS,
                    470:                  htonl(PIMD_LEVEL), datalen);
                    471: }
                    472: 
                    473: 
                    474: /*
                    475:  * Send a list of all of our neighbors to the requestor, `src'.
                    476:  * Used for mrinfo support.
                    477:  * XXX: currently, we cannot specify the used multicast routing protocol;
                    478:  * only a protocol version is returned.
                    479:  */
                    480: void
                    481: accept_neighbor_request2(src, dst)
                    482:     u_int32 src;
                    483:     u_int32 dst;
                    484: {
                    485:     vifi_t vifi;
                    486:     struct uvif *v;
                    487:     u_char *p, *ncount;
                    488: /*    struct listaddr *la; */
                    489:     pim_nbr_entry_t *pim_nbr;
                    490:     int datalen;
                    491:     u_int32 them = src;
                    492: 
                    493:     p = (u_char *) (igmp_send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN);
                    494:     datalen = 0;
                    495: 
                    496:     for (vifi = 0, v = uvifs; vifi < numvifs; vifi++, v++) {
                    497:         register u_int32 vflags = v->uv_flags;
                    498:         register u_char rflags = 0;
                    499:         if (vflags & VIFF_TUNNEL)
                    500:             rflags |= DVMRP_NF_TUNNEL;
                    501:         if (vflags & VIFF_SRCRT)
                    502:             rflags |= DVMRP_NF_SRCRT;
                    503:        if (vflags & VIFF_PIM_NBR)
                    504:            rflags |= DVMRP_NF_PIM;
                    505:         if (vflags & VIFF_DOWN)
                    506:             rflags |= DVMRP_NF_DOWN;
                    507:         if (vflags & VIFF_DISABLED)
                    508:             rflags |= DVMRP_NF_DISABLED;
                    509:         if (vflags & VIFF_QUERIER)
                    510:             rflags |= DVMRP_NF_QUERIER;
                    511:         if (vflags & VIFF_LEAF)
                    512:             rflags |= DVMRP_NF_LEAF;
                    513:         ncount = 0;
                    514:         pim_nbr = v->uv_pim_neighbors;
                    515:         if (pim_nbr == (pim_nbr_entry_t *)NULL) {
                    516:             /*
                    517:              * include down & disabled interfaces and interfaces on
                    518:              * leaf nets.
                    519:              */
                    520:             if (rflags & DVMRP_NF_TUNNEL)
                    521:                 rflags |= DVMRP_NF_DOWN;
                    522:             if (datalen > MAX_DVMRP_DATA_LEN - 12) {
                    523:                 send_igmp(igmp_send_buf, INADDR_ANY, them, IGMP_DVMRP,
                    524:                          DVMRP_NEIGHBORS2, htonl(PIMD_LEVEL), datalen);
                    525:                 p = (u_char *) (igmp_send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN);
                    526:                 datalen = 0;
                    527:             }
                    528:             *(u_int*)p = v->uv_lcl_addr;
                    529:             p += 4;
                    530:             *p++ = v->uv_metric;
                    531:             *p++ = v->uv_threshold;
                    532:             *p++ = rflags;
                    533:             *p++ = 1;
                    534:             *(u_int*)p =  v->uv_rmt_addr;
                    535:             p += 4;
                    536:             datalen += 12;
                    537:         } else {
                    538:             for ( ; pim_nbr; pim_nbr = pim_nbr->next) {
                    539:                 /* Make sure that there's room for this neighbor... */
                    540:                 if (datalen + (ncount == 0 ? 4+4+4 : 4) > MAX_DVMRP_DATA_LEN) {
                    541:                     send_igmp(igmp_send_buf, INADDR_ANY, them, IGMP_DVMRP,
                    542:                              DVMRP_NEIGHBORS2, htonl(PIMD_LEVEL), datalen);
                    543:                     p = (u_char *) (igmp_send_buf + MIN_IP_HEADER_LEN + IGMP_MINLEN);
                    544:                     datalen = 0;
                    545:                     ncount = 0;
                    546:                 }
                    547:                 /* Put out the header for this neighbor list... */
                    548:                 if (ncount == 0) {
                    549:                     *(u_int*)p = v->uv_lcl_addr;
                    550:                     p += 4;
                    551:                     *p++ = v->uv_metric;
                    552:                     *p++ = v->uv_threshold;
                    553:                     *p++ = rflags;
                    554:                     ncount = p;
                    555:                     *p++ = 0;
                    556:                     datalen += 4 + 4;
                    557:                 }
                    558:                 *(u_int*)p = pim_nbr->address;
                    559:                 p += 4;
                    560:                 datalen += 4;
                    561:                 (*ncount)++;
                    562:             }
                    563:         }
                    564:     }
                    565:     if (datalen != 0)
                    566:         send_igmp(igmp_send_buf, INADDR_ANY, them, IGMP_DVMRP,
                    567:                  DVMRP_NEIGHBORS2, htonl(PIMD_LEVEL), datalen);
                    568: }
                    569: 
                    570: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>