diff --git a/src/cli.c b/src/cli.c index 83dbc38..f4735ff 100644 --- a/src/cli.c +++ b/src/cli.c @@ -132,7 +132,6 @@ void acceptCli(void) return; } } - if (buf[0] == 'r') { logRouteTable("", buf[1] == 'h' ? 0 : 1, fd, addr, mask); } else if ((buf[0] == 'i' || buf[0] == 'f') && len > 2 && ! (IfDp = getIf(0, &buf[buf[1] == 'h' ? 3 : 2], 2))) { @@ -178,7 +177,7 @@ void cliCmd(char *cmd, int tbl) { struct sigaction sa; struct stat st; struct sockaddr_un srv_sa; - char buf[CLI_CMD_BUF+1] = "", paths[sizeof(RUN_PATHS)] = RUN_PATHS, *path, tpath[128]; + char buf[CLI_CMD_BUF+1] = "", *path, tpath[128]; sa.sa_handler = cliSignalHandler; sa.sa_flags = 0; /* Interrupt system calls */ @@ -195,7 +194,7 @@ void cliCmd(char *cmd, int tbl) { #endif // Check for daemon socket location. - path = strtok(paths, " "); + path = strtok(RUN_PATHS, " "); while (path) { sprintf(tpath, "%s/%s/root", path, fileName); if (lstat(tpath, &st) == 0 && (S_ISLNK(st.st_mode) || S_ISDIR(st.st_mode))) { @@ -222,15 +221,12 @@ void cliCmd(char *cmd, int tbl) { fprintf(stderr, "Cannot open daemon socket (%s). %s\n", srv_sa.sun_path, strerror(errno)); exit(-1); } - if (send(srv_fd, cmd, strlen(cmd), 0) < 0) { fprintf(stderr, "Cannot send command. %s\n", strerror(errno)); exit(-1); } - // Receive the daemon's answer. It will be closed by one single byte. for (int len = 0; (len = recv(srv_fd, &buf, CLI_CMD_BUF, 0)) > 0; buf[len] = '\0', fprintf(stdout, "%s", buf)); - close(srv_fd); } diff --git a/src/config.c b/src/config.c index 669aaac..e18c00c 100644 --- a/src/config.c +++ b/src/config.c @@ -53,7 +53,8 @@ static const char *options = " include phyint user group chroot defaultquickleav static const char *phyintopt = " table updownstream upstream downstream disabled proxylocalmc noproxylocalmc quickleave noquickleave ratelimit threshold nocksumverify cksumverify noquerierelection querierelection querierip querierver robustnessvalue queryinterval queryrepsonseinterval lastmemberinterval lastmembercount defaultfilter filter altnet whitelist disableipmrules"; // Daemon Configuration. -static struct Config conf, oldconf; +static struct Config conf, oldconf; +extern volatile sig_atomic_t sighandled; // From igmpv3proxy.c signal handler. // Structures to keep vif configuration and black/whitelists. static struct vifConfig *vifConf = NULL, *ovifConf = NULL; @@ -360,7 +361,6 @@ static inline bool parsePhyintToken(char *token) { LOG(LOG_WARNING, 0, "Config: You should at least name your interfeces."); return false; } - // Find existing or create new vifConf. for (tmpPtr = vifConf; tmpPtr && strncmp(tmpPtr->name, token + 1, IF_NAMESIZE); tmpPtr = tmpPtr->next); if (! tmpPtr) { @@ -539,7 +539,6 @@ static inline bool parsePhyintToken(char *token) { // Return false if error in interface config was detected. freeConfig will cleanup. if (logwarning) return false; - // Check Query response interval and adjust if necessary (query response must be <= query interval). if ((tmpPtr->qry.ver != 3 ? tmpPtr->qry.responseInterval : getIgmpExp(tmpPtr->qry.responseInterval, 0)) / 10 > tmpPtr->qry.interval) { @@ -551,7 +550,6 @@ static inline bool parsePhyintToken(char *token) { LOG(LOG_NOTICE, 0, "Config (%s): Setting default query interval to %ds. Default response interval %.1fs", tmpPtr->name, tmpPtr->qry.interval, f); } - if (!tmpPtr->noDefaultFilter) *filP = conf.defaultFilters; @@ -575,14 +573,13 @@ bool loadConfig(char *cfgFile) { char *token = NULL; struct stat st; - // Initialize common config on first entry. if (conf.cnt++ == 0) { + // Initialize common config on first entry. logwarning = 0; initCommonConfig(); filP = &conf.defaultFilters; rateP = &conf.defaultRates; } - if (conf.cnt == 0xFF) { // Check recursion and return if exceeded. LOG(LOG_WARNING, 0, "Config: Too many includes (%d) while loading '%s'.", 0xFF, cfgFile); @@ -599,7 +596,6 @@ bool loadConfig(char *cfgFile) { free(d[n]); } free(d); - //return !logwarning; } else if (!S_ISREG(st_mode) || ! (confFilePtr = configFile(cfgFile, 1))) { // Open config file. LOG(LOG_WARNING, errno, "Config: Failed to open config file '%s'.", cfgFile); @@ -643,7 +639,7 @@ bool loadConfig(char *cfgFile) { LOG(LOG_WARNING, 0, "Config: Failed to include config from '%s'.", token + 1); configFile(confFilePtr, 2); } else if (strcmp(" chroot", token) == 0 && nextToken(token) && (STARTUP || (token[1] = '\0'))) { - if (! (conf.chroot = malloc(strlen(token)))) // Freed by signalHandler() or Self + if (! (conf.chroot = malloc(strlen(token)))) // Freed by igmpProxyCleanUp() or Self LOG(LOG_ERR, eNOMEM, "Config: Out of Memory."); memcpy(conf.chroot, token + 1, strlen(token)); if (stat(token + 1, &st) != 0 && !(stat(dirname(token + 1), &st) == 0 && mkdir(conf.chroot, 0770) == 0)) { @@ -726,8 +722,8 @@ bool loadConfig(char *cfgFile) { if (intToken < 8 || intToken > 131072) LOG(LOG_WARNING, 0, "Config: hashtablesize must be 8 to 131072 bytes (multiples of 8)."); else { - conf.dHostsHTSize = (intToken - intToken % 8) * 8; - LOG(LOG_NOTICE, 0, "Config: Hash table size for quickleave is %d.", conf.dHostsHTSize / 8); + conf.dHostsHTSize = intToken % 8 == 0 ? intToken : intToken + (8 - (intToken % 8)); + LOG(LOG_NOTICE, 0, "Config: Hash table size for quickleave is %d.", conf.dHostsHTSize); } } else if (strcmp(" defaultupdown", token) == 0) { @@ -862,7 +858,7 @@ bool loadConfig(char *cfgFile) { else if ((! ((fp = fopen(token + 1, "w")) && (t = token + 1)) && ! (fp = fopen(t, "w"))) || fclose(fp) != 0) LOG(LOG_WARNING, errno, "Config: Cannot open log file '%s'.", token + 1); else if (! (conf.logFilePath = realloc(conf.logFilePath, strlen(token)))) - // Freed by signalHandler() + // Freed by igmpProxyCleanUp() or igmpProxyInit() LOG(LOG_ERR, eNOMEM, "loadConfig: Out of Memory."); else { strcpy(conf.logFilePath, t); @@ -888,12 +884,10 @@ bool loadConfig(char *cfgFile) { // Token may be " " if parsePhyintToken() returns without valid token. LOG(LOG_WARNING, 0, "Config: Unknown token '%s' in config file '%s'.", token + 1, cfgFile); } - // Close the configfile. When including files, we're done. Decrease count when file has loaded. Reset common flag. _free(token, var, MAX_TOKEN_LENGTH + READ_BUFFER_SIZE + 2 * sizeof(uint32_t)); // Alloced by self if (confFilePtr && (confFilePtr = configFile(NULL, 0))) LOG(LOG_WARNING, errno, "Config: Failed to close config file (%d) '%s'.", conf.cnt, cfgFile); - if (--conf.cnt > 0 || logwarning) return !logwarning; @@ -911,9 +905,10 @@ bool loadConfig(char *cfgFile) { } // Check if buffer sizes have changed. - if (CONFRELOAD && (conf.kBufsz != oldconf.kBufsz || conf.pBufsz != oldconf.pBufsz)) + if (mrt_tbl >= 0 && (CONFRELOAD || SHUP) && (conf.kBufsz != oldconf.kBufsz || conf.pBufsz != oldconf.pBufsz)) { initIgmp(false); - + initIgmp(true); + } // Check rescanvif status and start or clear timers if necessary. if (conf.rescanVif && timers.rescanVif == 0) { timers.rescanVif = timer_setTimer(conf.rescanVif * 10, "Rebuild Interfaces", rebuildIfVc, &timers.rescanVif); @@ -921,7 +916,6 @@ bool loadConfig(char *cfgFile) { timer_clearTimer(timers.rescanVif); timers.rescanVif = 0; } - // Check rescanconf status and start or clear timers if necessary. if (conf.rescanConf && timers.rescanConf == 0) { timers.rescanConf = timer_setTimer(conf.rescanConf * 10, "Reload Configuration", reloadConfig, &timers.rescanConf); @@ -929,7 +923,6 @@ bool loadConfig(char *cfgFile) { timer_clearTimer(timers.rescanConf); timers.rescanConf = 0; } - // Check bwcontrol status and start or clear timers if necessary.. if (oldconf.bwControlInterval != conf.bwControlInterval) { timer_clearTimer(timers.bwControl); @@ -941,7 +934,7 @@ bool loadConfig(char *cfgFile) { LOG(LOG_WARNING, errno, "Config: MRT_API_CONFIG Failed. Disabling bandwidth control."); conf.bwControlInterval = 0; } else if (!STARTUP) - clearGroups(getConfig); + clearGroups(CONF); #endif if (conf.bwControlInterval) timers.bwControl = timer_setTimer(conf.bwControlInterval * 10, "Bandwidth Control", @@ -1125,10 +1118,10 @@ void configureVifs(void) { } // Check if quickleave was enabled or disabled due to config change. - if ((CONFRELOAD || SHUP) && oldconf.dHostsHTSize != conf.dHostsHTSize) { - LOG(LOG_WARNING, 0, "configureVifs: Downstream host hashtable size changed from %d to %d, reinitializing group tables.", + if ((CONFRELOAD || SHUP) && oldconf.dHostsHTSize != conf.dHostsHTSize && mrt_tbl >= 0) { + LOG(LOG_WARNING, 0, "configureVifs: Downstream host hashtable size changed from %d to %d, restarting.", oldconf.dHostsHTSize, conf.dHostsHTSize); - clearGroups(&conf); + sighandled |= GOT_SIGURG; } // All vifs created / updated, check if there is an upstream and at least one downstream. diff --git a/src/ifvc.c b/src/ifvc.c index 21e5219..1b68c8e 100644 --- a/src/ifvc.c +++ b/src/ifvc.c @@ -74,11 +74,9 @@ void rebuildIfVc(uint64_t *tid) { sigstatus |= GOT_SIGUSR2; if (! IfDescL || IFREBUILD || SHUP || STARTUP) buildIfVc(); - // Call configureVifs to link the new IfDesc table. LOG(LOG_INFO,0,"rebuildIfVc: Configuring MC vifs."); configureVifs(); - // Free removed interfaces. freeIfDescL(); diff --git a/src/igmp.c b/src/igmp.c index a9666ba..fec6c38 100644 --- a/src/igmp.c +++ b/src/igmp.c @@ -64,7 +64,7 @@ int initIgmp(bool activate) { if (!activate) { _free(rcv_buf, rcv, memuse.rcv); // Alloced by Self _free(snd_buf, snd, memuse.snd); // Alloced by Self - if (fd != -1 && !RESTART) + if (fd != -1 && !RESTART && !SHUP && !CONFRELOAD) fd = k_disableMRouter(); return fd; } @@ -180,12 +180,12 @@ void acceptIgmp(int fd) { #endif #ifdef IGMPMSG_WRONGVIF case IGMPMSG_WRONGVIF: - LOG(LOG_NOTICE, 0, "Received WRONGVIF Upcall for Src %s Dst %s on %s.", + LOG(LOG_NOTICE, 0, "WRONGVIF Upcall for Src %s Dst %s on %s.", inetFmt(igmpMsg->im_src.s_addr, 1), inetFmt(igmpMsg->im_dst.s_addr, 2), IfDp->Name); return; #endif default: - LOG(LOG_NOTICE, 0, "Received unsupported upcall %d.", igmpMsg->im_msgtype); + LOG(LOG_NOTICE, 0, "Unsupported upcall %d.", igmpMsg->im_msgtype); return; } } else for (cmsgPtr = CMSG_FIRSTHDR(&msgHdr); cmsgPtr; cmsgPtr = CMSG_NXTHDR(&msgHdr, cmsgPtr)) @@ -211,14 +211,14 @@ void acceptIgmp(int fd) { register uint16_t cksum = igmp->igmp_cksum; igmp->igmp_cksum = 0; if (iphdrlen + ipdatalen != recvlen) - LOG(LOG_NOTICE, 0, "acceptIgmp: received packet from %s shorter (%u bytes) than hdr+data length (%u+%u).", - inetFmt(src, 1), recvlen, iphdrlen, ipdatalen); + LOG(LOG_NOTICE, 0, "Packet from %s shorter (%u bytes) than hdr+data length (%u+%u).", + inetFmt(src, 1), recvlen, iphdrlen, ipdatalen); else if ((ipdatalen < IGMP_MINLEN) || (igmp->igmp_type == IGMP_V3_MEMBERSHIP_REPORT && ipdatalen <= IGMPV3_MINLEN)) - LOG(LOG_NOTICE, 0, "acceptIgmp: received IP data field too short (%u bytes) for IGMP, from %s.", - ipdatalen, inetFmt(src, 1)); + LOG(LOG_NOTICE, 0, "IP data field too short (%u bytes) for IGMP, from %s.", + ipdatalen, inetFmt(src, 1)); else if (IfDp->conf->cksumVerify && cksum != inetChksum((uint16_t *)igmp, ipdatalen)) - LOG(LOG_NOTICE, 0, "acceptIgmp: Received packet from: %s for: %s on: %s checksum incorrect.", - inetFmt(src, 1), inetFmt(dst, 2), IfDp->Name); + LOG(LOG_NOTICE, 0, "Packet from: %s for: %s on: %s checksum incorrect.", + inetFmt(src, 1), inetFmt(dst, 2), IfDp->Name); else { struct igmpv3_query *igmpv3 = (struct igmpv3_query *)(rcv_buf + iphdrlen); struct igmpv3_report *igmpv3gr = (struct igmpv3_report *)(rcv_buf + iphdrlen); @@ -272,12 +272,14 @@ void sendIgmp(struct IfDesc *IfDp, struct igmpv3_query *query) { int len = 0; struct sockaddr_in sdst; - if (IS_DISABLED(IfDp->state) || !IQUERY) { + if (IfDp->conf->tbl != mrt_tbl) + LOG(LOG_ERR, eABNRML, "Requested to send packet on table %d interface %s.", IfDp->conf->tbl, IfDp->Name); + else if (IS_DISABLED(IfDp->state) || !IQUERY) { LOG(LOG_NOTICE, 0, "Not sending query for %s on %s interface %s.", inetFmt(query->igmp_group.s_addr, 1), IS_DISABLED(IfDp->state) ? "disabled" : "non querier", IfDp->Name); return; } else if (query && (IfDp->querier.ver == 1 || (IfDp->querier.ver == 2 && query->igmp_nsrcs > 0))) { - LOG(LOG_NOTICE, 0, "Request to send group specific query on %s while in v%d mode, not sending.", + LOG(LOG_NOTICE, 0, "Not sending group and source specific query on %s while in v%d mode.", IfDp->Name, IfDp->querier.ver); return; } @@ -360,10 +362,8 @@ static void acceptMemberQuery(struct IfDesc *IfDp, uint32_t src, uint32_t dst, s : ((getIgmpExp(IfDp->querier.qqi, 1) * IfDp->querier.qrv) * 10) + getIgmpExp(IfDp->querier.mrc, 1) / 2; else if (ver == 2) - timeout = dst == allhosts_group ? (IfDp->conf->qry.interval * IfDp->conf->qry.robustness * 10) - + igmpv3->igmp_code / 2 - : ((IfDp->querier.qqi * IfDp->querier.qrv * 10) * 10) - + IfDp->querier.mrc / 2; + timeout = dst == allhosts_group ? (IfDp->conf->qry.interval*IfDp->conf->qry.robustness*10) + igmpv3->igmp_code / 2 + : ((IfDp->querier.qqi*IfDp->querier.qrv*10) * 10) + IfDp->querier.mrc / 2; else timeout = (100 * IfDp->conf->qry.robustness) + 5; // Set timeout for other querier. diff --git a/src/igmpv3proxy.c b/src/igmpv3proxy.c index ceeec8d..35d83f0 100644 --- a/src/igmpv3proxy.c +++ b/src/igmpv3proxy.c @@ -50,7 +50,7 @@ static void igmpProxyRun(void); volatile sig_atomic_t sighandled; // Should be as private as possible. uint8_t sigstatus, logwarning; struct timespec curtime, utcoff, starttime; -char *rcv_buf = NULL, *fileName, tS[32], tE[32], RUNPATH[] = RUN_PATHS, CFGPATH[] = CFG_PATHS; +char *rcv_buf = NULL, *fileName, tS[32], tE[32]; struct memstats memuse = { 0 }, memalloc = { 0 }, memfree = { 0 }; static struct pollfd pollFD[2] = { {-1, POLLIN, 0}, {-1, POLLIN, 0} }; const struct timespec nto = { 0, 0 }; @@ -64,7 +64,7 @@ struct chld chld = { 0 }; */ int main(int ArgCn, char *ArgVc[]) { int c = 0, i = 0, j = 0, tbl = 0; - char *opts[2] = { ArgVc[0], NULL }, cmd[20] = "", *path = NULL; + char *opts[2] = { ArgVc[0], NULL }, cmd[20] = "", *path; struct stat st; fileName = basename(ArgVc[0]); @@ -154,7 +154,7 @@ int main(int ArgCn, char *ArgVc[]) { fprintf(stderr, "%s: Must be started as root.\n", fileName); exit(-1); } else if (! (CONF->configFilePath = calloc(1, sizeof(CFG_PATHS) + strlen(ArgVc[optind - !(optind == ArgCn - 1)])))) { - // Freed by signalHandler() + // Freed by igmpProxyInit() or igmpProxyCleanUp() fprintf(stderr, "%s. Out of Memory.\n", fileName); exit(-1); } else if (optind == ArgCn - 1 && !(stat(ArgVc[optind], &st) == 0 && (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)))) { @@ -164,23 +164,28 @@ int main(int ArgCn, char *ArgVc[]) { } else if (optind == ArgCn - 1) { strcpy(CONF->configFilePath, ArgVc[optind]); } else { - for (path = strtok(CFGPATH, " "); path && strcpy(CONF->configFilePath, path); path = strtok(NULL, " ")) { + fprintf(stderr, "%s: Looking for %s.conf config in default locations:", fileName, fileName); + for (i = 0, path = strtok(CFG_PATHS, " "); path && strcpy(CONF->configFilePath, path); path = strtok(NULL, " ")) { // Search for config in default locations. if (stat(strcat(strcat(CONF->configFilePath, fileName), ".conf"), &st) == 0) break; - path[strlen(CONF->configFilePath) - 5] = '/'; - path[strlen(CONF->configFilePath) - 4] = '\0'; + fprintf(stderr, " %s", CONF->configFilePath); + CONF->configFilePath[strlen(CONF->configFilePath) - 5] = '/'; + CONF->configFilePath[strlen(CONF->configFilePath) - 4] = '\0'; if (stat(strcat(strcat(CONF->configFilePath, fileName), ".conf"), &st) == 0) break; + fprintf(stderr, " %s", CONF->configFilePath); } - if (! path) { - fprintf(stderr, "%s. Config file path not found in %s.\n", fileName, CFG_PATHS); + if (path) + fprintf(stderr, "\n%s: Found %s\n", fileName, CONF->configFilePath); + else { + fprintf(stderr, "\n%s: None found\n", fileName); exit(-1); } } // Check for valid location to place socket and PID file. - for (path = strtok(RUNPATH, " "); path; path = strtok(NULL, " ")) { + for (path = strtok(RUN_PATHS, " "); path; path = strtok(NULL, " ")) { if (stat(path, &st) >= 0) { if (! (CONF->runPath = malloc(strlen(path) + strlen(fileName) + 8))) fprintf(stderr, "Out of memory."); // Freed by igmpProxyCleanup() @@ -424,11 +429,16 @@ static void igmpProxyInit(void) { // Switch root if chroot is configured. The config file must be placed there. if (CONF->chroot) { // Truncate config and log file path to /. - char *b = basename(CONF->configFilePath); - strcpy(CONF->configFilePath, b); + char *b, *c; + if (! (b = basename(CONF->configFilePath)) || ! (c = calloc(1, strlen(b) + 1)) || ! strcpy(c, b)) + LOG(LOG_ERR, eNOMEM, "Out of Memory."); + free(CONF->configFilePath); // Alloced by main() + CONF->configFilePath = c; if (CONF->logFilePath) { - b = basename(CONF->logFilePath); - strcpy(CONF->logFilePath, b); + if (! (b = basename(CONF->logFilePath)) || ! (c = calloc(1, strlen(b) + 1)) || ! strcpy(c, b)) + LOG(LOG_ERR, eNOMEM, "Out of Memory."); + free(CONF->logFilePath); // Alloced by loadConfig() + CONF->logFilePath = c; } // Link the root to the run directory and set runpath to /. if (symlink(CONF->chroot, strcat(CONF->runPath, "root")) != 0 && errno != EEXIST) @@ -495,7 +505,7 @@ void igmpProxyCleanUp(int code) { remove(rFile); sprintf(rFile, "%scli.sock", CONF->runPath); remove(rFile); - if (rmdir(CONF->runPath) < 0) + if (! CONF->chroot && rmdir(CONF->runPath) < 0) LOG(LOG_WARNING, errno, "Cannot remove run dir %s.", CONF->runPath); } if (!RESTART) diff --git a/src/igmpv3proxy.h b/src/igmpv3proxy.h index 1175f32..656d389 100644 --- a/src/igmpv3proxy.h +++ b/src/igmpv3proxy.h @@ -77,8 +77,8 @@ //################################################################################# // 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/" +static char RUN_PATHS[]="/run /var/run /tmp /var/tmp"; +static char CFG_PATHS[]="/etc/ /usr/local/etc/ /var/etc/ /usr/local/var/etc/"; struct Config { uint8_t cnt; // Daemon parameters. @@ -345,9 +345,11 @@ static const char *exitmsg[16] = { "gave up", "terminated abnormally", "was term // 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 _realloc(p,m,sp,sm) (((p=realloc(p,sp)) && (memuse.m+=(-(sm) + (sp))) > 0 && (++memalloc.m > 0) && (++memfree.m > 0)) \ + || getMemStats(0,-1)) +#define _recalloc(p,m,sp,sm) (((p=realloc(p,sp)) && (sp <= sm || memset((char *)p + (sm), 0, (sp) - (sm))) \ + && (memuse.m+=(-(sm) + (sp))) > 0 && (++memalloc.m > 0) && (++memfree.m > 0)) \ + || getMemStats(0,-1)) #define _free(p, m, s) if (p) { \ if ((memuse.m-=(s)) < 0 || (++memfree.m <= 0)) { \ getMemStats(0,-1); \ diff --git a/src/mctable.c b/src/mctable.c index f9e0a28..b753151 100644 --- a/src/mctable.c +++ b/src/mctable.c @@ -207,7 +207,6 @@ struct ifMct *delGroup(struct mcTable* mct, struct IfDesc *IfDp, struct ifMct *i } else { // Group can be removed from table. uint32_t mctHash = murmurhash3(mct->group) % CONF->mcTables; - LOG(LOG_DEBUG, 0, "delGroup: Deleting group %s from table %d.",inetFmt(mct->group, 1), mctHash); // Send Leave requests upstream. GETIFLIF(IfDp, IS_SET(mct, u, IfDp)) @@ -653,37 +652,24 @@ void clearGroups(void *Dp) { struct ifMct *imc; struct mcTable *mct; struct IfDesc *IfDp = Dp != CONF && Dp != getConfig ? Dp : NULL; - register uint8_t oldstate = IF_OLDSTATE(IfDp), newstate = IF_NEWSTATE(IfDp); + register uint8_t oldstate = IfDp ? IF_OLDSTATE(IfDp) : 0, newstate = IfDp ? IF_NEWSTATE(IfDp) : 0; - if (Dp == CONF || Dp == getConfig || (!IS_UPSTREAM(oldstate) && IS_UPSTREAM(newstate))) { + if (Dp == CONF || (!IS_UPSTREAM(oldstate) && IS_UPSTREAM(newstate))) { GETMRT(mct) { - if (Dp == CONF) { - struct src **src; - // Quickleave was enabled or disabled, or hastable size was changed. - // Reallocate appriopriate amount of memory and reinitialize downstreahosts tracking. - FOR_IF(src = &(mct->sources); *src; src = &(*src)->next, ! _recalloc(*src, src, SRCSZ, OSRCSZ)) - LOG(LOG_ERR, eNOMEM, "clearGroups: Out of memory."); - if (! _recalloc(mct, mct, MCESZ, OMCESZ)) - LOG(LOG_ERR, eNOMEM, "clearGroups: Out of memory."); - if (! mct->prev) - MCT[iz] = mct; - else - mct->prev->next = mct; - if (mct->next) - mct->next->prev = mct; + if (!IS_UPSTREAM(oldstate) && IS_UPSTREAM(newstate) && addGroup(mct, IfDp, 0, 1, (uint32_t)-1)) { + // New upstream interface join all relevant groups and sources. + for (struct src *src = mct->sources; src; joinBlockSrc(src, IfDp, true), src = src->next); #ifdef HAVE_STRUCT_BW_UPCALL_BU_SRC - } else if (Dp == getConfig) { + } else if (Dp == CONF) { // BW control interval was changed. Reinitialize all bw_upcalls. for (struct mfc *mfc = mct->mfc; mfc; mfc = mfc->next) { k_deleteUpcalls(mfc->src->ip, mct->group); activateRoute(mfc->IfDp, mfc->src, 0, 0, true); } #endif - } else if (!IS_UPSTREAM(oldstate) && addGroup(mct, IfDp, 0, 1, (uint32_t)-1)) - // New upstream interface join all relevant groups and sources. - for (struct src *src = mct->sources; src; joinBlockSrc(src, IfDp, true), src = src->next); + } } - if (Dp == CONF || Dp == getConfig) + if (Dp == CONF || !IS_DOWNSTREAM(oldstate) || IFREBUILD) return; } @@ -896,7 +882,6 @@ void updateGroup(struct IfDesc *IfDp, uint32_t ip, struct igmpv3_grec *grec) { } startQuery(IfDp, qlst); - LOG(LOG_DEBUG, 0, "Updated group entry for %s on VIF #%d", inetFmt(group, 1), IfDp->index); logRouteTable("Update Group", 1, -1, group, (uint32_t)-1); } diff --git a/src/querier.c b/src/querier.c index 7fcfa05..5d40bd7 100644 --- a/src/querier.c +++ b/src/querier.c @@ -48,7 +48,8 @@ static uint32_t qC = 0; // Querier count. */ void ctrlQuerier(int start, struct IfDesc *IfDp) { if (IfDp->conf->tbl != mrt_tbl) - return; + LOG(LOG_ERR, eABNRML, "Requested to %s querier on table %d interface %s.", + !start ? "stop" : start == 1 ? "start" : "restart", IfDp->conf->tbl, IfDp->Name); if (start == 0 || start == 2) { // Remove all queries, timers and reset all IGMP status for interface. LOG(LOG_INFO, 0, "ctrlQuerier: Stopping querier process on %s", IfDp->Name);