]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
fix long-standing bug with regard to protocol-on-demand-loading and iptables-save...
authorHarald Welte <laforge@gnumonks.org>
Mon, 26 Aug 2002 12:21:44 +0000 (12:21 +0000)
committerHarald Welte <laforge@gnumonks.org>
Mon, 26 Aug 2002 12:21:44 +0000 (12:21 +0000)
iptables.c

index cd3c1fe20587c01a5a639905dea5786fd8294abb..fa570c5c297e71007ea84efb8d167d55866aca1e 100644 (file)
@@ -1659,6 +1659,7 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
        const char *jumpto = "";
        char *protocol = NULL;
        const char *modprobe = NULL;
+       int proto_used = 0;
 
        memset(&fw, 0, sizeof(fw));
 
@@ -1686,7 +1687,7 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
        opterr = 0;
 
        while ((c = getopt_long(argc, argv,
-          "-A:C:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:",
+          "-A:D:R:I:L::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvnt:m:xc:",
                                           opts, NULL)) != -1) {
                switch (c) {
                        /*
@@ -1839,20 +1840,6 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
                                exit_error(PARAMETER_PROBLEM,
                                           "rule would never match protocol");
                        fw.nfcache |= NFC_IP_PROTO;
-
-                       /* try to load match with protocol name */
-                       if ((m = find_proto(protocol, TRY_LOAD,
-                                           options&OPT_NUMERIC))) {
-                               size_t size;
-                               size = IPT_ALIGN(sizeof(struct ipt_entry_match))
-                                                + m->size;
-                               m->m = fw_calloc(1, size);
-                               m->m->u.match_size = size;
-                               strcpy(m->m->u.user.name, m->name);
-                               m->init(m->m, &fw.nfcache);
-                               opts = merge_options(opts, m->extra_opts, &m->option_offset);
-                       }
-
                        break;
 
                case 's':
@@ -2038,6 +2025,59 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
                                                     &m->m))
                                                break;
                                }
+
+                               /* If you listen carefully, you can
+                                  actually hear this code suck. */
+
+                               /* some explanations (after four different bugs
+                                * in 3 different releases): If we encountere a
+                                * parameter, that has not been parsed yet,
+                                * it's not an option of an explicitly loaded
+                                * match or a target.  However, we support
+                                * implicit loading of the protocol match
+                                * extension.  '-p tcp' means 'l4 proto 6' and
+                                * at the same time 'load tcp protocol match on
+                                * demand if we specify --dport'.
+                                *
+                                * To make this work, we need to make sure:
+                                * - the parameter has not been parsed by
+                                *   a match (m above)
+                                * - a protocol has been specified
+                                * - the protocol extension has not been
+                                *   loaded yet, or is loaded and unused
+                                *   [think of iptables-restore!]
+                                * - the protocol extension can be successively
+                                *   loaded
+                                */
+                               if (m == NULL
+                                   && protocol
+                                   && (!find_proto(protocol, DONT_LOAD,
+                                                  options&OPT_NUMERIC) 
+                                       || (find_proto(protocol, DONT_LOAD,
+                                                       options&OPT_NUMERIC)
+                                           && (proto_used == 0))
+                                      )
+                                   && (m = find_proto(protocol, TRY_LOAD,
+                                                      options&OPT_NUMERIC))) {
+                                       /* Try loading protocol */
+                                       size_t size;
+                                       
+                                       proto_used = 1;
+
+                                       size = IPT_ALIGN(sizeof(struct ipt_entry_match))
+                                                        + m->size;
+
+                                       m->m = fw_calloc(1, size);
+                                       m->m->u.match_size = size;
+                                       strcpy(m->m->u.user.name, m->name);
+                                       m->init(m->m, &fw.nfcache);
+
+                                       opts = merge_options(opts,
+                                           m->extra_opts, &m->option_offset);
+
+                                       optind--;
+                                       continue;
+                               }
                                if (!m)
                                        exit_error(PARAMETER_PROBLEM,
                                                   "Unknown arg `%s'",