zones: add interface/subnet bound LOG rules
[project/firewall3.git] / forwards.c
index 9b369f3..b554b60 100644 (file)
@@ -31,71 +31,112 @@ 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 = calloc(1, sizeof(*forward));
-               if (!forward)
+               if (strcmp(type, "forwarding"))
                        continue;
 
-               forward->enabled = true;
-
-               if (!fw3_parse_options(forward, fw3_forward_opts, s))
-                       warn_elem(e, "has invalid options");
-
-               if (!forward->enabled)
-               {
-                       fw3_free_forward(forward);
+               forward = fw3_alloc_forward(state);
+               if (!forward)
                        continue;
-               }
 
-               if (forward->src.invert || forward->dest.invert)
+               if (!fw3_parse_blob_options(forward, fw3_forward_opts, entry, name))
                {
-                       warn_elem(e, "must not have inverted 'src' or 'dest' options");
+                       warn_section("forward", forward, NULL, "skipped due to invalid options");
                        fw3_free_forward(forward);
                        continue;
                }
-               else if (forward->src.set && !forward->src.any &&
-                        !(forward->_src = fw3_lookup_zone(state, forward->src.name)))
-               {
-                       warn_elem(e, "refers to not existing zone '%s'", forward->src.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;
-               }
-               else if (forward->dest.set && !forward->dest.any &&
-                        !(forward->_dest = fw3_lookup_zone(state, forward->dest.name)))
-               {
-                       warn_elem(e, "refers to not existing zone '%s'", forward->dest.name);
-                       fw3_free_forward(forward);
+
+               forward = fw3_alloc_forward(state);
+               if (!forward)
                        continue;
-               }
 
-               list_add_tail(&forward->list, &state->forwards);
-               continue;
-       }
+               if (!fw3_parse_options(forward, fw3_forward_opts, s))
+                       warn_elem(e, "has invalid options");
 
-       list_for_each_entry(forward, &state->forwards, list)
-       {
-               /* NB: forward family... */
-               if (forward->_dest)
-               {
-                       fw3_setbit(forward->_dest->flags[0], FW3_FLAG_ACCEPT);
-                       fw3_setbit(forward->_dest->flags[1], FW3_FLAG_ACCEPT);
-               }
+               if (!check_forward(state, forward, e))
+                       fw3_free_forward(forward);
        }
 }
 
@@ -142,7 +183,7 @@ print_forward(struct fw3_ipt_handle *handle, struct fw3_forward *forward)
        }
 
        r = fw3_ipt_rule_new(handle);
-       fw3_ipt_rule_comment(r, "forwarding %s -> %s", s, d);
+       fw3_ipt_rule_comment(r, "Zone %s to %s forwarding policy", s, d);
        set_target(r, forward);
        append_chain(r, forward);
 }