Skip to content

Commit

Permalink
Enable CLI for Monitor
Browse files Browse the repository at this point in the history
  • Loading branch information
Uglymotha committed Jul 20, 2024
1 parent 7fe8eb7 commit be61b1e
Show file tree
Hide file tree
Showing 9 changed files with 194 additions and 179 deletions.
77 changes: 50 additions & 27 deletions src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,15 @@
static void cliSignalHandler(int sig);

// Daemon CLI socket address.
extern volatile sig_atomic_t sighandled; // From igmpv3proxy.c signal handler.
static int cli_fd = -1;
static struct sockaddr_un cli_sa;
extern volatile sig_atomic_t sighandled; // From igmpv3proxy.c signal handler.

/**
* Opens and binds a socket for cli connections.
*/
int openCliFd(void) {
struct stat st;
int cli_fd;

memset(&cli_sa, 0, sizeof(struct sockaddr_un));
cli_sa.sun_family = AF_UNIX;

Expand Down Expand Up @@ -86,66 +85,90 @@ int openCliFd(void) {
/**
* Close and unlink CLI socket.
*/
int closeCliFd(int fd) {
if (!RESTART) {
shutdown(fd, SHUT_RDWR);
close(fd);
unlink(cli_sa.sun_path);
return -1;
int closeCliFd(void) {
if (!RESTART && cli_fd >= 0) {
if (!STARTUP)
shutdown(cli_fd, SHUT_RDWR);
if (close(cli_fd) < 0)
LOG(LOG_WARNING, errno, "closeCliFd: CLOSE %s", cli_sa.sun_path);
else {
LOG(LOG_INFO, 0, "closeCliFd: Closed CLI socket %s.", cli_sa.sun_path);
cli_fd = -1;
}
if (!STARTUP)
unlink(cli_sa.sun_path);
}
return fd;
return cli_fd;
}

/**
* Processes an incoming cli connection. Requires the fd of the cli socket.
*/
void acceptCli(int fd)
void acceptCli(void)
{
int pid = 0, cli_fd = -1, len = 0, s = sizeof(struct sockaddr);
int pid = 0, fd = -1, len = 0, s = sizeof(struct sockaddr);
uint32_t addr = (uint32_t)-1, mask = (uint32_t)-1;
char buf[CLI_CMD_BUF] = {0}, msg[CLI_CMD_BUF];
struct sockaddr cli_sa;
struct IfDesc *IfDp = NULL;

// Receive and answer the cli request.
if ((cli_fd = accept(fd, &cli_sa, (socklen_t *)&s)) < 0) {
if ((fd = accept(cli_fd, &cli_sa, (socklen_t *)&s)) < 0) {
LOG(LOG_WARNING, errno, "acceptCli: Failed accept()");
return;
} else {
if ((len = recv(cli_fd, &buf, CLI_CMD_BUF, MSG_DONTWAIT)) <= 0 || len > CLI_CMD_BUF ||
if ((len = recv(fd, &buf, CLI_CMD_BUF, MSG_DONTWAIT)) <= 0 || len > CLI_CMD_BUF ||
(buf[0] == 'r' && len > 2 &&
(!parseSubnetAddress(&buf[buf[1] == 'h' ? 3 : 2], &addr, &mask) || !IN_MULTICAST(ntohl(addr))))) {
LOG(LOG_DEBUG, 0, "acceptCli: Invalid command received.");
} else if (buf[0] == 'c' || buf[0] == 'b') {
sighandled |= buf[0] == 'c' ? GOT_SIGUSR1 : GOT_SIGUSR2;
buf[0] == 'c' ? send(cli_fd, "Reloading Configuration.\n", 26, MSG_DONTWAIT)
: send(cli_fd, "Rebuilding Interfaces.\n", 24, MSG_DONTWAIT);
buf[0] == 'c' ? send(fd, "Reloading Configuration.\n", 26, MSG_DONTWAIT)
: send(fd, "Rebuilding Interfaces.\n", 24, MSG_DONTWAIT);
#ifdef __linux__
IF_FOR_IF(mrt_tbl < 0, int i = 0; i < chld.nr; i++, chld.c[i].pid > 0)
kill(chld.c[i].pid, buf[0] == 'c' ? SIGUSR1 : SIGUSR2);
#endif
} else if ((pid = fork()) != 0)
pid < 0 ? LOG(LOG_WARNING, eNOFORK, "Cannot fork().") : LOG(LOG_DEBUG, 0, "acceptCli: Forked PID: %d", pid);
if (pid != 0 || buf[0] == 'c' || buf[0] == 'b') {
close(cli_fd);
close(fd);
return;
}
}

if (buf[0] == 'r') {
logRouteTable("", buf[1] == 'h' ? 0 : 1, cli_fd, addr, mask);
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))) {
sprintf(msg, "Interface %s Not Found\n", &buf[buf[1] == 'h' ? 3 : 2]);
send(cli_fd, msg, strlen(msg), MSG_DONTWAIT);
send(fd, msg, strlen(msg), MSG_DONTWAIT);
} else if (buf[0] == 'i') {
getIfStats(IfDp, buf[1] == 'h' ? 0 : 1, cli_fd);
getIfStats(IfDp, buf[1] == 'h' ? 0 : 1, fd);
} else if (buf[0] == 'f') {
getIfFilters(IfDp, len > 1 && buf[1] == 'h' ? 0 : 1, cli_fd);
getIfFilters(IfDp, len > 1 && buf[1] == 'h' ? 0 : 1, fd);
} else if (buf[0] == 't') {
debugQueue("", len > 1 && buf[1] == 'h' ? 0 : 1, cli_fd);
debugQueue("", len > 1 && buf[1] == 'h' ? 0 : 1, fd);
} else if (buf[0] == 'm') {
getMemStats(buf[1] == 'h' ? 0 : 1, cli_fd);
getMemStats(buf[1] == 'h' ? 0 : 1, fd);
#ifdef __linux__
} else if (buf[0] == 'p' && mrt_tbl < 0) {
send(fd, "Currently Running Processes:\n", 29, MSG_DONTWAIT);
for (int i = 0; i < chld.nr; i++) {
if (chld.c[i].pid > 0)
sprintf(msg, "Table: %d - PID: %d\n", chld.c[i].tbl, chld.c[i].pid);
else
sprintf(msg, "Table: %d - %s\n", chld.c[i].tbl, exitmsg[chld.c[i].st]);
send(fd, msg, strlen(msg), MSG_DONTWAIT);
}
} else if (buf[0] == 'p' && mrt_tbl >= 0) {
sprintf(msg, "Table: %d - PID: %d\n", mrt_tbl, getppid());
send(fd, msg, strlen(msg), MSG_DONTWAIT);
#endif
} else
send(cli_fd, "GO AWAY\n", 9, MSG_DONTWAIT);
send(fd, "GO AWAY\n", 9, MSG_DONTWAIT);

// Close connection.
close(cli_fd);
close(fd);
LOG(LOG_DEBUG, 0, "acceptCli: Finished command %s.", buf);
exit(0);
}
Expand Down Expand Up @@ -181,13 +204,13 @@ void cliCmd(char *cmd, int tbl) {
while (path) {
sprintf(tpath, "%s/%s/root", path, fileName);
if (lstat(tpath, &st) == 0 && (S_ISLNK(st.st_mode) || S_ISDIR(st.st_mode))) {
if (tbl)
if (tbl != 0)
sprintf(srv_sa.sun_path, "/%s/%s/root/cli-%d.sock", path, fileName, tbl);
else
sprintf(srv_sa.sun_path, "/%s/%s/root/cli.sock", path, fileName);
break;
}
if (tbl)
if (tbl != 0)
sprintf(tpath, "%s/%s/cli-%d.sock", path, fileName, tbl);
else
sprintf(tpath, "%s/%s/cli.sock", path, fileName);
Expand Down
86 changes: 28 additions & 58 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ static inline void parseFilters(char *in, char *token, struct filters ***filP,
static inline bool parsePhyintToken(char *token);

// All valid configuration options. Prepend whitespace to allow for strstr() exact token matching.
static const char *options = " include phyint user group chroot defaultquickleave quickleave maxorigins hashtablesize routetables defaultdown defaultup defaultupdown defaultthreshold defaultratelimit defaultquerierver defaultquerierip defaultrobustness defaultqueryinterval defaultqueryrepsonseinterval defaultlastmemberinterval defaultlastmembercount bwcontrol rescanvif rescanconf loglevel logfile defaultproxylocalmc defaultnoquerierelection proxylocalmc noproxylocalmc upstream downstream disabled ratelimit threshold querierver querierip robustness queryinterval queryrepsonseinterval lastmemberinterval lastmembercount defaultnocksumverify nocksumverify cksumverify noquerierelection querierelection nocksumverify cksumverify noquerierelection querierelection defaultfilterany nodefaultfilter filter altnet whitelist reqqueuesize kbufsize pbufsize maxtbl defaulttable disableipmrules";
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";
static const char *options = " include phyint user group chroot defaultquickleave quickleave maxorigins hashtablesize routetables defaultdown defaultup defaultupdown defaultthreshold defaultratelimit defaultquerierver defaultquerierip defaultrobustness defaultqueryinterval defaultqueryrepsonseinterval defaultlastmemberinterval defaultlastmembercount bwcontrol rescanvif rescanconf loglevel logfile defaultproxylocalmc defaultnoquerierelection proxylocalmc noproxylocalmc upstream downstream disabled ratelimit threshold querierver querierip robustness queryinterval queryrepsonseinterval lastmemberinterval lastmembercount defaultnocksumverify nocksumverify cksumverify noquerierelection querierelection nocksumverify cksumverify noquerierelection querierelection defaultfilterany nodefaultfilter filter altnet whitelist reqqueuesize kbufsize pbufsize maxtbl defaulttable defaultdisableipmrules";
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;
Expand All @@ -62,11 +62,6 @@ uint32_t uVifs;
// Keeps timer ids for configurable timed functions.
static struct timers timers = { 0, 0, 0 };

// Keeps the tables seen in the config file.
#ifdef __linux__
static int *tbl = NULL, ntbl = 0, tblsz = 32 * sizeof(int);
#endif

// Macro to get a token which should be integer.
#define INTTOKEN ((nextToken(token)) && ((intToken = atoll(token + 1)) || !intToken))

Expand Down Expand Up @@ -404,25 +399,21 @@ static inline bool parsePhyintToken(char *token) {
else {
tmpPtr->tbl = intToken;
LOG(LOG_INFO, 0, "Config (%s): Assigning to table %d.", tmpPtr->name, intToken);
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) {
tbl[ntbl++] = CONF->defaultTable;
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);
}
}
if (intToken > 0 && mrt_tbl < 0)
igmpProxyFork(0);
if (mrt_tbl < 0) // Check again becasue of fork().
igmpProxyFork(intToken);
}
#else
LOG(LOG_NOTICE, 0, "Config (%s): Table id is only valid on linux.", tmpPtr->name);
#endif

} else if (strcmp(" disableipmrules", token) == 0) {
#ifdef __linux__
LOG(LOG_NOTICE, 0, "Config (%s): Will disable ip mrules.", tmpPtr->name);
tmpPtr->disableIpMrules = true;
#else
LOG(LOG_NOTICE, 0, "disableipmrules is ony valid for linux.");
#endif
} else if (strcmp(" updownstream", token) == 0) {
tmpPtr->state = IF_STATE_UPDOWNSTREAM;
LOG(LOG_NOTICE, 0, "Config (%s): Setting to Updownstream.", tmpPtr->name);
Expand Down Expand Up @@ -670,21 +661,10 @@ bool loadConfig(char *cfgFile) {
LOG(LOG_NOTICE, 0, "Config: Default table id should be between 0 and 999999999.");
else {
conf.defaultTable = intToken;
if (mrt_tbl < 0 && ntbl % 32 == 0 && ! _recalloc(tbl, var, ((ntbl / 32) + 1) * tblsz, (ntbl / 32) * tblsz))
// Freed by Self
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(0);
if (mrt_tbl < 0) // Check again because of fork().
igmpProxyFork(conf.defaultTable);
}
if (mrt_tbl < 0 && 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);
}
Expand All @@ -702,12 +682,12 @@ bool loadConfig(char *cfgFile) {
LOG(LOG_NOTICE, 0, "Config: Run as user '%s' is only valid for linux.", token + 1);
#endif

} else if (strcmp(" disableipmrules", token) == 0) {
} else if (strcmp(" defaultdisableipmrules", token) == 0) {
#ifdef __linux__
LOG(LOG_NOTICE, 0, "Config: Will disable ip mrules for mc route tables.");
conf.disableIpMrules = true;
#else
LOG(LOG_NOTICE, 0, "disableipmrules is ony valid for linux.");
LOG(LOG_NOTICE, 0, "defaultdisableipmrules is ony valid for linux.");
#endif
} else if (strcmp(" group", token) == 0 && nextToken(token) && (STARTUP || (token[1] = '\0'))) {
if (! (conf.group = getgrnam(token + 1)))
Expand Down Expand Up @@ -919,19 +899,6 @@ bool loadConfig(char *cfgFile) {
if (confFilePtr && (confFilePtr = configFile(NULL, 0)))
LOG(LOG_WARNING, errno, "Config: Failed to close config file (%d) '%s'.", conf.cnt, cfgFile);

#ifdef __linux__
IF_FOR_IF(mrt_tbl < 0 && chld.c && !logwarning, int i = 0; i < chld.nr; i++, chld.c[i].pid > 0) {
// Check if any proxy needs to be stopped because it is no longer used.
int j;
for (j = 0; j < ntbl && chld.c[i].tbl != tbl[j]; j++);
if (j >= ntbl) {
kill(chld.c[i].pid, SIGINT); // SIGINT so process will not be restarted in SIGCHLD
LOG(LOG_NOTICE, 0, "Stopping PID: %d (%d) for table %d.", chld.c[i].pid, i, chld.c[i].tbl);
}
}
_free(tbl, var, (((ntbl - 1) / 32) + 1) * tblsz); // Alloced by Self
tbl = NULL, ntbl = 0;
#endif
if (--conf.cnt > 0 || logwarning)
return !logwarning;

Expand Down Expand Up @@ -985,7 +952,10 @@ bool loadConfig(char *cfgFile) {
timers.bwControl = timer_setTimer(conf.bwControlInterval * 10, "Bandwidth Control",
bwControl, &timers.bwControl);
}

#ifdef __linux__
if (mrt_tbl < 0 && !chld.nr)
mrt_tbl = 0;
#endif
return !logwarning;
}

Expand Down Expand Up @@ -1129,11 +1099,11 @@ void configureVifs(void) {
}

// Do maintenance on vifs according to their old and new state.
if ( IS_DISABLED(oldstate) && IS_UPSTREAM(newstate) ) { ctrlQuerier(1, IfDp); clearGroups(IfDp); }
else if ( IS_DISABLED(oldstate) && IS_DOWNSTREAM(newstate)) { ctrlQuerier(1, IfDp); }
else if (!IS_DISABLED(oldstate) && IS_DISABLED(newstate) ) { ctrlQuerier(0, IfDp); clearGroups(IfDp); }
else if ( oldstate != newstate) { ctrlQuerier(2, IfDp); clearGroups(IfDp); }
else if ( oldstate == newstate && !IS_DISABLED(newstate) ) { if (!IFREBUILD) clearGroups(IfDp); }
if ( IS_DISABLED(oldstate) && IS_UPSTREAM(newstate)) { ctrlQuerier(1, IfDp); clearGroups(IfDp); }
else if ((STARTUP || IS_DISABLED(oldstate)) && IS_DOWNSTREAM(newstate)) { ctrlQuerier(1, IfDp); }
else if (!STARTUP && !IS_DISABLED(oldstate) && IS_DISABLED(newstate)) { ctrlQuerier(0, IfDp); clearGroups(IfDp); }
else if (!STARTUP && oldstate != newstate) { ctrlQuerier(2, IfDp); clearGroups(IfDp); }
else if ( oldstate == newstate && !IS_DISABLED(newstate)) { if (!IFREBUILD) clearGroups(IfDp); }
IfDp->filCh = false;

// Check if vif needs to be removed.
Expand Down
50 changes: 22 additions & 28 deletions src/ifvc.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,15 @@ static struct IfDesc *IfDescL = NULL;
/**
* Frees the IfDesc table and cleans up on interface removal.
*/
void freeIfDescL(bool force) {
void freeIfDescL(void) {
struct IfDesc *IfDp = IfDescL, *fIfDp;
while (IfDp) {
if (force || IfDp->state & 0x80 || (IfDp->next && IfDp->next->state & 0x80)) {
if (SHUTDOWN || IfDp->state & 0x80 || (IfDp->next && IfDp->next->state & 0x80)) {
// Remove interface marked for deletion.
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)
LOG(LOG_NOTICE, 0, "Interface %s was removed.", IfDp->state & 0x80 ? IfDp->Name : IfDp->next->Name);
fIfDp = SHUTDOWN || (IfDp->state & 0x80) ? IfDescL : IfDp->next;
if (SHUTDOWN || IfDp->state & 0x80)
IfDescL = IfDp = IfDp->next;
else
IfDp->next = IfDp->next->next;
Expand All @@ -81,10 +80,10 @@ void rebuildIfVc(uint64_t *tid) {
configureVifs();

// Free removed interfaces.
freeIfDescL(false);
freeIfDescL();

// Restart timer when doing timed reload.
if (CONF->rescanVif && tid)
if (!SHUTDOWN && CONF->rescanVif && tid)
*tid = timer_setTimer(CONF->rescanVif * 10, "Rebuild Interfaces", rebuildIfVc, tid);
if (IFREBUILD || STARTUP) {
sigstatus &= ~GOT_SIGUSR2;
Expand Down Expand Up @@ -145,26 +144,21 @@ void buildIfVc(void) {
memset(&ifr, 0, sizeof(struct ifreq));
memcpy(ifr.ifr_name, tmpIfAddrsP->ifa_name, strlen(tmpIfAddrsP->ifa_name));

#ifdef __linux__
if (mrt_tbl < 0)
IfDp->mtu = 1;
else
#endif
if (ioctl(MROUTERFD, SIOCGIFMTU, &ifr) < 0) {
LOG(LOG_WARNING, errno, "Failed to get MTU for %s, disabling.", IfDp->Name);
IfDp->mtu = 0;
} else
IfDp->mtu = ifr.ifr_mtu;
// Enable multicast if necessary.
if (! (IfDp->Flags & IFF_MULTICAST)) {
ifr.ifr_flags = IfDp->Flags | IFF_MULTICAST;
if (ioctl(MROUTERFD, SIOCSIFFLAGS, &ifr) < 0)
LOG(LOG_WARNING, errno, "Failed to enable multicast on %s, disabling.", IfDp->Name);
else {
IfDp->Flags = ifr.ifr_flags;
LOG(LOG_NOTICE, 0, "Multicast enabled on %s.", IfDp->Name);
}
}
if (ioctl(MROUTERFD, SIOCGIFMTU, &ifr) < 0) {
LOG(LOG_WARNING, errno, "Failed to get MTU for %s, disabling.", IfDp->Name);
IfDp->mtu = 0;
} else
IfDp->mtu = ifr.ifr_mtu;
// Enable multicast if necessary.
if (! (IfDp->Flags & IFF_MULTICAST)) {
ifr.ifr_flags = IfDp->Flags | IFF_MULTICAST;
if (ioctl(MROUTERFD, SIOCSIFFLAGS, &ifr) < 0)
LOG(LOG_WARNING, errno, "Failed to enable multicast on %s, disabling.", IfDp->Name);
else {
IfDp->Flags = ifr.ifr_flags;
LOG(LOG_NOTICE, 0, "Multicast enabled on %s.", IfDp->Name);
}
}

// Log the result...
LOG(LOG_INFO, 0, "buildIfVc: Interface %s, IP: %s/%d, Flags: 0x%04x, MTU: %d",
Expand Down
4 changes: 4 additions & 0 deletions src/igmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ int initIgmp(bool activate) {
}
if (fd == -1)
fd = k_enableMRouter();
#ifdef __linux__
if (mrt_tbl < 0)
return fd;
#endif
if (! _calloc(rcv_buf, 1, rcv, CONF->pBufsz) || ! _calloc(snd_buf, 1, snd, CONF->pBufsz))
LOG(LOG_ERR, eNOMEM, "initIgmp: Out of Memory."); // Freed by Self
struct ip *ip = (struct ip *)snd_buf;
Expand Down
Loading

0 comments on commit be61b1e

Please sign in to comment.