@@ -85,26 +85,14 @@ check_policy(struct uci_element *e, enum fw3_flag *pol, const char *name)
}
static void
-check_kmod(struct uci_element *e, bool *module, const char *name)
+check_target(struct uci_element *e, bool *available, const char *target, const bool ipv6)
{
- FILE *f;
- char buf[128];
-
- if (!*module)
- return;
-
- snprintf(buf, sizeof(buf), "/sys/module/%s/refcnt", name);
-
- f = fopen(buf, "r");
-
- if (f)
+ const bool b = fw3_has_target(ipv6, target);
+ if (!b)
{
- fclose(f);
- return;
+ warn_elem(e, "requires unavailable target extension %s, disabling", target);
}
-
- warn_elem(e, "requires not available kernel module %s, disabling", name);
- *module = false;
+ *available = b;
}
static void
@@ -171,7 +159,8 @@ fw3_load_defaults(struct fw3_state *state, struct uci_package *p)
check_any_reject_code(e, &defs->any_reject_code);
- check_kmod(e, &defs->flow_offloading, "xt_FLOWOFFLOAD");
+ /* exists in both ipv4 and ipv6, if at all, so only check ipv4 */
+ check_target(e, &defs->flow_offloading, "FLOWOFFLOAD", false);
}
}
@@ -344,6 +344,33 @@ fw3_has_table(bool ipv6, const char *table)
return seen;
}
+bool
+fw3_has_target(const bool ipv6, const char *target)
+{
+ FILE *f;
+
+ char line[12];
+ bool seen = false;
+
+ const char *path = ipv6
+ ? "/proc/net/ip6_tables_targets" : "/proc/net/ip_tables_targets";
+
+ if (!(f = fopen(path, "r")))
+ return false;
+
+ while (fgets(line, sizeof(line), f))
+ {
+ if (!strncmp(line, target, MIN(sizeof(line), strlen(target))))
+ {
+ seen = true;
+ break;
+ }
+ }
+
+ fclose(f);
+
+ return seen;
+}
bool
fw3_lock_path(int *fd, const char *path)
@@ -89,6 +89,10 @@ void info(const char *format, ...)
(!(flags & ((1<<FW3_TABLE_FILTER)|(1<<FW3_TABLE_NAT)| \
(1<<FW3_TABLE_MANGLE)|(1<<FW3_TABLE_RAW))))
+#define MIN(a,b) \
+ ({ __typeof__ (a) _a = (a); \
+ __typeof__ (b) _b = (b); \
+ _a < _b ? _a : _b; })
void * fw3_alloc(size_t size);
char * fw3_strdup(const char *s);
@@ -105,6 +109,8 @@ void fw3_pr(const char *fmt, ...)
bool fw3_has_table(bool ipv6, const char *table);
+bool fw3_has_target(const bool ipv6, const char *target);
+
bool fw3_lock(void);
void fw3_unlock(void);
bool fw3_lock_path(int *fw3_lock_fd, const char *path);
v2: addressed Petr Štetiar's concerns and also changed the generic helper to check for the availability of IPv4 or IPv6 targets, as needed. The flowtable detection fails if the respective target module is built-in, since it's looking for the module itself. Create a generic helper and instead check for existence of the FLOWOFFLOAD target in /proc/net/ip_tables_targets. Signed-off-by: Rui Salvaterra <rsalvaterra@gmail.com> --- defaults.c | 25 +++++++------------------ utils.c | 27 +++++++++++++++++++++++++++ utils.h | 6 ++++++ 3 files changed, 40 insertions(+), 18 deletions(-)