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>
FW3_OPT("module", string, cthelper, module),
FW3_OPT("description", string, cthelper, description),
FW3_OPT("family", family, cthelper, family),
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),
{ }
FW3_OPT("port", port, cthelper, port),
{ }
+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)
check_cthelper(struct fw3_state *state, struct fw3_cthelper *helper, struct uci_element *e)
{
if (!helper->name || !*helper->name)
{
warn_section("helper", helper, e, "must have a module assigned");
}
{
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");
}
{
warn_section("helper", helper, e, "must specify a protocol");
}
helper->enabled = true;
helper->family = FW3_FAMILY_ANY;
helper->enabled = true;
helper->family = FW3_FAMILY_ANY;
+ INIT_LIST_HEAD(&helper->proto);
list_add_tail(&helper->list, &state->cthelpers);
list_add_tail(&helper->list, &state->cthelpers);
+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,
struct fw3_cthelper *
fw3_lookup_cthelper_by_proto_port(struct fw3_state *state,
struct fw3_protocol *proto,
if (!h->enabled)
continue;
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))
continue;
if (h->port.set && (!port || !port->set))
static void
print_helper_rule(struct fw3_ipt_handle *handle, struct fw3_cthelper *helper,
static void
print_helper_rule(struct fw3_ipt_handle *handle, struct fw3_cthelper *helper,
+ struct fw3_zone *zone, struct fw3_protocol *proto)
{
struct fw3_ipt_rule *r;
{
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);
if (helper->description && *helper->description)
fw3_ipt_rule_comment(r, helper->description);
fw3_ipt_rule_replace(r, "zone_%s_helper", zone->name);
}
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)
void
fw3_print_cthelpers(struct fw3_ipt_handle *handle, struct fw3_state *state,
struct fw3_zone *zone)
if (!test_module(helper))
continue;
if (!test_module(helper))
continue;
- print_helper_rule(handle, helper, zone);
+ expand_helper_rule(handle, helper, zone);
- print_helper_rule(handle, helper, zone);
+ expand_helper_rule(handle, helper, zone);
fw3_print_cthelpers(struct fw3_ipt_handle *handle, struct fw3_state *state,
struct fw3_zone *zone);
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);
static inline void fw3_free_cthelper(struct fw3_cthelper *helper)
{
list_del(&helper->list);
const char *module;
const char *description;
enum fw3_family family;
const char *module;
const char *description;
enum fw3_family family;
- struct fw3_protocol proto;
+ struct list_head proto;
case FW3_TABLE_RAW:
if (redir->target == FW3_FLAG_DNAT && redir->helper.ptr)
{
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);
{
info(" ! Skipping protocol %s since helper '%s' does not support it",
fw3_protoname(proto), redir->helper.ptr->name);
}
if (rule->helper.ptr &&
}
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);
{
info(" ! Skipping protocol %s since helper '%s' does not support it",
fw3_protoname(proto), rule->helper.ptr->name);
}
if (rule->set_helper.ptr &&
}
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);
{
info(" ! Skipping protocol %s since helper '%s' does not support it",
fw3_protoname(proto), rule->helper.ptr->name);