📄 rttable.c
字号:
/*** igmpproxy - IGMP proxy based multicast router ** Copyright (C) 2005 Johnny Egeland <johnny@rlo.org>**** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License as published by** the Free Software Foundation; either version 2 of the License, or** (at your option) any later version.**** This program is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the** GNU General Public License for more details.**** You should have received a copy of the GNU General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA****----------------------------------------------------------------------------**** This software is derived work from the following software. The original** source code has been modified from it's original state by the author** of igmpproxy.**** smcroute 0.92 - Copyright (C) 2001 Carsten Schill <carsten@cschill.de>** - Licensed under the GNU General Public License, version 2** ** mrouted 3.9-beta3 - COPYRIGHT 1989 by The Board of Trustees of ** Leland Stanford Junior University.** - Original license can be found in the "doc/mrouted-LINCESE" file.***//*** rttable.c ** Updates the routingtable according to * recieved request.*/#include "defs.h" /*** Routing table structure definition. Double linked list...*/struct RouteTable { struct RouteTable *nextroute; // Pointer to the next group in line. struct RouteTable *prevroute; // Pointer to the previous group in line. uint32 group; // The group to route uint32 originAddr; // The origin adress (only set on activated routes) uint32 vifBits; // Bits representing recieving VIFs. // Keeps the upstream membership state... short upstrState; // Upstream membership state. // These parameters contain aging details. uint32 ageVifBits; // Bits representing aging VIFs. int ageValue; // Downcounter for death. int ageActivity; // Records any acitivity that notes there are still listeners.}; // Keeper for the routing table...static struct RouteTable *routing_table;// Prototypesvoid logRouteTable(char *header);int internAgeRoute(struct RouteTable* croute);// Socket for sending join or leave requests.int mcGroupSock = 0;/*** Function for retrieving the Multicast Group socket.*/int getMcGroupSock() { if( ! mcGroupSock ) { mcGroupSock = openUdpSocket( INADDR_ANY, 0 );; } return mcGroupSock;} /*** Initializes the routing table.*/void initRouteTable() { unsigned Ix; struct IfDesc *Dp; // Clear routing table... routing_table = NULL; // Join the all routers group on downstream vifs... for ( Ix = 0; Dp = getIfByIx( Ix ); Ix++ ) { // If this is a downstream vif, we should join the All routers group... if( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) && Dp->state == IF_STATE_DOWNSTREAM) { IF_DEBUG log(LOG_DEBUG, 0, "Joining all-routers group %s on vif %s", inetFmt(allrouters_group,s1),inetFmt(Dp->InAdr.s_addr,s2)); //k_join(allrouters_group, Dp->InAdr.s_addr); joinMcGroup( getMcGroupSock(), Dp, allrouters_group ); } }}/*** Internal function to send join or leave requests for* a specified route upstream...*/void sendJoinLeaveUpstream(struct RouteTable* route, int join) { struct IfDesc* upstrIf; // Get the upstream VIF... upstrIf = getIfByIx( upStreamVif ); if(upstrIf == NULL) { log(LOG_ERR, 0 ,"FATAL: Unable to get Upstream IF."); } /* IF_DEBUG { log(LOG_DEBUG, 0, "Upstream IF addr : %s", inetFmt(upstrIf->InAdr.s_addr,s1)); log(LOG_DEBUG, 0, "Upstream IF state : %d", upstrIf->state); log(LOG_DEBUG, 0, "Upstream IF index : %d", upstrIf->index); }*/ // Send join or leave request... if(join) { // Only join a group if there are listeners downstream... if(route->vifBits > 0) { IF_DEBUG log(LOG_DEBUG, 0, "Joining group %s upstream on IF address %s", inetFmt(route->group, s1), inetFmt(upstrIf->InAdr.s_addr, s2)); //k_join(route->group, upstrIf->InAdr.s_addr); joinMcGroup( getMcGroupSock(), upstrIf, route->group ); route->upstrState = ROUTESTATE_JOINED; } else IF_DEBUG { log(LOG_DEBUG, 0, "No downstream listeners for group %s. No join sent.", inetFmt(route->group, s1)); } } else { // Only leave if group is not left already... if(route->upstrState != ROUTESTATE_NOTJOINED) { IF_DEBUG log(LOG_DEBUG, 0, "Leaving group %s upstream on IF address %s", inetFmt(route->group, s1), inetFmt(upstrIf->InAdr.s_addr, s2)); //k_leave(route->group, upstrIf->InAdr.s_addr); leaveMcGroup( getMcGroupSock(), upstrIf, route->group ); route->upstrState = ROUTESTATE_NOTJOINED; } }}/*** 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... IF_DEBUG log(LOG_DEBUG, 0, "Removing route entry for %s", inetFmt(croute->group, s1)); // Uninstall current route if(!internUpdateKernelRoute(croute, 0)) { 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... log(LOG_NOTICE, 0, "All routes removed. Routing table is empty.");} /*** Private access function to find a route from a given * Route Descriptor.*/struct RouteTable *findRoute(uint32 group) { struct RouteTable* croute; for(croute = routing_table; croute; croute = croute->nextroute) { if(croute->group == group) { return croute; } } return NULL;}/*** Adds a specified route to the routingtable.* If the route already exists, the existing route * is updated...*/int insertRoute(uint32 group, int ifx) { struct Config *conf = getCommonConfig(); struct RouteTable* croute; int result = 1; // Sanitycheck the group adress... if( ! IN_MULTICAST( ntohl(group) )) { 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) { 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; IF_DEBUG 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; newroute->originAddr = 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; IF_DEBUG log(LOG_DEBUG, 0, "No routes in table. Insert at beginning."); } else { IF_DEBUG 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) { IF_DEBUG 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; } } IF_DEBUG 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... 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... log(LOG_INFO, 0, "Updated route entry for %s on VIF #%d", inetFmt(croute->group, s1), ifx); // If the route is active, it must be reloaded into the Kernel.. if(croute->originAddr != 0) { // Update route in kernel... if(!internUpdateKernelRoute(croute, 1)) { log(LOG_WARNING, 0, "The insertion into Kernel failed."); return 0; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -