Loading include/net/netfilter/nf_conntrack.h +9 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,11 @@ struct nf_conntrack_net { #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> /* Handle NATTYPE Stuff,only if NATTYPE module was defined */ #ifdef CONFIG_IP_NF_TARGET_NATTYPE_MODULE #include <linux/netfilter_ipv4/ipt_NATTYPE.h> #endif struct nf_conn { /* Usage count in here is 1 for hash table, 1 per skb, * plus 1 for any connection(s) we are `master' for Loading Loading @@ -103,6 +108,10 @@ struct nf_conn { /* Extensions */ struct nf_ct_ext *ext; #ifdef CONFIG_IP_NF_TARGET_NATTYPE_MODULE unsigned long nattype_entry; #endif /* Storage reserved for other modules, must be the last member */ union nf_conntrack_proto proto; }; Loading include/net/netfilter/nf_conntrack_core.h +4 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,10 @@ void nf_conntrack_cleanup_end(void); bool nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, const struct nf_conntrack_tuple *orig); extern bool (*nattype_refresh_timer) (unsigned long nattype, unsigned long timeout_value) __rcu __read_mostly; /* Find a connection corresponding to a tuple. */ struct nf_conntrack_tuple_hash * Loading net/ipv4/netfilter/ipt_NATTYPE.c +96 −52 Original line number Diff line number Diff line Loading @@ -13,32 +13,32 @@ #include <linux/tcp.h> #include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_nat_rule.h> #include <net/netfilter/nf_nat.h> #include <linux/netfilter/x_tables.h> #include <linux/netfilter_ipv4/ipt_NATTYPE.h> #include <linux/atomic.h> #if !defined(NATTYPE_DEBUG) #define DEBUGP(type, args...) #else static const char * const types[] = {"TYPE_PORT_ADDRESS_RESTRICTED", "TYPE_ENDPOINT_INDEPENDENT", "TYPE_ADDRESS_RESTRICTED"}; static const char * const modes[] = {"MODE_DNAT", "MODE_FORWARD_IN", "MODE_FORWARD_OUT"}; #define DEBUGP(args...) pr_debug(args) #endif struct ipt_nattype { struct list_head list; struct timer_list timeout; unsigned long timeout_value; unsigned int nattype_cookie; unsigned short proto; /* Protocol: TCP or UDP */ struct nf_nat_ipv4_range range; /* LAN side src info*/ struct nf_nat_range range; /* LAN side source information */ unsigned short nat_port; /* Routed NAT port */ unsigned int dest_addr; /* Original egress packets dst addr */ unsigned short dest_port;/* Original egress packets destination port */ }; #define NATTYPE_COOKIE 0x11abcdef static LIST_HEAD(nattype_list); static DEFINE_SPINLOCK(nattype_lock); Loading @@ -48,11 +48,13 @@ static DEFINE_SPINLOCK(nattype_lock); static void nattype_nte_debug_print(const struct ipt_nattype *nte, const char *s) { DEBUGP("%p: %s - proto[%d], src[%pI4:%d], nat[<x>:%d], dest[%pI4:%d]\n", DEBUGP("%p:%s-proto[%d],src[%pI4:%d],nat[%d],dest[%pI4:%d]\n", nte, s, nte->proto, &nte->range.min_ip, ntohs(nte->range.min.all), &nte->range.min_addr.ip, ntohs(nte->range.min_proto.all), ntohs(nte->nat_port), &nte->dest_addr, ntohs(nte->dest_port)); DEBUGP("Timeout[%lx], Expires[%lx]\n", nte->timeout_value, nte->timeout.expires); } /* netfilter NATTYPE nattype_free() Loading @@ -60,20 +62,31 @@ static void nattype_nte_debug_print(const struct ipt_nattype *nte, */ static void nattype_free(struct ipt_nattype *nte) { nattype_nte_debug_print(nte, "free"); kfree(nte); } /* netfilter NATTYPE nattype_refresh_timer() * Refresh the timer for this object. */ static bool nattype_refresh_timer(struct ipt_nattype *nte) bool nattype_refresh_timer(unsigned long nat_type, unsigned long timeout_value) { struct ipt_nattype *nte = (struct ipt_nattype *)nat_type; if (!nte) return false; spin_lock_bh(&nattype_lock); if (nte->nattype_cookie != NATTYPE_COOKIE) { spin_unlock_bh(&nattype_lock); return false; } if (del_timer(&nte->timeout)) { nte->timeout.expires = jiffies + NATTYPE_TIMEOUT * HZ; nte->timeout.expires = timeout_value; add_timer(&nte->timeout); spin_unlock_bh(&nattype_lock); nattype_nte_debug_print(nte, "refresh"); return true; } spin_unlock_bh(&nattype_lock); return false; } Loading @@ -92,6 +105,7 @@ static void nattype_timer_timeout(unsigned long in_nattype) nattype_nte_debug_print(nte, "timeout"); spin_lock_bh(&nattype_lock); list_del(&nte->list); memset(nte, 0, sizeof(struct ipt_nattype)); spin_unlock_bh(&nattype_lock); nattype_free(nte); } Loading Loading @@ -171,7 +185,8 @@ static bool nattype_packet_in_match(const struct ipt_nattype *nte, /* netfilter NATTYPE nattype_compare * Compare two entries, return true if relevant fields are the same. */ static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2) static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2, const struct ipt_nattype_info *info) { /* netfilter NATTYPE Protocol * compare. Loading @@ -186,17 +201,18 @@ static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2) * Since we always keep min/max values the same, * just compare the min values. */ if (n1->range.min_ip != n2->range.min_ip) { DEBUGP("%s: r.min_ip mismatch: %pI4:%pI4\n", __func__, &n1->range.min_ip, &n2->range.min_ip); if (n1->range.min_addr.ip != n2->range.min_addr.ip) { DEBUGP("%s: r.min_addr.ip mismatch: %pI4:%pI4\n", __func__, &n1->range.min_addr.ip, &n2->range.min_addr.ip); return false; } if (n1->range.min.all != n2->range.min.all) { if (n1->range.min_proto.all != n2->range.min_proto.all) { DEBUGP("%s: r.min mismatch: %d:%d\n", __func__, ntohs(n1->range.min.all), ntohs(n2->range.min.all)); ntohs(n1->range.min_proto.all), ntohs(n2->range.min_proto.all)); return false; } Loading @@ -209,9 +225,6 @@ static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2) return false; } /* netfilter NATTYPE * Destination compare */ if (n1->dest_addr != n2->dest_addr) { DEBUGP("%s: dest_addr mismatch: %pI4:%pI4\n", __func__, &n1->dest_addr, &n2->dest_addr); Loading @@ -223,6 +236,16 @@ static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2) __func__, ntohs(n1->dest_port), ntohs(n2->dest_port)); return false; } /* netfilter NATTYPE Destination compare * Destination Comapre for Address Restricted Cone NAT. */ if (info->type == TYPE_ADDRESS_RESTRICTED && n1->dest_addr != n2->dest_addr) { DEBUGP("%s: dest_addr mismatch: %pI4:%pI4\n", __func__, &n1->dest_addr, &n2->dest_addr); return false; } return true; } Loading @@ -242,7 +265,7 @@ static unsigned int nattype_nat(struct sk_buff *skb, list_for_each_entry(nte, &nattype_list, list) { struct nf_conn *ct; enum ip_conntrack_info ctinfo; struct nf_nat_ipv4_range newrange; struct nf_nat_range newrange; unsigned int ret; if (!nattype_packet_in_match(nte, skb, par->targinfo)) Loading @@ -263,11 +286,22 @@ static unsigned int nattype_nat(struct sk_buff *skb, return XT_CONTINUE; } /* Expand the ingress conntrack * to include the reply as source /* netfilter * Refresh the timer, if we fail, break * out and forward fail as though we never * found the entry. */ if (!nattype_refresh_timer((unsigned long)nte, jiffies + nte->timeout_value)) break; /* netfilter * Expand the ingress conntrack to include the reply as source */ DEBUGP("Expand ingress conntrack=%p, type=%d, src[%pI4:%d]\n", ct, ctinfo, &newrange.min_ip, ntohs(newrange.min.all)); ct, ctinfo, &newrange.min_addr.ip, ntohs(newrange.min_proto.all)); ct->nattype_entry = (unsigned long)nte; ret = nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); DEBUGP("Expand returned: %d\n", ret); return ret; Loading @@ -290,12 +324,21 @@ static unsigned int nattype_forward(struct sk_buff *skb, enum ip_conntrack_info ctinfo; const struct ipt_nattype_info *info = par->targinfo; u16 nat_port; enum ip_conntrack_dir dir; if (par->hooknum != NF_INET_FORWARD) if (par->hooknum != NF_INET_POST_ROUTING) return XT_CONTINUE; /* Ingress packet, * refresh the timer if we find an entry. /* netfilter * Egress packet, create a new rule in our list. If conntrack does * not have an entry, skip this packet. */ ct = nf_ct_get(skb, &ctinfo); if (!ct) return XT_CONTINUE; /* netfilter * Ingress packet, refresh the timer if we find an entry. */ if (info->mode == MODE_FORWARD_IN) { spin_lock_bh(&nattype_lock); Loading @@ -307,12 +350,14 @@ static unsigned int nattype_forward(struct sk_buff *skb, if (!nattype_packet_in_match(nte, skb, info)) continue; spin_unlock_bh(&nattype_lock); /* netfilter NATTYPE * Refresh the timer, if we fail, break * out and forward fail as though we never * found the entry. */ if (!nattype_refresh_timer(nte)) if (!nattype_refresh_timer((unsigned long)nte, ct->timeout.expires)) break; /* netfilter NATTYPE Loading @@ -320,7 +365,6 @@ static unsigned int nattype_forward(struct sk_buff *skb, * entry values should not change so print * them outside the lock. */ spin_unlock_bh(&nattype_lock); nattype_nte_debug_print(nte, "refresh"); DEBUGP("FORWARD_IN_ACCEPT\n"); return NF_ACCEPT; Loading @@ -330,15 +374,9 @@ static unsigned int nattype_forward(struct sk_buff *skb, return XT_CONTINUE; } /* netfilter NATTYPE * Egress packet, create a new rule in our list. If conntrack does * not have an entry, skip this packet. */ ct = nf_ct_get(skb, &ctinfo); if (!ct || (ctinfo == IP_CT_NEW && ctinfo == IP_CT_RELATED)) return XT_CONTINUE; dir = CTINFO2DIR(ctinfo); nat_port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.all; nat_port = ct->tuplehash[!dir].tuple.dst.u.all; /* netfilter NATTYPE * Allocate a new entry Loading @@ -354,16 +392,18 @@ static unsigned int nattype_forward(struct sk_buff *skb, nte->proto = iph->protocol; nte->nat_port = nat_port; nte->dest_addr = iph->daddr; nte->range.min_ip = iph->saddr; nte->range.max_ip = nte->range.min_ip; nte->range.min_addr.ip = iph->saddr; nte->range.max_addr.ip = nte->range.min_addr.ip; if (iph->protocol == IPPROTO_TCP) { nte->range.min.tcp.port = ((struct tcphdr *)protoh)->source; nte->range.max.tcp.port = nte->range.min.tcp.port; nte->range.min_proto.tcp.port = ((struct tcphdr *)protoh)->source; nte->range.max_proto.tcp.port = nte->range.min_proto.tcp.port; nte->dest_port = ((struct tcphdr *)protoh)->dest; } else if (iph->protocol == IPPROTO_UDP) { nte->range.min.udp.port = ((struct udphdr *)protoh)->source; nte->range.max.udp.port = nte->range.min.udp.port; nte->range.min_proto.udp.port = ((struct udphdr *)protoh)->source; nte->range.max_proto.udp.port = nte->range.min_proto.udp.port; nte->dest_port = ((struct udphdr *)protoh)->dest; } nte->range.flags = (NF_NAT_RANGE_MAP_IPS | Loading @@ -384,15 +424,15 @@ static unsigned int nattype_forward(struct sk_buff *skb, */ spin_lock_bh(&nattype_lock); list_for_each_entry(nte2, &nattype_list, list) { if (!nattype_compare(nte, nte2)) if (!nattype_compare(nte, nte2, info)) continue; spin_unlock_bh(&nattype_lock); /* netfilter NATTYPE * If we can not refresh this entry, insert our new * entry as this one is timed out and will be removed * from the list shortly. */ if (!nattype_refresh_timer(nte2)) if (!nattype_refresh_timer((unsigned long)nte2, jiffies + nte2->timeout_value)) break; /* netfilter NATTYPE Loading @@ -401,7 +441,6 @@ static unsigned int nattype_forward(struct sk_buff *skb, * * Free up the new entry. */ spin_unlock_bh(&nattype_lock); nattype_nte_debug_print(nte2, "refresh"); nattype_free(nte); return XT_CONTINUE; Loading @@ -410,9 +449,12 @@ static unsigned int nattype_forward(struct sk_buff *skb, /* netfilter NATTYPE * Add the new entry to the list. */ nte->timeout.expires = jiffies + (NATTYPE_TIMEOUT * HZ); nte->timeout_value = ct->timeout.expires; nte->timeout.expires = ct->timeout.expires + jiffies; add_timer(&nte->timeout); list_add(&nte->list, &nattype_list); ct->nattype_entry = (unsigned long)nte; nte->nattype_cookie = NATTYPE_COOKIE; spin_unlock_bh(&nattype_lock); nattype_nte_debug_print(nte, "ADD"); return XT_CONTINUE; Loading Loading @@ -498,7 +540,7 @@ static int nattype_check(const struct xt_tgchk_param *par) __func__, types[info->type], modes[info->mode]); if (par->hook_mask & ~((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_FORWARD))) { (1 << NF_INET_POST_ROUTING))) { DEBUGP("%s: bad hooks %x.\n", __func__, par->hook_mask); return -EINVAL; } Loading Loading @@ -539,12 +581,14 @@ static struct xt_target nattype = { .checkentry = nattype_check, .targetsize = sizeof(struct ipt_nattype_info), .hooks = ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_FORWARD)), (1 << NF_INET_POST_ROUTING)), .me = THIS_MODULE, }; static int __init init(void) { WARN_ON(nattype_refresh_timer); RCU_INIT_POINTER(nattype_refresh_timer, nattype_refresh_timer_impl); return xt_register_target(&nattype); } Loading net/netfilter/nf_conntrack_core.c +27 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,12 @@ EXPORT_SYMBOL_GPL(nf_conntrack_expect_lock); struct hlist_nulls_head *nf_conntrack_hash __read_mostly; EXPORT_SYMBOL_GPL(nf_conntrack_hash); bool (*nattype_refresh_timer) (unsigned long nattype, unsigned long timeout_value) __rcu __read_mostly; EXPORT_SYMBOL(nattype_refresh_timer); struct conntrack_gc_work { struct delayed_work dwork; u32 last_bucket; Loading Loading @@ -1387,6 +1393,9 @@ __nf_conntrack_alloc(struct net *net, nf_ct_zone_add(ct, zone); #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) ct->nattype_entry = 0; #endif /* Because we use RCU lookups, we set ct_general.use to zero before * this is inserted in any list. */ Loading Loading @@ -1495,6 +1504,10 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, #endif #ifdef CONFIG_NF_CONNTRACK_SECMARK ct->secmark = exp->master->secmark; #endif /* Initialize the NAT type entry. */ #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) ct->nattype_entry = 0; #endif NF_CT_STAT_INC(net, expect_new); } Loading Loading @@ -1784,6 +1797,12 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, u32 extra_jiffies, bool do_acct) { #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) bool (*nattype_ref_timer) (unsigned long nattype, unsigned long timeout_value); #endif /* Only update if this is not a fixed timeout */ if (test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) goto acct; Loading @@ -1794,6 +1813,14 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, if (READ_ONCE(ct->timeout) != extra_jiffies) WRITE_ONCE(ct->timeout, extra_jiffies); /* Refresh the NAT type entry. */ #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) nattype_ref_timer = rcu_dereference(nattype_refresh_timer); if (nattype_ref_timer) nattype_ref_timer(ct->nattype_entry, ct->timeout.expires); #endif acct: if (do_acct) nf_ct_acct_update(ct, ctinfo, skb->len); Loading net/netfilter/nf_conntrack_netlink.c +11 −0 Original line number Diff line number Diff line Loading @@ -1686,6 +1686,11 @@ static int ctnetlink_change_timeout(struct nf_conn *ct, const struct nlattr * const cda[]) { u64 timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ; #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) bool (*nattype_ref_timer) (unsigned long nattype, unsigned long timeout_value); #endif if (timeout > INT_MAX) timeout = INT_MAX; Loading @@ -1694,6 +1699,12 @@ static int ctnetlink_change_timeout(struct nf_conn *ct, if (test_bit(IPS_DYING_BIT, &ct->status)) return -ETIME; /* Refresh the NAT type entry. */ #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) nattype_ref_timer = rcu_dereference(nattype_refresh_timer); if (nattype_ref_timer) nattype_ref_timer(ct->nattype_entry, ct->timeout.expires); #endif return 0; } Loading Loading
include/net/netfilter/nf_conntrack.h +9 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,11 @@ struct nf_conntrack_net { #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> /* Handle NATTYPE Stuff,only if NATTYPE module was defined */ #ifdef CONFIG_IP_NF_TARGET_NATTYPE_MODULE #include <linux/netfilter_ipv4/ipt_NATTYPE.h> #endif struct nf_conn { /* Usage count in here is 1 for hash table, 1 per skb, * plus 1 for any connection(s) we are `master' for Loading Loading @@ -103,6 +108,10 @@ struct nf_conn { /* Extensions */ struct nf_ct_ext *ext; #ifdef CONFIG_IP_NF_TARGET_NATTYPE_MODULE unsigned long nattype_entry; #endif /* Storage reserved for other modules, must be the last member */ union nf_conntrack_proto proto; }; Loading
include/net/netfilter/nf_conntrack_core.h +4 −0 Original line number Diff line number Diff line Loading @@ -43,6 +43,10 @@ void nf_conntrack_cleanup_end(void); bool nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, const struct nf_conntrack_tuple *orig); extern bool (*nattype_refresh_timer) (unsigned long nattype, unsigned long timeout_value) __rcu __read_mostly; /* Find a connection corresponding to a tuple. */ struct nf_conntrack_tuple_hash * Loading
net/ipv4/netfilter/ipt_NATTYPE.c +96 −52 Original line number Diff line number Diff line Loading @@ -13,32 +13,32 @@ #include <linux/tcp.h> #include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_nat_rule.h> #include <net/netfilter/nf_nat.h> #include <linux/netfilter/x_tables.h> #include <linux/netfilter_ipv4/ipt_NATTYPE.h> #include <linux/atomic.h> #if !defined(NATTYPE_DEBUG) #define DEBUGP(type, args...) #else static const char * const types[] = {"TYPE_PORT_ADDRESS_RESTRICTED", "TYPE_ENDPOINT_INDEPENDENT", "TYPE_ADDRESS_RESTRICTED"}; static const char * const modes[] = {"MODE_DNAT", "MODE_FORWARD_IN", "MODE_FORWARD_OUT"}; #define DEBUGP(args...) pr_debug(args) #endif struct ipt_nattype { struct list_head list; struct timer_list timeout; unsigned long timeout_value; unsigned int nattype_cookie; unsigned short proto; /* Protocol: TCP or UDP */ struct nf_nat_ipv4_range range; /* LAN side src info*/ struct nf_nat_range range; /* LAN side source information */ unsigned short nat_port; /* Routed NAT port */ unsigned int dest_addr; /* Original egress packets dst addr */ unsigned short dest_port;/* Original egress packets destination port */ }; #define NATTYPE_COOKIE 0x11abcdef static LIST_HEAD(nattype_list); static DEFINE_SPINLOCK(nattype_lock); Loading @@ -48,11 +48,13 @@ static DEFINE_SPINLOCK(nattype_lock); static void nattype_nte_debug_print(const struct ipt_nattype *nte, const char *s) { DEBUGP("%p: %s - proto[%d], src[%pI4:%d], nat[<x>:%d], dest[%pI4:%d]\n", DEBUGP("%p:%s-proto[%d],src[%pI4:%d],nat[%d],dest[%pI4:%d]\n", nte, s, nte->proto, &nte->range.min_ip, ntohs(nte->range.min.all), &nte->range.min_addr.ip, ntohs(nte->range.min_proto.all), ntohs(nte->nat_port), &nte->dest_addr, ntohs(nte->dest_port)); DEBUGP("Timeout[%lx], Expires[%lx]\n", nte->timeout_value, nte->timeout.expires); } /* netfilter NATTYPE nattype_free() Loading @@ -60,20 +62,31 @@ static void nattype_nte_debug_print(const struct ipt_nattype *nte, */ static void nattype_free(struct ipt_nattype *nte) { nattype_nte_debug_print(nte, "free"); kfree(nte); } /* netfilter NATTYPE nattype_refresh_timer() * Refresh the timer for this object. */ static bool nattype_refresh_timer(struct ipt_nattype *nte) bool nattype_refresh_timer(unsigned long nat_type, unsigned long timeout_value) { struct ipt_nattype *nte = (struct ipt_nattype *)nat_type; if (!nte) return false; spin_lock_bh(&nattype_lock); if (nte->nattype_cookie != NATTYPE_COOKIE) { spin_unlock_bh(&nattype_lock); return false; } if (del_timer(&nte->timeout)) { nte->timeout.expires = jiffies + NATTYPE_TIMEOUT * HZ; nte->timeout.expires = timeout_value; add_timer(&nte->timeout); spin_unlock_bh(&nattype_lock); nattype_nte_debug_print(nte, "refresh"); return true; } spin_unlock_bh(&nattype_lock); return false; } Loading @@ -92,6 +105,7 @@ static void nattype_timer_timeout(unsigned long in_nattype) nattype_nte_debug_print(nte, "timeout"); spin_lock_bh(&nattype_lock); list_del(&nte->list); memset(nte, 0, sizeof(struct ipt_nattype)); spin_unlock_bh(&nattype_lock); nattype_free(nte); } Loading Loading @@ -171,7 +185,8 @@ static bool nattype_packet_in_match(const struct ipt_nattype *nte, /* netfilter NATTYPE nattype_compare * Compare two entries, return true if relevant fields are the same. */ static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2) static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2, const struct ipt_nattype_info *info) { /* netfilter NATTYPE Protocol * compare. Loading @@ -186,17 +201,18 @@ static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2) * Since we always keep min/max values the same, * just compare the min values. */ if (n1->range.min_ip != n2->range.min_ip) { DEBUGP("%s: r.min_ip mismatch: %pI4:%pI4\n", __func__, &n1->range.min_ip, &n2->range.min_ip); if (n1->range.min_addr.ip != n2->range.min_addr.ip) { DEBUGP("%s: r.min_addr.ip mismatch: %pI4:%pI4\n", __func__, &n1->range.min_addr.ip, &n2->range.min_addr.ip); return false; } if (n1->range.min.all != n2->range.min.all) { if (n1->range.min_proto.all != n2->range.min_proto.all) { DEBUGP("%s: r.min mismatch: %d:%d\n", __func__, ntohs(n1->range.min.all), ntohs(n2->range.min.all)); ntohs(n1->range.min_proto.all), ntohs(n2->range.min_proto.all)); return false; } Loading @@ -209,9 +225,6 @@ static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2) return false; } /* netfilter NATTYPE * Destination compare */ if (n1->dest_addr != n2->dest_addr) { DEBUGP("%s: dest_addr mismatch: %pI4:%pI4\n", __func__, &n1->dest_addr, &n2->dest_addr); Loading @@ -223,6 +236,16 @@ static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2) __func__, ntohs(n1->dest_port), ntohs(n2->dest_port)); return false; } /* netfilter NATTYPE Destination compare * Destination Comapre for Address Restricted Cone NAT. */ if (info->type == TYPE_ADDRESS_RESTRICTED && n1->dest_addr != n2->dest_addr) { DEBUGP("%s: dest_addr mismatch: %pI4:%pI4\n", __func__, &n1->dest_addr, &n2->dest_addr); return false; } return true; } Loading @@ -242,7 +265,7 @@ static unsigned int nattype_nat(struct sk_buff *skb, list_for_each_entry(nte, &nattype_list, list) { struct nf_conn *ct; enum ip_conntrack_info ctinfo; struct nf_nat_ipv4_range newrange; struct nf_nat_range newrange; unsigned int ret; if (!nattype_packet_in_match(nte, skb, par->targinfo)) Loading @@ -263,11 +286,22 @@ static unsigned int nattype_nat(struct sk_buff *skb, return XT_CONTINUE; } /* Expand the ingress conntrack * to include the reply as source /* netfilter * Refresh the timer, if we fail, break * out and forward fail as though we never * found the entry. */ if (!nattype_refresh_timer((unsigned long)nte, jiffies + nte->timeout_value)) break; /* netfilter * Expand the ingress conntrack to include the reply as source */ DEBUGP("Expand ingress conntrack=%p, type=%d, src[%pI4:%d]\n", ct, ctinfo, &newrange.min_ip, ntohs(newrange.min.all)); ct, ctinfo, &newrange.min_addr.ip, ntohs(newrange.min_proto.all)); ct->nattype_entry = (unsigned long)nte; ret = nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); DEBUGP("Expand returned: %d\n", ret); return ret; Loading @@ -290,12 +324,21 @@ static unsigned int nattype_forward(struct sk_buff *skb, enum ip_conntrack_info ctinfo; const struct ipt_nattype_info *info = par->targinfo; u16 nat_port; enum ip_conntrack_dir dir; if (par->hooknum != NF_INET_FORWARD) if (par->hooknum != NF_INET_POST_ROUTING) return XT_CONTINUE; /* Ingress packet, * refresh the timer if we find an entry. /* netfilter * Egress packet, create a new rule in our list. If conntrack does * not have an entry, skip this packet. */ ct = nf_ct_get(skb, &ctinfo); if (!ct) return XT_CONTINUE; /* netfilter * Ingress packet, refresh the timer if we find an entry. */ if (info->mode == MODE_FORWARD_IN) { spin_lock_bh(&nattype_lock); Loading @@ -307,12 +350,14 @@ static unsigned int nattype_forward(struct sk_buff *skb, if (!nattype_packet_in_match(nte, skb, info)) continue; spin_unlock_bh(&nattype_lock); /* netfilter NATTYPE * Refresh the timer, if we fail, break * out and forward fail as though we never * found the entry. */ if (!nattype_refresh_timer(nte)) if (!nattype_refresh_timer((unsigned long)nte, ct->timeout.expires)) break; /* netfilter NATTYPE Loading @@ -320,7 +365,6 @@ static unsigned int nattype_forward(struct sk_buff *skb, * entry values should not change so print * them outside the lock. */ spin_unlock_bh(&nattype_lock); nattype_nte_debug_print(nte, "refresh"); DEBUGP("FORWARD_IN_ACCEPT\n"); return NF_ACCEPT; Loading @@ -330,15 +374,9 @@ static unsigned int nattype_forward(struct sk_buff *skb, return XT_CONTINUE; } /* netfilter NATTYPE * Egress packet, create a new rule in our list. If conntrack does * not have an entry, skip this packet. */ ct = nf_ct_get(skb, &ctinfo); if (!ct || (ctinfo == IP_CT_NEW && ctinfo == IP_CT_RELATED)) return XT_CONTINUE; dir = CTINFO2DIR(ctinfo); nat_port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.all; nat_port = ct->tuplehash[!dir].tuple.dst.u.all; /* netfilter NATTYPE * Allocate a new entry Loading @@ -354,16 +392,18 @@ static unsigned int nattype_forward(struct sk_buff *skb, nte->proto = iph->protocol; nte->nat_port = nat_port; nte->dest_addr = iph->daddr; nte->range.min_ip = iph->saddr; nte->range.max_ip = nte->range.min_ip; nte->range.min_addr.ip = iph->saddr; nte->range.max_addr.ip = nte->range.min_addr.ip; if (iph->protocol == IPPROTO_TCP) { nte->range.min.tcp.port = ((struct tcphdr *)protoh)->source; nte->range.max.tcp.port = nte->range.min.tcp.port; nte->range.min_proto.tcp.port = ((struct tcphdr *)protoh)->source; nte->range.max_proto.tcp.port = nte->range.min_proto.tcp.port; nte->dest_port = ((struct tcphdr *)protoh)->dest; } else if (iph->protocol == IPPROTO_UDP) { nte->range.min.udp.port = ((struct udphdr *)protoh)->source; nte->range.max.udp.port = nte->range.min.udp.port; nte->range.min_proto.udp.port = ((struct udphdr *)protoh)->source; nte->range.max_proto.udp.port = nte->range.min_proto.udp.port; nte->dest_port = ((struct udphdr *)protoh)->dest; } nte->range.flags = (NF_NAT_RANGE_MAP_IPS | Loading @@ -384,15 +424,15 @@ static unsigned int nattype_forward(struct sk_buff *skb, */ spin_lock_bh(&nattype_lock); list_for_each_entry(nte2, &nattype_list, list) { if (!nattype_compare(nte, nte2)) if (!nattype_compare(nte, nte2, info)) continue; spin_unlock_bh(&nattype_lock); /* netfilter NATTYPE * If we can not refresh this entry, insert our new * entry as this one is timed out and will be removed * from the list shortly. */ if (!nattype_refresh_timer(nte2)) if (!nattype_refresh_timer((unsigned long)nte2, jiffies + nte2->timeout_value)) break; /* netfilter NATTYPE Loading @@ -401,7 +441,6 @@ static unsigned int nattype_forward(struct sk_buff *skb, * * Free up the new entry. */ spin_unlock_bh(&nattype_lock); nattype_nte_debug_print(nte2, "refresh"); nattype_free(nte); return XT_CONTINUE; Loading @@ -410,9 +449,12 @@ static unsigned int nattype_forward(struct sk_buff *skb, /* netfilter NATTYPE * Add the new entry to the list. */ nte->timeout.expires = jiffies + (NATTYPE_TIMEOUT * HZ); nte->timeout_value = ct->timeout.expires; nte->timeout.expires = ct->timeout.expires + jiffies; add_timer(&nte->timeout); list_add(&nte->list, &nattype_list); ct->nattype_entry = (unsigned long)nte; nte->nattype_cookie = NATTYPE_COOKIE; spin_unlock_bh(&nattype_lock); nattype_nte_debug_print(nte, "ADD"); return XT_CONTINUE; Loading Loading @@ -498,7 +540,7 @@ static int nattype_check(const struct xt_tgchk_param *par) __func__, types[info->type], modes[info->mode]); if (par->hook_mask & ~((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_FORWARD))) { (1 << NF_INET_POST_ROUTING))) { DEBUGP("%s: bad hooks %x.\n", __func__, par->hook_mask); return -EINVAL; } Loading Loading @@ -539,12 +581,14 @@ static struct xt_target nattype = { .checkentry = nattype_check, .targetsize = sizeof(struct ipt_nattype_info), .hooks = ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_FORWARD)), (1 << NF_INET_POST_ROUTING)), .me = THIS_MODULE, }; static int __init init(void) { WARN_ON(nattype_refresh_timer); RCU_INIT_POINTER(nattype_refresh_timer, nattype_refresh_timer_impl); return xt_register_target(&nattype); } Loading
net/netfilter/nf_conntrack_core.c +27 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,12 @@ EXPORT_SYMBOL_GPL(nf_conntrack_expect_lock); struct hlist_nulls_head *nf_conntrack_hash __read_mostly; EXPORT_SYMBOL_GPL(nf_conntrack_hash); bool (*nattype_refresh_timer) (unsigned long nattype, unsigned long timeout_value) __rcu __read_mostly; EXPORT_SYMBOL(nattype_refresh_timer); struct conntrack_gc_work { struct delayed_work dwork; u32 last_bucket; Loading Loading @@ -1387,6 +1393,9 @@ __nf_conntrack_alloc(struct net *net, nf_ct_zone_add(ct, zone); #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) ct->nattype_entry = 0; #endif /* Because we use RCU lookups, we set ct_general.use to zero before * this is inserted in any list. */ Loading Loading @@ -1495,6 +1504,10 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, #endif #ifdef CONFIG_NF_CONNTRACK_SECMARK ct->secmark = exp->master->secmark; #endif /* Initialize the NAT type entry. */ #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) ct->nattype_entry = 0; #endif NF_CT_STAT_INC(net, expect_new); } Loading Loading @@ -1784,6 +1797,12 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, u32 extra_jiffies, bool do_acct) { #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) bool (*nattype_ref_timer) (unsigned long nattype, unsigned long timeout_value); #endif /* Only update if this is not a fixed timeout */ if (test_bit(IPS_FIXED_TIMEOUT_BIT, &ct->status)) goto acct; Loading @@ -1794,6 +1813,14 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, if (READ_ONCE(ct->timeout) != extra_jiffies) WRITE_ONCE(ct->timeout, extra_jiffies); /* Refresh the NAT type entry. */ #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) nattype_ref_timer = rcu_dereference(nattype_refresh_timer); if (nattype_ref_timer) nattype_ref_timer(ct->nattype_entry, ct->timeout.expires); #endif acct: if (do_acct) nf_ct_acct_update(ct, ctinfo, skb->len); Loading
net/netfilter/nf_conntrack_netlink.c +11 −0 Original line number Diff line number Diff line Loading @@ -1686,6 +1686,11 @@ static int ctnetlink_change_timeout(struct nf_conn *ct, const struct nlattr * const cda[]) { u64 timeout = (u64)ntohl(nla_get_be32(cda[CTA_TIMEOUT])) * HZ; #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) bool (*nattype_ref_timer) (unsigned long nattype, unsigned long timeout_value); #endif if (timeout > INT_MAX) timeout = INT_MAX; Loading @@ -1694,6 +1699,12 @@ static int ctnetlink_change_timeout(struct nf_conn *ct, if (test_bit(IPS_DYING_BIT, &ct->status)) return -ETIME; /* Refresh the NAT type entry. */ #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) nattype_ref_timer = rcu_dereference(nattype_refresh_timer); if (nattype_ref_timer) nattype_ref_timer(ct->nattype_entry, ct->timeout.expires); #endif return 0; } Loading