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