• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/firewall3/forwards.c

  1 /*
  2  * firewall3 - 3rd OpenWrt UCI firewall implementation
  3  *
  4  *   Copyright (C) 2013 Jo-Philipp Wich <jo@mein.io>
  5  *
  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.
  9  *
 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.
 17  */
 18 
 19 #include "forwards.h"
 20 
 21 
 22 const struct fw3_option fw3_forward_opts[] = {
 23         FW3_OPT("enabled",             bool,     forward,     enabled),
 24 
 25         FW3_OPT("name",                string,   forward,     name),
 26         FW3_OPT("family",              family,   forward,     family),
 27 
 28         FW3_OPT("src",                 device,   forward,     src),
 29         FW3_OPT("dest",                device,   forward,     dest),
 30 
 31         { }
 32 };
 33 
 34 static bool
 35 check_forward(struct fw3_state *state, struct fw3_forward *forward, struct uci_element *e)
 36 {
 37         if (!forward->enabled)
 38                 return false;
 39 
 40         if (forward->src.invert || forward->dest.invert)
 41         {
 42                 warn_section("forward", forward, e, "must not have inverted 'src' or 'dest' options");
 43                 return false;
 44         }
 45         else if (forward->src.set && !forward->src.any &&
 46                  !(forward->_src = fw3_lookup_zone(state, forward->src.name)))
 47         {
 48                 warn_section("forward", forward, e, "refers to not existing zone '%s'",
 49                                 forward->src.name);
 50                 return false;
 51         }
 52         else if (forward->dest.set && !forward->dest.any &&
 53                  !(forward->_dest = fw3_lookup_zone(state, forward->dest.name)))
 54         {
 55                 warn_section("forward", forward, e, "refers to not existing zone '%s'",
 56                                 forward->dest.name);
 57                 return false;
 58         }
 59 
 60         /* NB: forward family... */
 61         if (forward->_dest)
 62         {
 63                 fw3_setbit(forward->_dest->flags[0], FW3_FLAG_ACCEPT);
 64                 fw3_setbit(forward->_dest->flags[1], FW3_FLAG_ACCEPT);
 65         }
 66 
 67         return true;
 68 }
 69 
 70 static struct fw3_forward *
 71 fw3_alloc_forward(struct fw3_state *state)
 72 {
 73         struct fw3_forward *forward;
 74 
 75         forward = calloc(1, sizeof(*forward));
 76         if (!forward)
 77                 return NULL;
 78 
 79         forward->enabled = true;
 80 
 81         list_add_tail(&forward->list, &state->forwards);
 82 
 83         return forward;
 84 }
 85 
 86 void
 87 fw3_load_forwards(struct fw3_state *state, struct uci_package *p,
 88                 struct blob_attr *a)
 89 {
 90         struct uci_section *s;
 91         struct uci_element *e;
 92         struct fw3_forward *forward;
 93         struct blob_attr *entry;
 94         unsigned rem;
 95 
 96         INIT_LIST_HEAD(&state->forwards);
 97 
 98         blob_for_each_attr(entry, a, rem)
 99         {
100                 const char *type;
101                 const char *name = "ubus forward";
102 
103                 if (!fw3_attr_parse_name_type(entry, &name, &type))
104                         continue;
105 
106                 if (strcmp(type, "forwarding"))
107                         continue;
108 
109                 forward = fw3_alloc_forward(state);
110                 if (!forward)
111                         continue;
112 
113                 if (!fw3_parse_blob_options(forward, fw3_forward_opts, entry, name))
114                 {
115                         warn_section("forward", forward, NULL, "skipped due to invalid options");
116                         fw3_free_forward(forward);
117                         continue;
118                 }
119 
120                 if (!check_forward(state, forward, NULL))
121                         fw3_free_forward(forward);
122         }
123 
124         uci_foreach_element(&p->sections, e)
125         {
126                 s = uci_to_section(e);
127 
128                 if (strcmp(s->type, "forwarding"))
129                         continue;
130 
131                 forward = fw3_alloc_forward(state);
132                 if (!forward)
133                         continue;
134 
135                 if (!fw3_parse_options(forward, fw3_forward_opts, s))
136                         warn_elem(e, "has invalid options");
137 
138                 if (!check_forward(state, forward, e))
139                         fw3_free_forward(forward);
140         }
141 }
142 
143 
144 static void
145 append_chain(struct fw3_ipt_rule *r, struct fw3_forward *forward)
146 {
147         if (forward->src.any || !forward->src.set)
148                 fw3_ipt_rule_append(r, "FORWARD");
149         else
150                 fw3_ipt_rule_append(r, "zone_%s_forward", forward->src.name);
151 }
152 
153 static void set_target(struct fw3_ipt_rule *r, struct fw3_forward *forward)
154 {
155         if (forward->dest.any || !forward->dest.set)
156                 fw3_ipt_rule_target(r, "ACCEPT");
157         else
158                 fw3_ipt_rule_target(r, "zone_%s_dest_ACCEPT", forward->dest.name);
159 }
160 
161 static void
162 print_forward(struct fw3_ipt_handle *handle, struct fw3_forward *forward)
163 {
164         const char *s, *d;
165         struct fw3_ipt_rule *r;
166 
167         if (handle->table != FW3_TABLE_FILTER)
168                 return;
169 
170         if (!fw3_is_family(forward, handle->family))
171                 return;
172 
173         s = forward->_src  ? forward->_src->name  : "*";
174         d = forward->_dest ? forward->_dest->name : "*";
175 
176         info("   * Forward '%s' -> '%s'", s, d);
177 
178         if (!fw3_is_family(forward->_src, handle->family) ||
179             !fw3_is_family(forward->_dest, handle->family))
180         {
181                 info("     ! Skipping due to different family of zone");
182                 return;
183         }
184 
185         r = fw3_ipt_rule_new(handle);
186         fw3_ipt_rule_comment(r, "Zone %s to %s forwarding policy", s, d);
187         set_target(r, forward);
188         append_chain(r, forward);
189 }
190 
191 void
192 fw3_print_forwards(struct fw3_ipt_handle *handle, struct fw3_state *state)
193 {
194         struct fw3_forward *forward;
195 
196         list_for_each_entry(forward, &state->forwards, list)
197                 print_forward(handle, forward);
198 }
199 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt