forwards.c 4.9 KB

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