X-Git-Url: http://git.archive.openwrt.org/?p=project%2Ffirewall3.git;a=blobdiff_plain;f=forwards.c;h=b32b529a2337c9143802ed80404909d271f4f352;hp=158ccbffdcabce7b0522adf594576b22c28802c3;hb=02d68323ec83a5163caa4da3ed5f96860f607dae;hpb=46536e5263c4bf57a91c38b5d08d78c774649dda diff --git a/forwards.c b/forwards.c index 158ccbf..b32b529 100644 --- a/forwards.c +++ b/forwards.c @@ -1,7 +1,7 @@ /* * firewall3 - 3rd OpenWrt UCI firewall implementation * - * Copyright (C) 2013 Jo-Philipp Wich + * Copyright (C) 2013 Jo-Philipp Wich * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -31,105 +31,143 @@ const struct fw3_option fw3_forward_opts[] = { { } }; +static bool +check_forward(struct fw3_state *state, struct fw3_forward *forward, struct uci_element *e) +{ + if (!forward->enabled) + return false; + + if (forward->src.invert || forward->dest.invert) + { + warn_section("forward", forward, e, "must not have inverted 'src' or 'dest' options"); + return false; + } + else if (forward->src.set && !forward->src.any && + !(forward->_src = fw3_lookup_zone(state, forward->src.name))) + { + warn_section("forward", forward, e, "refers to not existing zone '%s'", + forward->src.name); + return false; + } + else if (forward->dest.set && !forward->dest.any && + !(forward->_dest = fw3_lookup_zone(state, forward->dest.name))) + { + warn_section("forward", forward, e, "refers to not existing zone '%s'", + forward->dest.name); + return false; + } + + /* NB: forward family... */ + if (forward->_dest) + { + fw3_setbit(forward->_dest->flags[0], FW3_FLAG_ACCEPT); + fw3_setbit(forward->_dest->flags[1], FW3_FLAG_ACCEPT); + } + + return true; +} + +static struct fw3_forward * +fw3_alloc_forward(struct fw3_state *state) +{ + struct fw3_forward *forward; + + forward = calloc(1, sizeof(*forward)); + if (!forward) + return NULL; + + forward->enabled = true; + + list_add_tail(&forward->list, &state->forwards); + + return forward; +} void -fw3_load_forwards(struct fw3_state *state, struct uci_package *p) +fw3_load_forwards(struct fw3_state *state, struct uci_package *p, + struct blob_attr *a) { struct uci_section *s; struct uci_element *e; struct fw3_forward *forward; + struct blob_attr *entry; + unsigned rem; INIT_LIST_HEAD(&state->forwards); - uci_foreach_element(&p->sections, e) + blob_for_each_attr(entry, a, rem) { - s = uci_to_section(e); + const char *type; + const char *name = "ubus forward"; - if (strcmp(s->type, "forwarding")) + if (!fw3_attr_parse_name_type(entry, &name, &type)) continue; - forward = malloc(sizeof(*forward)); + if (strcmp(type, "forwarding")) + continue; + forward = fw3_alloc_forward(state); if (!forward) continue; - memset(forward, 0, sizeof(*forward)); - - forward->enabled = true; - - fw3_parse_options(forward, fw3_forward_opts, s); - - if (!forward->enabled) + if (!fw3_parse_blob_options(forward, fw3_forward_opts, entry, name)) { + warn_section("forward", forward, NULL, "skipped due to invalid options"); fw3_free_forward(forward); continue; } - if (forward->src.invert || forward->dest.invert) - { - warn_elem(e, "must not have inverted 'src' or 'dest' options"); - fw3_free_forward(forward); - continue; - } - else if (forward->src.set && !forward->src.any && - !(forward->_src = fw3_lookup_zone(state, forward->src.name, false))) - { - warn_elem(e, "refers to not existing zone '%s'", forward->src.name); - fw3_free_forward(forward); - continue; - } - else if (forward->dest.set && !forward->dest.any && - !(forward->_dest = fw3_lookup_zone(state, forward->dest.name, false))) - { - warn_elem(e, "refers to not existing zone '%s'", forward->dest.name); + if (!check_forward(state, forward, NULL)) fw3_free_forward(forward); + } + + uci_foreach_element(&p->sections, e) + { + s = uci_to_section(e); + + if (strcmp(s->type, "forwarding")) continue; - } - if (forward->_dest) - { - setbit(forward->_dest->dst_flags, FW3_TARGET_ACCEPT); + forward = fw3_alloc_forward(state); + if (!forward) + continue; - if (forward->_src && - (forward->_src->conntrack || forward->_dest->conntrack)) - { - forward->_src->conntrack = forward->_dest->conntrack = true; - } - } + if (!fw3_parse_options(forward, fw3_forward_opts, s)) + warn_elem(e, "has invalid options"); - list_add_tail(&forward->list, &state->forwards); - continue; + if (!check_forward(state, forward, e)) + fw3_free_forward(forward); } } static void -print_chain(struct fw3_forward *forward) +append_chain(struct fw3_ipt_rule *r, struct fw3_forward *forward) { if (forward->src.any || !forward->src.set) - fw3_pr("-A delegate_forward"); + fw3_ipt_rule_append(r, "FORWARD"); else - fw3_pr("-A zone_%s_forward", forward->src.name); + fw3_ipt_rule_append(r, "zone_%s_forward", forward->src.name); } -static void print_target(struct fw3_forward *forward) +static void set_target(struct fw3_ipt_rule *r, struct fw3_forward *forward) { if (forward->dest.any || !forward->dest.set) - fw3_pr(" -j ACCEPT\n"); + fw3_ipt_rule_target(r, "ACCEPT"); else - fw3_pr(" -j zone_%s_dest_ACCEPT\n", forward->dest.name); + fw3_ipt_rule_target(r, "zone_%s_dest_ACCEPT", forward->dest.name); } static void -print_forward(enum fw3_table table, enum fw3_family family, - struct fw3_forward *forward) +print_forward(struct fw3_ipt_handle *handle, struct fw3_forward *forward) { const char *s, *d; + struct fw3_ipt_rule *r; - if (table != FW3_TABLE_FILTER) + if (handle->table != FW3_TABLE_FILTER) return; - if (!fw3_is_family(forward, family)) + if (!fw3_is_family(forward, handle->family)) return; s = forward->_src ? forward->_src->name : "*"; @@ -137,24 +175,24 @@ print_forward(enum fw3_table table, enum fw3_family family, info(" * Forward '%s' -> '%s'", s, d); - if (!fw3_is_family(forward->_src, family) || - !fw3_is_family(forward->_dest, family)) + if (!fw3_is_family(forward->_src, handle->family) || + !fw3_is_family(forward->_dest, handle->family)) { info(" ! Skipping due to different family of zone"); return; } - print_chain(forward); - fw3_format_comment("forwarding ", s, "->", d); - print_target(forward); + r = fw3_ipt_rule_new(handle); + fw3_ipt_rule_comment(r, "forwarding %s -> %s", s, d); + set_target(r, forward); + append_chain(r, forward); } void -fw3_print_forwards(enum fw3_table table, enum fw3_family family, - struct fw3_state *state) +fw3_print_forwards(struct fw3_ipt_handle *handle, struct fw3_state *state) { struct fw3_forward *forward; list_for_each_entry(forward, &state->forwards, list) - print_forward(table, family, forward); + print_forward(handle, forward); }