Rework zone flush logic
authorJo-Philipp Wich <jow@openwrt.org>
Mon, 11 Mar 2013 11:46:32 +0000 (12:46 +0100)
committerJo-Philipp Wich <jow@openwrt.org>
Mon, 11 Mar 2013 20:41:24 +0000 (21:41 +0100)
12 files changed:
defaults.c
defaults.h
forwards.c
ipsets.c
main.c
options.h
redirects.c
rules.c
utils.c
utils.h
zones.c
zones.h

index 7c04f1084eea60e7278c9169db37a22516a42906..8bf1aa366c174939025dad7d29116aa370c5c993 100644 (file)
@@ -33,10 +33,10 @@ static const struct chain default_chains[] = {
        C(ANY, FILTER, UNSPEC,        "delegate_input"),
        C(ANY, FILTER, UNSPEC,        "delegate_output"),
        C(ANY, FILTER, UNSPEC,        "delegate_forward"),
+       C(ANY, FILTER, UNSPEC,        "reject"),
        C(ANY, FILTER, CUSTOM_CHAINS, "input_rule"),
        C(ANY, FILTER, CUSTOM_CHAINS, "output_rule"),
        C(ANY, FILTER, CUSTOM_CHAINS, "forwarding_rule"),
-       C(ANY, FILTER, UNSPEC,        "reject"),
        C(ANY, FILTER, SYN_FLOOD,     "syn_flood"),
 
        C(V4,  NAT,    UNSPEC,        "delegate_prerouting"),
@@ -88,11 +88,15 @@ const struct fw3_option fw3_default_opts[] = {
 
 static bool
 print_chains(enum fw3_table table, enum fw3_family family,
-             const char *fmt, uint32_t flags,
+             const char *fmt, uint32_t *flags, uint32_t mask,
              const struct chain *chains, int n)
 {
        bool rv = false;
        const struct chain *c;
+       uint32_t f = flags ? flags[family == FW3_FAMILY_V6] : 0;
+
+       if (mask)
+               f &= mask;
 
        for (c = chains; n > 0; c++, n--)
        {
@@ -102,7 +106,7 @@ print_chains(enum fw3_table table, enum fw3_family family,
                if (c->table != table)
                        continue;
 
-               if ((c->flag != FW3_DEFAULT_UNSPEC) && !hasbit(flags, c->flag))
+               if ((c->flag != FW3_DEFAULT_UNSPEC) && !hasbit(f, c->flag))
                        continue;
 
                fw3_pr(fmt, c->name);
@@ -143,8 +147,6 @@ fw3_load_defaults(struct fw3_state *state, struct uci_package *p)
        defs->tcp_window_scaling   = true;
        defs->custom_chains        = true;
 
-       setbit(defs->flags, FW3_FAMILY_V4);
-
        uci_foreach_element(&p->sections, e)
        {
                s = uci_to_section(e);
@@ -163,28 +165,23 @@ fw3_load_defaults(struct fw3_state *state, struct uci_package *p)
                check_policy(e, &defs->policy_input, "input");
                check_policy(e, &defs->policy_output, "output");
                check_policy(e, &defs->policy_forward, "forward");
-
-               if (!defs->disable_ipv6)
-                       setbit(defs->flags, FW3_FAMILY_V6);
-
-               if (defs->custom_chains)
-                       setbit(defs->flags, FW3_DEFAULT_CUSTOM_CHAINS);
-
-               if (defs->syn_flood)
-                       setbit(defs->flags, FW3_DEFAULT_SYN_FLOOD);
        }
 }
 
 void
 fw3_print_default_chains(enum fw3_table table, enum fw3_family family,
-                         struct fw3_state *state)
+                         bool reload, struct fw3_state *state)
 {
+       bool rv;
        struct fw3_defaults *defs = &state->defaults;
        uint32_t custom_mask = ~0;
 
 #define policy(t) \
        ((t == FW3_TARGET_REJECT) ? "DROP" : fw3_flag_names[t])
 
+       if (family == FW3_FAMILY_V6 && defs->disable_ipv6)
+               return;
+
        if (table == FW3_TABLE_FILTER)
        {
                fw3_pr(":INPUT %s [0:0]\n", policy(defs->policy_input));
@@ -192,17 +189,26 @@ fw3_print_default_chains(enum fw3_table table, enum fw3_family family,
                fw3_pr(":OUTPUT %s [0:0]\n", policy(defs->policy_output));
        }
 
-       /* user chains already loaded, don't create again */
-       if (hasbit(state->defaults.running_flags, FW3_DEFAULT_CUSTOM_CHAINS))
+       /* Don't touch user chains on reload */
+       if (reload)
                delbit(custom_mask, FW3_DEFAULT_CUSTOM_CHAINS);
 
-       print_chains(table, family, ":%s - [0:0]\n", defs->flags & custom_mask,
-                    default_chains, ARRAY_SIZE(default_chains));
+       if (defs->custom_chains)
+               set(defs->flags, family, FW3_DEFAULT_CUSTOM_CHAINS);
+
+       if (defs->syn_flood)
+               set(defs->flags, family, FW3_DEFAULT_SYN_FLOOD);
+
+       rv = print_chains(table, family, ":%s - [0:0]\n", defs->flags, custom_mask,
+                         default_chains, ARRAY_SIZE(default_chains));
+
+       if (rv)
+               set(defs->flags, family, table);
 }
 
 void
 fw3_print_default_head_rules(enum fw3_table table, enum fw3_family family,
-                             struct fw3_state *state)
+                             bool reload, struct fw3_state *state)
 {
        int i;
        struct fw3_defaults *defs = &state->defaults;
@@ -212,7 +218,7 @@ fw3_print_default_head_rules(enum fw3_table table, enum fw3_family family,
                "forward", "forwarding",
        };
 
-       print_chains(table, family, "-A %s\n", 0,
+       print_chains(table, family, "-A %s\n", NULL, 0,
                     toplevel_rules, ARRAY_SIZE(toplevel_rules));
 
        switch (table)
@@ -278,7 +284,7 @@ fw3_print_default_head_rules(enum fw3_table table, enum fw3_family family,
 
 void
 fw3_print_default_tail_rules(enum fw3_table table, enum fw3_family family,
-                             struct fw3_state *state)
+                             bool reload, struct fw3_state *state)
 {
        struct fw3_defaults *defs = &state->defaults;
 
@@ -336,36 +342,37 @@ reset_policy(enum fw3_table table, enum fw3_target policy)
 
 void
 fw3_flush_rules(enum fw3_table table, enum fw3_family family,
-                bool pass2, struct fw3_state *state, enum fw3_target policy)
+                bool pass2, bool reload, struct fw3_state *state)
 {
        struct fw3_defaults *defs = &state->defaults;
        uint32_t custom_mask = ~0;
 
-       if (!hasbit(defs->running_flags, family))
+       if (!has(defs->flags, family, table))
                return;
 
        /* don't touch user chains on selective stop */
-       delbit(custom_mask, FW3_DEFAULT_CUSTOM_CHAINS);
+       if (reload)
+               delbit(custom_mask, FW3_DEFAULT_CUSTOM_CHAINS);
 
        if (!pass2)
        {
-               reset_policy(table, policy);
+               reset_policy(table, reload ? FW3_TARGET_DROP : FW3_TARGET_ACCEPT);
 
                print_chains(table, family, "-D %s\n",
-                            defs->running_flags & custom_mask,
+                            defs->flags, custom_mask,
                                         toplevel_rules, ARRAY_SIZE(toplevel_rules));
 
                print_chains(table, family, "-F %s\n",
-                            defs->running_flags & custom_mask,
+                            defs->flags, custom_mask,
                                         default_chains, ARRAY_SIZE(default_chains));
        }
        else
        {
                print_chains(table, family, "-X %s\n",
-                            defs->running_flags & custom_mask,
+                            defs->flags, custom_mask,
                                         default_chains, ARRAY_SIZE(default_chains));
 
-               delbit(defs->flags, family);
+               del(defs->flags, family, table);
        }
 }
 
index 9547acec0d10d7aebefa62806b01a6e4023a6d35..00144db23311c60bd4e2349f7228f5295bd323a6 100644 (file)
@@ -26,19 +26,18 @@ extern const struct fw3_option fw3_default_opts[];
 void fw3_load_defaults(struct fw3_state *state, struct uci_package *p);
 
 void fw3_print_default_chains(enum fw3_table table, enum fw3_family family,
-                              struct fw3_state *state);
+                              bool reload, struct fw3_state *state);
 
 void fw3_print_default_head_rules(enum fw3_table table, enum fw3_family family,
-                                  struct fw3_state *state);
+                                  bool reload, struct fw3_state *state);
 
 void fw3_print_default_tail_rules(enum fw3_table table, enum fw3_family family,
-                                  struct fw3_state *state);
+                                  bool reload, struct fw3_state *state);
 
 void fw3_set_defaults(struct fw3_state *state);
 
 void fw3_flush_rules(enum fw3_table table, enum fw3_family family,
-                     bool pass2, struct fw3_state *state,
-                     enum fw3_target policy);
+                     bool pass2, bool reload, struct fw3_state *state);
 
 void fw3_flush_all(enum fw3_table table);
 
index babf5e84ae3d1fdb5ff61eb021f0c9f496b41ff3..b7e056f220851eb79e6d4aaff9c5d2671765c35a 100644 (file)
@@ -86,9 +86,11 @@ fw3_load_forwards(struct fw3_state *state, struct uci_package *p)
                        continue;
                }
 
+               /* NB: forward family... */
                if (forward->_dest)
                {
-                       setbit(forward->_dest->flags, FW3_TARGET_ACCEPT);
+                       setbit(forward->_dest->flags[0], FW3_TARGET_ACCEPT);
+                       setbit(forward->_dest->flags[1], FW3_TARGET_ACCEPT);
 
                        if (forward->_src &&
                            (forward->_src->conntrack || forward->_dest->conntrack))
index 74706ff5f05dc2d3029d9c52fa4865549f832302..48aaa9c0100ede8b7d2aa4d5ca0938adeb38e653 100644 (file)
--- a/ipsets.c
+++ b/ipsets.c
@@ -379,9 +379,9 @@ fw3_destroy_ipsets(struct fw3_state *state, enum fw3_family family)
 
        list_for_each_entry_safe(s, tmp, &state->running_ipsets, running_list)
        {
-               delbit(s->running_flags, family);
+               del(s->flags, family, family);
 
-               if (fw3_no_family(s->running_flags))
+               if (fw3_no_family(s->flags[family == FW3_FAMILY_V6]))
                {
                        info(" * Deleting ipset %s", s->name);
 
diff --git a/main.c b/main.c
index 47951e64349593071a2f3d6067c51cb1a3517a69..c1f6505be173fd251110df27a56bca67655095b1 100644 (file)
--- a/main.c
+++ b/main.c
@@ -135,7 +135,7 @@ restore_pipe(enum fw3_family family, bool silent)
 static bool
 family_running(struct fw3_state *state, enum fw3_family family)
 {
-       return hasbit(state->defaults.running_flags, family);
+       return has(state->defaults.flags, family, family);
 }
 
 static bool
@@ -144,19 +144,13 @@ family_used(enum fw3_family family)
        return (use_family == FW3_FAMILY_ANY) || (use_family == family);
 }
 
-static bool
-family_loaded(struct fw3_state *state, enum fw3_family family)
-{
-       return hasbit(state->defaults.flags, family);
-}
-
 static void
 family_set(struct fw3_state *state, enum fw3_family family, bool set)
 {
        if (set)
-               setbit(state->defaults.flags, family);
+               set(state->defaults.flags, family, family);
        else
-               delbit(state->defaults.flags, family);
+               del(state->defaults.flags, family, family);
 }
 
 static int
@@ -167,7 +161,6 @@ stop(struct fw3_state *state, bool complete, bool reload)
        int rv = 1;
        enum fw3_family family;
        enum fw3_table table;
-       enum fw3_target policy = reload ? FW3_TARGET_DROP : FW3_TARGET_ACCEPT;
 
        if (!complete && !state->statefile)
        {
@@ -203,11 +196,11 @@ stop(struct fw3_state *state, bool complete, bool reload)
                        else
                        {
                                /* pass 1 */
-                               fw3_flush_rules(table, family, false, state, policy);
+                               fw3_flush_rules(table, family, false, reload, state);
                                fw3_flush_zones(table, family, false, reload, state);
 
                                /* pass 2 */
-                               fw3_flush_rules(table, family, true, state, policy);
+                               fw3_flush_rules(table, family, true, reload, state);
                                fw3_flush_zones(table, family, true, reload, state);
                        }
 
@@ -274,7 +267,7 @@ start(struct fw3_state *state, bool reload)
                        continue;
                }
 
-               if (!family_loaded(state, family) || !restore_pipe(family, false))
+               if (!restore_pipe(family, false))
                        continue;
 
                for (table = FW3_TABLE_FILTER; table <= FW3_TABLE_RAW; table++)
@@ -286,14 +279,14 @@ start(struct fw3_state *state, bool reload)
                             fw3_flag_names[family], fw3_flag_names[table]);
 
                        fw3_pr("*%s\n", fw3_flag_names[table]);
-                       fw3_print_default_chains(table, family, state);
-                       fw3_print_zone_chains(table, family, state);
-                       fw3_print_default_head_rules(table, family, state);
+                       fw3_print_default_chains(table, family, reload, state);
+                       fw3_print_zone_chains(table, family, reload, state);
+                       fw3_print_default_head_rules(table, family, reload, state);
                        fw3_print_rules(table, family, state);
                        fw3_print_redirects(table, family, state);
                        fw3_print_forwards(table, family, state);
-                       fw3_print_zone_rules(table, family, state);
-                       fw3_print_default_tail_rules(table, family, state);
+                       fw3_print_zone_rules(table, family, reload, state);
+                       fw3_print_default_tail_rules(table, family, reload, state);
                        fw3_pr("COMMIT\n");
                }
 
index 0bfb3e82daeeb87ec75edcf664e1fdc87641dfa5..9422f81b52991846d01e4805836c2dab3450f1f4 100644 (file)
--- a/options.h
+++ b/options.h
@@ -73,17 +73,16 @@ enum fw3_target
        FW3_TARGET_SRC_ACCEPT    = 12,
        FW3_TARGET_SRC_REJECT    = 13,
        FW3_TARGET_SRC_DROP      = 14,
-       FW3_TARGET_CUSTOM_CNS_V4 = 15,
-       FW3_TARGET_CUSTOM_CNS_V6 = 16,
+       FW3_TARGET_CUSTOM_CHAINS = 15,
 };
 
 enum fw3_default
 {
        FW3_DEFAULT_UNSPEC        = 0,
-       FW3_DEFAULT_CUSTOM_CHAINS = 17,
-       FW3_DEFAULT_SYN_FLOOD     = 18,
-       FW3_DEFAULT_MTU_FIX       = 19,
-       FW3_DEFAULT_DROP_INVALID  = 20,
+       FW3_DEFAULT_CUSTOM_CHAINS = 16,
+       FW3_DEFAULT_SYN_FLOOD     = 17,
+       FW3_DEFAULT_MTU_FIX       = 18,
+       FW3_DEFAULT_DROP_INVALID  = 19,
 };
 
 extern const char *fw3_flag_names[FW3_DEFAULT_DROP_INVALID + 1];
@@ -242,8 +241,7 @@ struct fw3_defaults
 
        bool disable_ipv6;
 
-       uint32_t flags;
-       uint32_t running_flags;
+       uint32_t flags[2];
 };
 
 struct fw3_zone
@@ -279,8 +277,7 @@ struct fw3_zone
 
        bool custom_chains;
 
-       uint32_t flags;
-       uint32_t running_flags;
+       uint32_t flags[2];
 };
 
 struct fw3_rule
@@ -398,8 +395,7 @@ struct fw3_ipset
 
        const char *external;
 
-       uint32_t flags;
-       uint32_t running_flags;
+       uint32_t flags[2];
 };
 
 struct fw3_include
index 23dc0341c8cdff5440f6719f143fdd7418f3678c..7cd26c8a078d94ac881bc20f62ab1e9bda2e7be2 100644 (file)
@@ -203,16 +203,16 @@ fw3_load_redirects(struct fw3_state *state, struct uci_package *p)
                                warn_elem(e, "has no source specified");
                        else
                        {
-                               setbit(redir->_src->flags, redir->target);
+                               set(redir->_src->flags, FW3_FAMILY_V4, redir->target);
                                redir->_src->conntrack = true;
                                valid = true;
                        }
 
                        if (redir->reflection && redir->_dest && redir->_src->masq)
                        {
-                               setbit(redir->_dest->flags, FW3_TARGET_ACCEPT);
-                               setbit(redir->_dest->flags, FW3_TARGET_DNAT);
-                               setbit(redir->_dest->flags, FW3_TARGET_SNAT);
+                               set(redir->_dest->flags, FW3_FAMILY_V4, FW3_TARGET_ACCEPT);
+                               set(redir->_dest->flags, FW3_FAMILY_V4, FW3_TARGET_DNAT);
+                               set(redir->_dest->flags, FW3_FAMILY_V4, FW3_TARGET_SNAT);
                        }
                }
                else
@@ -225,7 +225,7 @@ fw3_load_redirects(struct fw3_state *state, struct uci_package *p)
                                warn_elem(e, "has no src_dip option specified");
                        else
                        {
-                               setbit(redir->_dest->flags, redir->target);
+                               set(redir->_dest->flags, FW3_FAMILY_V4, redir->target);
                                redir->_dest->conntrack = true;
                                valid = true;
                        }
@@ -357,7 +357,7 @@ print_redirect(enum fw3_table table, enum fw3_family family,
                        return;
                }
 
-               setbit(redir->_ipset->flags, family);
+               set(redir->_ipset->flags, family, family);
        }
 
        fw3_foreach(proto, &redir->proto)
diff --git a/rules.c b/rules.c
index 77fe998f52edf6cb8dc4fae9e7d453c7989be46d..de6ddc9fbd70f957c4cde0a465ab4519a0325de1 100644 (file)
--- a/rules.c
+++ b/rules.c
@@ -161,8 +161,12 @@ fw3_load_rules(struct fw3_state *state, struct uci_package *p)
                        rule->target = FW3_TARGET_REJECT;
                }
 
+               /* NB: rule family... */
                if (rule->_dest)
-                       setbit(rule->_dest->flags, rule->target);
+               {
+                       setbit(rule->_dest->flags[0], rule->target);
+                       setbit(rule->_dest->flags[1], rule->target);
+               }
 
                list_add_tail(&rule->list, &state->rules);
                continue;
@@ -312,7 +316,7 @@ expand_rule(enum fw3_table table, enum fw3_family family,
                        return;
                }
 
-               setbit(rule->_ipset->flags, family);
+               set(rule->_ipset->flags, family, family);
        }
 
        list_for_each_entry(proto, &rule->proto, list)
diff --git a/utils.c b/utils.c
index ab1d68bbef66669b6955fe5af7c8c0d2ce3b8cbe..7f2dd6406b9641830c868081ed2be2a468df1e5a 100644 (file)
--- a/utils.c
+++ b/utils.c
@@ -356,7 +356,7 @@ fw3_read_statefile(void *state)
        char line[128];
        const char *p, *name;
 
-       uint32_t flags;
+       uint32_t flags[2];
 
        struct fw3_state *s = state;
        struct fw3_zone *zone;
@@ -380,17 +380,21 @@ fw3_read_statefile(void *state)
                if (!name)
                        continue;
 
-               p = strtok(NULL, " \t\n");
+               if (!(p = strtok(NULL, " \t\n")))
+                       continue;
 
-               if (!p)
+               flags[0] = strtoul(p, NULL, 16);
+
+               if (!(p = strtok(NULL, " \t\n")))
                        continue;
 
-               flags = strtoul(p, NULL, 16);
+               flags[1] = strtoul(p, NULL, 16);
 
                switch (type)
                {
                case FW3_TYPE_DEFAULTS:
-                       s->defaults.running_flags = flags;
+                       s->defaults.flags[0] = flags[0];
+                       s->defaults.flags[1] = flags[1];
                        break;
 
                case FW3_TYPE_ZONE:
@@ -405,7 +409,8 @@ fw3_read_statefile(void *state)
                                list_add_tail(&zone->list, &s->zones);
                        }
 
-                       zone->running_flags = flags;
+                       zone->flags[0] = flags[0];
+                       zone->flags[1] = flags[1];
                        list_add_tail(&zone->running_list, &s->running_zones);
                        break;
 
@@ -421,7 +426,8 @@ fw3_read_statefile(void *state)
                                list_add_tail(&ipset->list, &s->ipsets);
                        }
 
-                       ipset->running_flags = flags;
+                       ipset->flags[0] = flags[0];
+                       ipset->flags[1] = flags[1];
                        list_add_tail(&ipset->running_list, &s->running_ipsets);
                        break;
                }
@@ -441,7 +447,7 @@ fw3_write_statefile(void *state)
        struct fw3_zone *z;
        struct fw3_ipset *i;
 
-       if (fw3_no_family(d->flags))
+       if (fw3_no_table(d->flags[0]) && fw3_no_table(d->flags[1]))
        {
                if (unlink(FW3_STATEFILE))
                        warn("Unable to remove state %s: %s",
@@ -458,16 +464,24 @@ fw3_write_statefile(void *state)
                return;
        }
 
-       fprintf(sf, "%x - %x\n", FW3_TYPE_DEFAULTS, d->flags);
+       fprintf(sf, "%x - %x %x\n", FW3_TYPE_DEFAULTS, d->flags[0], d->flags[1]);
 
        list_for_each_entry(z, &s->running_zones, running_list)
        {
-               fprintf(sf, "%x %s %x\n", FW3_TYPE_ZONE, z->name, z->flags);
+               if (!fw3_no_table(z->flags[0]) || !fw3_no_table(z->flags[1]))
+               {
+                       fprintf(sf, "%x %s %x %x\n",
+                                       FW3_TYPE_ZONE, z->name, z->flags[0], z->flags[1]);
+               }
        }
 
        list_for_each_entry(i, &s->running_ipsets, running_list)
        {
-               fprintf(sf, "%x %s %x\n", FW3_TYPE_IPSET, i->name, i->flags);
+               if (!fw3_no_family(i->flags[0]) || !fw3_no_family(i->flags[1]))
+               {
+                       fprintf(sf, "%x %s %x %x\n",
+                                       FW3_TYPE_IPSET, i->name, i->flags[0], i->flags[1]);
+               }
        }
 
        fclose(sf);
diff --git a/utils.h b/utils.h
index c3dc974bfea513a15003d9e0b5d81be7c7166f40..77d0d7317d5bee3f5ebf0034364fed35fd415b77 100644 (file)
--- a/utils.h
+++ b/utils.h
@@ -46,6 +46,10 @@ void info(const char *format, ...);
 #define delbit(field, flag) field &= ~(1 << (flag))
 #define hasbit(field, flag) (field & (1 << (flag)))
 
+#define set(field, family, flag) setbit(field[family == FW3_FAMILY_V6], flag)
+#define del(field, family, flag) delbit(field[family == FW3_FAMILY_V6], flag)
+#define has(field, family, flag) hasbit(field[family == FW3_FAMILY_V6], flag)
+
 #define fw3_foreach(p, h)                                                  \
        for (p = list_empty(h) ? NULL : list_first_entry(h, typeof(*p), list); \
          list_empty(h) ? (p == NULL) : (&p->list != (h));                  \
@@ -58,6 +62,11 @@ void info(const char *format, ...);
 #define fw3_no_family(flags)                                               \
        (!(flags & ((1 << FW3_FAMILY_V4) | (1 << FW3_FAMILY_V6))))
 
+#define fw3_no_table(flags)                                                \
+    (!(flags & ((1<<FW3_TABLE_FILTER)|(1<<FW3_TABLE_NAT)|                  \
+                (1<<FW3_TABLE_MANGLE)|(1<<FW3_TABLE_RAW))))
+
+
 const char * fw3_find_command(const char *cmd);
 
 bool fw3_stdout_pipe(void);
diff --git a/zones.c b/zones.c
index 4bf7df4c1c79872368a99ecc2e601ab7f685e21e..f41cb0ffa1cad95e57b71f0cc75438ff676fc253 100644 (file)
--- a/zones.c
+++ b/zones.c
@@ -30,33 +30,28 @@ struct chain {
        const char *name;
 };
 
-static const struct chain src_chains[] = {
-       C(ANY, FILTER, UNSPEC,  "zone_%1$s_input"),
-       C(ANY, FILTER, UNSPEC,  "zone_%1$s_output"),
-       C(ANY, FILTER, UNSPEC,  "zone_%1$s_forward"),
-
-       C(ANY, FILTER, SRC_ACCEPT, "zone_%1$s_src_ACCEPT"),
-       C(ANY, FILTER, SRC_REJECT, "zone_%1$s_src_REJECT"),
-       C(ANY, FILTER, SRC_DROP,   "zone_%1$s_src_DROP"),
-};
+static const struct chain zone_chains[] = {
+       C(ANY, FILTER, UNSPEC,        "zone_%1$s_input"),
+       C(ANY, FILTER, UNSPEC,        "zone_%1$s_output"),
+       C(ANY, FILTER, UNSPEC,        "zone_%1$s_forward"),
+
+       C(ANY, FILTER, SRC_ACCEPT,    "zone_%1$s_src_ACCEPT"),
+       C(ANY, FILTER, SRC_REJECT,    "zone_%1$s_src_REJECT"),
+       C(ANY, FILTER, SRC_DROP,      "zone_%1$s_src_DROP"),
 
-static const struct chain dst_chains[] = {
-       C(ANY, FILTER, ACCEPT,  "zone_%1$s_dest_ACCEPT"),
-       C(ANY, FILTER, REJECT,  "zone_%1$s_dest_REJECT"),
-       C(ANY, FILTER, DROP,    "zone_%1$s_dest_DROP"),
+       C(ANY, FILTER, ACCEPT,        "zone_%1$s_dest_ACCEPT"),
+       C(ANY, FILTER, REJECT,        "zone_%1$s_dest_REJECT"),
+       C(ANY, FILTER, DROP,          "zone_%1$s_dest_DROP"),
 
-       C(V4,  NAT,    SNAT,    "zone_%1$s_postrouting"),
-       C(V4,  NAT,    DNAT,    "zone_%1$s_prerouting"),
+       C(V4,  NAT,    SNAT,          "zone_%1$s_postrouting"),
+       C(V4,  NAT,    DNAT,          "zone_%1$s_prerouting"),
 
-       C(ANY, FILTER, CUSTOM_CNS_V4, "input_%1$s_rule"),
-       C(ANY, FILTER, CUSTOM_CNS_V4, "output_%1$s_rule"),
-       C(ANY, FILTER, CUSTOM_CNS_V4, "forwarding_%1$s_rule"),
-       C(ANY, FILTER, CUSTOM_CNS_V6, "input_%1$s_rule"),
-       C(ANY, FILTER, CUSTOM_CNS_V6, "output_%1$s_rule"),
-       C(ANY, FILTER, CUSTOM_CNS_V6, "forwarding_%1$s_rule"),
+       C(ANY, FILTER, CUSTOM_CHAINS, "input_%1$s_rule"),
+       C(ANY, FILTER, CUSTOM_CHAINS, "output_%1$s_rule"),
+       C(ANY, FILTER, CUSTOM_CHAINS, "forwarding_%1$s_rule"),
 
-       C(V4,  NAT,    CUSTOM_CNS_V4, "prerouting_%1$s_rule"),
-       C(V4,  NAT,    CUSTOM_CNS_V4, "postrouting_%1$s_rule"),
+       C(V4,  NAT,    CUSTOM_CHAINS, "prerouting_%1$s_rule"),
+       C(V4,  NAT,    CUSTOM_CHAINS, "postrouting_%1$s_rule"),
 };
 
 
@@ -64,16 +59,13 @@ static const struct chain dst_chains[] = {
        "zone_%1$s_" #dir1 " -m comment --comment \"user chain for %1$s " \
        #dir2 "\" -j " #dir2 "_%1$s_rule"
 
-static const struct chain def_rules[] = {
-       C(ANY, FILTER, CUSTOM_CNS_V4, R(input, input)),
-       C(ANY, FILTER, CUSTOM_CNS_V4, R(output, output)),
-       C(ANY, FILTER, CUSTOM_CNS_V4, R(forward, forwarding)),
-       C(ANY, FILTER, CUSTOM_CNS_V6, R(input, input)),
-       C(ANY, FILTER, CUSTOM_CNS_V6, R(output, output)),
-       C(ANY, FILTER, CUSTOM_CNS_V6, R(forward, forwarding)),
+static const struct chain zone_rules[] = {
+       C(ANY, FILTER, CUSTOM_CHAINS, R(input, input)),
+       C(ANY, FILTER, CUSTOM_CHAINS, R(output, output)),
+       C(ANY, FILTER, CUSTOM_CHAINS, R(forward, forwarding)),
 
-       C(V4,  NAT,    CUSTOM_CNS_V4, R(prerouting, prerouting)),
-       C(V4,  NAT,    CUSTOM_CNS_V4, R(postrouting, postrouting)),
+       C(V4,  NAT,    CUSTOM_CHAINS, R(prerouting, prerouting)),
+       C(V4,  NAT,    CUSTOM_CHAINS, R(postrouting, postrouting)),
 };
 
 const struct fw3_option fw3_zone_opts[] = {
@@ -111,12 +103,16 @@ const struct fw3_option fw3_zone_opts[] = {
 
 static bool
 print_chains(enum fw3_table table, enum fw3_family family,
-             const char *fmt, const char *name, uint32_t targets,
+             const char *fmt, const char *name, uint32_t *targets, uint32_t mask,
              const struct chain *chains, int n)
 {
        bool rv = false;
        char cn[256] = { 0 };
        const struct chain *c;
+       uint32_t t = targets ? targets[family == FW3_FAMILY_V6] : 0;
+
+       if (mask)
+               t &= mask;
 
        for (c = chains; n > 0; c++, n--)
        {
@@ -126,7 +122,7 @@ print_chains(enum fw3_table table, enum fw3_family family,
                if (c->table != table)
                        continue;
 
-               if ((c->target != FW3_TARGET_UNSPEC) && !hasbit(targets, c->target))
+               if ((c->target != FW3_TARGET_UNSPEC) && !hasbit(t, c->target))
                        continue;
 
                snprintf(cn, sizeof(cn), c->name, name);
@@ -255,19 +251,23 @@ fw3_load_zones(struct fw3_state *state, struct uci_package *p)
 
                if (zone->masq)
                {
-                       setbit(zone->flags, FW3_TARGET_SNAT);
+                       setbit(zone->flags[0], FW3_TARGET_SNAT);
                        zone->conntrack = true;
                }
 
                if (zone->custom_chains)
                {
-                       setbit(zone->flags, FW3_TARGET_SNAT);
-                       setbit(zone->flags, FW3_TARGET_DNAT);
+                       setbit(zone->flags[0], FW3_TARGET_SNAT);
+                       setbit(zone->flags[0], FW3_TARGET_DNAT);
                }
 
-               setbit(zone->flags, fw3_to_src_target(zone->policy_input));
-               setbit(zone->flags, zone->policy_output);
-               setbit(zone->flags, zone->policy_forward);
+               setbit(zone->flags[0], fw3_to_src_target(zone->policy_input));
+               setbit(zone->flags[0], zone->policy_output);
+               setbit(zone->flags[0], zone->policy_forward);
+
+               setbit(zone->flags[1], fw3_to_src_target(zone->policy_input));
+               setbit(zone->flags[1], zone->policy_output);
+               setbit(zone->flags[1], zone->policy_forward);
 
                list_add_tail(&zone->list, &state->zones);
        }
@@ -276,52 +276,47 @@ fw3_load_zones(struct fw3_state *state, struct uci_package *p)
 
 static void
 print_zone_chain(enum fw3_table table, enum fw3_family family,
-                 struct fw3_zone *zone, struct fw3_state *state)
+                 struct fw3_zone *zone, bool reload, struct fw3_state *state)
 {
-       bool s, d, r;
-       enum fw3_target f;
+       bool c, r;
        uint32_t custom_mask = ~0;
 
        if (!fw3_is_family(zone, family))
                return;
 
-       setbit(zone->flags, family);
+       set(zone->flags, family, table);
 
-       /* user chains already loaded, don't create again */
-       for (f = FW3_TARGET_CUSTOM_CNS_V4; f <= FW3_TARGET_CUSTOM_CNS_V6; f++)
-               if (hasbit(zone->running_flags, f))
-                       delbit(custom_mask, f);
+       /* Don't touch user chains on reload */
+       if (reload)
+               delbit(custom_mask, FW3_TARGET_CUSTOM_CHAINS);
 
        if (zone->custom_chains)
-               setbit(zone->flags, (family == FW3_FAMILY_V4) ?
-                      FW3_TARGET_CUSTOM_CNS_V4 : FW3_TARGET_CUSTOM_CNS_V6);
+               set(zone->flags, family, FW3_TARGET_CUSTOM_CHAINS);
 
        if (!zone->conntrack && !state->defaults.drop_invalid)
-               setbit(zone->flags, FW3_TARGET_NOTRACK);
-
-       s = print_chains(table, family, ":%s - [0:0]\n", zone->name,
-                        zone->flags,
-                        src_chains, ARRAY_SIZE(src_chains));
+               set(zone->flags, family, FW3_TARGET_NOTRACK);
 
-       d = print_chains(table, family, ":%s - [0:0]\n", zone->name,
-                        zone->flags & custom_mask,
-                        dst_chains, ARRAY_SIZE(dst_chains));
+       c = print_chains(table, family, ":%s - [0:0]\n", zone->name,
+                        zone->flags, custom_mask,
+                        zone_chains, ARRAY_SIZE(zone_chains));
 
        r = print_chains(table, family, "-A %s\n", zone->name,
-                        zone->flags,
-                        def_rules, ARRAY_SIZE(def_rules));
+                        zone->flags, 0,
+                        zone_rules, ARRAY_SIZE(zone_rules));
 
-       if (s || d || r)
+       if (c || r)
        {
                info("   * Zone '%s'", zone->name);
                fw3_set_running(zone, &state->running_zones);
+
+               set(zone->flags, family, table);
        }
 }
 
 static void
 print_interface_rule(enum fw3_table table, enum fw3_family family,
                      struct fw3_zone *zone, struct fw3_device *dev,
-                     struct fw3_address *sub, bool disable_notrack)
+                     struct fw3_address *sub, bool reload, bool disable_notrack)
 {
        enum fw3_target t;
 
@@ -332,7 +327,7 @@ print_interface_rule(enum fw3_table table, enum fw3_family family,
        {
                for (t = FW3_TARGET_ACCEPT; t <= FW3_TARGET_DROP; t++)
                {
-                       if (hasbit(zone->flags, fw3_to_src_target(t)))
+                       if (has(zone->flags, family, fw3_to_src_target(t)))
                        {
                                fw3_pr("-A zone_%s_src_%s", zone->name, fw3_flag_names[t]);
                                fw3_format_in_out(dev, NULL);
@@ -341,7 +336,7 @@ print_interface_rule(enum fw3_table table, enum fw3_family family,
                                fw3_pr(" -j %s\n", jump_target(t));
                        }
 
-                       if (hasbit(zone->flags, t))
+                       if (has(zone->flags, family, t))
                        {
                                fw3_pr("-A zone_%s_dest_%s", zone->name, fw3_flag_names[t]);
                                fw3_format_in_out(NULL, dev);
@@ -371,7 +366,7 @@ print_interface_rule(enum fw3_table table, enum fw3_family family,
        }
        else if (table == FW3_TABLE_NAT)
        {
-               if (hasbit(zone->flags, FW3_TARGET_DNAT))
+               if (has(zone->flags, family, FW3_TARGET_DNAT))
                {
                        fw3_pr("-A delegate_prerouting");
                        fw3_format_in_out(dev, NULL);
@@ -380,7 +375,7 @@ print_interface_rule(enum fw3_table table, enum fw3_family family,
                        fw3_pr(" -j zone_%s_prerouting\n", zone->name);
                }
 
-               if (hasbit(zone->flags, FW3_TARGET_SNAT))
+               if (has(zone->flags, family, FW3_TARGET_SNAT))
                {
                        fw3_pr("-A delegate_postrouting");
                        fw3_format_in_out(NULL, dev);
@@ -428,7 +423,7 @@ print_interface_rule(enum fw3_table table, enum fw3_family family,
 
 static void
 print_interface_rules(enum fw3_table table, enum fw3_family family,
-                      struct fw3_zone *zone, bool disable_notrack)
+                      struct fw3_zone *zone, bool reload, bool disable_notrack)
 {
        struct fw3_device *dev;
        struct fw3_address *sub;
@@ -442,13 +437,13 @@ print_interface_rules(enum fw3_table table, enum fw3_family family,
                if (!dev && !sub)
                        continue;
 
-               print_interface_rule(table, family, zone, dev, sub, disable_notrack);
+               print_interface_rule(table, family, zone, dev, sub, reload, disable_notrack);
        }
 }
 
 static void
 print_zone_rule(enum fw3_table table, enum fw3_family family,
-                struct fw3_zone *zone, bool disable_notrack)
+                struct fw3_zone *zone, bool reload, bool disable_notrack)
 {
        struct fw3_address *msrc;
        struct fw3_address *mdest;
@@ -474,7 +469,7 @@ print_zone_rule(enum fw3_table table, enum fw3_family family,
                {
                        for (t = FW3_TARGET_REJECT; t <= FW3_TARGET_DROP; t++)
                        {
-                               if (hasbit(zone->flags, fw3_to_src_target(t)))
+                               if (has(zone->flags, family, fw3_to_src_target(t)))
                                {
                                        fw3_pr("-A zone_%s_src_%s", zone->name, fw3_flag_names[t]);
                                        fw3_format_limit(&zone->log_limit);
@@ -482,7 +477,7 @@ print_zone_rule(enum fw3_table table, enum fw3_family family,
                                                   fw3_flag_names[t], zone->name);
                                }
 
-                               if (hasbit(zone->flags, t))
+                               if (has(zone->flags, family, t))
                                {
                                        fw3_pr("-A zone_%s_dest_%s", zone->name, fw3_flag_names[t]);
                                        fw3_format_limit(&zone->log_limit);
@@ -511,27 +506,27 @@ print_zone_rule(enum fw3_table table, enum fw3_family family,
                break;
        }
 
-       print_interface_rules(table, family, zone, disable_notrack);
+       print_interface_rules(table, family, zone, reload, disable_notrack);
 }
 
 void
 fw3_print_zone_chains(enum fw3_table table, enum fw3_family family,
-                      struct fw3_state *state)
+                      bool reload, struct fw3_state *state)
 {
        struct fw3_zone *zone;
 
        list_for_each_entry(zone, &state->zones, list)
-               print_zone_chain(table, family, zone, state);
+               print_zone_chain(table, family, zone, reload, state);
 }
 
 void
 fw3_print_zone_rules(enum fw3_table table, enum fw3_family family,
-                     struct fw3_state *state)
+                     bool reload, struct fw3_state *state)
 {
        struct fw3_zone *zone;
 
        list_for_each_entry(zone, &state->zones, list)
-               print_zone_rule(table, family, zone, state->defaults.drop_invalid);
+               print_zone_rule(table, family, zone, reload, state->defaults.drop_invalid);
 }
 
 void
@@ -543,30 +538,20 @@ fw3_flush_zones(enum fw3_table table, enum fw3_family family,
 
        /* don't touch user chains on selective stop */
        if (reload)
-       {
-               delbit(custom_mask, FW3_TARGET_CUSTOM_CNS_V4);
-               delbit(custom_mask, FW3_TARGET_CUSTOM_CNS_V6);
-       }
+               delbit(custom_mask, FW3_TARGET_CUSTOM_CHAINS);
 
        list_for_each_entry_safe(z, tmp, &state->running_zones, running_list)
        {
-               if (!hasbit(z->flags, family))
+               if (!has(z->flags, family, table))
                        continue;
 
                print_chains(table, family, pass2 ? "-X %s\n" : "-F %s\n",
-                            z->name, z->running_flags,
-                            src_chains, ARRAY_SIZE(src_chains));
-
-               print_chains(table, family, pass2 ? "-X %s\n" : "-F %s\n",
-                            z->name, z->running_flags & custom_mask,
-                            dst_chains, ARRAY_SIZE(dst_chains));
+                            z->name, z->flags, custom_mask,
+                            zone_chains, ARRAY_SIZE(zone_chains));
 
                if (pass2)
                {
-                       delbit(z->running_flags, family);
-
-                       if (fw3_no_family(z->running_flags))
-                               fw3_set_running(z, NULL);
+                       del(z->flags, family, table);
                }
        }
 }
diff --git a/zones.h b/zones.h
index 7fd8e4cdeac7c65924ef1e655f07efef6799debb..c84897bb8539496ba03b4817e30acf2d7a8b0778 100644 (file)
--- a/zones.h
+++ b/zones.h
@@ -28,10 +28,10 @@ struct fw3_zone * fw3_alloc_zone(void);
 void fw3_load_zones(struct fw3_state *state, struct uci_package *p);
 
 void fw3_print_zone_chains(enum fw3_table table, enum fw3_family family,
-                           struct fw3_state *state);
+                           bool reload, struct fw3_state *state);
 
 void fw3_print_zone_rules(enum fw3_table table, enum fw3_family family,
-                          struct fw3_state *state);
+                          bool reload, struct fw3_state *state);
 
 void fw3_flush_zones(enum fw3_table table, enum fw3_family family,
                      bool pass2, bool reload, struct fw3_state *state);