1 /* 2 * firewall3 - 3rd OpenWrt UCI firewall implementation 3 * 4 * Copyright (C) 2018 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 "helpers.h" 20 21 22 const struct fw3_option fw3_cthelper_opts[] = { 23 FW3_OPT("enabled", bool, cthelper, enabled), 24 FW3_OPT("name", string, cthelper, name), 25 FW3_OPT("module", string, cthelper, module), 26 FW3_OPT("description", string, cthelper, description), 27 FW3_OPT("family", family, cthelper, family), 28 FW3_LIST("proto", protocol, cthelper, proto), 29 FW3_OPT("port", port, cthelper, port), 30 31 { } 32 }; 33 34 35 static bool 36 test_module(struct fw3_cthelper *helper) 37 { 38 struct stat s; 39 char path[sizeof("/sys/module/nf_conntrack_xxxxxxxxxxxxxxxx")]; 40 41 snprintf(path, sizeof(path), "/sys/module/%s", helper->module); 42 43 if (stat(path, &s) || !S_ISDIR(s.st_mode)) 44 return false; 45 46 return true; 47 } 48 49 static bool 50 check_cthelper_proto(const struct fw3_cthelper *helper) 51 { 52 struct fw3_protocol *proto; 53 54 if (list_empty(&helper->proto)) 55 return false; 56 57 list_for_each_entry(proto, &helper->proto, list) 58 { 59 if (!proto->protocol || proto->any || proto->invert) 60 return false; 61 } 62 63 return true; 64 } 65 66 static bool 67 check_cthelper(struct fw3_state *state, struct fw3_cthelper *helper, struct uci_element *e) 68 { 69 if (!helper->name || !*helper->name) 70 { 71 warn_section("helper", helper, e, "must have a name assigned"); 72 } 73 else if (!helper->module || !*helper->module) 74 { 75 warn_section("helper", helper, e, "must have a module assigned"); 76 } 77 else if (!check_cthelper_proto(helper)) 78 { 79 warn_section("helper", helper, e, "must specify a protocol"); 80 } 81 else if (helper->port.set && helper->port.invert) 82 { 83 warn_section("helper", helper, e, "must not specify negated ports"); 84 } 85 else 86 { 87 return true; 88 } 89 90 return false; 91 } 92 93 static struct fw3_cthelper * 94 fw3_alloc_cthelper(struct fw3_state *state) 95 { 96 struct fw3_cthelper *helper; 97 98 helper = calloc(1, sizeof(*helper)); 99 if (!helper) 100 return NULL; 101 102 helper->enabled = true; 103 helper->family = FW3_FAMILY_ANY; 104 INIT_LIST_HEAD(&helper->proto); 105 106 list_add_tail(&helper->list, &state->cthelpers); 107 108 return helper; 109 } 110 111 static void 112 load_cthelpers(struct fw3_state *state, struct uci_package *p) 113 { 114 struct fw3_cthelper *helper; 115 struct uci_section *s; 116 struct uci_element *e; 117 118 uci_foreach_element(&p->sections, e) 119 { 120 s = uci_to_section(e); 121 122 if (strcmp(s->type, "helper")) 123 continue; 124 125 helper = fw3_alloc_cthelper(state); 126 127 if (!helper) 128 continue; 129 130 if (!fw3_parse_options(helper, fw3_cthelper_opts, s)) 131 warn_elem(e, "has invalid options"); 132 133 if (!check_cthelper(state, helper, e)) 134 fw3_free_cthelper(helper); 135 } 136 } 137 138 void 139 fw3_load_cthelpers(struct fw3_state *state, struct uci_package *p) 140 { 141 struct uci_package *hp = NULL; 142 FILE *fp; 143 144 INIT_LIST_HEAD(&state->cthelpers); 145 146 fp = fopen(FW3_HELPERCONF, "r"); 147 148 if (fp) { 149 uci_import(state->uci, fp, "fw3_ct_helpers", &hp, true); 150 fclose(fp); 151 152 if (hp) 153 load_cthelpers(state, hp); 154 } 155 156 load_cthelpers(state, p); 157 } 158 159 struct fw3_cthelper * 160 fw3_lookup_cthelper(struct fw3_state *state, const char *name) 161 { 162 struct fw3_cthelper *h; 163 164 if (list_empty(&state->cthelpers)) 165 return NULL; 166 167 list_for_each_entry(h, &state->cthelpers, list) 168 { 169 if (strcasecmp(h->name, name)) 170 continue; 171 172 return h; 173 } 174 175 return NULL; 176 } 177 178 bool 179 fw3_cthelper_check_proto(const struct fw3_cthelper *h, const struct fw3_protocol *proto) 180 { 181 struct fw3_protocol *p; 182 183 list_for_each_entry(p, &h->proto, list) 184 { 185 if (p->protocol == proto->protocol) 186 return true; 187 } 188 189 return false; 190 } 191 192 struct fw3_cthelper * 193 fw3_lookup_cthelper_by_proto_port(struct fw3_state *state, 194 struct fw3_protocol *proto, 195 struct fw3_port *port) 196 { 197 struct fw3_cthelper *h; 198 199 if (list_empty(&state->cthelpers)) 200 return NULL; 201 202 if (!proto || !proto->protocol || proto->any || proto->invert) 203 return NULL; 204 205 if (port && port->invert) 206 return NULL; 207 208 list_for_each_entry(h, &state->cthelpers, list) 209 { 210 if (!h->enabled) 211 continue; 212 213 if (!fw3_cthelper_check_proto(h, proto)) 214 continue; 215 216 if (h->port.set && (!port || !port->set)) 217 continue; 218 219 if (!h->port.set && (!port || !port->set)) 220 return h; 221 222 if (h->port.set && port && port->set && 223 h->port.port_min <= port->port_min && 224 h->port.port_max >= port->port_max) 225 return h; 226 } 227 228 return NULL; 229 } 230 231 static void 232 print_helper_rule(struct fw3_ipt_handle *handle, struct fw3_cthelper *helper, 233 struct fw3_zone *zone, struct fw3_protocol *proto) 234 { 235 struct fw3_ipt_rule *r; 236 237 r = fw3_ipt_rule_create(handle, proto, NULL, NULL, NULL, NULL); 238 239 if (helper->description && *helper->description) 240 fw3_ipt_rule_comment(r, helper->description); 241 else 242 fw3_ipt_rule_comment(r, helper->name); 243 244 fw3_ipt_rule_sport_dport(r, NULL, &helper->port); 245 fw3_ipt_rule_target(r, "CT"); 246 fw3_ipt_rule_addarg(r, false, "--helper", helper->name); 247 fw3_ipt_rule_replace(r, "zone_%s_helper", zone->name); 248 } 249 250 static void 251 expand_helper_rule(struct fw3_ipt_handle *handle, struct fw3_cthelper *helper, 252 struct fw3_zone *zone) 253 { 254 struct fw3_protocol *proto; 255 256 list_for_each_entry(proto, &helper->proto, list) 257 print_helper_rule(handle, helper, zone, proto); 258 } 259 260 void 261 fw3_print_cthelpers(struct fw3_ipt_handle *handle, struct fw3_state *state, 262 struct fw3_zone *zone) 263 { 264 struct fw3_cthelper *helper; 265 struct fw3_cthelpermatch *match; 266 267 if (handle->table != FW3_TABLE_RAW) 268 return; 269 270 if (!fw3_is_family(zone, handle->family)) 271 return; 272 273 if (list_empty(&zone->cthelpers)) 274 { 275 if (zone->masq || !zone->auto_helper) 276 return; 277 278 if (list_empty(&state->cthelpers)) 279 return; 280 281 info(" - Using automatic conntrack helper attachment"); 282 283 list_for_each_entry(helper, &state->cthelpers, list) 284 { 285 if (!helper || !helper->enabled) 286 continue; 287 288 if (!fw3_is_family(helper, handle->family)) 289 continue; 290 291 if (!test_module(helper)) 292 continue; 293 294 expand_helper_rule(handle, helper, zone); 295 } 296 } 297 else 298 { 299 list_for_each_entry(match, &zone->cthelpers, list) 300 { 301 helper = match->ptr; 302 303 if (!helper || !helper->enabled) 304 continue; 305 306 if (!fw3_is_family(helper, handle->family)) 307 continue; 308 309 if (!test_module(helper)) 310 { 311 info(" ! Conntrack module '%s' for helper '%s' is not loaded", 312 helper->module, helper->name); 313 continue; 314 } 315 316 expand_helper_rule(handle, helper, zone); 317 } 318 } 319 } 320
This page was automatically generated by LXR 0.3.1. • OpenWrt