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

1.1       misho       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.16 1998/12/22 21:50:17 kurtw 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>