diff --git a/system/iptables/Kconfig b/system/iptables/Kconfig index 171b52ed0..a98f00771 100644 --- a/system/iptables/Kconfig +++ b/system/iptables/Kconfig @@ -29,4 +29,9 @@ config SYSTEM_IPTABLES_STACKSIZE int "iptables & ip6tables stack size" default DEFAULT_TASK_STACKSIZE +config SYSTEM_IPTABLES_LOCK_FILE_PATH + string "File lock path to prevent concurrent overwrite" + default "/tmp/iptables.lock" + depends on FS_LOCK_BUCKET_SIZE > 0 + endif diff --git a/system/iptables/iptables.c b/system/iptables/iptables.c index 673559634..367519a34 100644 --- a/system/iptables/iptables.c +++ b/system/iptables/iptables.c @@ -26,6 +26,7 @@ #include +#include #include #include @@ -33,17 +34,62 @@ #include "iptables.h" #include "netutils/netlib.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#if CONFIG_FS_LOCK_BUCKET_SIZE == 0 +# define iptables_lock() 0 +# define iptables_unlock(fd) (void)(fd) +#endif + /**************************************************************************** * Private Types ****************************************************************************/ typedef CODE int - (*iptables_command_func_t)(FAR const struct iptables_args_s *args); +(*iptables_command_func_t)(FAR const struct iptables_args_s *args); /**************************************************************************** * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: iptables_lock / iptables_unlock + * + * Description: + * Lock and unlock iptables to prevent concurrent overwrite. + * + ****************************************************************************/ + +#if CONFIG_FS_LOCK_BUCKET_SIZE > 0 +static int iptables_lock(void) +{ + struct flock lock; + int lockfd; + + lockfd = open(CONFIG_SYSTEM_IPTABLES_LOCK_FILE_PATH, O_CREAT | O_RDWR, + 0666); + if (lockfd < 0) + { + return lockfd; + } + + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = 0; + lock.l_len = 0; + fcntl(lockfd, F_SETLKW, &lock); + + return lockfd; +} + +static int iptables_unlock(int lockfd) +{ + return close(lockfd); +} +#endif + /**************************************************************************** * Name: iptables_addr2str * @@ -485,6 +531,7 @@ static int iptables_apply(FAR const struct iptables_args_s *args, int main(int argc, FAR char *argv[]) { struct iptables_args_s args; + int lock; int ret = iptables_parse(&args, argc, argv); if (ret < 0 || args.cmd == COMMAND_INVALID) @@ -493,6 +540,13 @@ int main(int argc, FAR char *argv[]) return ret; } + lock = iptables_lock(); + if (lock < 0) + { + printf("Failed to lock iptables!\n"); + return lock; + } + #ifdef CONFIG_NET_IPFILTER if (args.table == NULL || strcmp(args.table, XT_TABLE_NAME_FILTER) == 0) { @@ -520,5 +574,7 @@ int main(int argc, FAR char *argv[]) printf("Unknown table: %s\n", args.table); } + iptables_unlock(lock); + return ret; }