]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
Make sure to use matches in the order they are given when calling do_command() multip...
authorMartin Josefsson <gandalf@wlug.westbo.se>
Mon, 2 Feb 2004 20:01:18 +0000 (20:01 +0000)
committerMartin Josefsson <gandalf@wlug.westbo.se>
Mon, 2 Feb 2004 20:01:18 +0000 (20:01 +0000)
include/iptables.h
iptables-save.c
iptables.c

index 205984eb500261d5a5df1a64c7a26e0910972901..a0dda602223c3d6965ed21fda35cef1e9d37ae35 100644 (file)
@@ -4,6 +4,13 @@
 #include "iptables_common.h"
 #include "libiptc/libiptc.h"
 
+struct iptables_rule_match
+{
+       struct iptables_rule_match *next;
+
+       struct iptables_match *match;
+};
+
 /* Include file for additions: new matches and targets. */
 struct iptables_match
 {
@@ -50,7 +57,6 @@ struct iptables_match
        unsigned int option_offset;
        struct ipt_entry_match *m;
        unsigned int mflags;
-       unsigned int used;
 #ifdef NO_SHARED_LIBS
        unsigned int loaded; /* simulate loading so options are merged properly */
 #endif
@@ -134,7 +140,7 @@ enum ipt_tryload {
 };
 
 extern struct iptables_target *find_target(const char *name, enum ipt_tryload);
-extern struct iptables_match *find_match(const char *name, enum ipt_tryload);
+extern struct iptables_match *find_match(const char *name, enum ipt_tryload, struct iptables_rule_match **match);
 
 extern int delete_chain(const ipt_chainlabel chain, int verbose,
                        iptc_handle_t *handle);
index 90163b501aa1c0e67e5015200879591dcd7757cf..41173eaddf3438a74d671c94555d6828a74da3a2 100644 (file)
@@ -111,7 +111,7 @@ static int print_match(const struct ipt_entry_match *e,
                        const struct ipt_ip *ip)
 {
        struct iptables_match *match
-               = find_match(e->u.user.name, TRY_LOAD);
+               = find_match(e->u.user.name, TRY_LOAD, NULL);
 
        if (match) {
                printf("-m %s ", e->u.user.name);
index c438d604ddfb05656251447e467c96332e5bad84..2c6282a59c0fa3505bdaac617b9b5bb6e779139d 100644 (file)
@@ -661,7 +661,7 @@ parse_hostnetworkmask(const char *name, struct in_addr **addrpp,
 }
 
 struct iptables_match *
-find_match(const char *name, enum ipt_tryload tryload)
+find_match(const char *name, enum ipt_tryload tryload, struct iptables_rule_match **matches)
 {
        struct iptables_match *ptr;
 
@@ -678,7 +678,7 @@ find_match(const char *name, enum ipt_tryload tryload)
                if (dlopen(path, RTLD_NOW)) {
                        /* Found library.  If it didn't register itself,
                           maybe they specified target as match. */
-                       ptr = find_match(name, DONT_LOAD);
+                       ptr = find_match(name, DONT_LOAD, NULL);
 
                        if (!ptr)
                                exit_error(PARAMETER_PROBLEM,
@@ -702,15 +702,24 @@ find_match(const char *name, enum ipt_tryload tryload)
        }
 #endif
 
-       if (ptr)
-               ptr->used = 1;
+       if (ptr && matches) {
+               struct iptables_rule_match **i;
+               struct iptables_rule_match *newentry;
+
+               newentry = fw_malloc(sizeof(struct iptables_rule_match));
+
+               for (i = matches; *i; i = &(*i)->next);
+               newentry->match = ptr;
+               newentry->next = NULL;
+               *i = newentry;
+       }
 
        return ptr;
 }
 
 /* Christophe Burki wants `-p 6' to imply `-m tcp'.  */
 static struct iptables_match *
-find_proto(const char *pname, enum ipt_tryload tryload, int nolookup)
+find_proto(const char *pname, enum ipt_tryload tryload, int nolookup, struct iptables_rule_match **matches)
 {
        unsigned int proto;
 
@@ -718,9 +727,9 @@ find_proto(const char *pname, enum ipt_tryload tryload, int nolookup)
                char *protoname = proto_to_name(proto, nolookup);
 
                if (protoname)
-                       return find_match(protoname, tryload);
+                       return find_match(protoname, tryload, matches);
        } else
-               return find_match(pname, tryload);
+               return find_match(pname, tryload, matches);
 
        return NULL;
 }
@@ -1018,7 +1027,7 @@ register_match(struct iptables_match *me)
                exit(1);
        }
 
-       if (find_match(me->name, DONT_LOAD)) {
+       if (find_match(me->name, DONT_LOAD, NULL)) {
                fprintf(stderr, "%s: match `%s' already registered.\n",
                        program_name, me->name);
                exit(1);
@@ -1148,7 +1157,7 @@ print_match(const struct ipt_entry_match *m,
            const struct ipt_ip *ip,
            int numeric)
 {
-       struct iptables_match *match = find_match(m->u.user.name, TRY_LOAD);
+       struct iptables_match *match = find_match(m->u.user.name, TRY_LOAD, NULL);
 
        if (match) {
                if (match->print)
@@ -1364,20 +1373,16 @@ insert_entry(const ipt_chainlabel chain,
 }
 
 static unsigned char *
-make_delete_mask(struct ipt_entry *fw)
+make_delete_mask(struct ipt_entry *fw, struct iptables_rule_match *matches)
 {
        /* Establish mask for comparison */
        unsigned int size;
-       struct iptables_match *m;
+       struct iptables_rule_match *matchp;
        unsigned char *mask, *mptr;
 
        size = sizeof(struct ipt_entry);
-       for (m = iptables_matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               size += IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size;
-       }
+       for (matchp = matches; matchp; matchp = matchp->next)
+               size += IPT_ALIGN(sizeof(struct ipt_entry_match)) + matchp->match->size;
 
        mask = fw_calloc(1, size
                         + IPT_ALIGN(sizeof(struct ipt_entry_target))
@@ -1386,14 +1391,11 @@ make_delete_mask(struct ipt_entry *fw)
        memset(mask, 0xFF, sizeof(struct ipt_entry));
        mptr = mask + sizeof(struct ipt_entry);
 
-       for (m = iptables_matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
+       for (matchp = matches; matchp; matchp = matchp->next) {
                memset(mptr, 0xFF,
                       IPT_ALIGN(sizeof(struct ipt_entry_match))
-                      + m->userspacesize);
-               mptr += IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size;
+                      + matchp->match->userspacesize);
+               mptr += IPT_ALIGN(sizeof(struct ipt_entry_match)) + matchp->match->size;
        }
 
        memset(mptr, 0xFF,
@@ -1411,13 +1413,14 @@ delete_entry(const ipt_chainlabel chain,
             unsigned int ndaddrs,
             const struct in_addr daddrs[],
             int verbose,
-            iptc_handle_t *handle)
+            iptc_handle_t *handle,
+            struct iptables_rule_match *matches)
 {
        unsigned int i, j;
        int ret = 1;
        unsigned char *mask;
 
-       mask = make_delete_mask(fw);
+       mask = make_delete_mask(fw, matches);
        for (i = 0; i < nsaddrs; i++) {
                fw->ip.src.s_addr = saddrs[i].s_addr;
                for (j = 0; j < ndaddrs; j++) {
@@ -1616,20 +1619,16 @@ int iptables_insmod(const char *modname, const char *modprobe)
 
 static struct ipt_entry *
 generate_entry(const struct ipt_entry *fw,
-              struct iptables_match *matches,
+              struct iptables_rule_match *matches,
               struct ipt_entry_target *target)
 {
        unsigned int size;
-       struct iptables_match *m;
+       struct iptables_rule_match *matchp;
        struct ipt_entry *e;
 
        size = sizeof(struct ipt_entry);
-       for (m = matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               size += m->m->u.match_size;
-       }
+       for (matchp = matches; matchp; matchp = matchp->next)
+               size += matchp->match->m->u.match_size;
 
        e = fw_malloc(size + target->u.target_size);
        *e = *fw;
@@ -1637,18 +1636,28 @@ generate_entry(const struct ipt_entry *fw,
        e->next_offset = size + target->u.target_size;
 
        size = 0;
-       for (m = matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               memcpy(e->elems + size, m->m, m->m->u.match_size);
-               size += m->m->u.match_size;
+       for (matchp = matches; matchp; matchp = matchp->next) {
+               memcpy(e->elems + size, matchp->match->m, matchp->match->m->u.match_size);
+               size += matchp->match->m->u.match_size;
        }
        memcpy(e->elems + size, target, target->u.target_size);
 
        return e;
 }
 
+void clear_rule_matches(struct iptables_rule_match **matches)
+{
+       struct iptables_rule_match *matchp, *tmp;
+
+       for (matchp = *matches; matchp;) {
+               tmp = matchp->next;
+               free(matchp);
+               matchp = tmp;
+       }
+
+       *matches = NULL;
+}
+
 int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
 {
        struct ipt_entry fw, *e = NULL;
@@ -1664,6 +1673,8 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
        const char *pcnt = NULL, *bcnt = NULL;
        int ret = 1;
        struct iptables_match *m;
+       struct iptables_rule_match *matches = NULL;
+       struct iptables_rule_match *matchp;
        struct iptables_target *target = NULL;
        struct iptables_target *t;
        const char *jumpto = "";
@@ -1682,10 +1693,8 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
 
        /* clear mflags in case do_command gets called a second time
         * (we clear the global list of all matches for security)*/
-       for (m = iptables_matches; m; m = m->next) {
+       for (m = iptables_matches; m; m = m->next)
                m->mflags = 0;
-               m->used = 0;
-       }
 
        for (t = iptables_targets; t; t = t->next) {
                t->tflags = 0;
@@ -1826,7 +1835,7 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
 
                        /* iptables -p icmp -h */
                        if (!iptables_matches && protocol)
-                               find_match(protocol, TRY_LOAD);
+                               find_match(protocol, TRY_LOAD, NULL);
 
                        exit_printhelp();
 
@@ -1931,7 +1940,7 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
                                exit_error(PARAMETER_PROBLEM,
                                           "unexpected ! flag before --match");
 
-                       m = find_match(optarg, LOAD_MUST_SUCCEED);
+                       m = find_match(optarg, LOAD_MUST_SUCCEED, &matches);
                        size = IPT_ALIGN(sizeof(struct ipt_entry_match))
                                         + m->size;
                        m->m = fw_calloc(1, size);
@@ -2023,18 +2032,16 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
                                               argv, invert,
                                               &target->tflags,
                                               &fw, &target->t))) {
-                               for (m = iptables_matches; m; m = m->next) {
-                                       if (!m->used)
-                                               continue;
-
-                                       if (m->parse(c - m->option_offset,
+                               for (matchp = matches; matchp; matchp = matchp->next) {
+                                       if (matchp->match->parse(c - matchp->match->option_offset,
                                                     argv, invert,
-                                                    &m->mflags,
+                                                    &matchp->match->mflags,
                                                     &fw,
                                                     &fw.nfcache,
-                                                    &m->m))
+                                                    &matchp->match->m))
                                                break;
                                }
+                               m = matchp ? matchp->match : NULL;
 
                                /* If you listen carefully, you can
                                   actually hear this code suck. */
@@ -2062,13 +2069,13 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
                                if (m == NULL
                                    && protocol
                                    && (!find_proto(protocol, DONT_LOAD,
-                                                  options&OPT_NUMERIC) 
+                                                  options&OPT_NUMERIC, NULL
                                        || (find_proto(protocol, DONT_LOAD,
-                                                       options&OPT_NUMERIC)
+                                                       options&OPT_NUMERIC, NULL)
                                            && (proto_used == 0))
                                       )
                                    && (m = find_proto(protocol, TRY_LOAD,
-                                                      options&OPT_NUMERIC))) {
+                                                      options&OPT_NUMERIC, &matches))) {
                                        /* Try loading protocol */
                                        size_t size;
                                        
@@ -2097,12 +2104,8 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
                invert = FALSE;
        }
 
-       for (m = iptables_matches; m; m = m->next) {
-               if (!m->used)
-                       continue;
-
-               m->final_check(m->mflags);
-       }
+       for (matchp = matches; matchp; matchp = matchp->next)
+               matchp->match->final_check(matchp->match->mflags);
 
        if (target)
                target->final_check(target->tflags);
@@ -2220,7 +2223,7 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
                         * chain. */
                        find_target(jumpto, LOAD_MUST_SUCCEED);
                } else {
-                       e = generate_entry(&fw, iptables_matches, target->t);
+                       e = generate_entry(&fw, matches, target->t);
                }
        }
 
@@ -2235,7 +2238,7 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
                ret = delete_entry(chain, e,
                                   nsaddrs, saddrs, ndaddrs, daddrs,
                                   options&OPT_VERBOSE,
-                                  handle);
+                                  handle, matches);
                break;
        case CMD_DELETE_NUM:
                ret = iptc_delete_num_entry(chain, rulenum - 1, handle);
@@ -2296,5 +2299,7 @@ int do_command(int argc, char *argv[], char **table, iptc_handle_t *handle)
        if (verbose > 1)
                dump_entries(*handle);
 
+       clear_rule_matches(&matches);
+
        return ret;
 }