File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / pimdd / trace.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jun 12 07:58:55 2017 UTC (7 years ago) by misho
Branches: pimdd, MAIN
CVS tags: v0_2_1p0, v0_2_1, HEAD
pimdd-dense 0.2.1.0_2

    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.1.1.1 2017/06/12 07:58:55 misho 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>