diff --git a/src/config.c b/src/config.c index 54ac659..9863deb 100644 --- a/src/config.c +++ b/src/config.c @@ -407,13 +407,16 @@ static inline bool parsePhyintToken(char *token) { if (intToken > 0 && mrt_tbl < 0) { if (ntbl % 32 == 0 && ! _recalloc(tbl, var, ((ntbl / 32) + 1) * tblsz, (ntbl / 32) * tblsz)) LOG(LOG_ERR, eNOMEM, "Config (%s): Out of Memory", tmpPtr->name); // Freed by loadConfig() - if (!ntbl) + if (!ntbl) { tbl[ntbl++] = CONF->defaultTable; - for (i = 0; i < ntbl && tbl[i] != intToken; i++); - if (i >= ntbl) - tbl[ntbl++] = intToken; - // igmpProxyInit() will fork the process for table 0 after config is loaded - igmpProxyFork(intToken); + igmpProxyFork(0); + } + if (mrt_tbl < 0) { // Check again becasue of fork(). + for (i = 0; i < ntbl && tbl[i] != intToken; i++); + if (i >= ntbl) + tbl[ntbl++] = intToken; + igmpProxyFork(intToken); + } } } #else @@ -672,11 +675,16 @@ bool loadConfig(char *cfgFile) { LOG(LOG_ERR, eNOMEM, "Config: Out of Memory."); else if (mrt_tbl < 0) { int i; + if (!ntbl) + tbl[ntbl++] = 0; for (i = 0; i < ntbl && tbl[i] != conf.defaultTable; i++); if (i >= ntbl) tbl[ntbl++] = conf.defaultTable; - if (conf.defaultTable > 0) - igmpProxyFork(conf.defaultTable); + if (conf.defaultTable > 0) { + igmpProxyFork(0); + if (mrt_tbl < 0) // Check again because of fork(). + igmpProxyFork(conf.defaultTable); + } } LOG(LOG_NOTICE, 0, "Config: Default to table %d for interfaces.", conf.defaultTable); } @@ -1002,7 +1010,8 @@ void reloadConfig(uint64_t *tid) { memcpy(&conf, &oldconf, sizeof(struct Config)); } else { // Rebuild the interfaces config, then free the old configuration. - rebuildIfVc(NULL); + if (!STARTUP) + rebuildIfVc(NULL); freeConfig(1); LOG(LOG_WARNING, 0, "Configuration Reloaded from '%s'.", conf.configFilePath); } @@ -1037,7 +1046,7 @@ void configureVifs(void) { GETIFL(IfDp) { // Find and link matching config to interfaces, except when rescanning vifs and exisiting interface. oconf = NULL; - if (!IFREBUILD || !(IfDp->Flags & 0x40)) { + if (!IFREBUILD || ! IfDp->conf) { for (oconf = NULL, vconf = vifConf; vconf && strcmp(IfDp->Name, vconf->name); vconf = vconf->next); if (vconf) { LOG(LOG_INFO, 0, "Found config for %s", IfDp->Name); diff --git a/src/ifvc.c b/src/ifvc.c index 8f7e9b0..7301477 100644 --- a/src/ifvc.c +++ b/src/ifvc.c @@ -50,8 +50,9 @@ void freeIfDescL(bool force) { while (IfDp) { if (force || IfDp->state & 0x80 || (IfDp->next && IfDp->next->state & 0x80)) { // Remove interface marked for deletion. - LOG(SHUTDOWN ? LOG_NOTICE : LOG_WARNING, 0, "Interface %s was removed.", - force | (IfDp->state & 0x80) ? IfDp->Name : IfDp->next->Name); + if (!STARTUP) + LOG(SHUTDOWN ? LOG_WARNING : LOG_NOTICE, 0, "Interface %s was removed.", + force | (IfDp->state & 0x80) ? IfDp->Name : IfDp->next->Name); fIfDp = force || (IfDp->state & 0x80) ? IfDescL : IfDp->next; if (force || IfDp->state & 0x80) IfDescL = IfDp = IfDp->next; diff --git a/src/igmpv3proxy.c b/src/igmpv3proxy.c index 52b9c5b..fcaba94 100644 --- a/src/igmpv3proxy.c +++ b/src/igmpv3proxy.c @@ -40,18 +40,7 @@ #include "igmpv3proxy.h" -// Socket control message union. -union cmsg { - struct cmsghdr cmsgHdr; -#ifdef IP_PKTINFO - char cmsgData[sizeof(struct msghdr) + sizeof(struct in_pktinfo)]; -#elif IP_RECVIF - char cmsgData[sizeof(struct msghdr) + sizeof(struct sockaddr_dl)]; -#endif -}; - // Local function Prototypes -STRSIG; static void signalHandler(int sig, siginfo_t* siginfo, void* context); static void igmpProxyInit(void); static void igmpProxyMonitor(void); @@ -108,7 +97,7 @@ int main(int ArgCn, char *ArgVc[]) { tbl = atoll(optarg); break; #else - fprintf(stderr, "Only linux supports multiple tables."); + fprintf(stderr, "Only linux supports multiple tables.\n"); exit(1); #endif case 'c': @@ -264,6 +253,7 @@ static void igmpProxyRun(void) { LOG(LOG_WARNING, 0, "Ceci n'est pas une SIGPIPE."); } else if (sighandled & GOT_SIGCHLD) sighandled &= ~GOT_SIGCHLD; // Proxy ignores SIGCHLD. + sigstatus = 0; } if (!sighandled && (Rt <= 0 || i >= CONF->reqQsz)) { // Run queue aging (unless sigs pending), it wil return the time until next timer is scheduled. @@ -272,7 +262,6 @@ static void igmpProxyRun(void) { Rt = ppoll(pollFD, 2, timeout.tv_sec == -1 ? NULL : timeout.tv_nsec == -1 ? &nto : &timeout, NULL); i = 1; } - sigstatus =0; // log and ignore failures if (Rt < 0 && errno != EINTR) @@ -294,7 +283,6 @@ static void igmpProxyRun(void) { else acceptIgmp(recvlen, msgHdr); } - // Check if any cli connection needs to be handled. if (pollFD[1].revents & POLLIN) { LOG(LOG_DEBUG, 0, "igmpProxyRun: RECV CLI Request %d.", i); @@ -313,8 +301,7 @@ static void igmpProxyRun(void) { /** * Start a new igmpv3proxy process for route table. */ -void igmpProxyFork(int tbl) -{ +void igmpProxyFork(int tbl) { int i, pid, size = 32 * sizeof(struct pt); // On first start of new process, initialize the child processes table. Alloc per 32 entries. @@ -323,42 +310,43 @@ void igmpProxyFork(int tbl) LOG(LOG_ERR, eNOMEM, "igmpProxyFork: Out of Memory."); // Find a spot for the process in the table, increase child counter. // Child table is not shifted, but pid and tbl set to -1, after child exits. - for (i = 0; i < chld.nr && chld.c[i].pid != -1 && chld.c[i].tbl != tbl; i++); - if (i <= chld.nr && chld.c[i].tbl != tbl) { - // If there is an empty spot in the middle (exited child) put it there. - if ((pid = fork()) < 0) { - // Do not increase the nr. childs here if an emtpy spot was found and check validity. - LOG(LOG_ERR, eNOFORK, "igmpProxyFork: Cannot fork() child %d.", chld.nr); - } else if (pid == 0) { - // Child initializes its own start time. - clock_gettime(CLOCK_REALTIME, &starttime); - strcpy(tS, asctime(localtime(&starttime.tv_sec))); - tS[strlen(tS) - 1] = '\0'; - mrt_tbl = tbl; // Set routing table for process. - chld.nr = i + 1; // Just so that we know who we are. - } else { - // Parent sets the new child info in table. - chld.c[i].tbl = tbl; - chld.c[i].pid = pid; - if (i == chld.nr) - chld.nr++; - LOG(LOG_INFO, 0, "Forked child: %d PID: %d for table: %d.", i + 1, chld.c[i].pid, chld.c[i].tbl); - } - - } else + for (i = 0; i < chld.nr && chld.c[i].tbl != tbl; i++); + if (i < chld.nr && chld.c[i].pid > 0) { LOG(LOG_DEBUG, 0, "igmpProxyFork: Proxy for table %d already active.", tbl); + } else if ((pid = fork()) < 0) { + // Do not increase the nr. childs here if an emtpy spot was found and check validity. + LOG(LOG_ERR, eNOFORK, "igmpProxyFork: Cannot fork() child %d.", chld.nr); + } else if (pid == 0) { + // Child initializes its own start time. + clock_gettime(CLOCK_REALTIME, &starttime); + strcpy(tS, asctime(localtime(&starttime.tv_sec))); + tS[strlen(tS) - 1] = '\0'; + mrt_tbl = tbl; // Set routing table for process. + chld.nr = i + 1; // Just so that we know who we are. + _free(chld.c, var, (((chld.nr - 1) / 32) + 1) * 32 * sizeof(struct pt)); // Alloced by Self. + chld.c = NULL; + sigstatus = 1; + freeIfDescL(true); + } else { + // Parent sets the new child info in table. + chld.c[i].tbl = tbl; + chld.c[i].pid = pid; + chld.c[i].sig = chld.c[i].st = 0; + if (i == chld.nr) + chld.nr++; + LOG(LOG_INFO, 0, "Forked child: %d PID: %d for table: %d.", i + 1, chld.c[i].pid, chld.c[i].tbl); + } } /** * Monitor process when multiple proxies are running. * signalHandler will restart processes if the exit. loadConfig may start new procxies if needed. */ -const char *exitmsg[16] = { "gave up", "terminated abnormally", "was terminated", "failed to initialize", "failed to fork", "ran out of memory", "aborted", "failed to load config", "", "was murdered", "", "segfaulted", "", "", "" , "was terminated" }; static void igmpProxyMonitor(void) { + rebuildIfVc(NULL); struct timespec timeout = timer_ageQueue(); LOG(LOG_NOTICE, 0, "Monitoring %d proxy processes.", chld.nr); - rebuildIfVc(NULL); sigstatus = 0; // Simple busy sleeping loop here, it suits our needs. do { @@ -369,17 +357,14 @@ static void igmpProxyMonitor(void) { FOR_IF(int i = 0; i < chld.nr; i++, chld.c[i].sig == 1) { LOG(chld.c[i].st == 0 ? LOG_NOTICE : LOG_WARNING, 0, "Child: %d PID: %d for table: %d %s (%i)", i + 1, chld.c[i].pid, chld.c[i].tbl, exitmsg[chld.c[i].st], chld.c[i].st); - int tbl; if (chld.c[i].st < 0) chld.c[i].st = 0 - (chld.c[i].st); - tbl = chld.c[i].tbl; - chld.c[i].pid = chld.c[i].tbl = -1; - if (tbl > 0) - ipRules(tbl, false); - if (!SHUTDOWN && (chld.c[i].st == 15 || chld.c[i].st == 6 || chld.c[i].st == 11 || chld.c[i].st == 9)) + chld.c[i].pid = chld.c[i].sig = 0; + if (chld.c[i].tbl > 0 && !CONF->disableIpMrules) + ipRules(chld.c[i].tbl, false); + if (chld.c[i].st == 15 || chld.c[i].st == 6 || chld.c[i].st == 11 || chld.c[i].st == 9) // Start new proxy in case of unexpected shutdown. - igmpProxyFork(tbl); - chld.c[i].sig = chld.c[i].st = 0; + igmpProxyFork(chld.c[i].tbl); } } else if (sighandled & GOT_SIGTERM || sighandled & GOT_SIGURG || sighandled & GOT_SIGHUP || sighandled & GOT_SIGUSR1) { sigstatus = sighandled & GOT_SIGTERM ? GOT_SIGTERM : sighandled & GOT_SIGURG ? GOT_SIGURG : @@ -399,16 +384,13 @@ static void igmpProxyMonitor(void) { sighandled &= ~GOT_SIGPIPE; LOG(LOG_WARNING, 0, "Ceci n'est pas une SIGPIPE."); } + sigstatus = 0; } - sigstatus = 0; - // SIGCHLD or loadConfig() may have forked new proxy, set sigstatus to STARTUP. - if (mrt_tbl >= 0) { - // New proxy can keep using the (universal) config, but needs to create its own interface list. - freeIfDescL(true); - sigstatus = 1; + if (mrt_tbl < 0) + timeout = timer_ageQueue(); + if (mrt_tbl >= 0) + // SIGCHLD, ageQueue() or loadConfig() may have forked new proxy. return; // To igmpProxyInit() - } - timeout = timer_ageQueue(); if (timeout.tv_sec < 0) timeout = (struct timespec){ 2147483647, 0 }; } while (sighandled || timeout.tv_nsec < 0 || nanosleep(&timeout, NULL) >= 0 || true); @@ -481,18 +463,9 @@ static void igmpProxyInit(void) { SETSIGS; #ifdef __linux__ // When multiple tables are in use, process for default table 0 is forked off here. - if (mrt_tbl < 0 && chld.c && (pid = fork()) < 0) { - LOG(LOG_ERR, eNOFORK, "igmpProxyInit: Cannot fork()."); - } else if (pid > 0) { - // Parent becomes monitor. - LOG(LOG_INFO, 0, "Forked child: %d PID: %d for table: 0.", chld.nr + 1, pid); - chld.c[chld.nr].pid = pid; - chld.c[chld.nr++].tbl = 0; + if (mrt_tbl < 0 && chld.nr) igmpProxyMonitor(); - } else if (pid == 0) - // Child (or only process) becomes proxy for default mrt table 0. - chld.nr++; - if (mrt_tbl < 0) + else if (mrt_tbl < 0) mrt_tbl = 0; #endif // Enable mroute and open cli socket and add ip mrules while still running as root. @@ -500,10 +473,7 @@ static void igmpProxyInit(void) { pollFD[1].fd = openCliFd(); rebuildIfVc(NULL); #ifdef __linux__ - int size = (((chld.nr - 1) / 32) + 1) * 32 * sizeof(struct pt); - _free(chld.c, var, size); // Alloced by igmpProxyFork() - chld.c = NULL; - if (mrt_tbl > 0 && !CONF->disableIpMrules) + if (!CONF->disableIpMrules) ipRules(mrt_tbl, true); #endif // Make sure logfile and chroot directory are owned by configured user and switch ids. @@ -607,10 +577,12 @@ static void signalHandler(int sig, siginfo_t* siginfo, void* context) { } BLOCKSIGS; sighandled |= GOT_SIGTERM; + if (sig == SIGINT) + return; break; case SIGPIPE: sighandled |= GOT_SIGPIPE; - break; + return; case SIGURG: sighandled |= GOT_SIGURG; break; @@ -631,11 +603,11 @@ static void signalHandler(int sig, siginfo_t* siginfo, void* context) { chld.c[i].st = (int8_t)siginfo->si_status; break; } + return; } // Send SIG to children, except for SIGINT SIGPIPE and SIGCHLD. // If monitor is terminating we will end childs with SIGINT. - IF_FOR_IF(mrt_tbl < 0 && sig != SIGINT && sig != SIGPIPE && sig != SIGCHLD - && chld.c, i = 0; i < chld.nr; i++, chld.c[i].pid > 0) + IF_FOR_IF(mrt_tbl < 0 && chld.c, i = 0; i < chld.nr; i++, chld.c[i].pid > 0) kill(chld.c[i].pid, sig == SIGTERM ? SIGINT : sig); #else } diff --git a/src/igmpv3proxy.h b/src/igmpv3proxy.h index 38647c6..2b54e1e 100644 --- a/src/igmpv3proxy.h +++ b/src/igmpv3proxy.h @@ -75,16 +75,6 @@ //################################################################################# // Global definitions and declarations. //################################################################################# -#define IF_FOR(x, y) if (x) for (y) -#define FOR_IF(x, y) for (x) if (y) -#define IF_FOR_IF(x, y, z) if (x) for (y) if (z) - -// Set type of control message structure for received socket data. -#ifdef IP_PKTINFO -#define IFINFO IP_PKTINFO -#elif IP_RECVIF -#define IFINFO IP_RECVIF -#endif // Memory statistics. struct memstats { @@ -94,29 +84,6 @@ struct memstats { int64_t qry, tmr, var; // Queries, Timers, various. }; -#define _malloc(p,m,s) (((p=malloc(s)) && (memuse.m+=(s)) > 0 && (++memalloc.m > 0)) || getMemStats(0,-1)) -#define _calloc(p,n,m,s) (((p=calloc(n,s)) && (memuse.m+=(n * (s))) > 0 && (++memalloc.m > 0)) || getMemStats(0,-1)) -#define _realloc(p,m,sp,sm) (((p=realloc(p,sp)) && (memuse.m+=(-(sm) + (sp))) > 0 && (++memalloc.m > 0)) || getMemStats(0,-1)) -#define _recalloc(p,m,sp,sm) (((p=realloc(p,sp)) && (sp <= sm || memset(p + (sm), 0, (sp) - (sm))) \ - && (memuse.m+=(-(sm) + (sp))) > 0 && (++memalloc.m > 0)) || getMemStats(0,-1)) -#define _free(p, m, s) if (p) { \ - if ((memuse.m-=(s)) < 0 || (++memfree.m <= 0)) { \ - getMemStats(0,-1); \ - exit(6); \ - } \ - free(p); } - -// In / output buffering. -#define BUF_SIZE 9216 // Jumbo MTU -#define K_BUF_SIZE 512 // Default kernel ring buffer size in KB -#define REQQSZ 16 // Default request queue size -#define TMQSZ 4 // Default timer queue size - -// Limits of configuration / token. -#define READ_BUFFER_SIZE 512 -#define MAX_TOKEN_LENGTH 128 -#define MAX_GROUPNAME_SIZE 32 - // Keeps common configuration settings. #define RUN_PATHS "/run /var/run /tmp /var/tmp" #define CFG_PATHS "/etc/ /usr/local/etc/ /var/etc/ /usr/local/var/etc/" @@ -281,6 +248,17 @@ struct IfDesc { #define IF_OLDSTATE(x) ((x->state >> 2) & 0x3) #define IF_NEWSTATE(x) (x->state & 0x3) +// In / output buffering. +#define BUF_SIZE 9216 // Jumbo MTU +#define K_BUF_SIZE 512 // Default kernel ring buffer size in KB +#define REQQSZ 16 // Default request queue size +#define TMQSZ 4 // Default timer queue size + +// Limits of configuration / token. +#define READ_BUFFER_SIZE 512 +#define MAX_TOKEN_LENGTH 128 +#define MAX_GROUPNAME_SIZE 32 + // Multicast default values. #define DEFAULT_ROBUSTNESS 2 #define DEFAULT_THRESHOLD 1 @@ -317,7 +295,10 @@ struct IfDesc { #define SCHLD (sigstatus & GOT_SIGCHLD) #define SPIPE (sigstatus & GOT_SIGPIPE) #define SHUTDOWN (sigstatus & GOT_SIGTERM) -#define STRSIG const char *SIGS[32] = { "", "SIGHUP", "SIGINT", "", "", "", "SIGABRT", "", "", "SIGKILL", "SIGUSR1", "SIGSEGV", "SIGUSR2", "SIGPIPE", "", "SIGTERM", "SIGURG", "SIGCHLD", "", "", "SIGCHLD", "", "", "SIGURG", "", "", "", "", "", "", "SIGUSR1", "SIGUSR2" }; + +static const char *SIGS[32] = { "", "SIGHUP", "SIGINT", "", "", "", "SIGABRT", "", "", "SIGKILL", "SIGUSR1", "SIGSEGV", "SIGUSR2", "SIGPIPE", "", "SIGTERM", "SIGURG", "SIGCHLD", "", "", "SIGCHLD", "", "", "SIGURG", "", "", "", "", "", "", "SIGUSR1", "SIGUSR2" }; +static const char *exitmsg[16] = { "gave up", "terminated abnormally", "was terminated", "failed to initialize", "failed to fork", "ran out of memory", "aborted", "failed to load config", "", "was murdered", "", "segfaulted", "", "", "" , "was terminated" }; + #define SETSIGS struct sigaction sa = { 0 }; \ sa.sa_sigaction = signalHandler; \ sa.sa_flags = SA_SIGINFO; \ @@ -348,15 +329,48 @@ struct IfDesc { // CLI Defines. #define CLI_CMD_BUF 256 +// Memory (de)allocation macro's +#define _malloc(p,m,s) (((p=malloc(s)) && (memuse.m+=(s)) > 0 && (++memalloc.m > 0)) || getMemStats(0,-1)) +#define _calloc(p,n,m,s) (((p=calloc(n,s)) && (memuse.m+=(n * (s))) > 0 && (++memalloc.m > 0)) || getMemStats(0,-1)) +#define _realloc(p,m,sp,sm) (((p=realloc(p,sp)) && (memuse.m+=(-(sm) + (sp))) > 0 && (++memalloc.m > 0)) || getMemStats(0,-1)) +#define _recalloc(p,m,sp,sm) (((p=realloc(p,sp)) && (sp <= sm || memset(p + (sm), 0, (sp) - (sm))) \ + && (memuse.m+=(-(sm) + (sp))) > 0 && (++memalloc.m > 0)) || getMemStats(0,-1)) +#define _free(p, m, s) if (p) { \ + if ((memuse.m-=(s)) < 0 || (++memfree.m <= 0)) { \ + getMemStats(0,-1); \ + exit(6); } \ + free(p); } + // Bit manipulation macros. #define BIT_SET(X,n) ((X) |= 1 << (n)) #define BIT_CLR(X,n) ((X) &= ~(1 << (n))) #define BIT_TST(X,n) (((X) >> (n)) & 1) +// Conditional loop macro's +#define IF_FOR(x, y) if (x) for (y) +#define FOR_IF(x, y) for (x) if (y) +#define IF_FOR_IF(x, y, z) if (x) for (y) if (z) + //################################################################################# // Common IGMPv3 includes. Various OS dont provide common structs, so we just use our own. //################################################################################# +// Set type of control message structure for received socket data. +#ifdef IP_PKTINFO + #define IFINFO IP_PKTINFO +#elif IP_RECVIF + #define IFINFO IP_RECVIF +#endif +// Socket control message union. +union cmsg { +struct cmsghdr cmsgHdr; +#ifdef IP_PKTINFO + char cmsgData[sizeof(struct msghdr) + sizeof(struct in_pktinfo)]; +#elif IP_RECVIF + char cmsgData[sizeof(struct msghdr) + sizeof(struct sockaddr_dl)]; +#endif +}; + // IGMP Query Definition. struct igmpv3_query { u_char igmp_type; // version & type of IGMP message diff --git a/src/kern.c b/src/kern.c index 5812ebb..b25a760 100644 --- a/src/kern.c +++ b/src/kern.c @@ -39,7 +39,8 @@ #include "igmpv3proxy.h" -static int mrouterFD = -1; +static int mrouterFD = -1; +static uint32_t vifBits = 0; /** * Set the socket buffer. If we can't set it as large as we want, search around to try to find the highest acceptable @@ -205,7 +206,8 @@ int k_enableMRouter(void) { int k_disableMRouter(void) { if (setsockopt(mrouterFD, IPPROTO_IP, MRT_DONE, NULL, 0) != 0 || close(mrouterFD) < 0) LOG(LOG_WARNING, errno, "MRT_DONE/close"); - mrouterFD = -1; + else + mrouterFD = -1; return mrouterFD; } @@ -213,7 +215,8 @@ int k_disableMRouter(void) { * Delete vif when removed from config or disappeared from system. */ void k_delVIF(struct IfDesc *IfDp) { - struct vifctl vifCtl = { 0 }; + struct vifctl vifCtl; + memset(&vifCtl, 0, sizeof(struct vifctl)); vifCtl.vifc_vifi = IfDp->index; LOG(LOG_NOTICE, 0, "Removing VIF: %s, Ix: %d, Fl: 0x%x, IP: %s, Threshold: %d, Ratelimit: %d", IfDp->Name, IfDp->index, @@ -222,6 +225,7 @@ void k_delVIF(struct IfDesc *IfDp) { LOG(LOG_WARNING, errno, "delVIF: Error removing VIF %d:%s", IfDp->index, IfDp->Name); // Reset vif index. + BIT_CLR(vifBits, IfDp->index); IfDp->index = (uint8_t)-1; } @@ -229,40 +233,34 @@ void k_delVIF(struct IfDesc *IfDp) { * Adds the interface '*IfDp' as virtual interface to the mrouted API */ bool k_addVIF(struct IfDesc *IfDp) { - struct vifctl vifCtl; - struct IfDesc *Dp = NULL; - uint8_t Ix = 0; - uint32_t vifBits = 0; + struct vifctl vifCtl; + uint8_t Ix; - // Find available vifindex. - GETIFLIF(Dp, Dp->index != (uint8_t)-1) - BIT_SET(vifBits, Dp->index); - for (;Ix < MAXVIFS && (vifBits & (1 << Ix)); Ix++); - if (Ix >= MAXVIFS) { + if (vifBits == (uint32_t)-1) { LOG(LOG_WARNING, 0, "Out of VIF space"); return false; - } else - IfDp->index = Ix; + } + for (Ix = 0; Ix < MAXVIFS && (vifBits & (1 << Ix)); Ix++); + IfDp->index = Ix; + BIT_SET(vifBits, IfDp->index); + IfDp->bytes = IfDp->rate = 0; // Set the vif parameters, reset bw counters. + memset(&vifCtl, 0, sizeof(struct vifctl)); #ifdef HAVE_STRUCT_VIFCTL_VIFC_LCL_IFINDEX vifCtl = (struct vifctl){ Ix, 0, IfDp->conf->threshold, 0, {{IfDp->InAdr.s_addr}}, {INADDR_ANY} }; #else vifCtl = (struct vifctl){ Ix, 0, IfDp->conf->threshold, 0, {IfDp->InAdr.s_addr}, {INADDR_ANY} }; #endif - IfDp->bytes = IfDp->rate = 0; - // Log the VIF information. + // Log the VIF information and add. LOG(LOG_NOTICE, 0, "Adding VIF: %s, Ix: %d, Fl: 0x%x, IP: %s, Threshold: %d, Ratelimit: %d", IfDp->Name, vifCtl.vifc_vifi, vifCtl.vifc_flags, inetFmt(vifCtl.vifc_lcl_addr.s_addr, 1), vifCtl.vifc_threshold, IfDp->conf->ratelimit); - - // Add the vif. if (setsockopt(mrouterFD, IPPROTO_IP, MRT_ADD_VIF, (char *)&vifCtl, sizeof(vifCtl)) < 0) { LOG(LOG_WARNING, errno, "Error adding VIF %d:%s", IfDp->index, IfDp->Name); IfDp->index = (uint8_t)-1; return false; } - return true; } @@ -272,9 +270,13 @@ bool k_addVIF(struct IfDesc *IfDp) { void k_addMRoute(uint32_t src, uint32_t group, int vif, uint8_t ttlVc[MAXVIFS]) { // Inialize the mfc control structure. #ifdef HAVE_STRUCT_MFCCTL2_MFCC_TTLS - struct mfcctl2 CtlReq = { {src}, {group}, vif, {0}, {0}, 0 }; + struct mfcctl2 CtlReq; + memset(&CtlReq, 0, sizeof(struct mfcctl2)); + CtlReq = (struct mfcctl2){ {src}, {group}, vif, {0}, {0}, 0 }; #else - struct mfcctl CtlReq = { {src}, {group}, vif, {0}, 0, 0, 0, 0 }; + struct mfcctl CtlReq; + memset(&CtlReq, 0, sizeof(struct mfcctl)); + CtlReq = (struct mfcctl){ {src}, {group}, vif, {0}, 0, 0, 0, 0 }; #endif memcpy(CtlReq.mfcc_ttls, ttlVc, sizeof(CtlReq.mfcc_ttls)); @@ -298,9 +300,13 @@ void k_addMRoute(uint32_t src, uint32_t group, int vif, uint8_t ttlVc[MAXVIFS]) void k_delMRoute(uint32_t src, uint32_t group, int vif) { // Inialize the mfc control structure. #ifdef HAVE_STRUCT_MFCCTL2_MFCC_TTLS - struct mfcctl2 CtlReq = { {src}, {group}, vif, {0}, {0}, 0 }; + struct mfcctl2 CtlReq; + memset(&CtlReq, 0, sizeof(struct mfcctl2)); + CtlReq = (struct mfcctl2){ {src}, {group}, vif, {0}, {0}, 0 }; #else - struct mfcctl CtlReq = { {src}, {group}, vif, {0}, 0, 0, 0, 0 }; + struct mfcctl CtlReq; + memset(&CtlReq, 0, sizeof(struct mfcctl)); + CtlReq = (struct mfcctl){ {src}, {group}, vif, {0}, 0, 0, 0, 0 }; #endif // Remove mfc from kernel.