/** * Activates a passive group. If the group is already * activated, it's reinstalled in the kernel. If * the route is activated, no originAddr is needed. */ int activateRoute(uint32_t group, uint32_t originAddr) { struct RouteTable* croute; int result = 0; // Find the requested route. croute = findRoute(group); if(croute == NULL) { my_log(LOG_DEBUG, 0, "No table entry for %s [From: %s]. Inserting route.", inetFmt(group, s1),inetFmt(originAddr, s2)); // Insert route, but no interfaces have yet requested it downstream. insertRoute(group, -1); // Retrieve the route from table... croute = findRoute(group); } if(croute != NULL) { // If the origin address is set, update the route data. if(originAddr > 0) { // find this origin, or an unused slot int i; for (i = 0; i < MAX_ORIGINS; i++) { // unused slots are at the bottom, so we can't miss this origin if (croute->originAddrs[i] == originAddr || croute->originAddrs[i] == 0) { break; } } if (i == MAX_ORIGINS) { i = MAX_ORIGINS - 1; my_log(LOG_WARNING, 0, "Too many origins for route %s; replacing %s with %s", inetFmt(croute->group, s1), inetFmt(croute->originAddrs[i], s2), inetFmt(originAddr, s3)); } // set origin croute->originAddrs[i] = originAddr; // move it to the top while (i > 0) { uint32_t t = croute->originAddrs[i - 1]; croute->originAddrs[i - 1] = croute->originAddrs[i]; croute->originAddrs[i] = t; i--; } } // Only update kernel table if there are listeners ! if(croute->vifBits > 0) { result = internUpdateKernelRoute(croute, 1); } } logRouteTable("Activate Route"); return result; }
/** * Clear all routes from routing table, and alerts Leaves upstream. */ void clearAllRoutes() { struct RouteTable *croute, *remainroute; // Loop through all routes... for(croute = routing_table; croute; croute = remainroute) { remainroute = croute->nextroute; // Log the cleanup in debugmode... my_log(LOG_DEBUG, 0, "Removing route entry for %s", inetFmt(croute->group, s1)); // Uninstall current route if(!internUpdateKernelRoute(croute, 0)) { my_log(LOG_WARNING, 0, "The removal from Kernel failed."); } // Send Leave message upstream. sendJoinLeaveUpstream(croute, 0); // Clear memory, and set pointer to next route... free(croute); } routing_table = NULL; // Send a notice that the routing table is empty... my_log(LOG_NOTICE, 0, "All routes removed. Routing table is empty."); }
/** * Activates a passive group. If the group is already * activated, it's reinstalled in the kernel. If * the route is activated, no originAddr is needed. */ int activateRoute(struct in6_addr * group, struct in6_addr * originAddr) { int result = 0; struct RouteTable* croute; struct RouteTable* newroute; // Find the requested route. croute = findRoute(group, originAddr); if(croute != NULL) return 0; croute = findRoute(group, &allzero_addr); if (croute) { newroute = (struct RouteTable*)malloc(sizeof(struct RouteTable)); *newroute = *croute; newroute->originAddr = *originAddr; newroute->nextroute = routing_table; newroute->prevroute = NULL; routing_table->prevroute = newroute; routing_table = newroute; if( !internUpdateKernelRoute(newroute, 1) ) { atlog(LOG_WARNING, 0, "The insertion into Kernel failed."); return 0; } } return 1; }
/** * Remove a specified route. Returns 1 on success, * and 0 if route was not found. */ int removeRoute(struct RouteTable* croute) { struct Config *conf = getCommonConfig(); int result = 1; // If croute is null, no routes was found. if(croute==NULL) { return 0; } // Log the cleanup in debugmode... my_log(LOG_DEBUG, 0, "Removed route entry for %s from table.", inetFmt(croute->group, s1)); //BIT_ZERO(croute->vifBits); // Uninstall current route from kernel if(!internUpdateKernelRoute(croute, 0)) { my_log(LOG_WARNING, 0, "The removal from Kernel failed."); result = 0; } // Send Leave request upstream if group is joined if(croute->upstrState == ROUTESTATE_JOINED || (croute->upstrState == ROUTESTATE_CHECK_LAST_MEMBER && !conf->fastUpstreamLeave)) { sendJoinLeaveUpstream(croute, 0); } // Update pointers... if(croute->prevroute == NULL) { // Topmost node... if(croute->nextroute != NULL) { croute->nextroute->prevroute = NULL; } routing_table = croute->nextroute; } else { croute->prevroute->nextroute = croute->nextroute; if(croute->nextroute != NULL) { croute->nextroute->prevroute = croute->prevroute; } } // Free the memory, and set the route to NULL... free(croute); croute = NULL; logRouteTable("Remove route"); return result; }
/** * Ages a specific route */ int internAgeRoute(struct RouteTable* croute) { struct Config *conf = getCommonConfig(); int result = 0; // Drop age by 1. croute->ageValue--; // Check if there has been any activity... if( croute->ageVifBits > 0 && croute->ageActivity == 0 ) { // There was some activity, check if all registered vifs responded. if(croute->vifBits == croute->ageVifBits) { // Everything is in perfect order, so we just update the route age. croute->ageValue = conf->robustnessValue; //croute->ageActivity = 0; } else { // One or more VIF has not gotten any response. croute->ageActivity++; // Update the actual bits for the route... croute->vifBits = croute->ageVifBits; } } // Check if there have been activity in aging process... else if( croute->ageActivity > 0 ) { // If the bits are different in this round, we must if(croute->vifBits != croute->ageVifBits) { // Or the bits together to insure we don't lose any listeners. croute->vifBits |= croute->ageVifBits; // Register changes in this round as well.. croute->ageActivity++; } } // If the aging counter has reached zero, its time for updating... if(croute->ageValue == 0) { // Check for activity in the aging process, if(croute->ageActivity>0) { my_log(LOG_DEBUG, 0, "Updating route after aging : %s", inetFmt(croute->group,s1)); // Just update the routing settings in kernel... internUpdateKernelRoute(croute, 1); // We append the activity counter to the age, and continue... croute->ageValue = croute->ageActivity; croute->ageActivity = 0; } else { my_log(LOG_DEBUG, 0, "Removing group %s. Died of old age.", inetFmt(croute->group,s1)); // No activity was registered within the timelimit, so remove the route. removeRoute(croute); } // Tell that the route was updated... result = 1; } // The aging vif bits must be reset for each round... BIT_ZERO(croute->ageVifBits); return result; }
/** * Adds a specified route to the routingtable. * If the route already exists, the existing route * is updated... */ int insertRoute(uint32_t group, int ifx) { struct Config *conf = getCommonConfig(); struct RouteTable* croute; // Sanitycheck the group adress... if( ! IN_MULTICAST( ntohl(group) )) { my_log(LOG_WARNING, 0, "The group address %s is not a valid Multicast group. Table insert failed.", inetFmt(group, s1)); return 0; } // Santiycheck the VIF index... //if(ifx < 0 || ifx >= MAX_MC_VIFS) { if(ifx >= MAX_MC_VIFS) { my_log(LOG_WARNING, 0, "The VIF Ix %d is out of range (0-%d). Table insert failed.",ifx,MAX_MC_VIFS); return 0; } // Try to find an existing route for this group... croute = findRoute(group); if(croute==NULL) { struct RouteTable* newroute; my_log(LOG_DEBUG, 0, "No existing route for %s. Create new.", inetFmt(group, s1)); // Create and initialize the new route table entry.. newroute = (struct RouteTable*)malloc(sizeof(struct RouteTable)); // Insert the route desc and clear all pointers... newroute->group = group; memset(newroute->originAddrs, 0, MAX_ORIGINS * sizeof(newroute->originAddrs[0])); newroute->nextroute = NULL; newroute->prevroute = NULL; // The group is not joined initially. newroute->upstrState = ROUTESTATE_NOTJOINED; // The route is not active yet, so the age is unimportant. newroute->ageValue = conf->robustnessValue; newroute->ageActivity = 0; BIT_ZERO(newroute->ageVifBits); // Initially we assume no listeners. // Set the listener flag... BIT_ZERO(newroute->vifBits); // Initially no listeners... if(ifx >= 0) { BIT_SET(newroute->vifBits, ifx); } // Check if there is a table already.... if(routing_table == NULL) { // No location set, so insert in on the table top. routing_table = newroute; my_log(LOG_DEBUG, 0, "No routes in table. Insert at beginning."); } else { my_log(LOG_DEBUG, 0, "Found existing routes. Find insert location."); // Check if the route could be inserted at the beginning... if(routing_table->group > group) { my_log(LOG_DEBUG, 0, "Inserting at beginning, before route %s",inetFmt(routing_table->group,s1)); // Insert at beginning... newroute->nextroute = routing_table; newroute->prevroute = NULL; routing_table = newroute; // If the route has a next node, the previous pointer must be updated. if(newroute->nextroute != NULL) { newroute->nextroute->prevroute = newroute; } } else { // Find the location which is closest to the route. for( croute = routing_table; croute->nextroute != NULL; croute = croute->nextroute ) { // Find insert position. if(croute->nextroute->group > group) { break; } } my_log(LOG_DEBUG, 0, "Inserting after route %s",inetFmt(croute->group,s1)); // Insert after current... newroute->nextroute = croute->nextroute; newroute->prevroute = croute; if(croute->nextroute != NULL) { croute->nextroute->prevroute = newroute; } croute->nextroute = newroute; } } // Set the new route as the current... croute = newroute; // Log the cleanup in debugmode... my_log(LOG_INFO, 0, "Inserted route table entry for %s on VIF #%d", inetFmt(croute->group, s1),ifx); } else if(ifx >= 0) { // The route exists already, so just update it. BIT_SET(croute->vifBits, ifx); // Register the VIF activity for the aging routine BIT_SET(croute->ageVifBits, ifx); // Log the cleanup in debugmode... my_log(LOG_INFO, 0, "Updated route entry for %s on VIF #%d", inetFmt(croute->group, s1), ifx); // Update route in kernel... if(!internUpdateKernelRoute(croute, 1)) { my_log(LOG_WARNING, 0, "The insertion into Kernel failed."); return 0; } } // Send join message upstream, if the route has no joined flag... if(croute->upstrState != ROUTESTATE_JOINED) { // Send Join request upstream sendJoinLeaveUpstream(croute, 1); } logRouteTable("Insert Route"); return 1; }
/** * Remove a specified route. Returns 1 on success, * and 0 if route was not found. */ int removeRoute(struct RouteTable* croute) { int result = 1; struct RouteTable* tmpRoute; struct Config *conf = getCommonConfig(); // If croute is null, no routes was found. if(croute==NULL) return 0; //printf("removeRoute called\n"); //BIT_ZERO(croute->vifBits); // Uninstall current route from kernel if(!internUpdateKernelRoute(croute, 0)) { //printf("The removal from Kernel failed.\n"); atlog(LOG_WARNING, 0, "The removal from Kernel failed."); result = 0; } // Send Leave request upstream if group is joined if(croute->upstrState == ROUTESTATE_JOINED || (croute->upstrState == ROUTESTATE_CHECK_LAST_MEMBER && !conf->fastUpstreamLeave)) { tmpRoute = findNextRoute( &(croute->group), NULL); if (tmpRoute && tmpRoute->nextroute) tmpRoute = findNextRoute( &(croute->group), tmpRoute->nextroute); // the group is not used by others if (tmpRoute == NULL) sendJoinLeaveUpstream(croute, 0); } // Update pointers... if(croute->prevroute == NULL) { // Topmost node... if(croute->nextroute != NULL) { croute->nextroute->prevroute = NULL; } routing_table = croute->nextroute; } else { croute->prevroute->nextroute = croute->nextroute; if(croute->nextroute != NULL) { croute->nextroute->prevroute = croute->prevroute; } } // Free the memory, and set the route to NULL... free(croute); croute = NULL; IF_DEBUG atlogRouteTable("Remove route"); return result; }
/** * Adds a specified route to the routingtable. * If the route already exists, the existing route * is updated... */ int insertRoute(struct in6_addr *group, struct in6_addr *src, struct sockaddr_in6 *from) { struct Config *conf = getCommonConfig(); struct RouteTable *croute, *tmpRoute; //int result = 1; /* int i; printf("insertRoute called\n"); for (i = 0; i < 16; i ++) printf("%02x ", ((char*)group)[i] & 255 ); printf("\n"); for (i = 0; i < 16; i ++) printf("%02x ", ((char*)src)[i] & 255 ); printf("\n"); */ // Sanitycheck the group adress... if ( !IN6_IS_ADDR_MULTICAST(group) ) { atlog( LOG_DEBUG, 0, "Not multicast group"); return 0; } // Santiycheck the VIF index... if(from->sin6_scope_id >= MAX_MC_VIFS) { atlog(LOG_WARNING, 0, "The VIF Ix %d is out of range (0-%d). Table insert failed.", from->sin6_scope_id,MAX_MC_VIFS); return 0; } // Try to find an existing route for this group... croute = findRoute(group, src); if(croute==NULL) { struct RouteTable* newroute; /* IF_DEBUG atlog(LOG_DEBUG, 0, "No existing route for %s. Create new.", inetFmt(group, s1)); */ // Create and initialize the new route table entry.. newroute = (struct RouteTable*)malloc(sizeof(struct RouteTable)); // Insert the route desc and clear all pointers... newroute->group = *group; newroute->originAddr = *src; newroute->nextroute = NULL; newroute->prevroute = NULL; // The group is not joined initially. newroute->upstrState = ROUTESTATE_NOTJOINED; // The route is not active yet, so the age is unimportant. newroute->ageValue = conf->robustnessValue; newroute->ageActivity = 0; BIT_ZERO(newroute->ageVifBits); // Initially we assume no listeners. // Set the listener flag... BIT_ZERO(newroute->vifBits); // Initially no listeners... if(from->sin6_scope_id >= 0) { BIT_SET(newroute->vifBits, from->sin6_scope_id); } // Check if there is a table already.... if(routing_table == NULL) { // No location set, so insert in on the table top. routing_table = newroute; IF_DEBUG atlog(LOG_DEBUG, 0, "No routes in table. Insert at beginning."); } else { IF_DEBUG atlog(LOG_DEBUG, 0, "Found existing routes. Find insert location."); // Check if the route could be inserted at the beginning... if( memcmp(&routing_table->group, group, sizeof(struct in6_addr)) > 0 ) { //IF_DEBUG atlog(LOG_DEBUG, 0, "Inserting at beginning, before route %s",inetFmt(routing_table->group,s1)); // Insert at beginning... newroute->nextroute = routing_table; newroute->prevroute = NULL; routing_table = newroute; // If the route has a next node, the previous pointer must be updated. if(newroute->nextroute != NULL) { newroute->nextroute->prevroute = newroute; } } else { // Find the location which is closest to the route. for( croute = routing_table; croute->nextroute != NULL; croute = croute->nextroute ) { // Find insert position. if( memcmp( &(croute->nextroute->group), group, sizeof(struct in6_addr) ) > 0 ) break; } //IF_DEBUG atlog(LOG_DEBUG, 0, "Inserting after route %s",inetFmt(croute->group,s1)); // Insert after current... newroute->nextroute = croute->nextroute; newroute->prevroute = croute; if(croute->nextroute != NULL) { croute->nextroute->prevroute = newroute; } croute->nextroute = newroute; } } // Set the new route as the current... croute = newroute; if( !IN6_ARE_ADDR_EQUAL( &croute->originAddr, &allzero_addr) ) { // Update route in kernel... if( !internUpdateKernelRoute(croute, 1) ) { atlog(LOG_WARNING, 0, "The insertion into Kernel failed."); return 0; } } } else if(from->sin6_scope_id >= 0) { if( !IN6_ARE_ADDR_EQUAL( &croute->originAddr, &allzero_addr) ) { // The route exists already, so just update it. BIT_SET(croute->vifBits, from->sin6_scope_id); // Register the VIF activity for the aging routine BIT_SET(croute->ageVifBits, from->sin6_scope_id); } else { tmpRoute = findNextRoute(group, NULL); while (tmpRoute != NULL) { // The route exists already, so just update it. BIT_SET(tmpRoute->vifBits, from->sin6_scope_id); // Register the VIF activity for the aging routine BIT_SET(tmpRoute->ageVifBits, from->sin6_scope_id); if (tmpRoute->nextroute) tmpRoute = findNextRoute(group, tmpRoute->nextroute); else break; } } } // Send join message upstream, if the route has no joined flag... if(croute->upstrState != ROUTESTATE_JOINED) { // Send Join request upstream sendJoinLeaveUpstream(croute, 1); } IF_DEBUG atlogRouteTable("Insert Route"); return 1; }