Annotation of embedaddon/igmpproxy/src/rttable.c, revision 1.1.1.1

1.1       misho       1: /*
                      2: **  igmpproxy - IGMP proxy based multicast router 
                      3: **  Copyright (C) 2005 Johnny Egeland <johnny@rlo.org>
                      4: **
                      5: **  This program is free software; you can redistribute it and/or modify
                      6: **  it under the terms of the GNU General Public License as published by
                      7: **  the Free Software Foundation; either version 2 of the License, or
                      8: **  (at your option) any later version.
                      9: **
                     10: **  This program is distributed in the hope that it will be useful,
                     11: **  but WITHOUT ANY WARRANTY; without even the implied warranty of
                     12: **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     13: **  GNU General Public License for more details.
                     14: **
                     15: **  You should have received a copy of the GNU General Public License
                     16: **  along with this program; if not, write to the Free Software
                     17: **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     18: **
                     19: **----------------------------------------------------------------------------
                     20: **
                     21: **  This software is derived work from the following software. The original
                     22: **  source code has been modified from it's original state by the author
                     23: **  of igmpproxy.
                     24: **
                     25: **  smcroute 0.92 - Copyright (C) 2001 Carsten Schill <carsten@cschill.de>
                     26: **  - Licensed under the GNU General Public License, version 2
                     27: **  
                     28: **  mrouted 3.9-beta3 - COPYRIGHT 1989 by The Board of Trustees of 
                     29: **  Leland Stanford Junior University.
                     30: **  - Original license can be found in the Stanford.txt file.
                     31: **
                     32: */
                     33: /**
                     34: *   rttable.c 
                     35: *
                     36: *   Updates the routingtable according to 
                     37: *     recieved request.
                     38: */
                     39: 
                     40: #include "igmpproxy.h"
                     41:     
                     42: /**
                     43: *   Routing table structure definition. Double linked list...
                     44: */
                     45: struct RouteTable {
                     46:     struct RouteTable   *nextroute;     // Pointer to the next group in line.
                     47:     struct RouteTable   *prevroute;     // Pointer to the previous group in line.
                     48:     uint32_t              group;          // The group to route
                     49:     uint32_t              originAddr;     // The origin adress (only set on activated routes)
                     50:     uint32_t              vifBits;        // Bits representing recieving VIFs.
                     51: 
                     52:     // Keeps the upstream membership state...
                     53:     short               upstrState;     // Upstream membership state.
                     54: 
                     55:     // These parameters contain aging details.
                     56:     uint32_t              ageVifBits;     // Bits representing aging VIFs.
                     57:     int                 ageValue;       // Downcounter for death.          
                     58:     int                 ageActivity;    // Records any acitivity that notes there are still listeners.
                     59: };
                     60: 
                     61:                  
                     62: // Keeper for the routing table...
                     63: static struct RouteTable   *routing_table;
                     64: 
                     65: // Prototypes
                     66: void logRouteTable(char *header);
                     67: int  internAgeRoute(struct RouteTable*  croute);
                     68: int internUpdateKernelRoute(struct RouteTable *route, int activate);
                     69: 
                     70: // Socket for sending join or leave requests.
                     71: int mcGroupSock = 0;
                     72: 
                     73: 
                     74: /**
                     75: *   Function for retrieving the Multicast Group socket.
                     76: */
                     77: int getMcGroupSock() {
                     78:     if( ! mcGroupSock ) {
                     79:         mcGroupSock = openUdpSocket( INADDR_ANY, 0 );;
                     80:     }
                     81:     return mcGroupSock;
                     82: }
                     83:  
                     84: /**
                     85: *   Initializes the routing table.
                     86: */
                     87: void initRouteTable() {
                     88:     unsigned Ix;
                     89:     struct IfDesc *Dp;
                     90: 
                     91:     // Clear routing table...
                     92:     routing_table = NULL;
                     93: 
                     94:     // Join the all routers group on downstream vifs...
                     95:     for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) {
                     96:         // If this is a downstream vif, we should join the All routers group...
                     97:         if( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) && Dp->state == IF_STATE_DOWNSTREAM) {
                     98:             my_log(LOG_DEBUG, 0, "Joining all-routers group %s on vif %s",
                     99:                          inetFmt(allrouters_group,s1),inetFmt(Dp->InAdr.s_addr,s2));
                    100:             
                    101:             //k_join(allrouters_group, Dp->InAdr.s_addr);
                    102:             joinMcGroup( getMcGroupSock(), Dp, allrouters_group );
                    103:         }
                    104:     }
                    105: }
                    106: 
                    107: /**
                    108: *   Internal function to send join or leave requests for
                    109: *   a specified route upstream...
                    110: */
                    111: void sendJoinLeaveUpstream(struct RouteTable* route, int join) {
                    112:     struct IfDesc*      upstrIf;
                    113:     
                    114:     // Get the upstream VIF...
                    115:     upstrIf = getIfByIx( upStreamVif );
                    116:     if(upstrIf == NULL) {
                    117:         my_log(LOG_ERR, 0 ,"FATAL: Unable to get Upstream IF.");
                    118:     }
                    119: 
                    120:     // Send join or leave request...
                    121:     if(join) {
                    122: 
                    123:         // Only join a group if there are listeners downstream...
                    124:         if(route->vifBits > 0) {
                    125:             my_log(LOG_DEBUG, 0, "Joining group %s upstream on IF address %s",
                    126:                          inetFmt(route->group, s1), 
                    127:                          inetFmt(upstrIf->InAdr.s_addr, s2));
                    128: 
                    129:             //k_join(route->group, upstrIf->InAdr.s_addr);
                    130:             joinMcGroup( getMcGroupSock(), upstrIf, route->group );
                    131: 
                    132:             route->upstrState = ROUTESTATE_JOINED;
                    133:         } else {
                    134:             my_log(LOG_DEBUG, 0, "No downstream listeners for group %s. No join sent.",
                    135:                 inetFmt(route->group, s1));
                    136:         }
                    137: 
                    138:     } else {
                    139:         // Only leave if group is not left already...
                    140:         if(route->upstrState != ROUTESTATE_NOTJOINED) {
                    141:             my_log(LOG_DEBUG, 0, "Leaving group %s upstream on IF address %s",
                    142:                          inetFmt(route->group, s1), 
                    143:                          inetFmt(upstrIf->InAdr.s_addr, s2));
                    144:             
                    145:             //k_leave(route->group, upstrIf->InAdr.s_addr);
                    146:             leaveMcGroup( getMcGroupSock(), upstrIf, route->group );
                    147: 
                    148:             route->upstrState = ROUTESTATE_NOTJOINED;
                    149:         }
                    150:     }
                    151: }
                    152: 
                    153: /**
                    154: *   Clear all routes from routing table, and alerts Leaves upstream.
                    155: */
                    156: void clearAllRoutes() {
                    157:     struct RouteTable   *croute, *remainroute;
                    158: 
                    159:     // Loop through all routes...
                    160:     for(croute = routing_table; croute; croute = remainroute) {
                    161: 
                    162:         remainroute = croute->nextroute;
                    163: 
                    164:         // Log the cleanup in debugmode...
                    165:         my_log(LOG_DEBUG, 0, "Removing route entry for %s",
                    166:                      inetFmt(croute->group, s1));
                    167: 
                    168:         // Uninstall current route
                    169:         if(!internUpdateKernelRoute(croute, 0)) {
                    170:             my_log(LOG_WARNING, 0, "The removal from Kernel failed.");
                    171:         }
                    172: 
                    173:         // Send Leave message upstream.
                    174:         sendJoinLeaveUpstream(croute, 0);
                    175: 
                    176:         // Clear memory, and set pointer to next route...
                    177:         free(croute);
                    178:     }
                    179:     routing_table = NULL;
                    180: 
                    181:     // Send a notice that the routing table is empty...
                    182:     my_log(LOG_NOTICE, 0, "All routes removed. Routing table is empty.");
                    183: }
                    184:                  
                    185: /**
                    186: *   Private access function to find a route from a given 
                    187: *   Route Descriptor.
                    188: */
                    189: struct RouteTable *findRoute(uint32_t group) {
                    190:     struct RouteTable*  croute;
                    191: 
                    192:     for(croute = routing_table; croute; croute = croute->nextroute) {
                    193:         if(croute->group == group) {
                    194:             return croute;
                    195:         }
                    196:     }
                    197: 
                    198:     return NULL;
                    199: }
                    200: 
                    201: /**
                    202: *   Adds a specified route to the routingtable.
                    203: *   If the route already exists, the existing route 
                    204: *   is updated...
                    205: */
                    206: int insertRoute(uint32_t group, int ifx) {
                    207:     
                    208:     struct Config *conf = getCommonConfig();
                    209:     struct RouteTable*  croute;
                    210: 
                    211:     // Sanitycheck the group adress...
                    212:     if( ! IN_MULTICAST( ntohl(group) )) {
                    213:         my_log(LOG_WARNING, 0, "The group address %s is not a valid Multicast group. Table insert failed.",
                    214:             inetFmt(group, s1));
                    215:         return 0;
                    216:     }
                    217: 
                    218:     // Santiycheck the VIF index...
                    219:     //if(ifx < 0 || ifx >= MAX_MC_VIFS) {
                    220:     if(ifx >= MAX_MC_VIFS) {
                    221:         my_log(LOG_WARNING, 0, "The VIF Ix %d is out of range (0-%d). Table insert failed.",ifx,MAX_MC_VIFS);
                    222:         return 0;
                    223:     }
                    224: 
                    225:     // Try to find an existing route for this group...
                    226:     croute = findRoute(group);
                    227:     if(croute==NULL) {
                    228:         struct RouteTable*  newroute;
                    229: 
                    230:         my_log(LOG_DEBUG, 0, "No existing route for %s. Create new.",
                    231:                      inetFmt(group, s1));
                    232: 
                    233: 
                    234:         // Create and initialize the new route table entry..
                    235:         newroute = (struct RouteTable*)malloc(sizeof(struct RouteTable));
                    236:         // Insert the route desc and clear all pointers...
                    237:         newroute->group      = group;
                    238:         newroute->originAddr = 0;
                    239:         newroute->nextroute  = NULL;
                    240:         newroute->prevroute  = NULL;
                    241: 
                    242:         // The group is not joined initially.
                    243:         newroute->upstrState = ROUTESTATE_NOTJOINED;
                    244: 
                    245:         // The route is not active yet, so the age is unimportant.
                    246:         newroute->ageValue    = conf->robustnessValue;
                    247:         newroute->ageActivity = 0;
                    248:         
                    249:         BIT_ZERO(newroute->ageVifBits);     // Initially we assume no listeners.
                    250: 
                    251:         // Set the listener flag...
                    252:         BIT_ZERO(newroute->vifBits);    // Initially no listeners...
                    253:         if(ifx >= 0) {
                    254:             BIT_SET(newroute->vifBits, ifx);
                    255:         }
                    256: 
                    257:         // Check if there is a table already....
                    258:         if(routing_table == NULL) {
                    259:             // No location set, so insert in on the table top.
                    260:             routing_table = newroute;
                    261:             my_log(LOG_DEBUG, 0, "No routes in table. Insert at beginning.");
                    262:         } else {
                    263: 
                    264:             my_log(LOG_DEBUG, 0, "Found existing routes. Find insert location.");
                    265: 
                    266:             // Check if the route could be inserted at the beginning...
                    267:             if(routing_table->group > group) {
                    268:                 my_log(LOG_DEBUG, 0, "Inserting at beginning, before route %s",inetFmt(routing_table->group,s1));
                    269: 
                    270:                 // Insert at beginning...
                    271:                 newroute->nextroute = routing_table;
                    272:                 newroute->prevroute = NULL;
                    273:                 routing_table = newroute;
                    274: 
                    275:                 // If the route has a next node, the previous pointer must be updated.
                    276:                 if(newroute->nextroute != NULL) {
                    277:                     newroute->nextroute->prevroute = newroute;
                    278:                 }
                    279: 
                    280:             } else {
                    281: 
                    282:                 // Find the location which is closest to the route.
                    283:                 for( croute = routing_table; croute->nextroute != NULL; croute = croute->nextroute ) {
                    284:                     // Find insert position.
                    285:                     if(croute->nextroute->group > group) {
                    286:                         break;
                    287:                     }
                    288:                 }
                    289: 
                    290:                 my_log(LOG_DEBUG, 0, "Inserting after route %s",inetFmt(croute->group,s1));
                    291:                 
                    292:                 // Insert after current...
                    293:                 newroute->nextroute = croute->nextroute;
                    294:                 newroute->prevroute = croute;
                    295:                 if(croute->nextroute != NULL) {
                    296:                     croute->nextroute->prevroute = newroute; 
                    297:                 }
                    298:                 croute->nextroute = newroute;
                    299:             }
                    300:         }
                    301: 
                    302:         // Set the new route as the current...
                    303:         croute = newroute;
                    304: 
                    305:         // Log the cleanup in debugmode...
                    306:         my_log(LOG_INFO, 0, "Inserted route table entry for %s on VIF #%d",
                    307:             inetFmt(croute->group, s1),ifx);
                    308: 
                    309:     } else if(ifx >= 0) {
                    310: 
                    311:         // The route exists already, so just update it.
                    312:         BIT_SET(croute->vifBits, ifx);
                    313:         
                    314:         // Register the VIF activity for the aging routine
                    315:         BIT_SET(croute->ageVifBits, ifx);
                    316: 
                    317:         // Log the cleanup in debugmode...
                    318:         my_log(LOG_INFO, 0, "Updated route entry for %s on VIF #%d",
                    319:             inetFmt(croute->group, s1), ifx);
                    320: 
                    321:         // If the route is active, it must be reloaded into the Kernel..
                    322:         if(croute->originAddr != 0) {
                    323: 
                    324:             // Update route in kernel...
                    325:             if(!internUpdateKernelRoute(croute, 1)) {
                    326:                 my_log(LOG_WARNING, 0, "The insertion into Kernel failed.");
                    327:                 return 0;
                    328:             }
                    329:         }
                    330:     }
                    331: 
                    332:     // Send join message upstream, if the route has no joined flag...
                    333:     if(croute->upstrState != ROUTESTATE_JOINED) {
                    334:         // Send Join request upstream
                    335:         sendJoinLeaveUpstream(croute, 1);
                    336:     }
                    337: 
                    338:     logRouteTable("Insert Route");
                    339: 
                    340:     return 1;
                    341: }
                    342: 
                    343: /**
                    344: *   Activates a passive group. If the group is already
                    345: *   activated, it's reinstalled in the kernel. If
                    346: *   the route is activated, no originAddr is needed.
                    347: */
                    348: int activateRoute(uint32_t group, uint32_t originAddr) {
                    349:     struct RouteTable*  croute;
                    350:     int result = 0;
                    351: 
                    352:     // Find the requested route.
                    353:     croute = findRoute(group);
                    354:     if(croute == NULL) {
                    355:         my_log(LOG_DEBUG, 0,
                    356:                "No table entry for %s [From: %s]. Inserting route.",
                    357:                inetFmt(group, s1),inetFmt(originAddr, s2));
                    358: 
                    359:         // Insert route, but no interfaces have yet requested it downstream.
                    360:         insertRoute(group, -1);
                    361: 
                    362:         // Retrieve the route from table...
                    363:         croute = findRoute(group);
                    364:     }
                    365: 
                    366:     if(croute != NULL) {
                    367:         // If the origin address is set, update the route data.
                    368:         if(originAddr > 0) {
                    369:             if(croute->originAddr > 0 && croute->originAddr!=originAddr) {
                    370:                 my_log(LOG_WARNING, 0, "The origin for route %s changed from %s to %s",
                    371:                     inetFmt(croute->group, s1),
                    372:                     inetFmt(croute->originAddr, s2),
                    373:                     inetFmt(originAddr, s3));
                    374:             }
                    375:             croute->originAddr = originAddr;
                    376:         }
                    377: 
                    378:         // Only update kernel table if there are listeners !
                    379:         if(croute->vifBits > 0) {
                    380:             result = internUpdateKernelRoute(croute, 1);
                    381:         }
                    382:     }
                    383:     logRouteTable("Activate Route");
                    384: 
                    385:     return result;
                    386: }
                    387: 
                    388: 
                    389: /**
                    390: *   This function loops through all routes, and updates the age 
                    391: *   of any active routes.
                    392: */
                    393: void ageActiveRoutes() {
                    394:     struct RouteTable   *croute, *nroute;
                    395:     
                    396:     my_log(LOG_DEBUG, 0, "Aging routes in table.");
                    397: 
                    398:     // Scan all routes...
                    399:     for( croute = routing_table; croute != NULL; croute = nroute ) {
                    400:         
                    401:         // Keep the next route (since current route may be removed)...
                    402:         nroute = croute->nextroute;
                    403: 
                    404:         // Run the aging round algorithm.
                    405:         if(croute->upstrState != ROUTESTATE_CHECK_LAST_MEMBER) {
                    406:             // Only age routes if Last member probe is not active...
                    407:             internAgeRoute(croute);
                    408:         }
                    409:     }
                    410:     logRouteTable("Age active routes");
                    411: }
                    412: 
                    413: /**
                    414: *   Should be called when a leave message is recieved, to
                    415: *   mark a route for the last member probe state.
                    416: */
                    417: void setRouteLastMemberMode(uint32_t group) {
                    418:     struct Config       *conf = getCommonConfig();
                    419:     struct RouteTable   *croute;
                    420: 
                    421:     croute = findRoute(group);
                    422:     if(croute!=NULL) {
                    423:         // Check for fast leave mode...
                    424:         if(croute->upstrState == ROUTESTATE_JOINED && conf->fastUpstreamLeave) {
                    425:             // Send a leave message right away..
                    426:             sendJoinLeaveUpstream(croute, 0);
                    427:         }
                    428:         // Set the routingstate to Last member check...
                    429:         croute->upstrState = ROUTESTATE_CHECK_LAST_MEMBER;
                    430:         // Set the count value for expiring... (-1 since first aging)
                    431:         croute->ageValue = conf->lastMemberQueryCount;
                    432:     }
                    433: }
                    434: 
                    435: 
                    436: /**
                    437: *   Ages groups in the last member check state. If the
                    438: *   route is not found, or not in this state, 0 is returned.
                    439: */
                    440: int lastMemberGroupAge(uint32_t group) {
                    441:     struct RouteTable   *croute;
                    442: 
                    443:     croute = findRoute(group);
                    444:     if(croute!=NULL) {
                    445:         if(croute->upstrState == ROUTESTATE_CHECK_LAST_MEMBER) {
                    446:             return !internAgeRoute(croute);
                    447:         } else {
                    448:             return 0;
                    449:         }
                    450:     }
                    451:     return 0;
                    452: }
                    453: 
                    454: /**
                    455: *   Remove a specified route. Returns 1 on success,
                    456: *   and 0 if route was not found.
                    457: */
                    458: int removeRoute(struct RouteTable*  croute) {
                    459:     struct Config       *conf = getCommonConfig();
                    460:     int result = 1;
                    461:     
                    462:     // If croute is null, no routes was found.
                    463:     if(croute==NULL) {
                    464:         return 0;
                    465:     }
                    466: 
                    467:     // Log the cleanup in debugmode...
                    468:     my_log(LOG_DEBUG, 0, "Removed route entry for %s from table.",
                    469:                  inetFmt(croute->group, s1));
                    470: 
                    471:     //BIT_ZERO(croute->vifBits);
                    472: 
                    473:     // Uninstall current route from kernel
                    474:     if(!internUpdateKernelRoute(croute, 0)) {
                    475:         my_log(LOG_WARNING, 0, "The removal from Kernel failed.");
                    476:         result = 0;
                    477:     }
                    478: 
                    479:     // Send Leave request upstream if group is joined
                    480:     if(croute->upstrState == ROUTESTATE_JOINED || 
                    481:        (croute->upstrState == ROUTESTATE_CHECK_LAST_MEMBER && !conf->fastUpstreamLeave)) 
                    482:     {
                    483:         sendJoinLeaveUpstream(croute, 0);
                    484:     }
                    485: 
                    486:     // Update pointers...
                    487:     if(croute->prevroute == NULL) {
                    488:         // Topmost node...
                    489:         if(croute->nextroute != NULL) {
                    490:             croute->nextroute->prevroute = NULL;
                    491:         }
                    492:         routing_table = croute->nextroute;
                    493: 
                    494:     } else {
                    495:         croute->prevroute->nextroute = croute->nextroute;
                    496:         if(croute->nextroute != NULL) {
                    497:             croute->nextroute->prevroute = croute->prevroute;
                    498:         }
                    499:     }
                    500:     // Free the memory, and set the route to NULL...
                    501:     free(croute);
                    502:     croute = NULL;
                    503: 
                    504:     logRouteTable("Remove route");
                    505: 
                    506:     return result;
                    507: }
                    508: 
                    509: 
                    510: /**
                    511: *   Ages a specific route
                    512: */
                    513: int internAgeRoute(struct RouteTable*  croute) {
                    514:     struct Config *conf = getCommonConfig();
                    515:     int result = 0;
                    516: 
                    517:     // Drop age by 1.
                    518:     croute->ageValue--;
                    519: 
                    520:     // Check if there has been any activity...
                    521:     if( croute->ageVifBits > 0 && croute->ageActivity == 0 ) {
                    522:         // There was some activity, check if all registered vifs responded.
                    523:         if(croute->vifBits == croute->ageVifBits) {
                    524:             // Everything is in perfect order, so we just update the route age.
                    525:             croute->ageValue = conf->robustnessValue;
                    526:             //croute->ageActivity = 0;
                    527:         } else {
                    528:             // One or more VIF has not gotten any response.
                    529:             croute->ageActivity++;
                    530: 
                    531:             // Update the actual bits for the route...
                    532:             croute->vifBits = croute->ageVifBits;
                    533:         }
                    534:     } 
                    535:     // Check if there have been activity in aging process...
                    536:     else if( croute->ageActivity > 0 ) {
                    537: 
                    538:         // If the bits are different in this round, we must
                    539:         if(croute->vifBits != croute->ageVifBits) {
                    540:             // Or the bits together to insure we don't lose any listeners.
                    541:             croute->vifBits |= croute->ageVifBits;
                    542: 
                    543:             // Register changes in this round as well..
                    544:             croute->ageActivity++;
                    545:         }
                    546:     }
                    547: 
                    548:     // If the aging counter has reached zero, its time for updating...
                    549:     if(croute->ageValue == 0) {
                    550:         // Check for activity in the aging process,
                    551:         if(croute->ageActivity>0) {
                    552:             
                    553:             my_log(LOG_DEBUG, 0, "Updating route after aging : %s",
                    554:                          inetFmt(croute->group,s1));
                    555:             
                    556:             // Just update the routing settings in kernel...
                    557:             internUpdateKernelRoute(croute, 1);
                    558:     
                    559:             // We append the activity counter to the age, and continue...
                    560:             croute->ageValue = croute->ageActivity;
                    561:             croute->ageActivity = 0;
                    562:         } else {
                    563: 
                    564:             my_log(LOG_DEBUG, 0, "Removing group %s. Died of old age.",
                    565:                          inetFmt(croute->group,s1));
                    566: 
                    567:             // No activity was registered within the timelimit, so remove the route.
                    568:             removeRoute(croute);
                    569:         }
                    570:         // Tell that the route was updated...
                    571:         result = 1;
                    572:     }
                    573: 
                    574:     // The aging vif bits must be reset for each round...
                    575:     BIT_ZERO(croute->ageVifBits);
                    576: 
                    577:     return result;
                    578: }
                    579: 
                    580: /**
                    581: *   Updates the Kernel routing table. If activate is 1, the route
                    582: *   is (re-)activated. If activate is false, the route is removed.
                    583: */
                    584: int internUpdateKernelRoute(struct RouteTable *route, int activate) {
                    585:     struct   MRouteDesc     mrDesc;
                    586:     struct   IfDesc         *Dp;
                    587:     unsigned                Ix;
                    588:     
                    589:     if(route->originAddr>0) {
                    590: 
                    591:         // Build route descriptor from table entry...
                    592:         // Set the source address and group address...
                    593:         mrDesc.McAdr.s_addr     = route->group;
                    594:         mrDesc.OriginAdr.s_addr = route->originAddr;
                    595:     
                    596:         // clear output interfaces 
                    597:         memset( mrDesc.TtlVc, 0, sizeof( mrDesc.TtlVc ) );
                    598:     
                    599:         my_log(LOG_DEBUG, 0, "Vif bits : 0x%08x", route->vifBits);
                    600: 
                    601:         // Set the TTL's for the route descriptor...
                    602:         for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) {
                    603:             if(Dp->state == IF_STATE_UPSTREAM) {
                    604:                 mrDesc.InVif = Dp->index;
                    605:             }
                    606:             else if(BIT_TST(route->vifBits, Dp->index)) {
                    607:                 my_log(LOG_DEBUG, 0, "Setting TTL for Vif %d to %d", Dp->index, Dp->threshold);
                    608:                 mrDesc.TtlVc[ Dp->index ] = Dp->threshold;
                    609:             }
                    610:         }
                    611:     
                    612:         // Do the actual Kernel route update...
                    613:         if(activate) {
                    614:             // Add route in kernel...
                    615:             addMRoute( &mrDesc );
                    616:     
                    617:         } else {
                    618:             // Delete the route from Kernel...
                    619:             delMRoute( &mrDesc );
                    620:         }
                    621: 
                    622:     } else {
                    623:         my_log(LOG_NOTICE, 0, "Route is not active. No kernel updates done.");
                    624:     }
                    625: 
                    626:     return 1;
                    627: }
                    628: 
                    629: /**
                    630: *   Debug function that writes the routing table entries
                    631: *   to the log.
                    632: */
                    633: void logRouteTable(char *header) {
                    634:         struct RouteTable*  croute = routing_table;
                    635:         unsigned            rcount = 0;
                    636:     
                    637:         my_log(LOG_DEBUG, 0, "");
                    638:         my_log(LOG_DEBUG, 0, "Current routing table (%s):", header);
                    639:         my_log(LOG_DEBUG, 0, "-----------------------------------------------------");
                    640:         if(croute==NULL) {
                    641:             my_log(LOG_DEBUG, 0, "No routes in table...");
                    642:         } else {
                    643:             do {
                    644:                 /*
                    645:                 my_log(LOG_DEBUG, 0, "#%d: Src: %s, Dst: %s, Age:%d, St: %s, Prev: 0x%08x, T: 0x%08x, Next: 0x%08x",
                    646:                     rcount, inetFmt(croute->originAddr, s1), inetFmt(croute->group, s2),
                    647:                     croute->ageValue,(croute->originAddr>0?"A":"I"),
                    648:                     croute->prevroute, croute, croute->nextroute);
                    649:                 */
                    650:                 my_log(LOG_DEBUG, 0, "#%d: Src: %s, Dst: %s, Age:%d, St: %s, OutVifs: 0x%08x",
                    651:                     rcount, inetFmt(croute->originAddr, s1), inetFmt(croute->group, s2),
                    652:                     croute->ageValue,(croute->originAddr>0?"A":"I"),
                    653:                     croute->vifBits);
                    654:                   
                    655:                 croute = croute->nextroute; 
                    656:         
                    657:                 rcount++;
                    658:             } while ( croute != NULL );
                    659:         }
                    660:     
                    661:         my_log(LOG_DEBUG, 0, "-----------------------------------------------------");
                    662: }

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