It gives the ability to create redirect rules via procd services and netifd interface firewall data.
Signed-off-by: Pierre Lebleu <pme.leb...@gmail.com> --- main.c | 2 +- redirects.c | 108 ++++++++++++++++++++++++++++++++++++++++++----------------- redirects.h | 10 ++++-- 3 files changed, 85 insertions(+), 35 deletions(-) diff --git a/main.c b/main.c index e38963d..5888ab5 100644 --- a/main.c +++ b/main.c @@ -104,7 +104,7 @@ build_state(bool runtime) fw3_load_ipsets(state, p); fw3_load_zones(state, p); fw3_load_rules(state, p, b.head); - fw3_load_redirects(state, p); + fw3_load_redirects(state, p, b.head); fw3_load_snats(state, p, b.head); fw3_load_forwards(state, p); fw3_load_includes(state, p); diff --git a/redirects.c b/redirects.c index a657b6d..b9ad3d5 100644 --- a/redirects.c +++ b/redirects.c @@ -175,35 +175,72 @@ check_local(struct uci_element *e, struct fw3_redirect *redir, return redir->local; } +static struct fw3_redirect * +fw3_alloc_redirect(struct fw3_state *state) +{ + struct fw3_redirect *redir; + + redir = calloc(1, sizeof(*redir)); + if (!redir) + return NULL; + + INIT_LIST_HEAD(&redir->proto); + INIT_LIST_HEAD(&redir->mac_src); + + redir->enabled = true; + redir->reflection = true; + + list_add_tail(&redir->list, &state->redirects); + + return redir; +} + void -fw3_load_redirects(struct fw3_state *state, struct uci_package *p) +fw3_load_redirects(struct fw3_state *state, struct uci_package *p, + struct blob_attr *a) { struct uci_section *s; struct uci_element *e; - struct fw3_redirect *redir; - + struct fw3_redirect *redir, *n; + struct blob_attr *entry, *opt; + unsigned rem, orem; bool valid; INIT_LIST_HEAD(&state->redirects); - uci_foreach_element(&p->sections, e) + blob_for_each_attr(entry, a, rem) { - s = uci_to_section(e); + const char *type = NULL; + const char *name = "ubus redirect"; + blobmsg_for_each_attr(opt, entry, orem) + if (!strcmp(blobmsg_name(opt), "type")) + type = blobmsg_get_string(opt); + else if (!strcmp(blobmsg_name(opt), "name")) + name = blobmsg_get_string(opt); + + if (!type || strcmp(type, "redirect")) + continue; - if (strcmp(s->type, "redirect")) + if (!(redir = fw3_alloc_redirect(state))) continue; - redir = calloc(1, sizeof(*redir)); - if (!redir) + if (!fw3_parse_blob_options(redir, fw3_redirect_opts, entry, name)) + { + warn("%s skipped due to invalid options\n", name); + fw3_free_redirect(redir); continue; + } + } - INIT_LIST_HEAD(&redir->proto); - INIT_LIST_HEAD(&redir->mac_src); + uci_foreach_element(&p->sections, e) + { + s = uci_to_section(e); - redir->enabled = true; - redir->reflection = true; + if (strcmp(s->type, "redirect")) + continue; - valid = false; + if (!(redir = fw3_alloc_redirect(state))) + continue; if (!fw3_parse_options(redir, fw3_redirect_opts, s)) { @@ -211,7 +248,10 @@ fw3_load_redirects(struct fw3_state *state, struct uci_package *p) fw3_free_redirect(redir); continue; } + } + list_for_each_entry_safe(redir, n, &state->redirects, list) + { if (!redir->enabled) { fw3_free_redirect(redir); @@ -220,34 +260,37 @@ fw3_load_redirects(struct fw3_state *state, struct uci_package *p) if (redir->src.invert) { - warn_elem(e, "must not have an inverted source"); + warn("%s must not have an inverted source", redir->name); fw3_free_redirect(redir); continue; } else if (redir->src.set && !redir->src.any && !(redir->_src = fw3_lookup_zone(state, redir->src.name))) { - warn_elem(e, "refers to not existing zone '%s'", redir->src.name); + warn("%s refers to not existing zone '%s'", redir->name, + redir->src.name); fw3_free_redirect(redir); continue; } else if (redir->dest.set && !redir->dest.any && !(redir->_dest = fw3_lookup_zone(state, redir->dest.name))) { - warn_elem(e, "refers to not existing zone '%s'", redir->dest.name); + warn("%s refers to not existing zone '%s'", redir->name, + redir->dest.name); fw3_free_redirect(redir); continue; } else if (redir->ipset.set && state->disable_ipsets) { - warn_elem(e, "skipped due to disabled ipset support"); + warn("%s skipped due to disabled ipset support", redir->name); fw3_free_redirect(redir); continue; } else if (redir->ipset.set && !(redir->ipset.ptr = fw3_lookup_ipset(state, redir->ipset.name))) { - warn_elem(e, "refers to unknown ipset '%s'", redir->ipset.name); + warn("%s refers to unknown ipset '%s'", redir->name, + redir->ipset.name); fw3_free_redirect(redir); continue; } @@ -260,21 +303,26 @@ fw3_load_redirects(struct fw3_state *state, struct uci_package *p) if (redir->target == FW3_FLAG_UNSPEC) { - warn_elem(e, "has no target specified, defaulting to DNAT"); + warn("%s has no target specified, defaulting to DNAT", + redir->name); redir->target = FW3_FLAG_DNAT; } else if (redir->target < FW3_FLAG_DNAT || redir->target > FW3_FLAG_SNAT) { - warn_elem(e, "has invalid target specified, defaulting to DNAT"); + warn("%s has invalid target specified, defaulting to DNAT", + redir->name); redir->target = FW3_FLAG_DNAT; } + valid = false; + if (redir->target == FW3_FLAG_DNAT) { if (redir->src.any) - warn_elem(e, "must not have source '*' for DNAT target"); + warn("%s must not have source '*' for DNAT target", + redir->name); else if (!redir->_src) - warn_elem(e, "has no source specified"); + warn("%s has no source specified", redir->name); else { set(redir->_src->flags, FW3_FAMILY_V4, redir->target); @@ -283,8 +331,8 @@ fw3_load_redirects(struct fw3_state *state, struct uci_package *p) if (!check_local(e, redir, state) && !redir->dest.set && resolve_dest(e, redir, state)) { - warn_elem(e, "does not specify a destination, assuming '%s'", - redir->dest.name); + warn("%s does not specify a destination, assuming '%s'", + redir->name, redir->dest.name); } if (redir->reflection && redir->_dest && redir->_src->masq) @@ -298,13 +346,13 @@ fw3_load_redirects(struct fw3_state *state, struct uci_package *p) else { if (redir->dest.any) - warn_elem(e, "must not have destination '*' for SNAT target"); + warn("%s must not have destination '*' for SNAT target", redir->name); else if (!redir->_dest) - warn_elem(e, "has no destination specified"); + warn("%s has no destination specified", redir->name); else if (!redir->ip_dest.set) - warn_elem(e, "has no src_dip option specified"); + warn("%s has no src_dip option specified", redir->name); else if (!list_empty(&redir->mac_src)) - warn_elem(e, "must not use 'src_mac' option for SNAT target"); + warn("%s must not use 'src_mac' option for SNAT target", redir->name); else { set(redir->_dest->flags, FW3_FAMILY_V4, redir->target); @@ -314,7 +362,7 @@ fw3_load_redirects(struct fw3_state *state, struct uci_package *p) if (list_empty(&redir->proto)) { - warn_elem(e, "does not specify a protocol, assuming TCP+UDP"); + warn("%s does not specify a protocol, assuming TCP+UDP", redir->name); fw3_parse_protocol(&redir->proto, "tcpudp", true); } @@ -326,8 +374,6 @@ fw3_load_redirects(struct fw3_state *state, struct uci_package *p) if (!redir->port_redir.set) redir->port_redir = redir->port_dest; - - list_add_tail(&redir->list, &state->redirects); } } diff --git a/redirects.h b/redirects.h index b52d8c3..ac625f4 100644 --- a/redirects.h +++ b/redirects.h @@ -27,11 +27,15 @@ extern const struct fw3_option fw3_redirect_opts[]; -void fw3_load_redirects(struct fw3_state *state, struct uci_package *p); +void fw3_load_redirects(struct fw3_state *state, struct uci_package *p, + struct blob_attr *a); void fw3_print_redirects(struct fw3_ipt_handle *handle, struct fw3_state *state); -#define fw3_free_redirect(redir) \ - fw3_free_object(redir, fw3_redirect_opts) +static inline void fw3_free_redirect(struct fw3_redirect *redir) +{ + list_del(&redir->list); + fw3_free_object(redir, fw3_redirect_opts); +} #endif -- 1.7.9.5 _______________________________________________ Lede-dev mailing list Lede-dev@lists.infradead.org http://lists.infradead.org/mailman/listinfo/lede-dev