detailed information on the rule or rules to be printed. \fB\-v\fP may be
specified multiple times to possibly emit more detailed debug statements.
.TP
+\fB\-w\fP, \fB\-\-wait\fP
+Wait for the xtables lock.
+To prevent multiple instances of the program from running concurrently,
+an attempt will be made to obtain an exclusive lock at launch. By default,
+the program will exit if the lock cannot be obtained. This option will
+make the program wait until the exclusive lock can be obtained.
+.TP
\fB\-n\fP, \fB\-\-numeric\fP
Numeric output.
IP addresses and port numbers will be printed in numeric format.
{.name = "numeric", .has_arg = 0, .val = 'n'},
{.name = "out-interface", .has_arg = 1, .val = 'o'},
{.name = "verbose", .has_arg = 0, .val = 'v'},
+ {.name = "wait", .has_arg = 0, .val = 'w'},
{.name = "exact", .has_arg = 0, .val = 'x'},
{.name = "version", .has_arg = 0, .val = 'V'},
{.name = "help", .has_arg = 2, .val = 'h'},
" network interface name ([+] for wildcard)\n"
" --table -t table table to manipulate (default: `filter')\n"
" --verbose -v verbose mode\n"
+" --wait -w wait for the xtables lock\n"
" --line-numbers print line numbers when listing\n"
" --exact -x expand numbers (display exact values)\n"
/*"[!] --fragment -f match second or further fragments only\n"*/
struct in6_addr *smasks = NULL, *dmasks = NULL;
int verbose = 0;
+ bool wait = false;
const char *chain = NULL;
const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL;
const char *policy = NULL, *newname = NULL;
opts = xt_params->orig_opts;
while ((cs.c = getopt_long(argc, argv,
- "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:bvnt:m:xc:g:46",
+ "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:bvwnt:m:xc:g:46",
opts, NULL)) != -1) {
switch (cs.c) {
/*
verbose++;
break;
+ case 'w':
+ wait = true;
+ break;
+
case 'm':
command_match(&cs);
break;
"chain name `%s' too long (must be under %u chars)",
chain, XT_EXTENSION_MAXNAMELEN);
+ /* Attempt to acquire the xtables lock */
+ if (!xtables_lock(wait)) {
+ fprintf(stderr, "Another app is currently holding the xtables lock. "
+ "Perhaps you want to use the -w option?\n");
+ xtables_free_opts(1);
+ exit(RESOURCE_PROBLEM);
+ }
+
/* only allocate handle if we weren't called with a handle */
if (!*handle)
*handle = ip6tc_init(*table);
detailed information on the rule or rules to be printed. \fB\-v\fP may be
specified multiple times to possibly emit more detailed debug statements.
.TP
+\fB\-w\fP, \fB\-\-wait\fP
+Wait for the xtables lock.
+To prevent multiple instances of the program from running concurrently,
+an attempt will be made to obtain an exclusive lock at launch. By default,
+the program will exit if the lock cannot be obtained. This option will
+make the program wait until the exclusive lock can be obtained.
+.TP
\fB\-n\fP, \fB\-\-numeric\fP
Numeric output.
IP addresses and port numbers will be printed in numeric format.
{.name = "numeric", .has_arg = 0, .val = 'n'},
{.name = "out-interface", .has_arg = 1, .val = 'o'},
{.name = "verbose", .has_arg = 0, .val = 'v'},
+ {.name = "wait", .has_arg = 0, .val = 'w'},
{.name = "exact", .has_arg = 0, .val = 'x'},
{.name = "fragments", .has_arg = 0, .val = 'f'},
{.name = "version", .has_arg = 0, .val = 'V'},
" network interface name ([+] for wildcard)\n"
" --table -t table table to manipulate (default: `filter')\n"
" --verbose -v verbose mode\n"
+" --wait -w wait for the xtables lock\n"
" --line-numbers print line numbers when listing\n"
" --exact -x expand numbers (display exact values)\n"
"[!] --fragment -f match second or further fragments only\n"
struct in_addr *daddrs = NULL, *dmasks = NULL;
int verbose = 0;
+ bool wait = false;
const char *chain = NULL;
const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL;
const char *policy = NULL, *newname = NULL;
opts = xt_params->orig_opts;
while ((cs.c = getopt_long(argc, argv,
- "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:g:46",
+ "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvwnt:m:xc:g:46",
opts, NULL)) != -1) {
switch (cs.c) {
/*
verbose++;
break;
+ case 'w':
+ wait = true;
+ break;
+
case 'm':
command_match(&cs);
break;
"chain name `%s' too long (must be under %u chars)",
chain, XT_EXTENSION_MAXNAMELEN);
+ /* Attempt to acquire the xtables lock */
+ if (!xtables_lock(wait)) {
+ fprintf(stderr, "Another app is currently holding the xtables lock. "
+ "Perhaps you want to use the -w option?\n");
+ xtables_free_opts(1);
+ exit(RESOURCE_PROBLEM);
+ }
+
/* only allocate handle if we weren't called with a handle */
if (!*handle)
*handle = iptc_init(*table);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
#include <xtables.h>
#include "xshared.h"
+#define XT_SOCKET_NAME "xtables"
+#define XT_SOCKET_LEN 8
+
/*
* Print out any special helps. A user might like to be able to add a --help
* to the commandline, and see expected results. So we call help for all
if (match->init != NULL)
match->init(match->m);
}
+
+bool xtables_lock(bool wait)
+{
+ int i = 0, ret, xt_socket;
+ struct sockaddr_un xt_addr;
+
+ memset(&xt_addr, 0, sizeof(xt_addr));
+ xt_addr.sun_family = AF_UNIX;
+ strcpy(xt_addr.sun_path+1, XT_SOCKET_NAME);
+ xt_socket = socket(AF_UNIX, SOCK_STREAM, 0);
+ /* If we can't even create a socket, fall back to prior (lockless) behavior */
+ if (xt_socket < 0)
+ return true;
+
+ while (1) {
+ ret = bind(xt_socket, (struct sockaddr*)&xt_addr,
+ offsetof(struct sockaddr_un, sun_path)+XT_SOCKET_LEN);
+ if (ret == 0)
+ return true;
+ else if (wait == false)
+ return false;
+ if (++i % 2 == 0)
+ fprintf(stderr, "Another app is currently holding the xtables lock; "
+ "waiting for it to exit...\n");
+ sleep(1);
+ }
+}
#define IPTABLES_XSHARED_H 1
#include <limits.h>
+#include <stdbool.h>
#include <stdint.h>
#include <netinet/in.h>
#include <net/if.h>
extern int subcmd_main(int, char **, const struct subcommand *);
extern void xs_init_target(struct xtables_target *);
extern void xs_init_match(struct xtables_match *);
+extern bool xtables_lock(bool wait);
extern const struct xtables_afinfo *afinfo;