*
* This code is distributed under the terms of GNU GPL v2
*
- * $Id: iptables-restore.c,v 1.26 2003/05/02 15:30:11 laforge Exp $
+ * $Id: iptables-restore.c 3980 2005-06-12 15:54:15Z /C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=kaber/emailAddress=kaber@netfilter.org $
*/
#include <getopt.h>
static struct option options[] = {
{ "binary", 0, 0, 'b' },
{ "counters", 0, 0, 'c' },
- { "verbose", 1, 0, 'v' },
+ { "verbose", 0, 0, 'v' },
+ { "test", 0, 0, 't' },
{ "help", 0, 0, 'h' },
{ "noflush", 0, 0, 'n'},
{ "modprobe", 1, 0, 'M'},
static void print_usage(const char *name, const char *version)
{
- fprintf(stderr, "Usage: %s [-b] [-c] [-v] [-h]\n"
+ fprintf(stderr, "Usage: %s [-b] [-c] [-v] [-t] [-h]\n"
" [ --binary ]\n"
" [ --counters ]\n"
" [ --verbose ]\n"
+ " [ --test ]\n"
" [ --help ]\n"
" [ --noflush ]\n"
" [ --modprobe=<command>]\n", name);
int parse_counters(char *string, struct ipt_counters *ctr)
{
- if (string != NULL)
- return (sscanf(string, "[%llu:%llu]", &ctr->pcnt, &ctr->bcnt)
- == 2);
- else
- return (0 == 2);
+ return (sscanf(string, "[%llu:%llu]", (unsigned long long *)&ctr->pcnt, (unsigned long long *)&ctr->bcnt) == 2);
}
/* global new argv and argc */
free(newargv[i]);
}
-int main(int argc, char *argv[])
+#ifdef IPTABLES_MULTI
+int
+iptables_restore_main(int argc, char *argv[])
+#else
+int
+main(int argc, char *argv[])
+#endif
{
iptc_handle_t handle = NULL;
char buffer[10240];
char curtable[IPT_TABLE_MAXNAMELEN + 1];
FILE *in;
const char *modprobe = 0;
- int in_table = 0;
+ int in_table = 0, testing = 0;
program_name = "iptables-restore";
program_version = IPTABLES_VERSION;
line = 0;
+ lib_dir = getenv("IPTABLES_LIB_DIR");
+ if (!lib_dir)
+ lib_dir = IPT_LIB_DIR;
+
#ifdef NO_SHARED_LIBS
init_extensions();
#endif
- while ((c = getopt_long(argc, argv, "bcvhnM:", options, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "bcvthnM:", options, NULL)) != -1) {
switch (c) {
case 'b':
binary = 1;
case 'v':
verbose = 1;
break;
+ case 't':
+ testing = 1;
+ break;
case 'h':
print_usage("iptables-restore",
IPTABLES_VERSION);
int ret = 0;
line++;
- if (buffer[0] == '\n') continue;
+ if (buffer[0] == '\n')
+ continue;
else if (buffer[0] == '#') {
- if (verbose) fputs(buffer, stdout);
+ if (verbose)
+ fputs(buffer, stdout);
continue;
} else if ((strcmp(buffer, "COMMIT\n") == 0) && (in_table)) {
- DEBUGP("Calling commit\n");
- ret = iptc_commit(&handle);
+ if (!testing) {
+ DEBUGP("Calling commit\n");
+ ret = iptc_commit(&handle);
+ } else {
+ DEBUGP("Not calling commit, testing\n");
+ ret = 1;
+ }
in_table = 0;
} else if ((buffer[0] == '*') && (!in_table)) {
/* New table */
exit(1);
}
strncpy(curtable, table, IPT_TABLE_MAXNAMELEN);
+ curtable[IPT_TABLE_MAXNAMELEN] = '\0';
if (handle)
iptc_free(&handle);
exit(1);
}
- if (!iptc_builtin(chain, handle)) {
- DEBUGP("Creating new chain '%s'\n", chain);
- if (!iptc_create_chain(chain, &handle))
- exit_error(PARAMETER_PROBLEM,
- "error creating chain "
- "'%s':%s\n", chain,
- strerror(errno));
+ if (iptc_builtin(chain, handle) <= 0) {
+ if (noflush && iptc_is_chain(chain, handle)) {
+ DEBUGP("Flushing existing user defined chain '%s'\n", chain);
+ if (!iptc_flush_entries(chain, &handle))
+ exit_error(PARAMETER_PROBLEM,
+ "error flushing chain "
+ "'%s':%s\n", chain,
+ strerror(errno));
+ } else {
+ DEBUGP("Creating new chain '%s'\n", chain);
+ if (!iptc_create_chain(chain, &handle))
+ exit_error(PARAMETER_PROBLEM,
+ "error creating chain "
+ "'%s':%s\n", chain,
+ strerror(errno));
+ }
}
policy = strtok(NULL, " \t\n");
for (curchar = parsestart; *curchar; curchar++) {
if (*curchar == '"') {
- if (quote_open) {
+ /* quote_open cannot be true if there
+ * was no previous character. Thus,
+ * curchar-1 has to be within bounds */
+ if (quote_open &&
+ *(curchar-1) != '\\') {
quote_open = 0;
*curchar = ' ';
} else {
exit(1);
}
}
+ if (in_table) {
+ fprintf(stderr, "%s: COMMIT expected at line %u\n",
+ program_name, line + 1);
+ exit(1);
+ }
return 0;
}