aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Chion Tang <sdspeedonion@gmail.com> 2018-03-09 15:47:55 +0000
committerGravatar Chion Tang <sdspeedonion@gmail.com> 2018-03-09 15:47:55 +0000
commit4cb62a76feb844351c88d88f4d22ac147b828d4a (patch)
tree7113a890719f36255326d30fbb55dd04f8a25f01
parentfeature: mapping table clean & collision resolve (diff)
downloadnetfilter-full-cone-nat-4cb62a76feb844351c88d88f4d22ac147b828d4a.tar.gz
netfilter-full-cone-nat-4cb62a76feb844351c88d88f4d22ac147b828d4a.tar.bz2
netfilter-full-cone-nat-4cb62a76feb844351c88d88f4d22ac147b828d4a.zip
linux 4.9.x compat
-rw-r--r--xt_FULLCONENAT-old-kernel.c76
-rw-r--r--xt_FULLCONENAT.c1
2 files changed, 60 insertions, 17 deletions
diff --git a/xt_FULLCONENAT-old-kernel.c b/xt_FULLCONENAT-old-kernel.c
index 760fa66..b5f4e45 100644
--- a/xt_FULLCONENAT-old-kernel.c
+++ b/xt_FULLCONENAT-old-kernel.c
@@ -11,6 +11,8 @@
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h>
+#define xt_hooknum(par) (par->hooknum)
+
struct natmapping {
uint16_t port;
__be32 int_addr; /* internal source ip address */
@@ -24,7 +26,7 @@ static DEFINE_HASHTABLE(mapping_table, 10);
static DEFINE_SPINLOCK(fullconenat_lock);
-static struct natmapping* get_mapping(const uint16_t port) {
+static struct natmapping* get_mapping(const uint16_t port, const int create_new) {
struct natmapping *p_current, *p_new;
hash_for_each_possible(mapping_table, p_current, node, port) {
@@ -33,6 +35,10 @@ static struct natmapping* get_mapping(const uint16_t port) {
}
}
+ if (!create_new) {
+ return NULL;
+ }
+
p_new = kmalloc(sizeof(struct natmapping), GFP_ATOMIC);
if (p_new == NULL) {
return NULL;
@@ -62,10 +68,15 @@ static void destroy_mappings(void) {
struct natmapping *p_current;
struct hlist_node *tmp;
int i;
+
+ spin_lock(&fullconenat_lock);
+
hash_for_each_safe(mapping_table, i, tmp, p_current, node) {
hash_del(&p_current->node);
kfree(p_current);
}
+
+ spin_unlock(&fullconenat_lock);
}
static int is_mapping_active(const struct natmapping* mapping, const struct nf_conn *ct)
@@ -94,6 +105,23 @@ static int is_mapping_active(const struct natmapping* mapping, const struct nf_c
}
}
+static void clear_inactive_mappings(const struct nf_conn *ct) {
+ struct natmapping *p_current;
+ struct hlist_node *tmp;
+ int i;
+
+ spin_lock(&fullconenat_lock);
+
+ hash_for_each_safe(mapping_table, i, tmp, p_current, node) {
+ if (!is_mapping_active(p_current, ct)) {
+ hash_del(&p_current->node);
+ kfree(p_current);
+ }
+ }
+
+ spin_unlock(&fullconenat_lock);
+}
+
static __be32 get_device_ip(const struct net_device* dev) {
struct in_device* in_dev;
struct in_ifaddr* if_info;
@@ -110,12 +138,12 @@ static __be32 get_device_ip(const struct net_device* dev) {
}
}
-static void tg_destroy(const struct xt_tgdtor_param *par)
+static void fullconenat_tg_destroy(const struct xt_tgdtor_param *par)
{
}
-static unsigned int fullconenat_tg4(struct sk_buff *skb, const struct xt_action_param *par)
+static unsigned int fullconenat_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct nf_nat_ipv4_multi_range_compat *mr;
const struct nf_nat_ipv4_range *range;
@@ -140,13 +168,15 @@ static unsigned int fullconenat_tg4(struct sk_buff *skb, const struct xt_action_
ct = nf_ct_get(skb, &ctinfo);
+ clear_inactive_mappings(ct);
+
memset(&newrange.min_addr, 0, sizeof(newrange.min_addr));
memset(&newrange.max_addr, 0, sizeof(newrange.max_addr));
newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS;
newrange.min_proto = mr->range[0].min;
newrange.max_proto = mr->range[0].max;
- if (par->hooknum == NF_INET_PRE_ROUTING) {
+ if (xt_hooknum(par) == NF_INET_PRE_ROUTING) {
/* inbound packets */
ct_tuple = &(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
@@ -160,7 +190,7 @@ static unsigned int fullconenat_tg4(struct sk_buff *skb, const struct xt_action_
spin_lock(&fullconenat_lock);
/* find an active mapping based on the inbound port */
- mapping = get_mapping(port);
+ mapping = get_mapping(port, 0);
if (mapping == NULL) {
spin_unlock(&fullconenat_lock);
return ret;
@@ -172,13 +202,13 @@ static unsigned int fullconenat_tg4(struct sk_buff *skb, const struct xt_action_
newrange.min_proto.udp.port = cpu_to_be16(mapping->int_port);
newrange.max_proto = newrange.min_proto;
- ret = nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum));
+ ret = nf_nat_setup_info(ct, &newrange, HOOK2MANIP(xt_hooknum(par)));
}
spin_unlock(&fullconenat_lock);
return ret;
- } else if (par->hooknum == NF_INET_POST_ROUTING) {
+ } else if (xt_hooknum(par) == NF_INET_POST_ROUTING) {
/* outbound packets */
spin_lock(&fullconenat_lock);
@@ -189,14 +219,28 @@ static unsigned int fullconenat_tg4(struct sk_buff *skb, const struct xt_action_
ip = (ct_tuple_origin->src).u3.ip;
original_port = be16_to_cpu((ct_tuple_origin->src).u.udp.port);
- /* outbound nat: if a previously established mapping is active,
- we will reuse that mapping. */
-
src_mapping = get_mapping_by_original_src(ip, original_port);
if (src_mapping != NULL && is_mapping_active(src_mapping, ct)) {
+
+ /* outbound nat: if a previously established mapping is active,
+ we will reuse that mapping. */
+
newrange.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
newrange.min_proto.udp.port = cpu_to_be16(src_mapping->port);
newrange.max_proto = newrange.min_proto;
+
+ } else if (!(newrange.flags & NF_NAT_RANGE_PROTO_RANDOM)
+ && !(newrange.flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)) {
+
+ /* if multiple LAN hosts are using the same source port
+ and any PROTO_RANDOM is not specified,
+ we force a random port allocation to avoid collision. */
+
+ src_mapping = get_mapping(original_port, 0);
+ if (src_mapping != NULL
+ && is_mapping_active(src_mapping, ct)) {
+ newrange.flags |= NF_NAT_RANGE_PROTO_RANDOM;
+ }
}
}
@@ -204,7 +248,7 @@ static unsigned int fullconenat_tg4(struct sk_buff *skb, const struct xt_action_
newrange.min_addr.ip = new_ip;
newrange.max_addr.ip = new_ip;
- ret = nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum));
+ ret = nf_nat_setup_info(ct, &newrange, HOOK2MANIP(xt_hooknum(par)));
/* the reply tuple contains the mapped port. */
ct_tuple = &(ct->tuplehash[IP_CT_DIR_REPLY].tuple);
@@ -217,7 +261,7 @@ static unsigned int fullconenat_tg4(struct sk_buff *skb, const struct xt_action_
port = be16_to_cpu((ct_tuple->dst).u.udp.port);
/* store the mapping information to our mapping table */
- mapping = get_mapping(port);
+ mapping = get_mapping(port, 1);
if (mapping == NULL) {
spin_unlock(&fullconenat_lock);
return ret;
@@ -235,7 +279,7 @@ static unsigned int fullconenat_tg4(struct sk_buff *skb, const struct xt_action_
return ret;
}
-static int tg4_check(const struct xt_tgchk_param *par)
+static int fullconenat_tg_check(const struct xt_tgchk_param *par)
{
return 0;
@@ -246,13 +290,13 @@ static struct xt_target tg_reg[] __read_mostly = {
.name = "FULLCONENAT",
.family = NFPROTO_IPV4,
.revision = 0,
- .target = fullconenat_tg4,
+ .target = fullconenat_tg,
.targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),
.table = "nat",
.hooks = (1 << NF_INET_PRE_ROUTING) |
(1 << NF_INET_POST_ROUTING),
- .checkentry = tg4_check,
- .destroy = tg_destroy,
+ .checkentry = fullconenat_tg_check,
+ .destroy = fullconenat_tg_destroy,
.me = THIS_MODULE,
},
};
diff --git a/xt_FULLCONENAT.c b/xt_FULLCONENAT.c
index 00b0033..d2303cd 100644
--- a/xt_FULLCONENAT.c
+++ b/xt_FULLCONENAT.c
@@ -112,7 +112,6 @@ static void clear_inactive_mappings(const struct nf_conn *ct) {
hash_for_each_safe(mapping_table, i, tmp, p_current, node) {
if (!is_mapping_active(p_current, ct)) {
- printk("clear mapping at ext port = %d", p_current->port);
hash_del(&p_current->node);
kfree(p_current);
}