summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre Lebleu <pme.lebleu@gmail.com>2018-05-07 16:17:16 +0200
committerJohn Crispin <john@phrozen.org>2018-05-14 16:15:02 +0200
commit08b2c61b4d66bb78d98135d8ddb87ce34be55c81 (patch)
tree6ae78019add2d0a5b430b3dc87984782b1eb711f
parent35b3e74a184b709b8ddfaaa094919a656a6ec059 (diff)
downloadfirewall3-08b2c61b4d66bb78d98135d8ddb87ce34be55c81.tar.gz
helpers: make the proto field as a list rather than one option
The field proto in the struct fw3_cthelper should be implemented as a list in order to support multiple protocols. For example, the helper for SIP should be able to support both TCP and UDP within only one entry in the config file. config helper option name 'sip' option description 'SIP VoIP connection tracking' option module 'nf_conntrack_sip' option family 'any' option proto 'tcpudp' option port '5060' Signed-off-by: Pierre Lebleu <pme.lebleu@gmail.com>
-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);