X-Git-Url: http://git.openwrt.org/?p=project%2Ffirewall3.git;a=blobdiff_plain;f=iptables.c;fp=iptables.c;h=7ad1d2247ebf17a6f7c7ff54f3f6609e525e6978;hp=559fe7defef3be85c4eb2934884caf549f932bc5;hb=23cc543f4f7ca636400707161e7e8355b6ecd856;hpb=9d7f49df47ad40a95ea0a37b9dcf423ee07819a7 diff --git a/iptables.c b/iptables.c index 559fe7d..7ad1d22 100644 --- a/iptables.c +++ b/iptables.c @@ -329,9 +329,61 @@ delete_rules(struct fw3_ipt_handle *h, const char *target) } } +static bool +is_referenced(struct fw3_ipt_handle *h, const char *target) +{ + const struct ipt_entry *e; + const char *chain; + const char *t; + +#ifndef DISABLE_IPV6 + if (h->family == FW3_FAMILY_V6) + { + for (chain = ip6tc_first_chain(h->handle); + chain != NULL; + chain = ip6tc_next_chain(h->handle)) + { + const struct ip6t_entry *e6; + for (e6 = ip6tc_first_rule(chain, h->handle); + e6 != NULL; + e6 = ip6tc_next_rule(e6, h->handle)) + { + t = ip6tc_get_target(e6, h->handle); + + if (*t && !strcmp(t, target)) + return true; + } + } + } + else +#endif + { + for (chain = iptc_first_chain(h->handle); + chain != NULL; + chain = iptc_next_chain(h->handle)) + { + for (e = iptc_first_rule(chain, h->handle); + e != NULL; + e = iptc_next_rule(e, h->handle)) + { + t = iptc_get_target(e, h->handle); + + if (*t && !strcmp(t, target)) + return true; + } + } + } + + return false; +} + void -fw3_ipt_delete_chain(struct fw3_ipt_handle *h, const char *chain) +fw3_ipt_delete_chain(struct fw3_ipt_handle *h, bool if_unused, + const char *chain) { + if (if_unused && is_referenced(h, chain)) + return; + delete_rules(h, chain); if (fw3_pr_debug) @@ -425,8 +477,21 @@ fw3_ipt_delete_id_rules(struct fw3_ipt_handle *h, const char *chain) } } + +static bool +is_chain(struct fw3_ipt_handle *h, const char *name) +{ +#ifndef DISABLE_IPV6 + if (h->family == FW3_FAMILY_V6) + return ip6tc_is_chain(name, h->handle); + else +#endif + return iptc_is_chain(name, h->handle); +} + void -fw3_ipt_create_chain(struct fw3_ipt_handle *h, const char *fmt, ...) +fw3_ipt_create_chain(struct fw3_ipt_handle *h, bool ignore_existing, + const char *fmt, ...) { char buf[32]; va_list ap; @@ -435,6 +500,9 @@ fw3_ipt_create_chain(struct fw3_ipt_handle *h, const char *fmt, ...) vsnprintf(buf, sizeof(buf) - 1, fmt, ap); va_end(ap); + if (ignore_existing && is_chain(h, buf)) + return; + if (fw3_pr_debug) debug(h, "-N %s\n", buf); @@ -514,7 +582,7 @@ fw3_ipt_gc(struct fw3_ipt_handle *h) if (!chain_is_empty(h, chain)) continue; - fw3_ipt_delete_chain(h, chain); + fw3_ipt_delete_chain(h, false, chain); found = true; break; } @@ -537,7 +605,7 @@ fw3_ipt_gc(struct fw3_ipt_handle *h) warn("D=%s\n", chain); - fw3_ipt_delete_chain(h, chain); + fw3_ipt_delete_chain(h, false, chain); found = true; break; } @@ -588,17 +656,6 @@ fw3_ipt_rule_new(struct fw3_ipt_handle *h) } -static bool -is_chain(struct fw3_ipt_handle *h, const char *name) -{ -#ifndef DISABLE_IPV6 - if (h->family == FW3_FAMILY_V6) - return ip6tc_is_chain(name, h->handle); - else -#endif - return iptc_is_chain(name, h->handle); -} - static char * get_protoname(struct fw3_ipt_rule *r) {