Annotation of embedaddon/igmpproxy/src/rttable.c, revision 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>