summaryrefslogtreecommitdiffstats
path: root/plugin/firewall/iptables/efw-iptables.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugin/firewall/iptables/efw-iptables.c')
-rw-r--r--plugin/firewall/iptables/efw-iptables.c192
1 files changed, 79 insertions, 113 deletions
diff --git a/plugin/firewall/iptables/efw-iptables.c b/plugin/firewall/iptables/efw-iptables.c
index 8e90ac4..ed0ec9d 100644
--- a/plugin/firewall/iptables/efw-iptables.c
+++ b/plugin/firewall/iptables/efw-iptables.c
@@ -47,6 +47,16 @@
#define INTERFACEVER "1.0" /**< The version of this firewall interface (driver) */
#define INTERFACEAPIVER 1 /**< Define the API level this firewall interface uses. */
+static const char *eFWmode_str[7] = {
+ "ADD",
+ "DELETE",
+ "BLACKLIST",
+ "FLUSH",
+ "INITIALISE",
+ "SHUTDOWN",
+ NULL
+};
+
/**
* Mandatory function, contains driver information.
*
@@ -67,8 +77,8 @@ int eFWinterfaceAPIversion() {
}
-int process_input(eurephiaCTX *ctx, const char *fwcmd, const char *msg);
-int call_iptables(eurephiaCTX *ctx, const char *fwcmd, char **ipt_args);
+int process_input(eurephiaCTX *ctx, const char *fwcmd, const eFWupdateRequest *req);
+int call_iptables(eurephiaCTX *ctx, const char *fwcmd, const char **ipt_args);
/**
@@ -81,7 +91,7 @@ void eFW_RunFirewall(void *fwargs) {
eurephiaCTX *ctx = (eurephiaCTX *) cfg->ctx;
int quit = 0;
unsigned int prio;
- char buf[EFW_MSG_SIZE+2];
+ eFWupdateRequest req;
struct timespec tsp;
DEBUG(ctx, 28, "eFW_RunFirewall: Waiting for eFW master to get ready");
@@ -100,25 +110,26 @@ void eFW_RunFirewall(void *fwargs) {
// Main loop ... grab messages of the messague queue until shutdown command is sent, or a failure happens
while( quit == 0 ) {
- memset(buf, 0, EFW_MSG_SIZE+2);
- if( mq_receive(cfg->msgq, &buf[0], EFW_MSG_SIZE, &prio) == -1 ) {
+ memset(&req, 0, sizeof(req));
+ if( mq_receive(cfg->msgq, (char *)&req, EFW_MSG_SIZE, &prio) == -1 ) {
eurephia_log(ctx, LOG_FATAL, 0,
"eFW_RunFirewall: Error while reading messages from queue: %s",
strerror(errno));
exit(2);
}
- quit = (strncmp(buf, "FWSHUTDOWN", 10) == 0 );
- if( !quit ) {
+ if( req.mode != fwSHUTDOWN ) {
int res = 0;
- DEBUG(ctx, 20, "eFW_RunFirewall: Received '%s'", buf);
+ DEBUG(ctx, 20, "eFW_RunFirewall: Received %s", eFWmode_str[req.mode]);
- res = process_input(ctx, cfg->fw_command, buf);
+ res = process_input(ctx, cfg->fw_command, &req);
if( ! res ) {
quit = 1;
eurephia_log(ctx, LOG_FATAL, 0,
"eFW_RunFirewall: Failed updating iptables");
}
+ } else {
+ quit = 1;
}
}
@@ -160,151 +171,106 @@ void eFW_RunFirewall(void *fwargs) {
* @return Returns 1 on success, otherwise 0. If 0 is sent, it means the firewall process should shut down,
* and it should only be used in very critical situations.
*/
-int process_input(eurephiaCTX *ctx, const char *fwcmd, const char *input) {
- char mode[3], *addr = NULL, *destchain = NULL, *jump = NULL;
- char *msg = NULL, *orig_msg = NULL;
- char *iptables_args[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
- int ret = 0;
+int process_input(eurephiaCTX *ctx, const char *fwcmd, const eFWupdateRequest *req) {
+ const char *iptables_args[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
+ int ret = 0;
- orig_msg = strdup_nullsafe(input);
- msg = orig_msg;
- DEBUG(ctx, 36, "eFW_RunFirewall::process_input(ctx, '%s')", msg);
+ DEBUG(ctx, 36, "eFW_RunFirewall::process_input(ctx, %s, %s, %s, %s, %s)",
+ eFWmode_str[req->mode], req->ipaddress, req->macaddress,
+ req->rule_destination, req->goto_destination);
//
// Simple parsing of the input string
//
- mode[0] = '-';
- mode[1] = *msg;
- mode[2] = 0;
- msg += 2;
-
iptables_args[0] = (char *)fwcmd;
- switch( mode[1] ) {
- case 'A':
- case 'D':
- iptables_args[1] = mode;
- addr = msg; // start of string for macaddr
-
- // Search for end of macaddr and NULL terminate it
- destchain = addr+1;
- while( (*destchain != 0x20) || (*destchain == 0) ) {
- destchain++;
+ switch( req->mode ) {
+ case fwADD:
+ iptables_args[1] = "-A";
+ case fwDELETE:
+ if( iptables_args[1] == NULL ) {
+ iptables_args[1] = "-D";
}
- if( *destchain == 0 ) {
- return 0;
+ // Prepare iptables arguments
+ iptables_args[2] = req->rule_destination;
+ if( req->ipaddress ) {
+ iptables_args[3] = "-s\0";
+ iptables_args[4] = req->ipaddress;
}
- *destchain = 0; // end of string for macaddr
- destchain++; // start of string for destchain
- // Search for end of destchain and NULL terminate it
- jump = destchain+1;
- while( (*jump != 0x20) || (*jump == 0) ) {
- jump++;
+ if( req->macaddress ) {
+ iptables_args[3] = "-m\0";
+ iptables_args[4] = "mac\0";
+ iptables_args[5] = "--mac-source\0";
+ iptables_args[6] = req->macaddress;
}
- *jump = 0; // end of string for destchain
- jump++; // start of string for jump
-
- // Prepare iptables arguments
- iptables_args[2] = destchain;
- iptables_args[3] = "-m\0";
- iptables_args[4] = "mac\0";
- iptables_args[5] = "--mac-source\0";
- iptables_args[6] = addr;
iptables_args[7] = "-m\0";
iptables_args[8] = "state\0";
iptables_args[9] = "--state\0";
iptables_args[10] = "NEW\0";
iptables_args[11] = "-j\0";
- iptables_args[12] = jump;
+ iptables_args[12] = req->goto_destination;
iptables_args[13] = NULL;
eurephia_log(ctx, LOG_INFO, 3, "eFW_RunFirewall - updating iptables rules "
- "==> mode: %s macaddr: '%s' destchain: '%s' jump: '%s'",
- (mode[1] == 'A' ? "ADD":"DELETE"), addr, destchain, jump);
+ "==> mode: %s ipaddr: %s macaddr: '%s' destchain: '%s' jump: '%s'",
+ eFWmode_str[req->mode], req->ipaddress, req->macaddress,
+ req->rule_destination, req->goto_destination);
ret = call_iptables(ctx, fwcmd, iptables_args);
break;
- case 'B':
- addr = msg; // start of string for IP address to block
-
- // Search for end of IP address and NULL terminate it
- destchain = addr+1;
- while( (*destchain != 0x20) || (*destchain == 0) ) {
- destchain++;
- }
- if( *destchain == 0 ) {
- return 0;
- }
- *destchain = 0; // end of string for IP address
- destchain++; // start of string for destchain
-
- // Search for end of destchain and NULL terminate it
- jump = destchain+1;
- while( (*jump != 0x20) || (*jump == 0) ) {
- jump++;
- }
- *jump = 0; // end of string for destchain
- jump++; // start of string for jump
- if( *jump == 0 ) {
- return 0;
- }
-
+ case fwBLACKLIST:
iptables_args[1] = "-A\0";
- iptables_args[2] = destchain;
+ iptables_args[2] = req->rule_destination;
iptables_args[3] = "-s\0";
- iptables_args[4] = addr;
+ iptables_args[4] = req->ipaddress;
iptables_args[5] = "-j\0";
- iptables_args[6] = jump;
+ iptables_args[6] = strlen_nullsafe(req->goto_destination) > 0
+ ? req->goto_destination : "DROP\0";
iptables_args[7] = NULL;
eurephia_log(ctx, LOG_INFO, 3, "eFW_RunFirewall - updating iptables rules "
"==> mode: BLACKLIST destchain: '%s' IP address: %s Send to: '%s'",
- destchain, addr, jump);
- ret = call_iptables(ctx, fwcmd, iptables_args);
+ req->rule_destination, req->ipaddress, req->goto_destination);
+ ret = call_iptables(ctx, fwcmd, iptables_args);
break;
- case 'F':
- iptables_args[1] = mode;
- destchain = msg;
- iptables_args[2] = destchain;
- iptables_args[3] = NULL;
+ case fwFLUSH:
+ iptables_args[1] = "-F\0";
+ iptables_args[2] = req->rule_destination;
+ iptables_args[3] = NULL;
eurephia_log(ctx, LOG_INFO, 3, "eFW_RunFirewall - updating iptables rules "
- "==> mode: FLUSH destchain: '%s'", destchain);
- ret = call_iptables(ctx, fwcmd, iptables_args);
+ "==> mode: FLUSH destchain: '%s'", req->rule_destination);
+ ret = call_iptables(ctx, fwcmd, iptables_args);
break;
- case 'I':
- // Init chain - flush it and then add needed rule for stateful inspection
- destchain = msg;
-
+ case fwINITIALISE:
+ // Init chain - flush it and then add needed rule for stateful inspection
eurephia_log(ctx, LOG_INFO, 3, "eFW_RunFirewall - Initialising iptables chain '%s'",
- destchain);
-
- // Flush phase
- iptables_args[1] = "-F";
- destchain = msg;
- iptables_args[2] = destchain;
- iptables_args[3] = NULL;
- ret = call_iptables(ctx, fwcmd, iptables_args);
-
- // Add stateful inspection
- iptables_args[1] = "-I\0";
- iptables_args[2] = destchain;
- iptables_args[3] = "-m\0";
+ req->rule_destination);
+
+ // Flush phase
+ iptables_args[1] = "-F";
+ iptables_args[2] = req->rule_destination;
+ iptables_args[3] = NULL;
+ ret = call_iptables(ctx, fwcmd, iptables_args);
+
+ // Add stateful inspection
+ iptables_args[1] = "-I\0";
+ iptables_args[2] = req->rule_destination;
+ iptables_args[3] = "-m\0";
iptables_args[4] = "state\0";
iptables_args[5] = "--state\0";
iptables_args[6] = "ESTABLISHED,RELATED\0";
iptables_args[7] = "-j\0";
iptables_args[8] = "ACCEPT\0";
- ret &= call_iptables(ctx, fwcmd, iptables_args);
- break;
+ ret &= call_iptables(ctx, fwcmd, iptables_args);
+ break;
default:
eurephia_log(ctx, LOG_CRITICAL, 0, "eFW_RunFirewall::process_input: Malformed update request");
- ret = 1;
+ ret = 1;
}
- free_nullsafe(ctx, orig_msg);
- return ret;
+ return ret;
}
@@ -319,7 +285,7 @@ int process_input(eurephiaCTX *ctx, const char *fwcmd, const char *input) {
* @return Returns 1 on success, otherwise 0. When 0 is returned, the complete firewall process will be
* shut down.
*/
-int call_iptables(eurephiaCTX *ctx, const char *fwcmd, char **ipt_args) {
+int call_iptables(eurephiaCTX *ctx, const char *fwcmd, const char **ipt_args) {
pid_t pid;
int cmdret = -1;
@@ -333,7 +299,7 @@ int call_iptables(eurephiaCTX *ctx, const char *fwcmd, char **ipt_args) {
switch( pid ) {
case 0: // child process - execute the program and exit
- execve(fwcmd, ipt_args, NULL);
+ execve(fwcmd, (char * const*) ipt_args, NULL);
exit(1); // execve should replace the process, but if it fails to do so, make sure we exit
default: // parent process