File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / pimdd / mrt.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 Oregon.
    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:  *  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 Oregon.
   13:  *  The name of the University of Oregon may not be used to endorse or 
   14:  *  promote products derived from this software without specific prior 
   15:  *  written permission.
   16:  *
   17:  *  THE UNIVERSITY OF OREGON DOES NOT MAKE ANY REPRESENTATIONS
   18:  *  ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  THIS SOFTWARE IS
   19:  *  PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
   20:  *  INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
   21:  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND 
   22:  *  NON-INFRINGEMENT.
   23:  *
   24:  *  IN NO EVENT SHALL UO, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
   25:  *  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
   26:  *  TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH,
   27:  *  THE USE OR PERFORMANCE OF THIS SOFTWARE.
   28:  *
   29:  *  Other copyrights might apply to parts of this software and are so
   30:  *  noted when applicable.
   31:  */
   32: /*
   33:  *  Questions concerning this software should be directed to 
   34:  *  Kurt Windisch (kurtw@antc.uoregon.edu)
   35:  *
   36:  *  $Id: mrt.c,v 1.1.1.1 2017/06/12 07:58:55 misho Exp $
   37:  */
   38: /*
   39:  * Part of this program has been derived from PIM sparse-mode pimd.
   40:  * The pimd program is covered by the license in the accompanying file
   41:  * named "LICENSE.pimd".
   42:  *  
   43:  * The pimd program is COPYRIGHT 1998 by University of Southern California.
   44:  *
   45:  * Part of this program has been derived from mrouted.
   46:  * The mrouted program is covered by the license in the accompanying file
   47:  * named "LICENSE.mrouted".
   48:  * 
   49:  * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
   50:  * Leland Stanford Junior University.
   51:  *
   52:  */
   53: 
   54: #include "defs.h"
   55: 
   56: srcentry_t		*srclist;
   57: grpentry_t		*grplist;
   58: 
   59: /*
   60:  * Local functions definition
   61:  */
   62: static srcentry_t *create_srcentry     __P((u_int32 source));
   63: static int        search_srclist       __P((u_int32 source,
   64: 					    srcentry_t **sourceEntry));
   65: static int        search_srcmrtlink    __P((srcentry_t *srcentry_ptr,
   66: 					    u_int32 group,
   67: 					    mrtentry_t **mrtPtr));
   68: static void       insert_srcmrtlink    __P((mrtentry_t *elementPtr,
   69: 					    mrtentry_t *insertPtr,
   70: 					    srcentry_t *srcListPtr));
   71: static grpentry_t *create_grpentry     __P((u_int32 group));
   72: static int        search_grplist       __P((u_int32 group,
   73: 					    grpentry_t **groupEntry));
   74: static int        search_grpmrtlink    __P((grpentry_t *grpentry_ptr,
   75: 					    u_int32 source,
   76: 					    mrtentry_t **mrtPtr));
   77: static void       insert_grpmrtlink    __P((mrtentry_t *elementPtr,
   78: 					    mrtentry_t *insertPtr,
   79: 					    grpentry_t *grpListPtr));
   80: static mrtentry_t *alloc_mrtentry      __P((srcentry_t *srcentry_ptr,
   81: 					    grpentry_t *grpentry_ptr));
   82: static mrtentry_t *create_mrtentry     __P((srcentry_t *srcentry_ptr,
   83: 					    grpentry_t *grpentry_ptr,
   84: 					    u_int16 flags));
   85: 
   86: 
   87: void 
   88: init_pim_mrt()
   89: {
   90: 
   91:     /* TODO: delete any existing routing table */
   92: 
   93:     /* Initialize the source list */
   94:     /* The first entry has address 'INADDR_ANY' and is not used */
   95:     /* The order is the smallest address first. */
   96:     srclist	        = (srcentry_t *)malloc(sizeof(srcentry_t));
   97:     srclist->next       = (srcentry_t *)NULL;
   98:     srclist->prev       = (srcentry_t *)NULL;
   99:     srclist->address	= INADDR_ANY_N;
  100:     srclist->mrtlink    = (mrtentry_t *)NULL;
  101:     srclist->incoming   = NO_VIF;
  102:     srclist->upstream   = (pim_nbr_entry_t *)NULL;
  103:     srclist->metric     = 0;
  104:     srclist->preference = 0;
  105:     RESET_TIMER(srclist->timer);
  106:     
  107:     /* Initialize the group list */
  108:     /* The first entry has address 'INADDR_ANY' and is not used */
  109:     /* The order is the smallest address first. */
  110:     grplist	        = (grpentry_t *)malloc(sizeof(grpentry_t));
  111:     grplist->next       = (grpentry_t *)NULL;
  112:     grplist->prev       = (grpentry_t *)NULL;
  113:     grplist->group	= INADDR_ANY_N;
  114:     grplist->mrtlink    = (mrtentry_t *)NULL;
  115: }
  116: 
  117: 
  118: grpentry_t*
  119: find_group(group)
  120:     u_int32 group;
  121: {
  122:     grpentry_t *grpentry_ptr;
  123: 
  124:     if (!IN_MULTICAST(ntohl(group)))
  125: 	return (grpentry_t *)NULL;
  126:     
  127:     if (search_grplist(group, &grpentry_ptr) == TRUE) {
  128: 	/* Group found! */
  129: 	return (grpentry_ptr);
  130:     }
  131:     return (grpentry_t *)NULL;
  132: }
  133: 
  134: 
  135: srcentry_t *
  136: find_source(source)
  137:     u_int32 source;
  138: {
  139:     srcentry_t *srcentry_ptr;
  140: 
  141:     if (!inet_valid_host(source))
  142: 	return (srcentry_t *)NULL;
  143:     
  144:     if (search_srclist(source, &srcentry_ptr) == TRUE) {
  145: 	/* Source found! */
  146: 	return (srcentry_ptr);
  147:     }
  148:     return (srcentry_t *)NULL;
  149: }
  150: 
  151: 
  152: mrtentry_t *
  153: find_route(source, group, flags, create)
  154:     u_int32 source, group;
  155:     u_int16 flags;
  156:     char create;
  157: {
  158:     srcentry_t *srcentry_ptr;
  159:     grpentry_t *grpentry_ptr;
  160:     mrtentry_t *mrtentry_ptr;
  161: 
  162:     if (!IN_MULTICAST(ntohl(group)))
  163: 	return (mrtentry_t *)NULL;
  164:     
  165:     if (!inet_valid_host(source))
  166: 	return (mrtentry_t *)NULL;
  167:     
  168:     if (create == DONT_CREATE) {
  169: 	if (search_grplist(group, &grpentry_ptr) == FALSE) 
  170: 	    return (mrtentry_t *)NULL;
  171: 	/* Search for the source */
  172: 	if (search_grpmrtlink(grpentry_ptr, source,
  173: 			      &mrtentry_ptr) == TRUE) {
  174: 	    /* Exact (S,G) entry found */
  175: 	    return (mrtentry_ptr);
  176: 	}
  177: 	return (mrtentry_t *)NULL;
  178:     }
  179: 
  180: 
  181:     /* Creation allowed */
  182: 
  183:     grpentry_ptr = create_grpentry(group);
  184:     if (grpentry_ptr == (grpentry_t *)NULL) {
  185: 	return (mrtentry_t *)NULL;
  186:     }
  187: 
  188:     /* Setup the (S,G) routing entry */
  189:     srcentry_ptr = create_srcentry(source);
  190:     if (srcentry_ptr == (srcentry_t *)NULL) {
  191: 	if (grpentry_ptr->mrtlink == (mrtentry_t *)NULL) {
  192: 	    /* New created grpentry. Delete it. */
  193: 	    delete_grpentry(grpentry_ptr);
  194: 	}
  195: 	return (mrtentry_t *)NULL;
  196:     }
  197: 
  198:     mrtentry_ptr = create_mrtentry(srcentry_ptr, grpentry_ptr, MRTF_SG);
  199:     if (mrtentry_ptr == (mrtentry_t *)NULL) {
  200: 	if (grpentry_ptr->mrtlink == (mrtentry_t *)NULL) {
  201: 	    /* New created grpentry. Delete it. */
  202: 	    delete_grpentry(grpentry_ptr);
  203: 	}
  204: 	if (srcentry_ptr->mrtlink == (mrtentry_t *)NULL) {
  205: 	    /* New created srcentry. Delete it. */
  206: 	    delete_srcentry(srcentry_ptr);
  207: 	}
  208: 	return (mrtentry_t *)NULL;
  209:     }
  210:     
  211:     if (mrtentry_ptr->flags & MRTF_NEW) {
  212: 	/* The mrtentry pref/metric should be the pref/metric of the 
  213: 	 * _upstream_ assert winner. Since this isn't known now, 
  214: 	 * set it to the config'ed default
  215: 	 */
  216: 	mrtentry_ptr->incoming = srcentry_ptr->incoming;
  217: 	mrtentry_ptr->upstream = srcentry_ptr->upstream;
  218: 	mrtentry_ptr->metric   = srcentry_ptr->metric;
  219: 	mrtentry_ptr->preference = srcentry_ptr->preference;
  220:     }
  221:     
  222:     return (mrtentry_ptr);
  223: }
  224: 
  225: 
  226: void
  227: delete_srcentry(srcentry_ptr)
  228:     srcentry_t *srcentry_ptr;
  229: {
  230:     mrtentry_t *mrtentry_ptr;
  231:     mrtentry_t *mrtentry_next;
  232: 
  233:     if (srcentry_ptr == (srcentry_t *)NULL)
  234: 	return;
  235:     /* TODO: XXX: the first entry is unused and always there */
  236:     srcentry_ptr->prev->next = 	srcentry_ptr->next;
  237:     if (srcentry_ptr->next != (srcentry_t *)NULL)
  238: 	srcentry_ptr->next->prev = srcentry_ptr->prev;
  239:     
  240:     for (mrtentry_ptr = srcentry_ptr->mrtlink;
  241: 	 mrtentry_ptr != (mrtentry_t *)NULL;
  242: 	 mrtentry_ptr = mrtentry_next) {
  243: 	mrtentry_next = mrtentry_ptr->srcnext;
  244: 	if (mrtentry_ptr->grpprev != (mrtentry_t *)NULL)
  245: 	    mrtentry_ptr->grpprev->grpnext = mrtentry_ptr->grpnext;
  246: 	else {
  247: 	    mrtentry_ptr->group->mrtlink = mrtentry_ptr->grpnext;
  248: 	    if (mrtentry_ptr->grpnext == (mrtentry_t *)NULL) {
  249: 		/* Delete the group entry */
  250: 		delete_grpentry(mrtentry_ptr->group);
  251: 	    }
  252: 	}
  253: 	if (mrtentry_ptr->grpnext != (mrtentry_t *)NULL)
  254: 	    mrtentry_ptr->grpnext->grpprev = mrtentry_ptr->grpprev;
  255: 	FREE_MRTENTRY(mrtentry_ptr);
  256:     }
  257:     free((char *)srcentry_ptr);
  258: }
  259: 
  260: 
  261: void
  262: delete_grpentry(grpentry_ptr)
  263:     grpentry_t *grpentry_ptr;
  264: {
  265:     mrtentry_t *mrtentry_ptr;
  266:     mrtentry_t *mrtentry_next;
  267:     
  268:     if (grpentry_ptr == (grpentry_t *)NULL)
  269: 	return;
  270:     /* TODO: XXX: the first entry is unused and always there */
  271:     grpentry_ptr->prev->next = grpentry_ptr->next;
  272:     if (grpentry_ptr->next != (grpentry_t *)NULL)
  273: 	grpentry_ptr->next->prev = grpentry_ptr->prev;
  274:     
  275:     for (mrtentry_ptr = grpentry_ptr->mrtlink;
  276: 	 mrtentry_ptr != (mrtentry_t *)NULL;
  277: 	 mrtentry_ptr = mrtentry_next) {
  278: 	mrtentry_next = mrtentry_ptr->grpnext;
  279: 	if (mrtentry_ptr->srcprev != (mrtentry_t *)NULL)
  280: 	    mrtentry_ptr->srcprev->srcnext = mrtentry_ptr->srcnext;
  281: 	else {
  282: 	    mrtentry_ptr->source->mrtlink = mrtentry_ptr->srcnext;
  283: 	    if (mrtentry_ptr->srcnext == (mrtentry_t *)NULL) {
  284: 		/* Delete the srcentry if this was the last routing entry */
  285: 		delete_srcentry(mrtentry_ptr->source);
  286: 	    }
  287: 	}
  288: 	if (mrtentry_ptr->srcnext != (mrtentry_t *)NULL)
  289: 	    mrtentry_ptr->srcnext->srcprev = mrtentry_ptr->srcprev;
  290: 	FREE_MRTENTRY(mrtentry_ptr);
  291:     }
  292:     free((char *)grpentry_ptr);
  293: }
  294: 
  295: 
  296: void
  297: delete_mrtentry(mrtentry_ptr)
  298:     mrtentry_t *mrtentry_ptr;
  299: {
  300:     if (mrtentry_ptr == (mrtentry_t *)NULL)
  301: 	return;
  302: 
  303:     /* Delete the kernel cache first */
  304:     k_del_mfc(igmp_socket, mrtentry_ptr->source->address,
  305: 		  mrtentry_ptr->group->group);
  306: 
  307: #ifdef RSRR
  308:     /* Tell the reservation daemon */
  309:     rsrr_cache_clean(mrtentry_ptr);
  310: #endif /* RSRR */
  311: 
  312:    /* (S,G) mrtentry */
  313:     /* Delete from the grpentry MRT chain */
  314:     if (mrtentry_ptr->grpprev != (mrtentry_t *)NULL)
  315: 	mrtentry_ptr->grpprev->grpnext = mrtentry_ptr->grpnext;
  316:     else {
  317: 	mrtentry_ptr->group->mrtlink = mrtentry_ptr->grpnext;
  318: 	if (mrtentry_ptr->grpnext == (mrtentry_t *)NULL) {
  319: 	    /* Delete the group entry */
  320: 	    delete_grpentry(mrtentry_ptr->group);
  321: 	}
  322:     }
  323: 	
  324:     if (mrtentry_ptr->grpnext != (mrtentry_t *)NULL)
  325: 	mrtentry_ptr->grpnext->grpprev = mrtentry_ptr->grpprev;
  326:     
  327:     /* Delete from the srcentry MRT chain */
  328:     if (mrtentry_ptr->srcprev != (mrtentry_t *)NULL)
  329: 	mrtentry_ptr->srcprev->srcnext = mrtentry_ptr->srcnext;
  330:     else {
  331: 	mrtentry_ptr->source->mrtlink = mrtentry_ptr->srcnext;
  332: 	if (mrtentry_ptr->srcnext == (mrtentry_t *)NULL) {
  333: 	    /* Delete the srcentry if this was the last routing entry */
  334: 	    delete_srcentry(mrtentry_ptr->source);
  335: 	}
  336:     }
  337:     if (mrtentry_ptr->srcnext != (mrtentry_t *)NULL)
  338: 	mrtentry_ptr->srcnext->srcprev = mrtentry_ptr->srcprev;
  339: 
  340:     FREE_MRTENTRY(mrtentry_ptr);
  341: }
  342: 
  343: 
  344: static int
  345: search_srclist(source, sourceEntry)
  346:     u_int32 source;
  347:     register srcentry_t **sourceEntry;
  348: {
  349:     register srcentry_t *s_prev,*s;
  350:     u_int32 source_h = ntohl(source);
  351:     
  352:     for (s_prev = srclist, s = s_prev->next; s != (srcentry_t *)NULL;
  353: 	 s_prev = s, s = s->next) {
  354: 	/* The srclist is ordered with the smallest addresses first.
  355: 	 * The first entry is not used.
  356: 	 */
  357: 	if (ntohl(s->address) < source_h)
  358: 	    continue;
  359: 	if (s->address == source) {
  360: 	    *sourceEntry = s;
  361: 	    return(TRUE);
  362: 	}
  363: 	break;  
  364:     }
  365:     *sourceEntry = s_prev;   /* The insertion point is between s_prev and s */
  366:     return(FALSE);
  367: }
  368: 
  369: 
  370: static int
  371: search_grplist(group, groupEntry)
  372:     u_int32 group;
  373:     register grpentry_t **groupEntry;
  374: {
  375:     register grpentry_t *g_prev, *g;
  376:     u_int32 group_h = ntohl(group);
  377:     
  378:     for (g_prev = grplist, g = g_prev->next; g != (grpentry_t *)NULL;
  379: 	 g_prev = g, g = g->next) {
  380: 	/* The grplist is ordered with the smallest address first.
  381: 	 * The first entry is not used.
  382: 	 */
  383: 	if (ntohl(g->group) < group_h)
  384: 	    continue;
  385: 	if (g->group == group) {
  386: 	    *groupEntry = g;
  387: 	    return(TRUE);
  388: 	}
  389: 	break;
  390:     }
  391:     *groupEntry = g_prev;    /* The insertion point is between g_prev and g */
  392:     return(FALSE);
  393: }
  394: 
  395: 
  396: static srcentry_t *
  397: create_srcentry(source)
  398:     u_int32 source;
  399: {
  400:     register srcentry_t *srcentry_ptr;
  401:     srcentry_t *srcentry_prev;
  402: 
  403:     if (search_srclist(source, &srcentry_prev) == TRUE)
  404: 	return (srcentry_prev);
  405:     
  406:     srcentry_ptr = (srcentry_t *)malloc(sizeof(srcentry_t));
  407:     if (srcentry_ptr == (srcentry_t *)NULL) {
  408: 	log(LOG_WARNING, 0, "Memory allocation error for srcentry %s",
  409: 	    inet_fmt(source, s1));
  410: 	return (srcentry_t *)NULL;
  411:     }
  412: 
  413:     srcentry_ptr->address = source;
  414:     /*
  415:      * Free the memory if there is error getting the iif and
  416:      * the next hop (upstream) router.
  417:      */ 
  418:     if (set_incoming(srcentry_ptr, PIM_IIF_SOURCE) == FALSE) {
  419: 	free((char *)srcentry_ptr);
  420: 	return (srcentry_t *)NULL;
  421:     }
  422:     srcentry_ptr->mrtlink = (mrtentry_t *)NULL;
  423:     RESET_TIMER(srcentry_ptr->timer);
  424:     srcentry_ptr->next	= srcentry_prev->next;
  425:     srcentry_prev->next = srcentry_ptr;
  426:     srcentry_ptr->prev = srcentry_prev;
  427:     if (srcentry_ptr->next != (srcentry_t *)NULL)
  428: 	srcentry_ptr->next->prev = srcentry_ptr;
  429:     
  430:     IF_DEBUG(DEBUG_MFC)
  431: 	log(LOG_DEBUG, 0, "create source entry, source %s",
  432: 	    inet_fmt(source, s1));
  433:     return (srcentry_ptr);
  434: }
  435: 
  436: 
  437: static grpentry_t *
  438: create_grpentry(group)
  439:     u_int32 group;
  440: {
  441:     register grpentry_t *grpentry_ptr;
  442:     grpentry_t *grpentry_prev;
  443: 
  444:     if (search_grplist(group, &grpentry_prev) == TRUE)
  445: 	return (grpentry_prev);
  446:     
  447:     grpentry_ptr = (grpentry_t *)malloc(sizeof(grpentry_t));
  448:     if (grpentry_ptr == (grpentry_t *)NULL) {
  449: 	log(LOG_WARNING, 0, "Memory allocation error for grpentry %s",
  450: 	    inet_fmt(group, s1));
  451: 	return (grpentry_t *)NULL;
  452:     }
  453: 
  454:     grpentry_ptr->group	        = group;
  455:     grpentry_ptr->mrtlink       = (mrtentry_t *)NULL;
  456: 
  457:     /* Now it is safe to include the new group entry */
  458:     grpentry_ptr->next		= grpentry_prev->next;
  459:     grpentry_prev->next         = grpentry_ptr;
  460:     grpentry_ptr->prev          = grpentry_prev;
  461:     if (grpentry_ptr->next != (grpentry_t *)NULL)
  462: 	grpentry_ptr->next->prev = grpentry_ptr;
  463:     
  464:     IF_DEBUG(DEBUG_MFC)
  465: 	log(LOG_DEBUG, 0, "create group entry, group %s", inet_fmt(group, s1));
  466:     return(grpentry_ptr);
  467: }
  468: 
  469: 
  470: /*
  471:  * Return TRUE if the entry is found and then *mrtPtr is set to point to that
  472:  * entry. Otherwise return FALSE and *mrtPtr points the the previous entry
  473:  * (or NULL if first in the chain.
  474:  */
  475: static int
  476: search_srcmrtlink(srcentry_ptr, group, mrtPtr)
  477:     srcentry_t *srcentry_ptr;	
  478:     u_int32 group;
  479:     mrtentry_t **mrtPtr;
  480: {
  481:     register mrtentry_t *mrtentry_ptr;
  482:     register mrtentry_t *m_prev = (mrtentry_t *)NULL;
  483:     u_int32 group_h = ntohl(group);
  484:     
  485:     for(mrtentry_ptr = srcentry_ptr->mrtlink;
  486: 	mrtentry_ptr != (mrtentry_t *)NULL;
  487: 	m_prev = mrtentry_ptr, mrtentry_ptr = mrtentry_ptr->srcnext) {
  488: 	/* The entries are ordered with the smaller group address first.
  489: 	 * The addresses are in network order.
  490: 	 */
  491: 	if (ntohl(mrtentry_ptr->group->group) < group_h)
  492: 	    continue;
  493: 	if (mrtentry_ptr->group->group == group) {
  494: 	    *mrtPtr = mrtentry_ptr;
  495: 	    return(TRUE);
  496: 	}
  497: 	break;
  498:     }
  499:     *mrtPtr = m_prev;
  500:     return(FALSE);
  501: }
  502: 
  503: 
  504: /*
  505:  * Return TRUE if the entry is found and then *mrtPtr is set to point to that
  506:  * entry. Otherwise return FALSE and *mrtPtr points the the previous entry
  507:  * (or NULL if first in the chain.
  508:  */
  509: static int
  510: search_grpmrtlink(grpentry_ptr, source, mrtPtr)
  511:     grpentry_t *grpentry_ptr;
  512:     u_int32 source;
  513:     mrtentry_t **mrtPtr;
  514: {
  515:     register mrtentry_t *mrtentry_ptr;
  516:     register mrtentry_t *m_prev = (mrtentry_t *)NULL;
  517:     u_int32 source_h = ntohl(source);
  518:     
  519:     for (mrtentry_ptr = grpentry_ptr->mrtlink;
  520: 	 mrtentry_ptr != (mrtentry_t *)NULL;
  521: 	 m_prev = mrtentry_ptr, mrtentry_ptr = mrtentry_ptr->grpnext) {
  522: 	/* The entries are ordered with the smaller source address first.
  523: 	 * The addresses are in network order.
  524: 	 */
  525: 	if (ntohl(mrtentry_ptr->source->address) < source_h)
  526: 	    continue;
  527: 	if (source == mrtentry_ptr->source->address) {
  528: 	    *mrtPtr = mrtentry_ptr;
  529: 	    return(TRUE);
  530: 	}
  531: 	break;
  532:     }
  533:     *mrtPtr = m_prev;
  534:     return(FALSE);
  535: }
  536: 
  537: 
  538: static void
  539: insert_srcmrtlink(mrtentry_new, mrtentry_prev, srcentry_ptr)
  540:     mrtentry_t *mrtentry_new;
  541:     mrtentry_t *mrtentry_prev;
  542:     srcentry_t *srcentry_ptr;
  543: {
  544:     if (mrtentry_prev == (mrtentry_t *)NULL) {
  545: 	/* Has to be insert as the head entry for this source */
  546: 	mrtentry_new->srcnext = srcentry_ptr->mrtlink;
  547: 	mrtentry_new->srcprev = (mrtentry_t *)NULL;
  548: 	srcentry_ptr->mrtlink = mrtentry_new;
  549:     }
  550:     else {
  551: 	/* Insert right after the mrtentry_prev */
  552: 	mrtentry_new->srcnext = mrtentry_prev->srcnext;
  553: 	mrtentry_new->srcprev = mrtentry_prev;
  554: 	mrtentry_prev->srcnext = mrtentry_new;
  555:     }
  556:     if (mrtentry_new->srcnext != (mrtentry_t *)NULL)
  557: 	mrtentry_new->srcnext->srcprev = mrtentry_new;
  558: }
  559: 
  560: 
  561: static void
  562: insert_grpmrtlink(mrtentry_new, mrtentry_prev, grpentry_ptr)
  563:     mrtentry_t *mrtentry_new;
  564:     mrtentry_t *mrtentry_prev;
  565:     grpentry_t *grpentry_ptr;
  566: {
  567:     if (mrtentry_prev == (mrtentry_t *)NULL) {
  568: 	/* Has to be insert as the head entry for this group */
  569: 	mrtentry_new->grpnext = grpentry_ptr->mrtlink;
  570: 	mrtentry_new->grpprev = (mrtentry_t *)NULL;
  571: 	grpentry_ptr->mrtlink = mrtentry_new;
  572:     }
  573:     else {
  574: 	/* Insert right after the mrtentry_prev */
  575: 	mrtentry_new->grpnext = mrtentry_prev->grpnext;
  576: 	mrtentry_new->grpprev = mrtentry_prev;
  577: 	mrtentry_prev->grpnext = mrtentry_new;
  578:     }
  579:     if (mrtentry_new->grpnext != (mrtentry_t *)NULL)
  580: 	mrtentry_new->grpnext->grpprev = mrtentry_new;
  581: }
  582: 
  583: 
  584: static mrtentry_t *
  585: alloc_mrtentry(srcentry_ptr, grpentry_ptr)
  586:     srcentry_t *srcentry_ptr;
  587:     grpentry_t *grpentry_ptr;
  588: {
  589:     register mrtentry_t *mrtentry_ptr;
  590:     u_int16 i, *i_ptr;
  591:     u_long  *il_ptr;
  592:     u_int8  vif_numbers;
  593:     
  594:     mrtentry_ptr = (mrtentry_t *)malloc(sizeof(mrtentry_t));
  595:     if (mrtentry_ptr == (mrtentry_t *)NULL) {
  596: 	log(LOG_WARNING, 0, "alloc_mrtentry(): out of memory");
  597: 	return (mrtentry_t *)NULL;
  598:     }
  599:     
  600:     /*
  601:      * grpnext, grpprev, srcnext, srcprev will be setup when we link the
  602:      * mrtentry to the source and group chains
  603:      */
  604:     mrtentry_ptr->source  = srcentry_ptr;
  605:     mrtentry_ptr->group   = grpentry_ptr;
  606:     mrtentry_ptr->incoming = NO_VIF;
  607:     VIFM_CLRALL(mrtentry_ptr->leaves);
  608:     VIFM_CLRALL(mrtentry_ptr->pruned_oifs);
  609:     VIFM_CLRALL(mrtentry_ptr->oifs);
  610:     mrtentry_ptr->upstream = (pim_nbr_entry_t *)NULL;
  611:     mrtentry_ptr->metric = 0;
  612:     mrtentry_ptr->preference = 0;
  613: #ifdef RSRR
  614:     mrtentry_ptr->rsrr_cache = (struct rsrr_cache *)NULL;
  615: #endif /* RSRR */
  616: 
  617: /*
  618:  * XXX: TODO: if we are short in memory, we can reserve as few as possible
  619:  * space for vif timers (per group and/or routing entry), but then everytime
  620:  * when a new interfaces is configured, the router will be restarted and
  621:  * will delete the whole routing table. The "memory is cheap" solution is
  622:  * to reserve timer space for all potential vifs in advance and then no
  623:  * need to delete the routing table and disturb the forwarding.
  624:  */
  625: #ifdef SAVE_MEMORY
  626:     mrtentry_ptr->prune_timers = (u_int16 *)malloc(sizeof(u_int16) * numvifs);
  627:     mrtentry_ptr->prune_delay_timerids = 
  628: 	(u_long *)malloc(sizeof(u_long) * numvifs);
  629:     mrtentry_ptr->last_assert = (u_long *)malloc(sizeof(u_long) * numvifs);
  630:     mrtentry_ptr->last_prune = (u_long *)malloc(sizeof(u_long) * numvifs);
  631:     vif_numbers = numvifs;
  632: #else
  633:     mrtentry_ptr->prune_timers =
  634: 	(u_int16 *)malloc(sizeof(u_int16) * total_interfaces);
  635:     mrtentry_ptr->prune_delay_timerids =
  636: 	(u_long *)malloc(sizeof(u_long) * total_interfaces);
  637:     mrtentry_ptr->last_assert =
  638: 	(u_long *)malloc(sizeof(u_long) * total_interfaces);
  639:     mrtentry_ptr->last_prune =
  640: 	(u_long *)malloc(sizeof(u_long) * total_interfaces);
  641:     vif_numbers = total_interfaces;
  642: #endif /* SAVE_MEMORY */
  643:     if ((mrtentry_ptr->prune_timers == (u_int16 *)NULL) ||
  644: 	(mrtentry_ptr->prune_delay_timerids == (u_long *)NULL) ||
  645: 	(mrtentry_ptr->last_assert == (u_long *)NULL) ||
  646: 	(mrtentry_ptr->last_prune == (u_long *)NULL)) {
  647: 	log(LOG_WARNING, 0, "alloc_mrtentry(): out of memory");
  648: 	FREE_MRTENTRY(mrtentry_ptr);
  649: 	return (mrtentry_t *)NULL;
  650:     }
  651:     /* Reset the timers */
  652:     for (i = 0, i_ptr = mrtentry_ptr->prune_timers; i < vif_numbers;
  653: 	 i++, i_ptr++)
  654: 	RESET_TIMER(*i_ptr);
  655:     for (i = 0, il_ptr = mrtentry_ptr->prune_delay_timerids; i < vif_numbers;
  656: 	 i++, il_ptr++)
  657: 	RESET_TIMER(*il_ptr);
  658:     for (i = 0, il_ptr = mrtentry_ptr->last_assert; i < vif_numbers;
  659: 	 i++, il_ptr++)
  660: 	RESET_TIMER(*il_ptr);
  661:     for (i = 0, il_ptr = mrtentry_ptr->last_prune; i < vif_numbers;
  662: 	 i++, il_ptr++)
  663: 	RESET_TIMER(*il_ptr);
  664: 
  665:     mrtentry_ptr->flags = MRTF_NEW;
  666:     RESET_TIMER(mrtentry_ptr->timer);
  667:     mrtentry_ptr->join_delay_timerid = 0;
  668:     RESET_TIMER(mrtentry_ptr->assert_timer);
  669:     mrtentry_ptr->graft = (pim_graft_entry_t *)NULL;
  670: 
  671:     return(mrtentry_ptr);
  672: }
  673: 
  674: 
  675: static mrtentry_t *
  676: create_mrtentry(srcentry_ptr, grpentry_ptr, flags)
  677:     srcentry_t *srcentry_ptr;
  678:     grpentry_t *grpentry_ptr;
  679:     u_int16 flags;
  680: {
  681:     mrtentry_t *r_new;
  682:     mrtentry_t *r_grp_insert, *r_src_insert; /* pointers to insert */
  683:     u_int32 source;
  684:     u_int32 group;
  685: 
  686:     /* (S,G) entry */
  687:     source = srcentry_ptr->address;
  688:     group  = grpentry_ptr->group;
  689:     
  690:     if (search_grpmrtlink(grpentry_ptr, source, &r_grp_insert) == TRUE) {
  691: 	return(r_grp_insert);
  692:     }
  693:     if (search_srcmrtlink(srcentry_ptr, group, &r_src_insert) == TRUE) {
  694: 	/*
  695: 	 * Hmmm, search_grpmrtlink() didn't find the entry, but
  696: 	 * search_srcmrtlink() did find it! Shoudn't happen. Panic!
  697: 	 */
  698: 	log(LOG_ERR, 0, "MRT inconsistency for src %s and grp %s\n",
  699: 	    inet_fmt(source, s1), inet_fmt(group, s2));
  700: 	/* not reached but to make lint happy */
  701: 	return (mrtentry_t *)NULL;
  702:     }
  703:     /*
  704:      * Create and insert in group mrtlink and source mrtlink chains.
  705:      */
  706:     r_new = alloc_mrtentry(srcentry_ptr, grpentry_ptr);
  707:     if (r_new == (mrtentry_t *)NULL)
  708: 	return (mrtentry_t *)NULL;
  709:     /*
  710:      * r_new has to be insert right after r_grp_insert in the
  711:      * grp mrtlink chain and right after r_src_insert in the 
  712:      * src mrtlink chain
  713:      */
  714:     insert_grpmrtlink(r_new, r_grp_insert, grpentry_ptr);
  715:     insert_srcmrtlink(r_new, r_src_insert, srcentry_ptr);
  716:     r_new->flags |= MRTF_SG;
  717:     return (r_new);
  718: }

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