firewall3: add UBUS support for forwarding sections
authorPierre Lebleu <pme.lebleu@gmail.com>
Thu, 4 May 2017 08:52:55 +0000 (10:52 +0200)
committerJo-Philipp Wich <jo@mein.io>
Tue, 9 May 2017 21:54:15 +0000 (23:54 +0200)
It gives the ability to create forward rules via procd
services and netifd interface firewall data.

Signed-off-by: Pierre Lebleu <pme.lebleu@gmail.com>
forwards.c
forwards.h
main.c

index 9b369f386979d1acb5f0dc74b8bda1c474ae3e90..b32b529a2337c9143802ed80404909d271f4f352 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);
        }
 }
 
index 3006e9ecf35b7a4140699bffb417127d293a3927..06d3e06ef2da6d8d0f2bf7f1efcce2798c55b2f4 100644 (file)
 
 extern const struct fw3_option fw3_forward_opts[];
 
-void fw3_load_forwards(struct fw3_state *state, struct uci_package *p);
+void fw3_load_forwards(struct fw3_state *state, struct uci_package *p, struct blob_attr *a);
 void fw3_print_forwards(struct fw3_ipt_handle *handle, struct fw3_state *state);
 
-#define fw3_free_forward(forward) \
-       fw3_free_object(forward, fw3_forward_opts)
+static inline void fw3_free_forward(struct fw3_forward *forward)
+{
+       list_del(&forward->list);
+       fw3_free_object(forward, fw3_forward_opts);
+}
 
 #endif
diff --git a/main.c b/main.c
index 5888ab50285a6e416d3434ea28f9e16901d7106a..4cf46fd84227d1034a52e3471fd0776d038bbbbf 100644 (file)
--- a/main.c
+++ b/main.c
@@ -106,7 +106,7 @@ build_state(bool runtime)
        fw3_load_rules(state, p, b.head);
        fw3_load_redirects(state, p, b.head);
        fw3_load_snats(state, p, b.head);
-       fw3_load_forwards(state, p);
+       fw3_load_forwards(state, p, b.head);
        fw3_load_includes(state, p);
 
        return true;