From 9517ac5e34cf6d1a2fdb134e9dfbd9b9c1c3602b Mon Sep 17 00:00:00 2001 From: Sietse van Zanen Date: Tue, 26 May 2020 17:31:02 +0200 Subject: [PATCH] Changes to timing and igmpproxy This commit contains a number of changes to the timing structure and main event loops. Also several variables and structs were moved to igmpproxy.h in preperation to coming changes. Includes minor changes to config.c and request.c to include new blacklists for interfaces. callout.c is modified to a simpler and more stable algorithm. igmpproxy.h and igmpproxy.c are sanitized and adopted to the new callout queue. FIXES: https://github.com/pali/igmpproxy/issues/58 Fixed a few typos and comments Added sighup_action to struct Config --- src/callout.c | 214 +++++++++++------------------------------------- src/config.c | 25 +++--- src/igmpproxy.c | 174 +++++++++++++++------------------------ src/igmpproxy.h | 143 +++++++++++++++++++------------- src/request.c | 10 --- src/rttable.c | 2 - 6 files changed, 212 insertions(+), 356 deletions(-) diff --git a/src/callout.c b/src/callout.c index c49da6cf..11b652a4 100644 --- a/src/callout.c +++ b/src/callout.c @@ -37,91 +37,47 @@ /* the code below implements a callout queue */ static int id = 0; -static struct timeOutQueue *queue = 0; /* pointer to the beginning of timeout queue */ +static struct timeOutQueue *queue = NULL; /* pointer to the beginning of timeout queue */ struct timeOutQueue { - struct timeOutQueue *next; // Next event in queue int id; timer_f func; // function to call void *data; // Data for function - int time; // Time offset for next event + long time; // Time for event + struct timeOutQueue *next; // Next event in queue }; // Method for dumping the Queue to the log. static void debugQueue(void); -/** -* Initializes the callout queue -*/ -void callout_init(void) { - queue = NULL; -} - /** * Clears all scheduled timeouts... */ void free_all_callouts(void) { struct timeOutQueue *p; - - while (queue) { - p = queue; - queue = queue->next; - free(p); + for (p = queue ? queue->next : NULL; queue; queue = p, p = p ? p->next : NULL) { + free(queue); // Alloced by timer_setTimer() } + my_log(LOG_DEBUG, 0, "free_all_callouts: All Timeouts removed, Queue is empty."); } - /** - * elapsed_time seconds have passed; perform all the events that should - * happen. + * Execute all expired timers, using .5s grace. */ -void age_callout_queue(int elapsed_time) { - struct timeOutQueue *ptr; - struct timeOutQueue *_queue = NULL; - struct timeOutQueue *last = NULL; - int i = 0; - - for (ptr = queue; ptr; ptr = ptr->next) { - if (ptr->time > elapsed_time) { - ptr->time -= elapsed_time; - break; - } else { - elapsed_time -= ptr->time; - if (_queue == NULL) - _queue = ptr; - last = ptr; - } - } - - queue = ptr; - if (last) { - last->next = NULL; - } - - /* process existing events */ - for (ptr = _queue; ptr; ptr = _queue, i++) { - _queue = _queue->next; +void age_callout_queue(struct timespec curtime) { + struct timeOutQueue *ptr = queue; + int i = 1; + if (curtime.tv_sec == 0) clock_gettime (CLOCK_MONOTONIC, &curtime); + while (ptr && ((ptr->time <= curtime.tv_sec) || (curtime.tv_nsec >= 500000000 && ptr->time <= curtime.tv_sec-1))) { my_log(LOG_DEBUG, 0, "About to call timeout %d (#%d)", ptr->id, i); - if (ptr->func) - ptr->func(ptr->data); - free(ptr); - } -} - -/** - * Return in how many seconds age_callout_queue() would like to be called. - * Return -1 if there are no events pending. - */ -int timer_nextTimer(void) { - if (queue) { - if (queue->time < 0) { - my_log(LOG_WARNING, 0, "timer_nextTimer top of queue says %d", - queue->time); - return 0; + struct timeOutQueue *tmp = ptr; + if (ptr->func) { + ptr->func(ptr->data); } - return queue->time; + queue = ptr = ptr->next; + free(tmp); // Alloced by timer_setTimer() + i++; } - return -1; } /** @@ -131,61 +87,41 @@ int timer_nextTimer(void) { * @param data - Pointer to the function data to supply... */ int timer_setTimer(int delay, timer_f action, void *data) { - struct timeOutQueue *ptr, *node, *prev; - int i = 0; + struct timeOutQueue *ptr = queue, *node; + struct timespec curtime; + int i = 1; - /* create a node */ + // create a node. Freed by free_all_callouts() and age_callout_queue(). node = (struct timeOutQueue *)malloc(sizeof(struct timeOutQueue)); - if (node == 0) { + if (! node) { my_log(LOG_WARNING, 0, "Malloc Failed in timer_settimer\n"); return -1; } + clock_gettime(CLOCK_MONOTONIC, &curtime); node->func = action; node->data = data; - node->time = delay; - node->next = 0; + node->time = curtime.tv_sec + delay; node->id = ++id; + node->next = NULL; - prev = ptr = queue; - - /* insert node in the queue */ - - /* if the queue is empty, insert the node and return */ - if (!queue) { + if (! queue) { + // if the queue is empty, insert the node and return. queue = node; - } - else { - /* chase the pointer looking for the right place */ - while (ptr) { - if (delay < ptr->time) { - // We found the correct node - node->next = ptr; - if (ptr == queue) { - queue = node; - } - else { - prev->next = node; - } - ptr->time -= node->time; - my_log(LOG_DEBUG, 0, - "Created timeout %d (#%d) - delay %d secs", - node->id, i, node->time); - debugQueue(); - return node->id; - } else { - // Continur to check nodes. - delay -= ptr->time; node->time = delay; - prev = ptr; - ptr = ptr->next; - } - i++; + } else { + // chase the queue looking for the right place. + for (i++; ptr->next && node->time >= ptr->next->time; ptr = ptr->next, i++); + if (ptr == queue && node->time < ptr->time) { + // Start of queue, insert. + queue = node; + node->next = ptr; + } else { + node->next = ptr->next; + ptr->next = node; } - prev->next = node; } - my_log(LOG_DEBUG, 0, "Created timeout %d (#%d) - delay %d secs", - node->id, i, node->time); - debugQueue(); + debugQueue(); + my_log(LOG_DEBUG, 0, "Created timeout %d (#%d) - delay %d secs", node->id, i, delay); return node->id; } @@ -194,76 +130,22 @@ int timer_setTimer(int delay, timer_f action, void *data) { */ int timer_leftTimer(int timer_id) { struct timeOutQueue *ptr; - int left = 0; - - if (!timer_id) - return -1; - - for (ptr = queue; ptr; ptr = ptr->next) { - left += ptr->time; - if (ptr->id == timer_id) { - return left; - } + struct timespec curtime; + for (ptr = queue; ptr && ptr->id != timer_id; ptr = ptr->next); + if (ptr) { + clock_gettime(CLOCK_MONOTONIC, &curtime); + return (ptr->time - curtime.tv_sec); } return -1; } -/** -* clears the associated timer. Returns 1 if succeeded. -*/ -int timer_clearTimer(int timer_id) { - struct timeOutQueue *ptr, *prev; - int i = 0; - - if (!timer_id) - return 0; - - prev = ptr = queue; - - /* - * find the right node, delete it. the subsequent node's time - * gets bumped up - */ - - debugQueue(); - while (ptr) { - if (ptr->id == timer_id) { - /* got the right node */ - - /* unlink it from the queue */ - if (ptr == queue) - queue = queue->next; - else - prev->next = ptr->next; - - /* increment next node if any */ - if (ptr->next != 0) - (ptr->next)->time += ptr->time; - - if (ptr->data) - free(ptr->data); - my_log(LOG_DEBUG, 0, "deleted timer %d (#%d)", ptr->id, i); - free(ptr); - debugQueue(); - return 1; - } - prev = ptr; - ptr = ptr->next; - i++; - } - // If we get here, the timer was not deleted. - my_log(LOG_DEBUG, 0, "failed to delete timer %d (#%d)", timer_id, i); - debugQueue(); - return 0; -} - /** * debugging utility */ static void debugQueue(void) { struct timeOutQueue *ptr; - - for (ptr = queue; ptr; ptr = ptr->next) { - my_log(LOG_DEBUG, 0, "(Id:%d, Time:%d) ", ptr->id, ptr->time); + int i; + for (i = 1, ptr = queue; ptr; ptr = ptr->next, i++) { + my_log(LOG_DEBUG, 0, "(%d - Id:%d, Time:%d) ", i, ptr->id, ptr->time); } } diff --git a/src/config.c b/src/config.c index 030da1ac..878fb1c5 100644 --- a/src/config.c +++ b/src/config.c @@ -47,9 +47,11 @@ struct vifconfig { // Keep allowed nets for VIF. struct SubnetList* allowednets; + struct SubnetList* deniednets; // Allowed Groups struct SubnetList* allowedgroups; + struct SubnetList* deniedgroups; // Next config in list... struct vifconfig* next; @@ -226,32 +228,29 @@ void configureVifs(void) { } // Loop through all VIFs... - for ( Ix = 0; (Dp = getIfByIx(Ix)); Ix++ ) { - if ( Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK) ) { - + for (Ix = 0; (Dp = getIfByIx(Ix)); Ix++) { + if (Dp->InAdr.s_addr && ! (Dp->Flags & IFF_LOOPBACK)) { // Now try to find a matching config... - for( confPtr = vifconf; confPtr; confPtr = confPtr->next) { - + for (confPtr = vifconf; confPtr; confPtr = confPtr->next) { // I the VIF names match... - if(strcmp(Dp->Name, confPtr->name)==0) { + if (strcmp(Dp->Name, confPtr->name) == 0) { struct SubnetList *vifLast; my_log(LOG_DEBUG, 0, "Found config for %s", Dp->Name); - // Set the VIF state Dp->state = confPtr->state; - Dp->threshold = confPtr->threshold; Dp->ratelimit = confPtr->ratelimit; - // Go to last allowed net on VIF... - for(vifLast = Dp->allowednets; vifLast->next; vifLast = vifLast->next); - - // Insert the configured nets... + // Go to last allowed net on VIF and insert configured nets. + for (vifLast = Dp->allowednets; vifLast->next; vifLast = vifLast->next); vifLast->next = confPtr->allowednets; + // Link the black- and whitelists. + Dp->deniednets = confPtr->deniednets; Dp->allowedgroups = confPtr->allowedgroups; + Dp->deniedgroups = confPtr->deniedgroups; break; } @@ -290,7 +289,9 @@ struct vifconfig *parsePhyintToken(void) { tmpPtr->threshold = 1; tmpPtr->state = commonConfig.defaultInterfaceState; tmpPtr->allowednets = NULL; + tmpPtr->deniednets = NULL; tmpPtr->allowedgroups = NULL; + tmpPtr->deniedgroups = NULL; // Make a copy of the token to store the IF name tmpPtr->name = strdup( token ); diff --git a/src/igmpproxy.c b/src/igmpproxy.c index c72a567f..4ffc2b71 100644 --- a/src/igmpproxy.c +++ b/src/igmpproxy.c @@ -61,23 +61,19 @@ int igmpProxyInit(void); void igmpProxyCleanUp(void); void igmpProxyRun(void); -// Global vars... -static int sighandled = 0; -#define GOT_SIGINT 0x01 -#define GOT_SIGHUP 0x02 -#define GOT_SIGUSR1 0x04 -#define GOT_SIGUSR2 0x08 - // Holds the indeces of the upstream IF... int upStreamIfIdx[MAX_UPS_VIFS]; +// Global variables. +int sighandled = 0; +char *configFilePath; + /** * Program main method. Is invoked when the program is started * on commandline. The number of commandline arguments, and a * pointer to the arguments are received on the line... */ -int main( int ArgCn, char *ArgVc[] ) { - +int main(int ArgCn, char *ArgVc[]) { int c; bool NotAsDaemon = false; @@ -113,7 +109,7 @@ int main( int ArgCn, char *ArgVc[] ) { fputs("You must specify the configuration file.\n", stderr); exit(1); } - char *configFilePath = ArgVc[optind]; + configFilePath = ArgVc[optind]; // Chech that we are root if (geteuid() != 0) { @@ -126,41 +122,37 @@ int main( int ArgCn, char *ArgVc[] ) { // Write debug notice with file path... my_log(LOG_DEBUG, 0, "Searching for config file at '%s'" , configFilePath); - do { + // Loads the config file... + if (! loadConfig(configFilePath)) { + my_log(LOG_ERR, 0, "Unable to load config file..."); + exit(1); + } - // Loads the config file... - if( ! loadConfig( configFilePath ) ) { - my_log(LOG_ERR, 0, "Unable to load config file..."); - break; - } + // Initializes the deamon. + if (!igmpProxyInit()) { + my_log(LOG_ERR, 0, "Unable to initialize IGMPproxy."); + exit(1); + } - // Initializes the deamon. - if ( !igmpProxyInit() ) { - my_log(LOG_ERR, 0, "Unable to initialize IGMPproxy."); - break; + if (! NotAsDaemon) { + // Only daemon goes past this line... + if (fork()) { + exit(0); } - if ( !NotAsDaemon ) { - - // Only daemon goes past this line... - if (fork()) exit(0); - - // Detach daemon from terminal - if ( close( 0 ) < 0 || close( 1 ) < 0 || close( 2 ) < 0 - || open( "/dev/null", 0 ) != 0 || dup2( 0, 1 ) < 0 || dup2( 0, 2 ) < 0 - || setpgid( 0, 0 ) < 0 - ) { - my_log( LOG_ERR, errno, "failed to detach daemon" ); - } + // Detach daemon from terminal + if (close(0) < 0 || close(1) < 0 || close(2) < 0 + || open("/dev/null", 0) != 0 || dup2(0, 1) < 0 || dup2(0, 2) < 0 + || setpgid(0, 0) < 0) { + my_log( LOG_ERR, errno, "failed to detach daemon" ); } + } - // Go to the main loop. - igmpProxyRun(); - - // Clean up - igmpProxyCleanUp(); + // Go to the main loop. + igmpProxyRun(); - } while ( false ); + // Clean up + igmpProxyCleanUp(); // Inform that we are exiting. my_log(LOG_INFO, 0, "Shutdown complete...."); @@ -187,10 +179,10 @@ int igmpProxyInit(void) { // Configures IF states and settings configureVifs(); - switch ( Err = enableMRouter() ) { + switch (Err = enableMRouter()) { case 0: break; - case EADDRINUSE: my_log( LOG_ERR, EADDRINUSE, "MC-Router API already in use" ); break; - default: my_log( LOG_ERR, Err, "MRT_INIT failed" ); + case EADDRINUSE: my_log(LOG_ERR, EADDRINUSE, "MC-Router API already in use"); break; + default: my_log(LOG_ERR, Err, "MRT_INIT failed"); } /* create VIFs for all IP, non-loop interfaces @@ -237,8 +229,6 @@ int igmpProxyInit(void) { initIgmp(); // Initialize Routing table initRouteTable(); - // Initialize timer - callout_init(); return 1; } @@ -258,28 +248,22 @@ void igmpProxyCleanUp(void) { * Main daemon loop. */ void igmpProxyRun(void) { - // Get the config. - struct Config *config = getCommonConfig(); - // Set some needed values. register int recvlen; - int MaxFD, Rt, secs; + int MaxFD, Rt; fd_set ReadFDS; socklen_t dummy = 0; - struct timespec curtime, lasttime, difftime, tv; - // The timeout is a pointer in order to set it to NULL if nessecary. - struct timespec *timeout = &tv; + struct timespec curtime, lasttime, difftime, *timeout = &difftime; + + // First thing we send a membership query in downstream VIF's... + sendGeneralMembershipQuery(); // Initialize timer vars difftime.tv_nsec = 0; clock_gettime(CLOCK_MONOTONIC, &curtime); lasttime = curtime; - // First thing we send a membership query in downstream VIF's... - sendGeneralMembershipQuery(); - // Loop until the end... - for (;;) { - + while (true) { // Process signaling... if (sighandled) { if (sighandled & GOT_SIGINT) { @@ -289,79 +273,51 @@ void igmpProxyRun(void) { } } - /* aimwang: call rebuildIfVc */ - if (config->rescanVif) - rebuildIfVc(); - - // Prepare timeout... - secs = timer_nextTimer(); - if(secs == -1) { - timeout = NULL; + // Timeout = 1s - difference between current and last time age_callout queue with .01s grace. + // This will make sure age_callout_queue is run once every s (timer resolution) +- 0.01s. + // If aging queues takes > .01s on very slow systems or when queue is very large, + // this will become less accurate by about the time it takes to age the queue + time to process a request. + clock_gettime(CLOCK_MONOTONIC, &curtime); + difftime.tv_sec = curtime.tv_sec - lasttime.tv_sec; + if (curtime.tv_nsec >= lasttime.tv_nsec) { + timeout->tv_nsec = 999999999 - (curtime.tv_nsec - lasttime.tv_nsec); } else { - timeout->tv_nsec = 0; - timeout->tv_sec = (secs > 3) ? 3 : secs; // aimwang: set max timeout + timeout->tv_nsec = 999999999 - (1000000000 - lasttime.tv_nsec + curtime.tv_nsec); + difftime.tv_sec--; + } + if (difftime.tv_sec > 0 || timeout->tv_nsec < 10000000) { + timeout->tv_nsec = 999999999; + timeout->tv_sec = 0; + lasttime = curtime; + age_callout_queue(curtime); } // Prepare for select. MaxFD = MRouterFD; - FD_ZERO( &ReadFDS ); - FD_SET( MRouterFD, &ReadFDS ); + FD_ZERO(&ReadFDS); + FD_SET(MRouterFD, &ReadFDS); // wait for input - Rt = pselect( MaxFD +1, &ReadFDS, NULL, NULL, timeout, NULL ); + Rt = pselect(MaxFD + 1, &ReadFDS, NULL, NULL, timeout, NULL); // log and ignore failures - if( Rt < 0 ) { + if (Rt < 0) { my_log( LOG_WARNING, errno, "select() failure" ); continue; - } - else if( Rt > 0 ) { - + } else if (Rt > 0) { // Read IGMP request, and handle it... - if( FD_ISSET( MRouterFD, &ReadFDS ) ) { - - recvlen = recvfrom(MRouterFD, recv_buf, RECV_BUF_SIZE, - 0, NULL, &dummy); + if (FD_ISSET( MRouterFD, &ReadFDS)) { + recvlen = recvfrom(MRouterFD, recv_buf, RECV_BUF_SIZE, 0, NULL, &dummy); if (recvlen < 0) { - if (errno != EINTR) my_log(LOG_ERR, errno, "recvfrom"); + if (errno != EINTR) { + my_log(LOG_ERR, errno, "recvfrom"); + } continue; } - acceptIgmp(recvlen); } } - - // At this point, we can handle timeouts... - do { - /* - * If the select timed out, then there's no other - * activity to account for and we don't need to - * call gettimeofday. - */ - if (Rt == 0) { - curtime.tv_sec = lasttime.tv_sec + secs; - curtime.tv_nsec = lasttime.tv_nsec; - Rt = -1; /* don't do this next time through the loop */ - } else { - clock_gettime(CLOCK_MONOTONIC, &curtime); - } - difftime.tv_sec = curtime.tv_sec - lasttime.tv_sec; - difftime.tv_nsec += curtime.tv_nsec - lasttime.tv_nsec; - while (difftime.tv_nsec > 1000000000) { - difftime.tv_sec++; - difftime.tv_nsec -= 1000000000; - } - if (difftime.tv_nsec < 0) { - difftime.tv_sec--; - difftime.tv_nsec += 1000000000; - } - lasttime = curtime; - if (secs == 0 || difftime.tv_sec > 0) - age_callout_queue(difftime.tv_sec); - secs = -1; - } while (difftime.tv_sec > 0); - } } diff --git a/src/igmpproxy.h b/src/igmpproxy.h index 4122a857..7b1e4af9 100644 --- a/src/igmpproxy.h +++ b/src/igmpproxy.h @@ -59,6 +59,7 @@ #include #include #include +#include /* * Limit on length of route data @@ -68,7 +69,11 @@ #define MAX_IP_HEADER_LEN 60 #define IP_HEADER_RAOPT_LEN 24 +/* + * Limits on vifs / routes +*/ #define MAX_UPS_VIFS 8 +#define MAX_ORIGINS 4 // Useful macros.. #define VCMC( Vc ) (sizeof( Vc ) / sizeof( (Vc)[ 0 ] )) @@ -97,7 +102,14 @@ extern char s2[]; extern char s3[]; extern char s4[]; - +/* +** Signal Handling. +*/ +extern int sighandled; +#define GOT_SIGINT 0x01 +#define GOT_SIGHUP 0x02 +#define GOT_SIGUSR1 0x04 +#define GOT_SIGUSR2 0x08 //################################################################################# // Lib function prototypes. @@ -108,7 +120,7 @@ extern char s4[]; extern bool Log2Stderr; // Log to stderr instead of to syslog extern int LogLevel; // Log threshold, LOG_WARNING .... LOG_DEBUG -void my_log( int Serverity, int Errno, const char *FmtSt, ... ); +void my_log(int Serverity, int Errno, const char *FmtSt, ...); /* ifvc.c */ @@ -129,14 +141,11 @@ void my_log( int Serverity, int Errno, const char *FmtSt, ... ); // Define timer constants (in seconds...) #define INTERVAL_QUERY 125 #define INTERVAL_QUERY_RESPONSE 10 -//#define INTERVAL_QUERY_RESPONSE 10 #define ROUTESTATE_NOTJOINED 0 // The group corresponding to route is not joined #define ROUTESTATE_JOINED 1 // The group corresponding to route is joined #define ROUTESTATE_CHECK_LAST_MEMBER 2 // The router is checking for hosts - - // Linked list of networks... struct SubnetList { uint32_t subnet_addr; @@ -144,19 +153,58 @@ struct SubnetList { struct SubnetList *next; }; +// List of interfaces. struct IfDesc { char Name[IF_NAMESIZE]; struct in_addr InAdr; /* == 0 for non IP interfaces */ short Flags; short state; struct SubnetList* allowednets; + struct SubnetList* deniednets; struct SubnetList* allowedgroups; + struct SubnetList* deniedgroups; unsigned int robustness; unsigned char threshold; /* ttl limit */ unsigned int ratelimit; unsigned int index; }; +struct IfDescP { + struct IfDesc *S; + struct IfDesc *E; + unsigned int nrint; +}; + +void rebuildIfVc(void); +void buildIfVc(void); +struct IfDesc *getIfByName(const char *IfName); +struct IfDesc *getIfByIx(unsigned Ix); +struct IfDesc *getIfByAddress(uint32_t Ix); +struct IfDesc *getIfByVifIndex(unsigned vifindex); +int isAdressValidForIf(struct IfDesc* intrface, uint32_t ipaddr); + +/* mroute-api.c + */ +struct MRouteDesc { + struct in_addr OriginAdr, McAdr; + short InVif; + uint8_t TtlVc[MAXVIFS]; +}; + +// IGMP socket as interface for the mrouted API +// - receives the IGMP messages +extern int MRouterFD; + +int enableMRouter(void); +void disableMRouter(void); +void addVIF(struct IfDesc *Dp); +void delVIF(struct IfDesc *Dp); +int addMRoute(struct MRouteDesc * Dp); +int delMRoute(struct MRouteDesc * Dp); +int getVifIx(struct IfDesc *IfDp); + +/* config.c + */ // Keeps common configuration settings struct Config { unsigned int robustnessValue; @@ -172,51 +220,26 @@ struct Config { unsigned short fastUpstreamLeave; // Size in bytes of hash table of downstream hosts used for fast leave unsigned int downstreamHostsHashTableSize; - //~ aimwang added - // Set if nneed to detect new interface. - unsigned short rescanVif; // Set if not detect new interface for down stream. - unsigned short defaultInterfaceState; // 0: disable, 2: downstream - //~ aimwang added done + unsigned short defaultInterfaceState; // 0: disable, 2: downstream + // Set sighup behaviour (rescanvif 0/ rescanconf 1). + unsigned short sighup_action; + // Set if nneed to detect new interface. + unsigned short rescanVif; + // Set if nneed to detect config change. + unsigned short rescanConf; + // Set if need to proxy IANA local multicast range 224.0.0.0/8. + unsigned short proxyLocalMc; }; // Holds the indeces of the upstream IF... extern int upStreamIfIdx[MAX_UPS_VIFS]; -/* ifvc.c - */ -void rebuildIfVc( void ); -void buildIfVc( void ); -struct IfDesc *getIfByName( const char *IfName ); -struct IfDesc *getIfByIx( unsigned Ix ); -struct IfDesc *getIfByAddress( uint32_t Ix ); -struct IfDesc *getIfByVifIndex( unsigned vifindex ); -int isAdressValidForIf(struct IfDesc* intrface, uint32_t ipaddr); - -/* mroute-api.c - */ -struct MRouteDesc { - struct in_addr OriginAdr, McAdr; - short InVif; - uint8_t TtlVc[MAXVIFS]; -}; - -// IGMP socket as interface for the mrouted API -// - receives the IGMP messages -extern int MRouterFD; - -int enableMRouter( void ); -void disableMRouter( void ); -void addVIF( struct IfDesc *Dp ); -void delVIF( struct IfDesc *Dp ); -int addMRoute( struct MRouteDesc * Dp ); -int delMRoute( struct MRouteDesc * Dp ); -int getVifIx( struct IfDesc *IfDp ); - -/* config.c - */ +extern char *configFilePath; +void reloadConfig(void); int loadConfig(char *configFile); void configureVifs(void); +void createVifs(struct IfDescP *RebuildP); struct Config *getCommonConfig(void); /* igmp.c @@ -226,11 +249,11 @@ extern uint32_t allrouters_group; extern uint32_t alligmp3_group; void initIgmp(void); void acceptIgmp(int); -void sendIgmp (uint32_t, uint32_t, int, int, uint32_t,int); +void sendIgmp(uint32_t, uint32_t, int, int, uint32_t,int); /* lib.c */ -char *fmtInAdr( char *St, struct in_addr InAdr ); +char *fmtInAdr(char *St, struct in_addr InAdr); char *inetFmt(uint32_t addr, char *s); char *inetFmts(uint32_t addr, uint32_t mask, char *s); uint16_t inetChksum(uint16_t *addr, int len); @@ -242,23 +265,31 @@ void k_hdr_include(int hdrincl); void k_set_ttl(int t); void k_set_loop(int l); void k_set_if(uint32_t ifa); -/* -void k_join(uint32_t grp, uint32_t ifa); -void k_leave(uint32_t grp, uint32_t ifa); -*/ /* udpsock.c */ -int openUdpSocket( uint32_t PeerInAdr, uint16_t PeerPort ); +int openUdpSocket(uint32_t PeerInAdr, uint16_t PeerPort); /* mcgroup.c */ -int joinMcGroup( int UdpSock, struct IfDesc *IfDp, uint32_t mcastaddr ); -int leaveMcGroup( int UdpSock, struct IfDesc *IfDp, uint32_t mcastaddr ); - +int joinMcGroup(int UdpSock, struct IfDesc *IfDp, uint32_t mcastaddr); +int leaveMcGroup(int UdpSock, struct IfDesc *IfDp, uint32_t mcastaddr); /* rttable.c */ +// Group specific query structs. +typedef struct { + uint32_t group; + struct IfDesc *sourceVif; + short started; +} GroupVifDesc; + +struct gvDescL { + GroupVifDesc *gvDesc; + struct gvDescL *next; +}; + +struct gvDescL *clearRoutes(struct IfDesc *IfDp, struct IfDescP *RebuildP); void initRouteTable(void); void clearAllRoutes(void); int insertRoute(uint32_t group, int ifx, uint32_t src); @@ -273,18 +304,16 @@ int getMcGroupSock(void); */ void acceptGroupReport(uint32_t src, uint32_t group); void acceptLeaveMessage(uint32_t src, uint32_t group); +void sendGroupSpecificMemberQuery(void *argument); void sendGeneralMembershipQuery(void); -/* callout.c +/* callout.c */ typedef void (*timer_f)(void *); -void callout_init(void); void free_all_callouts(void); -void age_callout_queue(int); -int timer_nextTimer(void); +void age_callout_queue(struct timespec curtime); int timer_setTimer(int, timer_f, void *); -int timer_clearTimer(int); int timer_leftTimer(int); /* confread.c diff --git a/src/request.c b/src/request.c index 06d14c44..3134c0f0 100644 --- a/src/request.c +++ b/src/request.c @@ -40,16 +40,6 @@ #include "igmpproxy.h" -// Prototypes... -void sendGroupSpecificMemberQuery(void *argument); - -typedef struct { - uint32_t group; - // uint32_t vifAddr; - short started; -} GroupVifDesc; - - /** * Handles incoming membership reports, and * appends them to the routing table. diff --git a/src/rttable.c b/src/rttable.c index d3fb84c1..9d4c3ba4 100644 --- a/src/rttable.c +++ b/src/rttable.c @@ -40,8 +40,6 @@ #include "igmpproxy.h" -#define MAX_ORIGINS 4 - /** * Routing table structure definition. Double linked list... */