Fix compatibility with older libiptc/libip6tc
authorJo-Philipp Wich <jow@openwrt.org>
Mon, 27 May 2013 09:17:06 +0000 (11:17 +0200)
committerJo-Philipp Wich <jow@openwrt.org>
Mon, 27 May 2013 11:32:36 +0000 (13:32 +0200)
iptables.c
iptables.h
xtables-10.h [new file with mode: 0644]
xtables-5.h [new file with mode: 0644]

index 2684933970ef26d08bbbeaafffbaaa5fe0cf9fb8..a1897454d3bda39b3e1b9a51c6da72f88db21ce3 100644 (file)
@@ -39,7 +39,7 @@ static struct xtables_globals xtg6 = {
 };
 
 /* Required by certain extensions like SNAT and DNAT */
-int kernel_version;
+int kernel_version = 0;
 
 void
 get_kernel_version(void)
@@ -51,7 +51,7 @@ get_kernel_version(void)
                sprintf(uts.release, "3.0.0");
 
        sscanf(uts.release, "%d.%d.%d", &x, &y, &z);
-       kernel_version = LINUX_VERSION(x, y, z);
+       kernel_version = 0x10000 * x + 0x100 * y + z;
 }
 
 #undef __ipt_module
@@ -358,16 +358,14 @@ init_match(struct fw3_ipt_rule *r, struct xtables_match *m, bool no_clone)
        s = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size;
 
        m->m = fw3_alloc(s);
-       strcpy(m->m->u.user.name, m->real_name ? m->real_name : m->name);
+
+       fw3_xt_set_match_name(m);
+
        m->m->u.user.revision = m->revision;
        m->m->u.match_size = s;
 
        /* free previous userspace data */
-       if (m->udata_size)
-       {
-               free(m->udata);
-               m->udata = fw3_alloc(m->udata_size);
-       }
+       fw3_xt_free_match_udata(m);
 
        if (m->init)
                m->init(m->m);
@@ -378,14 +376,7 @@ init_match(struct fw3_ipt_rule *r, struct xtables_match *m, bool no_clone)
 
        /* merge option table */
        g = (r->h->family == FW3_FAMILY_V6) ? &xtg6 : &xtg;
-
-       if (m->x6_options)
-               g->opts = xtables_options_xfrm(g->orig_opts, g->opts,
-                                                                          m->x6_options, &m->option_offset);
-
-       if (m->extra_opts)
-               g->opts = xtables_merge_options(g->orig_opts, g->opts,
-                                                                               m->extra_opts, &m->option_offset);
+       fw3_xt_merge_match_options(g, m);
 }
 
 static bool
@@ -431,32 +422,20 @@ get_target(struct fw3_ipt_rule *r, const char *name)
        s = XT_ALIGN(sizeof(struct xt_entry_target)) + t->size;
        t->t = fw3_alloc(s);
 
-       if (!t->real_name)
-               strcpy(t->t->u.user.name, name);
-       else
-               strcpy(t->t->u.user.name, t->real_name);
+       fw3_xt_set_target_name(t, name);
 
        t->t->u.user.revision = t->revision;
        t->t->u.target_size = s;
 
-       if (t->udata_size)
-       {
-               free(t->udata);
-               t->udata = fw3_alloc(t->udata_size);
-       }
+       /* free previous userspace data */
+       fw3_xt_free_target_udata(t);
 
        if (t->init)
                t->init(t->t);
 
        /* merge option table */
        g = (r->h->family == FW3_FAMILY_V6) ? &xtg6 : &xtg;
-
-       if (t->x6_options)
-               g->opts = xtables_options_xfrm(g->orig_opts, g->opts,
-                                              t->x6_options, &t->option_offset);
-       else
-               g->opts = xtables_merge_options(g->orig_opts, g->opts,
-                                               t->extra_opts, &t->option_offset);
+       fw3_xt_merge_target_options(g, t);
 
        r->target = t;
 
@@ -1028,7 +1007,7 @@ rule_print(struct fw3_ipt_rule *r, const char *chain)
        for (rm = r->matches; rm; rm = rm->next)
        {
                m = rm->match;
-               printf(" -m %s", m->alias ? m->alias(m->m) : m->m->u.user.name);
+               printf(" -m %s", fw3_xt_get_match_name(m));
 
                if (m->save)
                        m->save(&r->e.ip, m->m);
@@ -1037,7 +1016,7 @@ rule_print(struct fw3_ipt_rule *r, const char *chain)
        if (r->target)
        {
                t = r->target;
-               printf(" -j %s", t->alias ? t->alias(t->t) : t->t->u.user.name);
+               printf(" -j %s", fw3_xt_get_target_name(t));
 
                if (t->save)
                        t->save(&r->e.ip, t->t);
@@ -1053,7 +1032,7 @@ parse_option(struct fw3_ipt_rule *r, int optc, bool inv)
        struct xtables_match *em;
 
        /* is a target option */
-       if (r->target && (r->target->parse || r->target->x6_parse) &&
+       if (r->target && fw3_xt_has_target_parse(r->target) &&
                optc >= r->target->option_offset &&
                optc < (r->target->option_offset + 256))
        {
@@ -1066,7 +1045,7 @@ parse_option(struct fw3_ipt_rule *r, int optc, bool inv)
        {
                em = m->match;
 
-               if (m->completed || (!em->parse && !em->x6_parse))
+               if (m->completed || !fw3_xt_has_match_parse(em))
                        continue;
 
                if (optc < em->option_offset ||
index c8c86eca0058a3deff1c78361401363a56012691..05a1c7288be9eac3a66e35858d8786fe2c660f69 100644 (file)
 #include "options.h"
 
 
+#if (XTABLES_VERSION_CODE == 10)
+# include "xtables-10.h"
+#elif (XTABLES_VERSION_CODE == 5)
+# include "xtables-5.h"
+#else
+# error "Unsupported xtables version"
+#endif
+
 extern struct xtables_match *xtables_pending_matches;
 extern struct xtables_target *xtables_pending_targets;
 
@@ -74,7 +82,7 @@ void get_kernel_version(void);
 struct fw3_ipt_handle {
        enum fw3_family family;
        enum fw3_table table;
-       struct xtc_handle *handle;
+       void *handle;
 };
 
 struct fw3_ipt_rule {
diff --git a/xtables-10.h b/xtables-10.h
new file mode 100644 (file)
index 0000000..6b52fff
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * firewall3 - 3rd OpenWrt UCI firewall implementation
+ *
+ *   Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __FW3_XTABLES_10_H
+#define __FW3_XTABLES_10_H
+
+static inline const char *
+fw3_xt_get_match_name(struct xtables_match *m)
+{
+    if (m->alias)
+        return m->alias(m->m);
+
+    return m->m->u.user.name;
+}
+
+static inline void
+fw3_xt_set_match_name(struct xtables_match *m)
+{
+    if (m->real_name)
+        strcpy(m->m->u.user.name, m->real_name);
+    else
+        strcpy(m->m->u.user.name, m->name);
+}
+
+static inline bool
+fw3_xt_has_match_parse(struct xtables_match *m)
+{
+    return (m->parse || m->x6_parse);
+}
+
+static inline void
+fw3_xt_free_match_udata(struct xtables_match *m)
+{
+    if (m->udata_size)
+    {
+        free(m->udata);
+        m->udata = fw3_alloc(m->udata_size);
+    }
+}
+
+static inline void
+fw3_xt_merge_match_options(struct xtables_globals *g, struct xtables_match *m)
+{
+       if (m->x6_options)
+               g->opts = xtables_options_xfrm(g->orig_opts, g->opts,
+                                                                          m->x6_options, &m->option_offset);
+
+       if (m->extra_opts)
+               g->opts = xtables_merge_options(g->orig_opts, g->opts,
+                                                                               m->extra_opts, &m->option_offset);
+}
+
+
+static inline const char *
+fw3_xt_get_target_name(struct xtables_target *t)
+{
+    if (t->alias)
+        return t->alias(t->t);
+
+    return t->t->u.user.name;
+}
+
+static inline void
+fw3_xt_set_target_name(struct xtables_target *t, const char *name)
+{
+    if (t->real_name)
+        strcpy(t->t->u.user.name, t->real_name);
+    else
+        strcpy(t->t->u.user.name, name);
+}
+
+static inline bool
+fw3_xt_has_target_parse(struct xtables_target *t)
+{
+    return (t->parse || t->x6_parse);
+}
+
+static inline void
+fw3_xt_free_target_udata(struct xtables_target *t)
+{
+    if (t->udata_size)
+    {
+        free(t->udata);
+        t->udata = fw3_alloc(t->udata_size);
+    }
+}
+
+static inline void
+fw3_xt_merge_target_options(struct xtables_globals *g, struct xtables_target *t)
+{
+       if (t->x6_options)
+               g->opts = xtables_options_xfrm(g->orig_opts, g->opts,
+                                              t->x6_options, &t->option_offset);
+       else
+               g->opts = xtables_merge_options(g->orig_opts, g->opts,
+                                               t->extra_opts, &t->option_offset);
+}
+
+#endif
diff --git a/xtables-5.h b/xtables-5.h
new file mode 100644 (file)
index 0000000..263d012
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * firewall3 - 3rd OpenWrt UCI firewall implementation
+ *
+ *   Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __FW3_XTABLES_5_H
+#define __FW3_XTABLES_5_H
+
+static inline const char *
+fw3_xt_get_match_name(struct xtables_match *m)
+{
+    return m->m->u.user.name;
+}
+
+static inline void
+fw3_xt_set_match_name(struct xtables_match *m)
+{
+    strcpy(m->m->u.user.name, m->name);
+}
+
+static inline bool
+fw3_xt_has_match_parse(struct xtables_match *m)
+{
+    return !!m->parse;
+}
+
+static inline void
+fw3_xt_free_match_udata(struct xtables_match *m)
+{
+    return;
+}
+
+static inline void
+fw3_xt_merge_match_options(struct xtables_globals *g, struct xtables_match *m)
+{
+       g->opts = xtables_merge_options(g->opts, m->extra_opts, &m->option_offset);
+}
+
+
+static inline const char *
+fw3_xt_get_target_name(struct xtables_target *t)
+{
+    return t->t->u.user.name;
+}
+
+static inline void
+fw3_xt_set_target_name(struct xtables_target *t, const char *name)
+{
+    strcpy(t->t->u.user.name, name);
+}
+
+static inline bool
+fw3_xt_has_target_parse(struct xtables_target *t)
+{
+    return !!t->parse;
+}
+
+static inline void
+fw3_xt_free_target_udata(struct xtables_target *t)
+{
+    return;
+}
+
+static inline void
+fw3_xt_merge_target_options(struct xtables_globals *g, struct xtables_target *t)
+{
+       g->opts = xtables_merge_options(g->opts, t->extra_opts, &t->option_offset);
+}
+
+
+/* xtables api addons */
+
+static inline void
+xtables_option_mpcall(unsigned int c, char **argv, bool invert,
+                      struct xtables_match *m, void *fw)
+{
+       if (m->parse)
+               m->parse(c - m->option_offset, argv, invert, &m->mflags, fw, &m->m);
+}
+
+static inline void
+xtables_option_mfcall(struct xtables_match *m)
+{
+       if (m->final_check)
+               m->final_check(m->mflags);
+}
+
+static inline void
+xtables_option_tpcall(unsigned int c, char **argv, bool invert,
+                      struct xtables_target *t, void *fw)
+{
+       if (t->parse)
+               t->parse(c - t->option_offset, argv, invert, &t->tflags, fw, &t->t);
+}
+
+static inline void
+xtables_option_tfcall(struct xtables_target *t)
+{
+       if (t->final_check)
+               t->final_check(t->tflags);
+}
+
+static inline void
+xtables_rule_matches_free(struct xtables_rule_match **matches)
+{
+       struct xtables_rule_match *mp, *tmp;
+
+       for (mp = *matches; mp;)
+       {
+               tmp = mp->next;
+
+               if (mp->match->m)
+               {
+                       free(mp->match->m);
+                       mp->match->m = NULL;
+               }
+
+               if (mp->match == mp->match->next)
+               {
+                       free(mp->match);
+                       mp->match = NULL;
+               }
+
+               free(mp);
+               mp = tmp;
+       }
+
+       *matches = NULL;
+}
+
+static inline int
+xtables_ipmask_to_cidr(const struct in_addr *mask)
+{
+       int bits;
+       uint32_t m;
+
+       for (m = ntohl(mask->s_addr), bits = 0; m & 0x80000000; m <<= 1)
+               bits++;
+
+       return bits;
+}
+
+static inline int
+xtables_ip6mask_to_cidr(const struct in6_addr *mask)
+{
+       int bits = 0;
+       uint32_t a, b, c, d;
+
+       a = ntohl(mask->s6_addr32[0]);
+       b = ntohl(mask->s6_addr32[1]);
+       c = ntohl(mask->s6_addr32[2]);
+       d = ntohl(mask->s6_addr32[3]);
+
+       while (a & 0x80000000U)
+       {
+               a <<= 1;
+               a  |= (b >> 31) & 1;
+               b <<= 1;
+               b  |= (c >> 31) & 1;
+               c <<= 1;
+               c  |= (d >> 31) & 1;
+               d <<= 1;
+
+               bits++;
+       }
+
+       return bits;
+}
+
+#endif