summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--helpers.c56
-rw-r--r--helpers.h3
-rw-r--r--options.h2
-rw-r--r--redirects.c2
-rw-r--r--rules.c4
5 files changed, 56 insertions, 11 deletions
diff --git a/helpers.c b/helpers.c
index 8cad0b3..36317d2 100644
--- a/helpers.c
+++ b/helpers.c
@@ -25,7 +25,7 @@ const struct fw3_option fw3_cthelper_opts[] = {
FW3_OPT("module", string, cthelper, module),
FW3_OPT("description", string, cthelper, description),
FW3_OPT("family", family, cthelper, family),
- FW3_OPT("proto", protocol, cthelper, proto),
+ FW3_LIST("proto", protocol, cthelper, proto),
FW3_OPT("port", port, cthelper, port),
{ }
@@ -47,6 +47,23 @@ test_module(struct fw3_cthelper *helper)
}
static bool
+check_cthelper_proto(const struct fw3_cthelper *helper)
+{
+ struct fw3_protocol *proto;
+
+ if (list_empty(&helper->proto))
+ return false;
+
+ list_for_each_entry(proto, &helper->proto, list)
+ {
+ if (!proto->protocol || proto->any || proto->invert)
+ return false;
+ }
+
+ return true;
+}
+
+static bool
check_cthelper(struct fw3_state *state, struct fw3_cthelper *helper, struct uci_element *e)
{
if (!helper->name || !*helper->name)
@@ -57,7 +74,7 @@ check_cthelper(struct fw3_state *state, struct fw3_cthelper *helper, struct uci_
{
warn_section("helper", helper, e, "must have a module assigned");
}
- else if (!helper->proto.protocol || helper->proto.any || helper->proto.invert)
+ else if (!check_cthelper_proto(helper))
{
warn_section("helper", helper, e, "must specify a protocol");
}
@@ -84,6 +101,7 @@ fw3_alloc_cthelper(struct fw3_state *state)
helper->enabled = true;
helper->family = FW3_FAMILY_ANY;
+ INIT_LIST_HEAD(&helper->proto);
list_add_tail(&helper->list, &state->cthelpers);
@@ -157,6 +175,20 @@ fw3_lookup_cthelper(struct fw3_state *state, const char *name)
return NULL;
}
+bool
+fw3_cthelper_check_proto(const struct fw3_cthelper *h, const struct fw3_protocol *proto)
+{
+ struct fw3_protocol *p;
+
+ list_for_each_entry(p, &h->proto, list)
+ {
+ if (p->protocol == proto->protocol)
+ return true;
+ }
+
+ return false;
+}
+
struct fw3_cthelper *
fw3_lookup_cthelper_by_proto_port(struct fw3_state *state,
struct fw3_protocol *proto,
@@ -178,7 +210,7 @@ fw3_lookup_cthelper_by_proto_port(struct fw3_state *state,
if (!h->enabled)
continue;
- if (h->proto.protocol != proto->protocol)
+ if (!fw3_cthelper_check_proto(h, proto))
continue;
if (h->port.set && (!port || !port->set))
@@ -198,11 +230,11 @@ fw3_lookup_cthelper_by_proto_port(struct fw3_state *state,
static void
print_helper_rule(struct fw3_ipt_handle *handle, struct fw3_cthelper *helper,
- struct fw3_zone *zone)
+ struct fw3_zone *zone, struct fw3_protocol *proto)
{
struct fw3_ipt_rule *r;
- r = fw3_ipt_rule_create(handle, &helper->proto, NULL, NULL, NULL, NULL);
+ r = fw3_ipt_rule_create(handle, proto, NULL, NULL, NULL, NULL);
if (helper->description && *helper->description)
fw3_ipt_rule_comment(r, helper->description);
@@ -215,6 +247,16 @@ print_helper_rule(struct fw3_ipt_handle *handle, struct fw3_cthelper *helper,
fw3_ipt_rule_replace(r, "zone_%s_helper", zone->name);
}
+static void
+expand_helper_rule(struct fw3_ipt_handle *handle, struct fw3_cthelper *helper,
+ struct fw3_zone *zone)
+{
+ struct fw3_protocol *proto;
+
+ list_for_each_entry(proto, &helper->proto, list)
+ print_helper_rule(handle, helper, zone, proto);
+}
+
void
fw3_print_cthelpers(struct fw3_ipt_handle *handle, struct fw3_state *state,
struct fw3_zone *zone)
@@ -249,7 +291,7 @@ fw3_print_cthelpers(struct fw3_ipt_handle *handle, struct fw3_state *state,
if (!test_module(helper))
continue;
- print_helper_rule(handle, helper, zone);
+ expand_helper_rule(handle, helper, zone);
}
}
else
@@ -271,7 +313,7 @@ fw3_print_cthelpers(struct fw3_ipt_handle *handle, struct fw3_state *state,
continue;
}
- print_helper_rule(handle, helper, zone);
+ expand_helper_rule(handle, helper, zone);
}
}
}
diff --git a/helpers.h b/helpers.h
index 450428e..e2a99cd 100644
--- a/helpers.h
+++ b/helpers.h
@@ -41,6 +41,9 @@ void
fw3_print_cthelpers(struct fw3_ipt_handle *handle, struct fw3_state *state,
struct fw3_zone *zone);
+bool
+fw3_cthelper_check_proto(const struct fw3_cthelper *h, const struct fw3_protocol *proto);
+
static inline void fw3_free_cthelper(struct fw3_cthelper *helper)
{
list_del(&helper->list);
diff --git a/options.h b/options.h
index 15cd504..08fecf6 100644
--- a/options.h
+++ b/options.h
@@ -526,7 +526,7 @@ struct fw3_cthelper
const char *module;
const char *description;
enum fw3_family family;
- struct fw3_protocol proto;
+ struct list_head proto;
struct fw3_port port;
};
diff --git a/redirects.c b/redirects.c
index 660cdd2..7f9948c 100644
--- a/redirects.c
+++ b/redirects.c
@@ -576,7 +576,7 @@ print_redirect(struct fw3_ipt_handle *h, struct fw3_state *state,
case FW3_TABLE_RAW:
if (redir->target == FW3_FLAG_DNAT && redir->helper.ptr)
{
- if (redir->helper.ptr->proto.protocol != proto->protocol)
+ if (!fw3_cthelper_check_proto(redir->helper.ptr, proto))
{
info(" ! Skipping protocol %s since helper '%s' does not support it",
fw3_protoname(proto), redir->helper.ptr->name);
diff --git a/rules.c b/rules.c
index ea66771..58edcd4 100644
--- a/rules.c
+++ b/rules.c
@@ -436,7 +436,7 @@ print_rule(struct fw3_ipt_handle *handle, struct fw3_state *state,
}
if (rule->helper.ptr &&
- rule->helper.ptr->proto.protocol != proto->protocol)
+ !fw3_cthelper_check_proto(rule->helper.ptr, proto))
{
info(" ! Skipping protocol %s since helper '%s' does not support it",
fw3_protoname(proto), rule->helper.ptr->name);
@@ -444,7 +444,7 @@ print_rule(struct fw3_ipt_handle *handle, struct fw3_state *state,
}
if (rule->set_helper.ptr &&
- rule->set_helper.ptr->proto.protocol != proto->protocol)
+ !fw3_cthelper_check_proto(rule->set_helper.ptr, proto))
{
info(" ! Skipping protocol %s since helper '%s' does not support it",
fw3_protoname(proto), rule->helper.ptr->name);