for (c = default_chains; c->format; c++)
{
- /* don't touch user chains on selective stop */
- if (reload && c->flag == FW3_FLAG_CUSTOM_CHAINS)
- continue;
-
if (!fw3_is_family(c, handle->family))
continue;
!fw3_hasbit(defs->flags[handle->family == FW3_FAMILY_V6], c->flag))
continue;
- fw3_ipt_create_chain(handle, c->format);
+ fw3_ipt_create_chain(handle, reload, c->format);
}
set(defs->flags, handle->family, handle->table);
fw3_ipt_delete_id_rules(handle, "PREROUTING");
fw3_ipt_delete_id_rules(handle, "POSTROUTING");
+ /* first flush all the rules ... */
for (c = default_chains; c->format; c++)
{
/* don't touch user chains on selective stop */
continue;
fw3_ipt_flush_chain(handle, c->format);
+ }
+
+ /* ... then remove the chains */
+ for (c = default_chains; c->format; c++)
+ {
+ if (!fw3_is_family(c, handle->family))
+ continue;
- /* keep certain basic chains that do not depend on any settings to
- avoid purging unrelated user rules pointing to them */
- if (reload && !c->flag)
+ if (c->table != handle->table)
+ continue;
+
+ if (c->flag && !has(defs->flags, handle->family, c->flag))
continue;
- fw3_ipt_delete_chain(handle, c->format);
+ fw3_ipt_delete_chain(handle, reload, c->format);
}
del(defs->flags, handle->family, handle->table);
}
}
+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)
}
}
+
+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;
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);
if (!chain_is_empty(h, chain))
continue;
- fw3_ipt_delete_chain(h, chain);
+ fw3_ipt_delete_chain(h, false, chain);
found = true;
break;
}
warn("D=%s\n", chain);
- fw3_ipt_delete_chain(h, chain);
+ fw3_ipt_delete_chain(h, false, chain);
found = true;
break;
}
}
-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)
{
void fw3_ipt_flush_chain(struct fw3_ipt_handle *h, const char *chain);
-void fw3_ipt_delete_chain(struct fw3_ipt_handle *h, const char *chain);
+void fw3_ipt_delete_chain(struct fw3_ipt_handle *h, bool if_unused,
+ const char *chain);
void fw3_ipt_delete_id_rules(struct fw3_ipt_handle *h, const char *chain);
-void fw3_ipt_create_chain(struct fw3_ipt_handle *h, const char *fmt, ...);
+void fw3_ipt_create_chain(struct fw3_ipt_handle *h, bool ignore_existing,
+ const char *fmt, ...);
void fw3_ipt_flush(struct fw3_ipt_handle *h);
for (c = zone_chains; c->format; c++)
{
- /* don't touch user chains on selective stop */
- if (reload && c->flag == FW3_FLAG_CUSTOM_CHAINS)
- continue;
-
if (!fw3_is_family(c, handle->family))
continue;
!fw3_hasbit(zone->flags[handle->family == FW3_FAMILY_V6], c->flag))
continue;
- fw3_ipt_create_chain(handle, c->format, zone->name);
+ fw3_ipt_create_chain(handle, reload, c->format, zone->name);
}
if (zone->custom_chains)
if (!has(z->flags, handle->family, handle->table))
continue;
+ /* first flush all rules ... */
for (c = zone_chains; c->format; c++)
{
/* don't touch user chains on selective stop */
snprintf(chain, sizeof(chain), c->format, z->name);
fw3_ipt_flush_chain(handle, chain);
+ }
+
+ /* ... then remove the chains */
+ for (c = zone_chains; c->format; c++)
+ {
+ if (!fw3_is_family(c, handle->family))
+ continue;
- /* keep certain basic chains that do not depend on any settings to
- avoid purging unrelated user rules pointing to them */
- if (reload && !c->flag)
+ if (c->table != handle->table)
continue;
- fw3_ipt_delete_chain(handle, chain);
+ if (c->flag && !has(z->flags, handle->family, c->flag))
+ continue;
+
+ snprintf(chain, sizeof(chain), c->format, z->name);
+
+ fw3_ipt_delete_chain(handle, reload, chain);
}
del(z->flags, handle->family, handle->table);