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

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