From: Timothy Ace <[email protected]>

Adds support for IPv6 DNAT, SNAT, and REDIRECT.

Signed-off-by: Timothy Ace <[email protected]>
---
This is a git patch for the firewall3 git repo at git://nbd.name/firewall3.git

Note1: Luci updates still need to be made in a separate patch to support IPv6 
address entry on the port forwards page, but this works using manual entries in 
/etc/config/firewall for now.

Note2: I changed the section in compare_addr() from this:

-       return ((a->address.v4.s_addr & a->mask.v4.s_addr) ==
-               (b->address.v4.s_addr & a->mask.v4.s_addr));

to this:

+       return ((a->address.v4.s_addr & a->mask.v4.s_addr) ==
+               (b->address.v4.s_addr & b->mask.v4.s_addr));

... because using "a->mask" instead of "b->mask" on the second line looked 
wrong to me. Please let me know if that was intentional and I'll re-submit a 
patch that accounts for that change for the v4 and new v6 sections.


>From 83cdcf604b8c81c75065a91f50459721e87740b0 Mon Sep 17 00:00:00 2001
From: Timothy Ace <[email protected]>
Date: Thu, 13 Aug 2015 00:28:02 -0400
Subject: [PATCH] Adds support for IPv6 DNAT, SNAT, and REDIRECT

---
defaults.c  |  8 ++++----
redirects.c | 42 ++++++++++++++++++++++++++++++++++--------
snats.c     |  1 +
ubus.c      | 24 ++++++++++++++++++++----
utils.c     | 10 ++++++++--
zones.c     | 13 ++++++++-----
6 files changed, 75 insertions(+), 23 deletions(-)

diff --git a/defaults.c b/defaults.c
index 396cbf7..45d6de6 100644
--- a/defaults.c
+++ b/defaults.c
@@ -32,10 +32,10 @@ static const struct fw3_chain_spec default_chains[] = {
        C(ANY, FILTER, CUSTOM_CHAINS, "forwarding_rule"),
        C(ANY, FILTER, SYN_FLOOD,     "syn_flood"),

-       C(V4,  NAT,    UNSPEC,        "delegate_prerouting"),
-       C(V4,  NAT,    UNSPEC,        "delegate_postrouting"),
-       C(V4,  NAT,    CUSTOM_CHAINS, "prerouting_rule"),
-       C(V4,  NAT,    CUSTOM_CHAINS, "postrouting_rule"),
+       C(ANY, NAT,    UNSPEC,        "delegate_prerouting"),
+       C(ANY, NAT,    UNSPEC,        "delegate_postrouting"),
+       C(ANY, NAT,    CUSTOM_CHAINS, "prerouting_rule"),
+       C(ANY, NAT,    CUSTOM_CHAINS, "postrouting_rule"),

        C(ANY, MANGLE, UNSPEC,        "mssfix"),
        C(ANY, MANGLE, UNSPEC,        "fwmark"),
diff --git a/redirects.c b/redirects.c
index 5b8d7a9..0751e93 100644
--- a/redirects.c
+++ b/redirects.c
@@ -116,11 +116,26 @@ check_families(struct uci_element *e, struct fw3_redirect 
*r)
static bool
compare_addr(struct fw3_address *a, struct fw3_address *b)
{
-       if (a->family != FW3_FAMILY_V4 || b->family != FW3_FAMILY_V4)
+       if (a->family != b->family)
                return false;

-       return ((a->address.v4.s_addr & a->mask.v4.s_addr) ==
-               (b->address.v4.s_addr & a->mask.v4.s_addr));
+       if (a->family == FW3_FAMILY_V4)
+       {
+               return ((a->address.v4.s_addr & a->mask.v4.s_addr) ==
+                       (b->address.v4.s_addr & b->mask.v4.s_addr));
+       }
+       else if (a->family == FW3_FAMILY_V6)
+       {
+               int i;
+               for (i = 0; i < 16; i++)
+               {
+                       if ((a->address.v6.s6_addr[i] & a->mask.v6.s6_addr[i]) 
!=
+                           (b->address.v6.s6_addr[i] & b->mask.v6.s6_addr[i]))
+                               return false;
+               }
+               return true;
+       }
+       return false;
}

static bool
@@ -278,6 +293,7 @@ fw3_load_redirects(struct fw3_state *state, struct 
uci_package *p)
                        else
                        {
                                set(redir->_src->flags, FW3_FAMILY_V4, 
redir->target);
+                               set(redir->_src->flags, FW3_FAMILY_V6, 
redir->target);
                                redir->_src->conntrack = true;
                                valid = true;

@@ -293,6 +309,9 @@ fw3_load_redirects(struct fw3_state *state, struct 
uci_package *p)
                                        set(redir->_dest->flags, FW3_FAMILY_V4, 
FW3_FLAG_ACCEPT);
                                        set(redir->_dest->flags, FW3_FAMILY_V4, 
FW3_FLAG_DNAT);
                                        set(redir->_dest->flags, FW3_FAMILY_V4, 
FW3_FLAG_SNAT);
+                                       set(redir->_dest->flags, FW3_FAMILY_V6, 
FW3_FLAG_ACCEPT);
+                                       set(redir->_dest->flags, FW3_FAMILY_V6, 
FW3_FLAG_DNAT);
+                                       set(redir->_dest->flags, FW3_FAMILY_V6, 
FW3_FLAG_SNAT);
                                }
                        }
                }
@@ -309,6 +328,7 @@ fw3_load_redirects(struct fw3_state *state, struct 
uci_package *p)
                        else
                        {
                                set(redir->_dest->flags, FW3_FAMILY_V4, 
redir->target);
+                               set(redir->_dest->flags, FW3_FAMILY_V6, 
redir->target);
                                redir->_dest->conntrack = true;
                                valid = true;
                        }
@@ -364,13 +384,22 @@ static void
set_snat_dnat(struct fw3_ipt_rule *r, enum fw3_flag target,
             struct fw3_address *addr, struct fw3_port *port)
{
-       char buf[sizeof("255.255.255.255:65535-65535\0")];
+       char buf[INET6_ADDRSTRLEN + sizeof("[]:65535-65535\0")];

        buf[0] = '\0';

        if (addr && addr->set)
        {
-               inet_ntop(AF_INET, &addr->address.v4, buf, sizeof(buf));
+               if (addr->family == FW3_FAMILY_V4)
+               {
+                       inet_ntop(AF_INET, &addr->address.v4, buf, sizeof(buf));
+               }
+               else if (addr->family == FW3_FAMILY_V6)
+               {
+                       buf[0] = '[';
+                       inet_ntop(AF_INET6, &addr->address.v6, buf + 1, 
sizeof(buf) - 2);
+                       sprintf(buf + strlen(buf), "]");
+               }
        }

        if (port && port->set)
@@ -607,9 +636,6 @@ fw3_print_redirects(struct fw3_ipt_handle *handle, struct 
fw3_state *state)
        int num = 0;
        struct fw3_redirect *redir;

-       if (handle->family == FW3_FAMILY_V6)
-               return;
-
        if (handle->table != FW3_TABLE_FILTER && handle->table != FW3_TABLE_NAT)
                return;

diff --git a/snats.c b/snats.c
index 0f7d851..1d22e33 100644
--- a/snats.c
+++ b/snats.c
@@ -254,6 +254,7 @@ fw3_load_snats(struct fw3_state *state, struct uci_package 
*p, struct blob_attr
                if (snat->_src)
                {
                        set(snat->_src->flags, FW3_FAMILY_V4, FW3_FLAG_SNAT);
+                       set(snat->_src->flags, FW3_FAMILY_V6, FW3_FLAG_SNAT);
                        snat->_src->conntrack = true;
                }
        }
diff --git a/ubus.c b/ubus.c
index 9e034c8..4ae5c8b 100644
--- a/ubus.c
+++ b/ubus.c
@@ -93,11 +93,27 @@ parse_subnet(enum fw3_family family, struct blob_attr 
*dict, int rem)
        __blob_for_each_attr(cur, dict, rem)
        {
                if (!strcmp(blobmsg_name(cur), "address"))
-                       inet_pton(family == FW3_FAMILY_V4 ? AF_INET : AF_INET6,
-                                 blobmsg_get_string(cur), &addr->address.v6);
-
+               {
+                       if (family == FW3_FAMILY_V4)
+                       {
+                               inet_pton(AF_INET, blobmsg_get_string(cur), 
&addr->address.v4);
+                       }
+                       else
+                       {
+                               inet_pton(AF_INET6, blobmsg_get_string(cur), 
&addr->address.v6);
+                       }
+               }
                else if (!strcmp(blobmsg_name(cur), "mask"))
-                       fw3_bitlen2netmask(family, blobmsg_get_u32(cur), 
&addr->mask.v6);
+               {
+                       if (family == FW3_FAMILY_V4)
+                       {
+                               fw3_bitlen2netmask(family, 
blobmsg_get_u32(cur), &addr->mask.v4);
+                       }
+                       else
+                       {
+                               fw3_bitlen2netmask(family, 
blobmsg_get_u32(cur), &addr->mask.v6);
+                       }
+               }
        }

        return addr;
diff --git a/utils.c b/utils.c
index b2fbe02..4b8d44e 100644
--- a/utils.c
+++ b/utils.c
@@ -882,8 +882,14 @@ fw3_flush_conntrack(void *state)

                        if (!found)
                        {
-                               inet_ntop(addr->family == FW3_FAMILY_V4 ? 
AF_INET : AF_INET6,
-                                                 &addr->address.v4, buf, 
sizeof(buf));
+                               if (addr->family == FW3_FAMILY_V4)
+                               {
+                                       inet_ntop(AF_INET, &addr->address.v4, 
buf, sizeof(buf));
+                               }
+                               else
+                               {
+                                       inet_ntop(AF_INET6, &addr->address.v6, 
buf, sizeof(buf));
+                               }

                                info(" * Flushing conntrack: %s", buf);
                                fprintf(ct, "%s\n", buf);
diff --git a/zones.c b/zones.c
index 2ddd7b4..ff2403f 100644
--- a/zones.c
+++ b/zones.c
@@ -36,8 +36,8 @@ static const struct fw3_chain_spec zone_chains[] = {
        C(ANY, FILTER, REJECT,        "zone_%s_dest_REJECT"),
        C(ANY, FILTER, DROP,          "zone_%s_dest_DROP"),

-       C(V4,  NAT,    SNAT,          "zone_%s_postrouting"),
-       C(V4,  NAT,    DNAT,          "zone_%s_prerouting"),
+       C(ANY, NAT,    SNAT,          "zone_%s_postrouting"),
+       C(ANY, NAT,    DNAT,          "zone_%s_prerouting"),

        C(ANY, RAW,    NOTRACK,       "zone_%s_notrack"),

@@ -45,8 +45,8 @@ static const struct fw3_chain_spec zone_chains[] = {
        C(ANY, FILTER, CUSTOM_CHAINS, "output_%s_rule"),
        C(ANY, FILTER, CUSTOM_CHAINS, "forwarding_%s_rule"),

-       C(V4,  NAT,    CUSTOM_CHAINS, "prerouting_%s_rule"),
-       C(V4,  NAT,    CUSTOM_CHAINS, "postrouting_%s_rule"),
+       C(ANY, NAT,    CUSTOM_CHAINS, "prerouting_%s_rule"),
+       C(ANY, NAT,    CUSTOM_CHAINS, "postrouting_%s_rule"),

        { }
};
@@ -217,13 +217,16 @@ fw3_load_zones(struct fw3_state *state, struct 
uci_package *p)
                if (zone->masq)
                {
                        setbit(zone->flags[0], FW3_FLAG_SNAT);
+                       setbit(zone->flags[1], FW3_FLAG_SNAT);
                        zone->conntrack = true;
                }

                if (zone->custom_chains)
                {
                        setbit(zone->flags[0], FW3_FLAG_SNAT);
+                       setbit(zone->flags[1], FW3_FLAG_SNAT);
                        setbit(zone->flags[0], FW3_FLAG_DNAT);
+                       setbit(zone->flags[1], FW3_FLAG_DNAT);
                }

                setbit(zone->flags[0], fw3_to_src_target(zone->policy_input));
@@ -540,7 +543,7 @@ print_zone_rule(struct fw3_ipt_handle *handle, struct 
fw3_state *state,
                break;

        case FW3_TABLE_NAT:
-               if (zone->masq && handle->family == FW3_FAMILY_V4)
+               if (zone->masq)
                {
                        fw3_foreach(msrc, &zone->masq_src)
                        fw3_foreach(mdest, &zone->masq_dest)
-- 
2.3.2 (Apple Git-55)
_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to