iptables: Fix setting policy
[platform/upstream/connman.git] / src / iptables.c
index 9e56d0b..158dcf3 100644 (file)
@@ -1054,7 +1054,7 @@ static int iptables_delete_rule(struct connman_iptables *table,
 static int iptables_change_policy(struct connman_iptables *table,
                                const char *chain_name, const char *policy)
 {
-       GList *chain_head;
+       GList *chain_head, *chain_tail;
        struct connman_iptables_entry *entry;
        struct xt_entry_target *target;
        struct xt_standard_target *t;
@@ -1072,6 +1072,11 @@ static int iptables_change_policy(struct connman_iptables *table,
        if (entry->builtin < 0)
                return -EINVAL;
 
+       chain_tail = find_chain_tail(table, chain_name);
+       if (chain_tail == NULL)
+               return -EINVAL;
+
+       entry = chain_tail->prev->data;
        target = ipt_get_target(entry->entry);
 
        t = (struct xt_standard_target *)target;
@@ -1600,9 +1605,6 @@ static struct xtables_match *prepare_matches(struct connman_iptables *table,
        if (xt_m->init != NULL)
                xt_m->init(xt_m->m);
 
-       if (xt_m == xt_m->next)
-               goto done;
-
 #if XTABLES_VERSION_CODE > 5
        if (xt_m->x6_options != NULL)
                iptables_globals.opts =
@@ -1627,7 +1629,6 @@ static struct xtables_match *prepare_matches(struct connman_iptables *table,
                xt_m = NULL;
        }
 
-done:
        return xt_m;
 }
 
@@ -2310,6 +2311,14 @@ void flush_table(const char *name)
                        table->blob_entries->size,
                        flush_table_cb, &chains);
 
+
+       /*
+        * The offset update code is fragile and it works
+        * only safe if we remove elements and move forwards
+        * in the table.
+        */
+       chains = g_slist_reverse(chains);
+
        for (list = chains; list != NULL; list = list->next) {
                char *chain = list->data;