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 "zones.h" 20 #include "ubus.h" 21 #include "helpers.h" 22 23 24 #define C(f, tbl, tgt, fmt) \ 25 { FW3_FAMILY_##f, FW3_TABLE_##tbl, FW3_FLAG_##tgt, fmt } 26 27 static const struct fw3_chain_spec zone_chains[] = { 28 C(ANY, FILTER, UNSPEC, "zone_?_input"), 29 C(ANY, FILTER, UNSPEC, "zone_?_output"), 30 C(ANY, FILTER, UNSPEC, "zone_?_forward"), 31 32 C(ANY, FILTER, SRC_ACCEPT, "zone_?_src_ACCEPT"), 33 C(ANY, FILTER, SRC_REJECT, "zone_?_src_REJECT"), 34 C(ANY, FILTER, SRC_DROP, "zone_?_src_DROP"), 35 36 C(ANY, FILTER, ACCEPT, "zone_?_dest_ACCEPT"), 37 C(ANY, FILTER, REJECT, "zone_?_dest_REJECT"), 38 C(ANY, FILTER, DROP, "zone_?_dest_DROP"), 39 40 C(V4, NAT, SNAT, "zone_?_postrouting"), 41 C(V4, NAT, DNAT, "zone_?_prerouting"), 42 43 C(ANY, RAW, HELPER, "zone_?_helper"), 44 C(ANY, RAW, NOTRACK, "zone_?_notrack"), 45 46 C(ANY, FILTER, CUSTOM_CHAINS, "input_?_rule"), 47 C(ANY, FILTER, CUSTOM_CHAINS, "output_?_rule"), 48 C(ANY, FILTER, CUSTOM_CHAINS, "forwarding_?_rule"), 49 50 C(V4, NAT, CUSTOM_CHAINS, "prerouting_?_rule"), 51 C(V4, NAT, CUSTOM_CHAINS, "postrouting_?_rule"), 52 53 { } 54 }; 55 56 enum fw3_zone_logmask { 57 FW3_ZONE_LOG_FILTER = (1 << 0), 58 FW3_ZONE_LOG_MANGLE = (1 << 1), 59 }; 60 61 const struct fw3_option fw3_zone_opts[] = { 62 FW3_OPT("enabled", bool, zone, enabled), 63 64 FW3_OPT("name", string, zone, name), 65 FW3_OPT("family", family, zone, family), 66 67 FW3_LIST("network", device, zone, networks), 68 FW3_LIST("device", device, zone, devices), 69 FW3_LIST("subnet", network, zone, subnets), 70 71 FW3_OPT("input", target, zone, policy_input), 72 FW3_OPT("forward", target, zone, policy_forward), 73 FW3_OPT("output", target, zone, policy_output), 74 75 FW3_OPT("masq", bool, zone, masq), 76 FW3_OPT("masq_allow_invalid", bool, zone, masq_allow_invalid), 77 FW3_LIST("masq_src", network, zone, masq_src), 78 FW3_LIST("masq_dest", network, zone, masq_dest), 79 80 FW3_OPT("extra", string, zone, extra_src), 81 FW3_OPT("extra_src", string, zone, extra_src), 82 FW3_OPT("extra_dest", string, zone, extra_dest), 83 84 FW3_OPT("mtu_fix", bool, zone, mtu_fix), 85 FW3_OPT("custom_chains", bool, zone, custom_chains), 86 87 FW3_OPT("log", int, zone, log), 88 FW3_OPT("log_limit", limit, zone, log_limit), 89 90 FW3_OPT("auto_helper", bool, zone, auto_helper), 91 FW3_LIST("helper", cthelper, zone, cthelpers), 92 93 FW3_OPT("__flags_v4", int, zone, flags[0]), 94 FW3_OPT("__flags_v6", int, zone, flags[1]), 95 96 FW3_LIST("__addrs", address, zone, old_addrs), 97 98 { } 99 }; 100 101 static void 102 check_policy(struct uci_element *e, enum fw3_flag *pol, enum fw3_flag def, 103 const char *name) 104 { 105 if (*pol == FW3_FLAG_UNSPEC) 106 { 107 warn_elem(e, "has no %s policy specified, using default", name); 108 *pol = def; 109 } 110 else if (*pol > FW3_FLAG_DROP) 111 { 112 warn_elem(e, "has invalid %s policy, using default", name); 113 *pol = def; 114 } 115 } 116 117 static bool 118 check_masq_addrs(struct list_head *head) 119 { 120 struct fw3_address *addr; 121 int n_addr = 0, n_failed = 0; 122 123 list_for_each_entry(addr, head, list) 124 { 125 if (addr->invert) 126 continue; 127 128 n_addr++; 129 130 if (!addr->set && addr->resolved) 131 n_failed++; 132 } 133 134 return (n_addr == 0 || n_failed < n_addr); 135 } 136 137 static void 138 resolve_networks(struct uci_element *e, struct fw3_zone *zone) 139 { 140 struct fw3_device *net, *dev, *tmp; 141 142 list_for_each_entry(net, &zone->networks, list) 143 { 144 tmp = fw3_ubus_device(net->name); 145 146 if (!tmp) 147 { 148 warn_elem(e, "cannot resolve device of network '%s'", net->name); 149 continue; 150 } 151 152 list_for_each_entry(dev, &zone->devices, list) 153 if (!strcmp(dev->name, tmp->name)) 154 goto alias; 155 156 snprintf(tmp->network, sizeof(tmp->network), "%s", net->name); 157 list_add_tail(&tmp->list, &zone->devices); 158 continue; 159 alias: 160 free(tmp); 161 } 162 } 163 164 static void 165 resolve_cthelpers(struct fw3_state *s, struct uci_element *e, struct fw3_zone *zone) 166 { 167 struct fw3_cthelpermatch *match; 168 169 if (list_empty(&zone->cthelpers)) 170 { 171 if (!zone->masq && zone->auto_helper) 172 { 173 fw3_setbit(zone->flags[0], FW3_FLAG_HELPER); 174 fw3_setbit(zone->flags[1], FW3_FLAG_HELPER); 175 } 176 177 return; 178 } 179 180 list_for_each_entry(match, &zone->cthelpers, list) 181 { 182 if (match->invert) 183 { 184 warn_elem(e, "must not use a negated helper match"); 185 continue; 186 } 187 188 match->ptr = fw3_lookup_cthelper(s, match->name); 189 190 if (!match->ptr) 191 { 192 warn_elem(e, "refers to not existing helper '%s'", match->name); 193 continue; 194 } 195 196 if (fw3_is_family(match->ptr, FW3_FAMILY_V4)) 197 fw3_setbit(zone->flags[0], FW3_FLAG_HELPER); 198 199 if (fw3_is_family(match->ptr, FW3_FAMILY_V6)) 200 fw3_setbit(zone->flags[1], FW3_FLAG_HELPER); 201 } 202 } 203 204 struct fw3_zone * 205 fw3_alloc_zone(void) 206 { 207 struct fw3_zone *zone; 208 209 zone = calloc(1, sizeof(*zone)); 210 if (!zone) 211 return NULL; 212 213 INIT_LIST_HEAD(&zone->networks); 214 INIT_LIST_HEAD(&zone->devices); 215 INIT_LIST_HEAD(&zone->subnets); 216 INIT_LIST_HEAD(&zone->masq_src); 217 INIT_LIST_HEAD(&zone->masq_dest); 218 INIT_LIST_HEAD(&zone->cthelpers); 219 220 INIT_LIST_HEAD(&zone->old_addrs); 221 222 zone->enabled = true; 223 zone->auto_helper = true; 224 zone->custom_chains = true; 225 zone->log_limit.rate = 10; 226 227 return zone; 228 } 229 230 void 231 fw3_load_zones(struct fw3_state *state, struct uci_package *p) 232 { 233 struct uci_section *s; 234 struct uci_element *e; 235 struct fw3_zone *zone; 236 struct fw3_defaults *defs = &state->defaults; 237 238 INIT_LIST_HEAD(&state->zones); 239 240 uci_foreach_element(&p->sections, e) 241 { 242 s = uci_to_section(e); 243 244 if (strcmp(s->type, "zone")) 245 continue; 246 247 zone = fw3_alloc_zone(); 248 249 if (!zone) 250 continue; 251 252 if (!fw3_parse_options(zone, fw3_zone_opts, s)) 253 warn_elem(e, "has invalid options"); 254 255 if (!zone->enabled) 256 { 257 fw3_free_zone(zone); 258 continue; 259 } 260 261 if (!zone->extra_dest) 262 zone->extra_dest = zone->extra_src; 263 264 if (!defs->custom_chains && zone->custom_chains) 265 zone->custom_chains = false; 266 267 if (!defs->auto_helper && zone->auto_helper) 268 zone->auto_helper = false; 269 270 if (!zone->name || !*zone->name) 271 { 272 warn_elem(e, "has no name - ignoring"); 273 fw3_free_zone(zone); 274 continue; 275 } 276 277 if (strlen(zone->name) > FW3_ZONE_MAXNAMELEN) 278 { 279 warn_elem(e, "must not have a name longer than %u characters", 280 FW3_ZONE_MAXNAMELEN); 281 fw3_free_zone(zone); 282 continue; 283 } 284 285 fw3_ubus_zone_devices(zone); 286 287 if (list_empty(&zone->networks) && list_empty(&zone->devices) && 288 list_empty(&zone->subnets) && !zone->extra_src) 289 { 290 warn_elem(e, "has no device, network, subnet or extra options"); 291 } 292 293 if (!check_masq_addrs(&zone->masq_src)) 294 { 295 warn_elem(e, "has unresolved masq_src, disabling masq"); 296 zone->masq = false; 297 } 298 299 if (!check_masq_addrs(&zone->masq_dest)) 300 { 301 warn_elem(e, "has unresolved masq_dest, disabling masq"); 302 zone->masq = false; 303 } 304 305 check_policy(e, &zone->policy_input, defs->policy_input, "input"); 306 check_policy(e, &zone->policy_output, defs->policy_output, "output"); 307 check_policy(e, &zone->policy_forward, defs->policy_forward, "forward"); 308 309 resolve_networks(e, zone); 310 311 if (zone->masq) 312 { 313 fw3_setbit(zone->flags[0], FW3_FLAG_SNAT); 314 } 315 316 if (zone->custom_chains) 317 { 318 fw3_setbit(zone->flags[0], FW3_FLAG_SNAT); 319 fw3_setbit(zone->flags[0], FW3_FLAG_DNAT); 320 } 321 322 resolve_cthelpers(state, e, zone); 323 324 fw3_setbit(zone->flags[0], fw3_to_src_target(zone->policy_input)); 325 fw3_setbit(zone->flags[0], zone->policy_forward); 326 fw3_setbit(zone->flags[0], zone->policy_output); 327 328 fw3_setbit(zone->flags[1], fw3_to_src_target(zone->policy_input)); 329 fw3_setbit(zone->flags[1], zone->policy_forward); 330 fw3_setbit(zone->flags[1], zone->policy_output); 331 332 list_add_tail(&zone->list, &state->zones); 333 } 334 } 335 336 337 static char * 338 format_chain(const char *fmt, const char *zonename) 339 { 340 static char chain[32]; 341 size_t rem; 342 char *p; 343 int len; 344 345 for (p = chain, rem = sizeof(chain); *fmt; fmt++) { 346 if (*fmt == '?') { 347 len = snprintf(p, rem, "%s", zonename); 348 349 if (len < 0 || len >= rem) 350 break; 351 352 rem -= len; 353 p += len; 354 } 355 else { 356 if (rem <= 1) 357 break; 358 359 *p++ = *fmt; 360 rem--; 361 } 362 } 363 364 *p = 0; 365 366 return chain; 367 } 368 369 static void 370 print_zone_chain(struct fw3_ipt_handle *handle, struct fw3_state *state, 371 bool reload, struct fw3_zone *zone) 372 { 373 int i; 374 struct fw3_ipt_rule *r; 375 const struct fw3_chain_spec *c; 376 377 const char *flt_chains[] = { 378 "input", "input", 379 "output", "output", 380 "forward", "forwarding", 381 }; 382 383 const char *nat_chains[] = { 384 "prerouting", "prerouting", 385 "postrouting", "postrouting", 386 }; 387 388 if (!fw3_is_family(zone, handle->family)) 389 return; 390 391 set(zone->flags, handle->family, handle->table); 392 393 if (zone->custom_chains) 394 set(zone->flags, handle->family, FW3_FLAG_CUSTOM_CHAINS); 395 396 for (c = zone_chains; c->format; c++) 397 { 398 if (!fw3_is_family(c, handle->family)) 399 continue; 400 401 if (c->table != handle->table) 402 continue; 403 404 if (c->flag && 405 !fw3_hasbit(zone->flags[handle->family == FW3_FAMILY_V6], c->flag)) 406 continue; 407 408 fw3_ipt_create_chain(handle, reload, format_chain(c->format, zone->name)); 409 } 410 411 if (zone->custom_chains) 412 { 413 if (handle->table == FW3_TABLE_FILTER) 414 { 415 for (i = 0; i < sizeof(flt_chains)/sizeof(flt_chains[0]); i += 2) 416 { 417 r = fw3_ipt_rule_new(handle); 418 fw3_ipt_rule_comment(r, "Custom %s %s rule chain", zone->name, flt_chains[i+1]); 419 fw3_ipt_rule_target(r, "%s_%s_rule", flt_chains[i+1], zone->name); 420 fw3_ipt_rule_append(r, "zone_%s_%s", zone->name, flt_chains[i]); 421 } 422 } 423 else if (handle->table == FW3_TABLE_NAT) 424 { 425 for (i = 0; i < sizeof(nat_chains)/sizeof(nat_chains[0]); i += 2) 426 { 427 r = fw3_ipt_rule_new(handle); 428 fw3_ipt_rule_comment(r, "Custom %s %s rule chain", zone->name, nat_chains[i+1]); 429 fw3_ipt_rule_target(r, "%s_%s_rule", nat_chains[i+1], zone->name); 430 fw3_ipt_rule_append(r, "zone_%s_%s", zone->name, nat_chains[i]); 431 } 432 } 433 } 434 435 set(zone->flags, handle->family, handle->table); 436 } 437 438 static void 439 print_interface_rule(struct fw3_ipt_handle *handle, struct fw3_state *state, 440 bool reload, struct fw3_zone *zone, 441 struct fw3_device *dev, struct fw3_address *sub) 442 { 443 struct fw3_protocol tcp = { .protocol = 6 }; 444 struct fw3_ipt_rule *r; 445 enum fw3_flag t; 446 447 char buf[32]; 448 449 int i; 450 451 const char *chains[] = { 452 "input", "INPUT", 453 "output", "OUTPUT", 454 "forward", "FORWARD", 455 }; 456 457 #define jump_target(t) \ 458 ((t == FW3_FLAG_REJECT) ? "reject" : fw3_flag_names[t]) 459 460 if (handle->table == FW3_TABLE_FILTER) 461 { 462 for (t = FW3_FLAG_ACCEPT; t <= FW3_FLAG_DROP; t++) 463 { 464 if (t > FW3_FLAG_ACCEPT && zone->log & FW3_ZONE_LOG_FILTER) 465 { 466 if (has(zone->flags, handle->family, fw3_to_src_target(t))) 467 { 468 r = fw3_ipt_rule_create(handle, NULL, dev, NULL, sub, NULL); 469 470 snprintf(buf, sizeof(buf) - 1, "%s %s in: ", 471 fw3_flag_names[t], zone->name); 472 473 fw3_ipt_rule_limit(r, &zone->log_limit); 474 fw3_ipt_rule_target(r, "LOG"); 475 fw3_ipt_rule_addarg(r, false, "--log-prefix", buf); 476 fw3_ipt_rule_replace(r, "zone_%s_src_%s", 477 zone->name, fw3_flag_names[t]); 478 } 479 480 if (has(zone->flags, handle->family, t)) 481 { 482 r = fw3_ipt_rule_create(handle, NULL, NULL, dev, NULL, sub); 483 484 snprintf(buf, sizeof(buf) - 1, "%s %s out: ", 485 fw3_flag_names[t], zone->name); 486 487 fw3_ipt_rule_limit(r, &zone->log_limit); 488 fw3_ipt_rule_target(r, "LOG"); 489 fw3_ipt_rule_addarg(r, false, "--log-prefix", buf); 490 fw3_ipt_rule_replace(r, "zone_%s_dest_%s", 491 zone->name, fw3_flag_names[t]); 492 } 493 } 494 495 if (has(zone->flags, handle->family, fw3_to_src_target(t))) 496 { 497 r = fw3_ipt_rule_create(handle, NULL, dev, NULL, sub, NULL); 498 fw3_ipt_rule_target(r, jump_target(t)); 499 fw3_ipt_rule_extra(r, zone->extra_src); 500 501 if (t == FW3_FLAG_ACCEPT && !state->defaults.drop_invalid) 502 fw3_ipt_rule_extra(r, 503 "-m conntrack --ctstate NEW,UNTRACKED"); 504 505 fw3_ipt_rule_replace(r, "zone_%s_src_%s", zone->name, 506 fw3_flag_names[t]); 507 } 508 509 if (has(zone->flags, handle->family, t)) 510 { 511 if (t == FW3_FLAG_ACCEPT && 512 zone->masq && !zone->masq_allow_invalid) 513 { 514 r = fw3_ipt_rule_create(handle, NULL, NULL, dev, NULL, sub); 515 fw3_ipt_rule_extra(r, "-m conntrack --ctstate INVALID"); 516 fw3_ipt_rule_comment(r, "Prevent NAT leakage"); 517 fw3_ipt_rule_target(r, fw3_flag_names[FW3_FLAG_DROP]); 518 fw3_ipt_rule_replace(r, "zone_%s_dest_%s", zone->name, 519 fw3_flag_names[t]); 520 } 521 522 r = fw3_ipt_rule_create(handle, NULL, NULL, dev, NULL, sub); 523 fw3_ipt_rule_target(r, jump_target(t)); 524 fw3_ipt_rule_extra(r, zone->extra_dest); 525 fw3_ipt_rule_replace(r, "zone_%s_dest_%s", zone->name, 526 fw3_flag_names[t]); 527 } 528 } 529 530 for (i = 0; i < sizeof(chains)/sizeof(chains[0]); i += 2) 531 { 532 if (*chains[i] == 'o') 533 r = fw3_ipt_rule_create(handle, NULL, NULL, dev, NULL, sub); 534 else 535 r = fw3_ipt_rule_create(handle, NULL, dev, NULL, sub, NULL); 536 537 fw3_ipt_rule_target(r, "zone_%s_%s", zone->name, chains[i]); 538 539 if (*chains[i] == 'o') 540 fw3_ipt_rule_extra(r, zone->extra_dest); 541 else 542 fw3_ipt_rule_extra(r, zone->extra_src); 543 544 fw3_ipt_rule_replace(r, chains[i + 1]); 545 } 546 } 547 else if (handle->table == FW3_TABLE_NAT) 548 { 549 if (has(zone->flags, handle->family, FW3_FLAG_DNAT)) 550 { 551 r = fw3_ipt_rule_create(handle, NULL, dev, NULL, sub, NULL); 552 fw3_ipt_rule_target(r, "zone_%s_prerouting", zone->name); 553 fw3_ipt_rule_extra(r, zone->extra_src); 554 fw3_ipt_rule_replace(r, "PREROUTING"); 555 } 556 557 if (has(zone->flags, handle->family, FW3_FLAG_SNAT)) 558 { 559 r = fw3_ipt_rule_create(handle, NULL, NULL, dev, NULL, sub); 560 fw3_ipt_rule_target(r, "zone_%s_postrouting", zone->name); 561 fw3_ipt_rule_extra(r, zone->extra_dest); 562 fw3_ipt_rule_replace(r, "POSTROUTING"); 563 } 564 } 565 else if (handle->table == FW3_TABLE_MANGLE) 566 { 567 if (zone->mtu_fix) 568 { 569 if (zone->log & FW3_ZONE_LOG_MANGLE) 570 { 571 snprintf(buf, sizeof(buf) - 1, "MSSFIX %s out: ", zone->name); 572 573 r = fw3_ipt_rule_create(handle, &tcp, NULL, dev, NULL, sub); 574 fw3_ipt_rule_addarg(r, false, "--tcp-flags", "SYN,RST"); 575 fw3_ipt_rule_addarg(r, false, "SYN", NULL); 576 fw3_ipt_rule_limit(r, &zone->log_limit); 577 fw3_ipt_rule_comment(r, "Zone %s MTU fix logging", zone->name); 578 fw3_ipt_rule_target(r, "LOG"); 579 fw3_ipt_rule_addarg(r, false, "--log-prefix", buf); 580 fw3_ipt_rule_replace(r, "FORWARD"); 581 } 582 583 r = fw3_ipt_rule_create(handle, &tcp, NULL, dev, NULL, sub); 584 fw3_ipt_rule_addarg(r, false, "--tcp-flags", "SYN,RST"); 585 fw3_ipt_rule_addarg(r, false, "SYN", NULL); 586 fw3_ipt_rule_comment(r, "Zone %s MTU fixing", zone->name); 587 fw3_ipt_rule_target(r, "TCPMSS"); 588 fw3_ipt_rule_addarg(r, false, "--clamp-mss-to-pmtu", NULL); 589 fw3_ipt_rule_replace(r, "FORWARD"); 590 591 r = fw3_ipt_rule_create(handle, &tcp, dev, NULL, sub, NULL); 592 fw3_ipt_rule_addarg(r, false, "--tcp-flags", "SYN,RST"); 593 fw3_ipt_rule_addarg(r, false, "SYN", NULL); 594 fw3_ipt_rule_comment(r, "Zone %s MTU fixing", zone->name); 595 fw3_ipt_rule_target(r, "TCPMSS"); 596 fw3_ipt_rule_addarg(r, false, "--clamp-mss-to-pmtu", NULL); 597 fw3_ipt_rule_replace(r, "FORWARD"); 598 } 599 } 600 else if (handle->table == FW3_TABLE_RAW) 601 { 602 bool loopback_dev = (dev != NULL && !dev->any && 603 !dev->invert && fw3_check_loopback_dev(dev->name)); 604 char *chain = loopback_dev || (sub != NULL && !sub->invert && fw3_check_loopback_addr(sub)) ? 605 "OUTPUT" : "PREROUTING"; 606 607 if (has(zone->flags, handle->family, FW3_FLAG_HELPER)) 608 { 609 r = fw3_ipt_rule_create(handle, NULL, loopback_dev ? NULL : dev, NULL, sub, NULL); 610 fw3_ipt_rule_comment(r, "%s CT helper assignment", zone->name); 611 fw3_ipt_rule_target(r, "zone_%s_helper", zone->name); 612 fw3_ipt_rule_extra(r, zone->extra_src); 613 fw3_ipt_rule_replace(r, chain); 614 } 615 616 if (has(zone->flags, handle->family, FW3_FLAG_NOTRACK)) 617 { 618 r = fw3_ipt_rule_create(handle, NULL, loopback_dev ? NULL : dev, NULL, sub, NULL); 619 fw3_ipt_rule_comment(r, "%s CT bypass", zone->name); 620 fw3_ipt_rule_target(r, "zone_%s_notrack", zone->name); 621 fw3_ipt_rule_extra(r, zone->extra_src); 622 fw3_ipt_rule_replace(r, chain); 623 } 624 } 625 } 626 627 static void 628 print_interface_rules(struct fw3_ipt_handle *handle, struct fw3_state *state, 629 bool reload, struct fw3_zone *zone) 630 { 631 struct fw3_device *dev; 632 struct fw3_address *sub; 633 634 fw3_foreach(dev, &zone->devices) 635 fw3_foreach(sub, &zone->subnets) 636 { 637 if (!fw3_is_family(sub, handle->family)) 638 continue; 639 640 if (!dev && !sub && !zone->extra_src && !zone->extra_dest) 641 continue; 642 643 print_interface_rule(handle, state, reload, zone, dev, sub); 644 } 645 } 646 647 static struct fw3_address * 648 next_addr(struct fw3_address *addr, struct list_head *list, 649 enum fw3_family family, bool invert) 650 { 651 struct list_head *p; 652 struct fw3_address *rv; 653 654 for (p = addr ? addr->list.next : list->next; p != list; p = p->next) 655 { 656 rv = list_entry(p, struct fw3_address, list); 657 658 if (fw3_is_family(rv, family) && rv->set && rv->invert == invert) 659 return rv; 660 } 661 662 return NULL; 663 } 664 665 static void 666 print_zone_rule(struct fw3_ipt_handle *handle, struct fw3_state *state, 667 bool reload, struct fw3_zone *zone) 668 { 669 bool first_src, first_dest; 670 struct fw3_address *msrc; 671 struct fw3_address *mdest; 672 struct fw3_ipt_rule *r; 673 674 if (!fw3_is_family(zone, handle->family)) 675 return; 676 677 info(" * Zone '%s'", zone->name); 678 679 switch (handle->table) 680 { 681 case FW3_TABLE_FILTER: 682 if (has(zone->flags, handle->family, FW3_FLAG_DNAT)) 683 { 684 r = fw3_ipt_rule_new(handle); 685 fw3_ipt_rule_extra(r, "-m conntrack --ctstate DNAT"); 686 fw3_ipt_rule_comment(r, "Accept port redirections"); 687 fw3_ipt_rule_target(r, fw3_flag_names[FW3_FLAG_ACCEPT]); 688 fw3_ipt_rule_append(r, "zone_%s_input", zone->name); 689 690 r = fw3_ipt_rule_new(handle); 691 fw3_ipt_rule_extra(r, "-m conntrack --ctstate DNAT"); 692 fw3_ipt_rule_comment(r, "Accept port forwards"); 693 fw3_ipt_rule_target(r, fw3_flag_names[FW3_FLAG_ACCEPT]); 694 fw3_ipt_rule_append(r, "zone_%s_forward", zone->name); 695 } 696 697 r = fw3_ipt_rule_new(handle); 698 fw3_ipt_rule_target(r, "zone_%s_src_%s", zone->name, 699 fw3_flag_names[zone->policy_input]); 700 fw3_ipt_rule_append(r, "zone_%s_input", zone->name); 701 702 r = fw3_ipt_rule_new(handle); 703 fw3_ipt_rule_target(r, "zone_%s_dest_%s", zone->name, 704 fw3_flag_names[zone->policy_forward]); 705 fw3_ipt_rule_append(r, "zone_%s_forward", zone->name); 706 707 r = fw3_ipt_rule_new(handle); 708 fw3_ipt_rule_target(r, "zone_%s_dest_%s", zone->name, 709 fw3_flag_names[zone->policy_output]); 710 fw3_ipt_rule_append(r, "zone_%s_output", zone->name); 711 712 break; 713 714 case FW3_TABLE_NAT: 715 if (zone->masq && handle->family == FW3_FAMILY_V4) 716 { 717 /* for any negated masq_src ip, emit -s addr -j RETURN rules */ 718 for (msrc = NULL; 719 (msrc = next_addr(msrc, &zone->masq_src, 720 handle->family, true)) != NULL; ) 721 { 722 msrc->invert = false; 723 r = fw3_ipt_rule_new(handle); 724 fw3_ipt_rule_src_dest(r, msrc, NULL); 725 fw3_ipt_rule_target(r, "RETURN"); 726 fw3_ipt_rule_append(r, "zone_%s_postrouting", zone->name); 727 msrc->invert = true; 728 } 729 730 /* for any negated masq_dest ip, emit -d addr -j RETURN rules */ 731 for (mdest = NULL; 732 (mdest = next_addr(mdest, &zone->masq_dest, 733 handle->family, true)) != NULL; ) 734 { 735 mdest->invert = false; 736 r = fw3_ipt_rule_new(handle); 737 fw3_ipt_rule_src_dest(r, NULL, mdest); 738 fw3_ipt_rule_target(r, "RETURN"); 739 fw3_ipt_rule_append(r, "zone_%s_postrouting", zone->name); 740 mdest->invert = true; 741 } 742 743 /* emit masquerading entries for non-negated addresses 744 and ensure that both src and dest loops run at least once, 745 even if there are no relevant addresses */ 746 for (first_src = true, msrc = NULL; 747 (msrc = next_addr(msrc, &zone->masq_src, 748 handle->family, false)) || first_src; 749 first_src = false) 750 { 751 for (first_dest = true, mdest = NULL; 752 (mdest = next_addr(mdest, &zone->masq_dest, 753 handle->family, false)) || first_dest; 754 first_dest = false) 755 { 756 r = fw3_ipt_rule_new(handle); 757 fw3_ipt_rule_src_dest(r, msrc, mdest); 758 fw3_ipt_rule_target(r, "MASQUERADE"); 759 fw3_ipt_rule_append(r, "zone_%s_postrouting", zone->name); 760 } 761 } 762 } 763 break; 764 765 case FW3_TABLE_RAW: 766 fw3_print_cthelpers(handle, state, zone); 767 break; 768 769 case FW3_TABLE_MANGLE: 770 break; 771 } 772 773 print_interface_rules(handle, state, reload, zone); 774 } 775 776 void 777 fw3_print_zone_chains(struct fw3_ipt_handle *handle, struct fw3_state *state, 778 bool reload) 779 { 780 struct fw3_zone *zone; 781 782 list_for_each_entry(zone, &state->zones, list) 783 print_zone_chain(handle, state, reload, zone); 784 } 785 786 void 787 fw3_print_zone_rules(struct fw3_ipt_handle *handle, struct fw3_state *state, 788 bool reload) 789 { 790 struct fw3_zone *zone; 791 792 list_for_each_entry(zone, &state->zones, list) 793 print_zone_rule(handle, state, reload, zone); 794 } 795 796 void 797 fw3_flush_zones(struct fw3_ipt_handle *handle, struct fw3_state *state, 798 bool reload) 799 { 800 struct fw3_zone *z, *tmp; 801 const struct fw3_chain_spec *c; 802 803 list_for_each_entry_safe(z, tmp, &state->zones, list) 804 { 805 if (!has(z->flags, handle->family, handle->table)) 806 continue; 807 808 /* first flush all rules ... */ 809 for (c = zone_chains; c->format; c++) 810 { 811 /* don't touch user chains on selective stop */ 812 if (reload && c->flag == FW3_FLAG_CUSTOM_CHAINS) 813 continue; 814 815 if (!fw3_is_family(c, handle->family)) 816 continue; 817 818 if (c->table != handle->table) 819 continue; 820 821 if (c->flag && !has(z->flags, handle->family, c->flag)) 822 continue; 823 824 fw3_ipt_flush_chain(handle, format_chain(c->format, z->name)); 825 } 826 827 /* ... then remove the chains */ 828 for (c = zone_chains; c->format; c++) 829 { 830 if (!fw3_is_family(c, handle->family)) 831 continue; 832 833 if (c->table != handle->table) 834 continue; 835 836 if (c->flag && !has(z->flags, handle->family, c->flag)) 837 continue; 838 839 fw3_ipt_delete_chain(handle, reload, 840 format_chain(c->format, z->name)); 841 } 842 843 del(z->flags, handle->family, handle->table); 844 } 845 } 846 847 void 848 fw3_hotplug_zones(struct fw3_state *state, bool add) 849 { 850 struct fw3_zone *z; 851 struct fw3_device *d; 852 853 list_for_each_entry(z, &state->zones, list) 854 { 855 if (add != fw3_hasbit(z->flags[0], FW3_FLAG_HOTPLUG)) 856 { 857 list_for_each_entry(d, &z->devices, list) 858 fw3_hotplug(add, z, d); 859 860 if (add) 861 fw3_setbit(z->flags[0], FW3_FLAG_HOTPLUG); 862 else 863 fw3_delbit(z->flags[0], FW3_FLAG_HOTPLUG); 864 } 865 } 866 } 867 868 struct fw3_zone * 869 fw3_lookup_zone(struct fw3_state *state, const char *name) 870 { 871 struct fw3_zone *z; 872 873 if (list_empty(&state->zones)) 874 return NULL; 875 876 list_for_each_entry(z, &state->zones, list) 877 { 878 if (strcmp(z->name, name)) 879 continue; 880 881 return z; 882 } 883 884 return NULL; 885 } 886 887 struct list_head * 888 fw3_resolve_zone_addresses(struct fw3_zone *zone, struct fw3_address *addr) 889 { 890 struct fw3_device *net; 891 struct fw3_address *cur, *tmp; 892 struct list_head *all; 893 894 all = calloc(1, sizeof(*all)); 895 if (!all) 896 return NULL; 897 898 INIT_LIST_HEAD(all); 899 900 if (addr && addr->set) 901 { 902 tmp = malloc(sizeof(*tmp)); 903 904 if (tmp) 905 { 906 *tmp = *addr; 907 list_add_tail(&tmp->list, all); 908 } 909 } 910 else 911 { 912 list_for_each_entry(net, &zone->networks, list) 913 fw3_ubus_address(all, net->name); 914 915 list_for_each_entry(cur, &zone->subnets, list) 916 { 917 tmp = malloc(sizeof(*tmp)); 918 919 if (!tmp) 920 continue; 921 922 *tmp = *cur; 923 list_add_tail(&tmp->list, all); 924 } 925 } 926 927 return all; 928 } 929
This page was automatically generated by LXR 0.3.1. • OpenWrt