From 20dcf0cc7424dc95c842395c4d7d1805daa8961c Mon Sep 17 00:00:00 2001 From: Sietse van Zanen Date: Tue, 26 May 2020 17:03:12 +0200 Subject: [PATCH] Changes to callout and igmpproxy First PR for a complete rewrite of igmpproxy. This rewrite will include several fixes, and new functionality. This PR changes callout.c to a simpler and more stable callout queue algorithm. Also igmpproxy.c is sanitized and the main event loop based on the new callout queue. Several structs and variables are moved to igmpproxy.h, a few prototypes added and sanitized into the unified style. config.c is modified slightly to add NULL pointers for new blacklists that will be added. Fixes: https://github.com/pali/igmpproxy/issues/58 --- src/callout.c | 214 +++++++++++------------------------------------- src/config.c | 17 ++-- src/igmpproxy.c | 168 ++++++++++++++----------------------- src/igmpproxy.h | 134 +++++++++++++++++------------- src/request.c | 10 --- 5 files changed, 195 insertions(+), 348 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..6ae2f649 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; @@ -228,30 +230,27 @@ void configureVifs(void) { // Loop through all VIFs... 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) { - // I the VIF names match... 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..55f10f6c 100644 --- a/src/igmpproxy.c +++ b/src/igmpproxy.c @@ -61,13 +61,6 @@ 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]; @@ -76,8 +69,7 @@ int upStreamIfIdx[MAX_UPS_VIFS]; * 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 +105,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 +118,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 +175,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 +225,6 @@ int igmpProxyInit(void) { initIgmp(); // Initialize Routing table initRouteTable(); - // Initialize timer - callout_init(); return 1; } @@ -258,28 +244,23 @@ 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, rescanvif_timer = -1, rescanconf_timer = -1; 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 +270,52 @@ 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..ae67b945 100644 --- a/src/igmpproxy.h +++ b/src/igmpproxy.h @@ -59,6 +59,7 @@ #include #include #include +#include /* * Limit on length of route data @@ -97,7 +98,11 @@ extern char s2[]; extern char s3[]; extern char s4[]; - +int sighandled; +#define GOT_SIGINT 0x01 +#define GOT_SIGHUP 0x02 +#define GOT_SIGUSR1 0x04 +#define GOT_SIGUSR2 0x08 //################################################################################# // Lib function prototypes. @@ -108,7 +113,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 +134,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 +146,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 +213,24 @@ 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 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 - */ +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 +240,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 +256,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 +295,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.