iptables-1.3.2-20050720
[iptables.git] / iptables-restore.c
index 79cb259..95e2cbe 100644 (file)
@@ -4,7 +4,7 @@
  *
  * 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>
@@ -27,7 +27,8 @@ static int binary = 0, counters = 0, verbose = 0, noflush = 0;
 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'},
@@ -38,10 +39,11 @@ static void print_usage(const char *name, const char *version) __attribute__((no
 
 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);
@@ -71,11 +73,7 @@ iptc_handle_t create_handle(const char *tablename, const char* modprobe )
 
 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 */
@@ -101,7 +99,13 @@ static void free_argv(void) {
                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];
@@ -109,17 +113,21 @@ int main(int argc, char *argv[])
        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;
@@ -130,6 +138,9 @@ int main(int argc, char *argv[])
                        case 'v':
                                verbose = 1;
                                break;
+                       case 't':
+                               testing = 1;
+                               break;
                        case 'h':
                                print_usage("iptables-restore",
                                            IPTABLES_VERSION);
@@ -162,13 +173,20 @@ int main(int argc, char *argv[])
                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 */
@@ -183,6 +201,7 @@ int main(int argc, char *argv[])
                                exit(1);
                        }
                        strncpy(curtable, table, IPT_TABLE_MAXNAMELEN);
+                       curtable[IPT_TABLE_MAXNAMELEN] = '\0';
 
                        if (handle)
                                iptc_free(&handle);
@@ -216,13 +235,22 @@ int main(int argc, char *argv[])
                                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");
@@ -322,7 +350,11 @@ int main(int argc, char *argv[])
                        
                        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 {
@@ -383,6 +415,11 @@ int main(int argc, char *argv[])
                        exit(1);
                }
        }
+       if (in_table) {
+               fprintf(stderr, "%s: COMMIT expected at line %u\n",
+                               program_name, line + 1);
+               exit(1);
+       }
 
        return 0;
 }