2 * firewall3 - 3rd OpenWrt UCI firewall implementation
4 * Copyright (C) 2018 Jo-Philipp Wich <jo@mein.io>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 const struct fw3_option fw3_cthelper_opts
[] = {
23 FW3_OPT("enabled", bool, cthelper
, enabled
),
24 FW3_OPT("name", string
, cthelper
, name
),
25 FW3_OPT("module", string
, cthelper
, module
),
26 FW3_OPT("description", string
, cthelper
, description
),
27 FW3_OPT("family", family
, cthelper
, family
),
28 FW3_OPT("proto", protocol
, cthelper
, proto
),
29 FW3_OPT("port", port
, cthelper
, port
),
36 test_module(struct fw3_cthelper
*helper
)
39 char path
[sizeof("/sys/module/nf_conntrack_xxxxxxxxxxxxxxxx")];
41 snprintf(path
, sizeof(path
), "/sys/module/%s", helper
->module
);
43 if (stat(path
, &s
) || !S_ISDIR(s
.st_mode
))
50 check_cthelper(struct fw3_state
*state
, struct fw3_cthelper
*helper
, struct uci_element
*e
)
52 if (!helper
->name
|| !*helper
->name
)
54 warn_section("helper", helper
, e
, "must have a name assigned");
56 else if (!helper
->module
|| !*helper
->module
)
58 warn_section("helper", helper
, e
, "must have a module assigned");
60 else if (!helper
->proto
.protocol
|| helper
->proto
.any
|| helper
->proto
.invert
)
62 warn_section("helper", helper
, e
, "must specify a protocol");
64 else if (helper
->port
.set
&& helper
->port
.invert
)
66 warn_section("helper", helper
, e
, "must not specify negated ports");
76 static struct fw3_cthelper
*
77 fw3_alloc_cthelper(struct fw3_state
*state
)
79 struct fw3_cthelper
*helper
;
81 helper
= calloc(1, sizeof(*helper
));
85 helper
->enabled
= true;
86 helper
->family
= FW3_FAMILY_ANY
;
88 list_add_tail(&helper
->list
, &state
->cthelpers
);
94 load_cthelpers(struct fw3_state
*state
, struct uci_package
*p
)
96 struct fw3_cthelper
*helper
;
97 struct uci_section
*s
;
98 struct uci_element
*e
;
100 uci_foreach_element(&p
->sections
, e
)
102 s
= uci_to_section(e
);
104 if (strcmp(s
->type
, "helper"))
107 helper
= fw3_alloc_cthelper(state
);
112 if (!fw3_parse_options(helper
, fw3_cthelper_opts
, s
))
113 warn_elem(e
, "has invalid options");
115 if (!check_cthelper(state
, helper
, e
))
116 fw3_free_cthelper(helper
);
121 fw3_load_cthelpers(struct fw3_state
*state
, struct uci_package
*p
)
123 struct uci_package
*hp
= NULL
;
126 INIT_LIST_HEAD(&state
->cthelpers
);
128 fp
= fopen(FW3_HELPERCONF
, "r");
131 uci_import(state
->uci
, fp
, "fw3_ct_helpers", &hp
, true);
135 load_cthelpers(state
, hp
);
138 load_cthelpers(state
, p
);
141 struct fw3_cthelper
*
142 fw3_lookup_cthelper(struct fw3_state
*state
, const char *name
)
144 struct fw3_cthelper
*h
;
146 if (list_empty(&state
->cthelpers
))
149 list_for_each_entry(h
, &state
->cthelpers
, list
)
151 if (strcasecmp(h
->name
, name
))
160 struct fw3_cthelper
*
161 fw3_lookup_cthelper_by_proto_port(struct fw3_state
*state
,
162 struct fw3_protocol
*proto
,
163 struct fw3_port
*port
)
165 struct fw3_cthelper
*h
;
167 if (list_empty(&state
->cthelpers
))
170 if (!proto
|| !proto
->protocol
|| proto
->any
|| proto
->invert
)
173 if (port
&& port
->invert
)
176 list_for_each_entry(h
, &state
->cthelpers
, list
)
181 if (h
->proto
.protocol
!= proto
->protocol
)
184 if (h
->port
.set
&& (!port
|| !port
->set
))
187 if (!h
->port
.set
&& (!port
|| !port
->set
))
190 if (h
->port
.set
&& port
&& port
->set
&&
191 h
->port
.port_min
<= port
->port_min
&&
192 h
->port
.port_max
>= port
->port_max
)
200 print_helper_rule(struct fw3_ipt_handle
*handle
, struct fw3_cthelper
*helper
,
201 struct fw3_zone
*zone
)
203 struct fw3_ipt_rule
*r
;
205 r
= fw3_ipt_rule_create(handle
, &helper
->proto
, NULL
, NULL
, NULL
, NULL
);
207 if (helper
->description
&& *helper
->description
)
208 fw3_ipt_rule_comment(r
, helper
->description
);
210 fw3_ipt_rule_comment(r
, helper
->name
);
212 fw3_ipt_rule_sport_dport(r
, NULL
, &helper
->port
);
213 fw3_ipt_rule_target(r
, "CT");
214 fw3_ipt_rule_addarg(r
, false, "--helper", helper
->name
);
215 fw3_ipt_rule_replace(r
, "zone_%s_helper", zone
->name
);
219 fw3_print_cthelpers(struct fw3_ipt_handle
*handle
, struct fw3_state
*state
,
220 struct fw3_zone
*zone
)
222 struct fw3_cthelper
*helper
;
223 struct fw3_cthelpermatch
*match
;
225 if (handle
->table
!= FW3_TABLE_RAW
)
228 if (!fw3_is_family(zone
, handle
->family
))
231 if (list_empty(&zone
->cthelpers
))
233 if (zone
->masq
|| !zone
->auto_helper
)
236 if (list_empty(&state
->cthelpers
))
239 info(" - Using automatic conntrack helper attachment");
241 list_for_each_entry(helper
, &state
->cthelpers
, list
)
243 if (!helper
|| !helper
->enabled
)
246 if (!fw3_is_family(helper
, handle
->family
))
249 if (!test_module(helper
))
252 print_helper_rule(handle
, helper
, zone
);
257 list_for_each_entry(match
, &zone
->cthelpers
, list
)
261 if (!helper
|| !helper
->enabled
)
264 if (!fw3_is_family(helper
, handle
->family
))
267 if (!test_module(helper
))
269 info(" ! Conntrack module '%s' for helper '%s' is not loaded",
270 helper
->module
, helper
->name
);
274 print_helper_rule(handle
, helper
, zone
);