Loading include/net/netfilter/nf_conntrack_core.h +3 −1 Original line number Original line Diff line number Diff line Loading @@ -54,7 +54,9 @@ bool nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, const struct nf_conntrack_l3proto *l3proto, const struct nf_conntrack_l3proto *l3proto, const struct nf_conntrack_l4proto *l4proto); const struct nf_conntrack_l4proto *l4proto); extern void (*delete_sfe_entry)(struct nf_conn *ct); extern void (*delete_sfe_entry)(struct nf_conn *ct); extern bool (*nattype_refresh_timer)(unsigned long nattype); extern bool (*nattype_refresh_timer) (unsigned long nattype, unsigned long timeout_value); /* Find a connection corresponding to a tuple. */ /* Find a connection corresponding to a tuple. */ struct nf_conntrack_tuple_hash * struct nf_conntrack_tuple_hash * Loading net/ipv4/netfilter/ipt_NATTYPE.c +75 −56 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ * Ubicom32 implementation derived from * Ubicom32 implementation derived from * Cameo's implementation(with many thanks): * Cameo's implementation(with many thanks): */ */ #include <linux/types.h> #include <linux/types.h> #include <linux/ip.h> #include <linux/ip.h> #include <linux/udp.h> #include <linux/udp.h> Loading @@ -36,21 +37,17 @@ #include <linux/tcp.h> #include <linux/tcp.h> #include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_core.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/x_tables.h> #include <linux/netfilter_ipv4/ipt_NATTYPE.h> #include <linux/netfilter_ipv4/ipt_NATTYPE.h> #include <linux/atomic.h> #include <linux/atomic.h> #if !defined(NATTYPE_DEBUG) #define DEBUGP(type, args...) #else static const char * const types[] = {"TYPE_PORT_ADDRESS_RESTRICTED", static const char * const types[] = {"TYPE_PORT_ADDRESS_RESTRICTED", "TYPE_ENDPOINT_INDEPENDENT", "TYPE_ENDPOINT_INDEPENDENT", "TYPE_ADDRESS_RESTRICTED"}; "TYPE_ADDRESS_RESTRICTED"}; static const char * const modes[] = {"MODE_DNAT", "MODE_FORWARD_IN", static const char * const modes[] = {"MODE_DNAT", "MODE_FORWARD_IN", "MODE_FORWARD_OUT"}; "MODE_FORWARD_OUT"}; #define DEBUGP(args...) pr_debug(args) #define DEBUGP(args...) pr_debug(args) #endif /* netfilter NATTYPE TODO: /* netfilter NATTYPE TODO: * Add magic value checks to data structure. * Add magic value checks to data structure. Loading @@ -58,14 +55,17 @@ static const char * const modes[] = {"MODE_DNAT", "MODE_FORWARD_IN", struct ipt_nattype { struct ipt_nattype { struct list_head list; struct list_head list; struct timer_list timeout; struct timer_list timeout; unsigned char is_valid; unsigned long timeout_value; unsigned int nattype_cookie; unsigned short proto; /* Protocol: TCP or UDP */ 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 short nat_port; /* Routed NAT port */ unsigned int dest_addr; /* Original egress packets dst addr */ unsigned int dest_addr; /* Original egress packets dst addr */ unsigned short dest_port;/* Original egress packets destination port */ unsigned short dest_port;/* Original egress packets destination port */ }; }; #define NATTYPE_COOKIE 0x11abcdef /* TODO: It might be better to use a hash table for performance in /* TODO: It might be better to use a hash table for performance in * heavy traffic. * heavy traffic. */ */ Loading @@ -78,11 +78,13 @@ static DEFINE_SPINLOCK(nattype_lock); static void nattype_nte_debug_print(const struct ipt_nattype *nte, static void nattype_nte_debug_print(const struct ipt_nattype *nte, const char *s) 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, 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), ntohs(nte->nat_port), &nte->dest_addr, ntohs(nte->dest_port)); &nte->dest_addr, ntohs(nte->dest_port)); DEBUGP("Timeout[%lx], Expires[%lx]\n", nte->timeout_value, nte->timeout.expires); } } /* netfilter NATTYPE nattype_free() /* netfilter NATTYPE nattype_free() Loading @@ -90,28 +92,28 @@ static void nattype_nte_debug_print(const struct ipt_nattype *nte, */ */ static void nattype_free(struct ipt_nattype *nte) static void nattype_free(struct ipt_nattype *nte) { { nattype_nte_debug_print(nte, "free"); kfree(nte); kfree(nte); } } /* netfilter NATTYPE nattype_refresh_timer() /* netfilter NATTYPE nattype_refresh_timer() * Refresh the timer for this object. * Refresh the timer for this object. */ */ bool nattype_refresh_timer_impl(unsigned long nat_type) bool nattype_refresh_timer(unsigned long nat_type, unsigned long timeout_value) { { struct ipt_nattype *nte = (struct ipt_nattype *)nat_type; struct ipt_nattype *nte = (struct ipt_nattype *)nat_type; if (!nte) if (!nte) return false; return false; spin_lock_bh(&nattype_lock); spin_lock_bh(&nattype_lock); if (!nte->is_valid) { if (nte->nattype_cookie != NATTYPE_COOKIE) { spin_unlock_bh(&nattype_lock); spin_unlock_bh(&nattype_lock); return false; return false; } } if (del_timer(&nte->timeout)) { if (del_timer(&nte->timeout)) { nte->timeout.expires = jiffies + NATTYPE_TIMEOUT * HZ; nte->timeout.expires = timeout_value; add_timer(&nte->timeout); add_timer(&nte->timeout); spin_unlock_bh(&nattype_lock); spin_unlock_bh(&nattype_lock); nattype_nte_debug_print(nte, "refresh"); return true; return true; } } spin_unlock_bh(&nattype_lock); spin_unlock_bh(&nattype_lock); Loading Loading @@ -213,7 +215,8 @@ static bool nattype_packet_in_match(const struct ipt_nattype *nte, /* netfilter NATTYPE nattype_compare /* netfilter NATTYPE nattype_compare * Compare two entries, return true if relevant fields are the same. * 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 /* netfilter NATTYPE Protocol * compare. * compare. Loading @@ -228,16 +231,16 @@ static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2) * Since we always keep min/max values the same, * Since we always keep min/max values the same, * just compare the min values. * just compare the min values. */ */ if (n1->range.min_ip != n2->range.min_ip) { if (n1->range.min_addr.ip != n2->range.min_addr.ip) { DEBUGP("nattype_compare: r.min_ip mismatch: %pI4:%pI4\n", DEBUGP("nattype_compare: r.min_addr.ip mismatch: %pI4:%pI4\n", &n1->range.min_ip, &n2->range.min_ip); &n1->range.min_addr.ip, &n2->range.min_addr.ip); return false; return false; } } if (n1->range.min.all != n2->range.min.all) { if (n1->range.min_proto.all != n2->range.min_proto.all) { DEBUGP("nattype_compare: r.min mismatch: %d:%d\n", DEBUGP("nattype_compare: r.min mismatch: %d:%d\n", ntohs(n1->range.min.all), ntohs(n1->range.min_proto.all), ntohs(n2->range.min.all)); ntohs(n2->range.min_proto.all)); return false; return false; } } Loading @@ -250,20 +253,16 @@ static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2) return false; return false; } } /* netfilter NATTYPE /* netfilter NATTYPE Destination compare * Destination compare * Destination Comapre for Address Restricted Cone NAT. */ */ if (n1->dest_addr != n2->dest_addr) { if ((info->type == TYPE_ADDRESS_RESTRICTED) && (n1->dest_addr != n2->dest_addr)) { DEBUGP("nattype_compare: dest_addr mismatch: %pI4:%pI4\n", DEBUGP("nattype_compare: dest_addr mismatch: %pI4:%pI4\n", &n1->dest_addr, &n2->dest_addr); &n1->dest_addr, &n2->dest_addr); return false; return false; } } if (n1->dest_port != n2->dest_port) { DEBUGP("nattype_compare: dest_port mismatch: %d:%d\n", ntohs(n1->dest_port), ntohs(n2->dest_port)); return false; } return true; return true; } } Loading @@ -283,7 +282,7 @@ static unsigned int nattype_nat(struct sk_buff *skb, list_for_each_entry(nte, &nattype_list, list) { list_for_each_entry(nte, &nattype_list, list) { struct nf_conn *ct; struct nf_conn *ct; enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo; struct nf_nat_ipv4_range newrange; struct nf_nat_range newrange; unsigned int ret; unsigned int ret; if (!nattype_packet_in_match(nte, skb, par->targinfo)) if (!nattype_packet_in_match(nte, skb, par->targinfo)) Loading @@ -304,11 +303,21 @@ static unsigned int nattype_nat(struct sk_buff *skb, return XT_CONTINUE; return XT_CONTINUE; } } /* Expand the ingress conntrack /* netfilter * to include the reply as source * 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", 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; ct->nattype_entry = (unsigned long)nte; ret = nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); ret = nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); DEBUGP("Expand returned: %d\n", ret); DEBUGP("Expand returned: %d\n", ret); Loading @@ -332,12 +341,22 @@ static unsigned int nattype_forward(struct sk_buff *skb, enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo; const struct ipt_nattype_info *info = par->targinfo; const struct ipt_nattype_info *info = par->targinfo; u16 nat_port; u16 nat_port; enum ip_conntrack_dir dir; if (par->hooknum != NF_INET_FORWARD) if (par->hooknum != NF_INET_POST_ROUTING) return XT_CONTINUE; /* 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; return XT_CONTINUE; /* Ingress packet, /* netfilter * refresh the timer if we find an entry. * Ingress packet, refresh the timer if we find an entry. */ */ if (info->mode == MODE_FORWARD_IN) { if (info->mode == MODE_FORWARD_IN) { spin_lock_bh(&nattype_lock); spin_lock_bh(&nattype_lock); Loading @@ -355,7 +374,8 @@ static unsigned int nattype_forward(struct sk_buff *skb, * out and forward fail as though we never * out and forward fail as though we never * found the entry. * found the entry. */ */ if (!nattype_refresh_timer((unsigned long)nte)) if (!nattype_refresh_timer((unsigned long)nte, ct->timeout.expires)) break; break; /* netfilter NATTYPE /* netfilter NATTYPE Loading @@ -372,15 +392,9 @@ static unsigned int nattype_forward(struct sk_buff *skb, return XT_CONTINUE; return XT_CONTINUE; } } /* netfilter NATTYPE dir = CTINFO2DIR(ctinfo); * 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; nat_port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.all; nat_port = ct->tuplehash[!dir].tuple.dst.u.all; /* netfilter NATTYPE /* netfilter NATTYPE * Allocate a new entry * Allocate a new entry Loading @@ -396,20 +410,22 @@ static unsigned int nattype_forward(struct sk_buff *skb, nte->proto = iph->protocol; nte->proto = iph->protocol; nte->nat_port = nat_port; nte->nat_port = nat_port; nte->dest_addr = iph->daddr; nte->dest_addr = iph->daddr; nte->range.min_ip = iph->saddr; nte->range.min_addr.ip = iph->saddr; nte->range.max_ip = nte->range.min_ip; nte->range.max_addr.ip = nte->range.min_addr.ip; /* netfilter NATTYPE /* netfilter NATTYPE * TOOD: Would it be better to get this information from the * TOOD: Would it be better to get this information from the * conntrack instead of the headers. * conntrack instead of the headers. */ */ if (iph->protocol == IPPROTO_TCP) { if (iph->protocol == IPPROTO_TCP) { nte->range.min.tcp.port = ((struct tcphdr *)protoh)->source; nte->range.min_proto.tcp.port = nte->range.max.tcp.port = nte->range.min.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; nte->dest_port = ((struct tcphdr *)protoh)->dest; } else if (iph->protocol == IPPROTO_UDP) { } else if (iph->protocol == IPPROTO_UDP) { nte->range.min.udp.port = ((struct udphdr *)protoh)->source; nte->range.min_proto.udp.port = nte->range.max.udp.port = nte->range.min.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->dest_port = ((struct udphdr *)protoh)->dest; } } nte->range.flags = (NF_NAT_RANGE_MAP_IPS | nte->range.flags = (NF_NAT_RANGE_MAP_IPS | Loading @@ -430,7 +446,7 @@ static unsigned int nattype_forward(struct sk_buff *skb, */ */ spin_lock_bh(&nattype_lock); spin_lock_bh(&nattype_lock); list_for_each_entry(nte2, &nattype_list, list) { list_for_each_entry(nte2, &nattype_list, list) { if (!nattype_compare(nte, nte2)) if (!nattype_compare(nte, nte2, info)) continue; continue; spin_unlock_bh(&nattype_lock); spin_unlock_bh(&nattype_lock); /* netfilter NATTYPE /* netfilter NATTYPE Loading @@ -438,7 +454,9 @@ static unsigned int nattype_forward(struct sk_buff *skb, * entry as this one is timed out and will be removed * entry as this one is timed out and will be removed * from the list shortly. * from the list shortly. */ */ if (!nattype_refresh_timer((unsigned long)nte2)) if (!nattype_refresh_timer( (unsigned long)nte2, jiffies + nte2->timeout_value)) break; break; /* netfilter NATTYPE /* netfilter NATTYPE Loading @@ -455,11 +473,12 @@ static unsigned int nattype_forward(struct sk_buff *skb, /* netfilter NATTYPE /* netfilter NATTYPE * Add the new entry to the list. * 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); add_timer(&nte->timeout); list_add(&nte->list, &nattype_list); list_add(&nte->list, &nattype_list); ct->nattype_entry = (unsigned long)nte; ct->nattype_entry = (unsigned long)nte; nte->is_valid = 1; nte->nattype_cookie = NATTYPE_COOKIE; spin_unlock_bh(&nattype_lock); spin_unlock_bh(&nattype_lock); nattype_nte_debug_print(nte, "ADD"); nattype_nte_debug_print(nte, "ADD"); return XT_CONTINUE; return XT_CONTINUE; Loading Loading @@ -549,7 +568,7 @@ static int nattype_check(const struct xt_tgchk_param *par) types[info->type], modes[info->mode]); types[info->type], modes[info->mode]); if (par->hook_mask & ~((1 << NF_INET_PRE_ROUTING) | if (par->hook_mask & ~((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_FORWARD))) { (1 << NF_INET_POST_ROUTING))) { DEBUGP("nattype_check: bad hooks %x.\n", par->hook_mask); DEBUGP("nattype_check: bad hooks %x.\n", par->hook_mask); return -EINVAL; return -EINVAL; } } Loading Loading @@ -590,7 +609,7 @@ static struct xt_target nattype = { .checkentry = nattype_check, .checkentry = nattype_check, .targetsize = sizeof(struct ipt_nattype_info), .targetsize = sizeof(struct ipt_nattype_info), .hooks = ((1 << NF_INET_PRE_ROUTING) | .hooks = ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_FORWARD)), (1 << NF_INET_POST_ROUTING)), .me = THIS_MODULE, .me = THIS_MODULE, }; }; Loading net/ipv4/netfilter/nf_nat_masquerade_ipv4.c +6 −0 Original line number Original line Diff line number Diff line Loading @@ -68,7 +68,13 @@ nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum, newrange.max_proto = range->max_proto; newrange.max_proto = range->max_proto; /* Hand modified range to generic setup. */ /* Hand modified range to generic setup. */ #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC); return XT_CONTINUE; #else return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC); return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC); #endif } } EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv4); EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv4); Loading net/netfilter/nf_conntrack_core.c +11 −3 Original line number Original line Diff line number Diff line Loading @@ -72,7 +72,10 @@ EXPORT_SYMBOL_GPL(nf_conntrack_expect_lock); struct hlist_nulls_head *nf_conntrack_hash __read_mostly; struct hlist_nulls_head *nf_conntrack_hash __read_mostly; EXPORT_SYMBOL_GPL(nf_conntrack_hash); EXPORT_SYMBOL_GPL(nf_conntrack_hash); bool (*nattype_refresh_timer)(unsigned long nattype) __rcu __read_mostly; bool (*nattype_refresh_timer) (unsigned long nattype, unsigned long timeout_value) __rcu __read_mostly; EXPORT_SYMBOL(nattype_refresh_timer); EXPORT_SYMBOL(nattype_refresh_timer); struct conntrack_gc_work { struct conntrack_gc_work { Loading Loading @@ -1110,6 +1113,9 @@ __nf_conntrack_alloc(struct net *net, nf_ct_zone_add(ct, zone); 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 /* Because we use RCU lookups, we set ct_general.use to zero before * this is inserted in any list. * this is inserted in any list. */ */ Loading Loading @@ -1482,7 +1488,9 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, struct nf_conn_acct *acct; struct nf_conn_acct *acct; u64 pkts; u64 pkts; #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) bool (*nattype_ref_timer)(unsigned long nattype); bool (*nattype_ref_timer) (unsigned long nattype, unsigned long timeout_value); #endif #endif NF_CT_ASSERT(skb); NF_CT_ASSERT(skb); Loading @@ -1500,7 +1508,7 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) nattype_ref_timer = rcu_dereference(nattype_refresh_timer); nattype_ref_timer = rcu_dereference(nattype_refresh_timer); if (nattype_ref_timer) if (nattype_ref_timer) nattype_ref_timer(ct->nattype_entry); nattype_ref_timer(ct->nattype_entry, ct->timeout.expires); #endif #endif acct: acct: Loading net/netfilter/nf_conntrack_netlink.c +11 −0 Original line number Original line Diff line number Diff line Loading @@ -1540,12 +1540,23 @@ static int ctnetlink_change_timeout(struct nf_conn *ct, const struct nlattr * const cda[]) const struct nlattr * const cda[]) { { u_int32_t timeout = ntohl(nla_get_be32(cda[CTA_TIMEOUT])); u_int32_t timeout = ntohl(nla_get_be32(cda[CTA_TIMEOUT])); #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) bool (*nattype_ref_timer) (unsigned long nattype, unsigned long timeout_value); #endif ct->timeout = nfct_time_stamp + timeout * HZ; ct->timeout = nfct_time_stamp + timeout * HZ; if (test_bit(IPS_DYING_BIT, &ct->status)) if (test_bit(IPS_DYING_BIT, &ct->status)) return -ETIME; 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; return 0; } } Loading Loading
include/net/netfilter/nf_conntrack_core.h +3 −1 Original line number Original line Diff line number Diff line Loading @@ -54,7 +54,9 @@ bool nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, const struct nf_conntrack_l3proto *l3proto, const struct nf_conntrack_l3proto *l3proto, const struct nf_conntrack_l4proto *l4proto); const struct nf_conntrack_l4proto *l4proto); extern void (*delete_sfe_entry)(struct nf_conn *ct); extern void (*delete_sfe_entry)(struct nf_conn *ct); extern bool (*nattype_refresh_timer)(unsigned long nattype); extern bool (*nattype_refresh_timer) (unsigned long nattype, unsigned long timeout_value); /* Find a connection corresponding to a tuple. */ /* Find a connection corresponding to a tuple. */ struct nf_conntrack_tuple_hash * struct nf_conntrack_tuple_hash * Loading
net/ipv4/netfilter/ipt_NATTYPE.c +75 −56 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,7 @@ * Ubicom32 implementation derived from * Ubicom32 implementation derived from * Cameo's implementation(with many thanks): * Cameo's implementation(with many thanks): */ */ #include <linux/types.h> #include <linux/types.h> #include <linux/ip.h> #include <linux/ip.h> #include <linux/udp.h> #include <linux/udp.h> Loading @@ -36,21 +37,17 @@ #include <linux/tcp.h> #include <linux/tcp.h> #include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_core.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/x_tables.h> #include <linux/netfilter_ipv4/ipt_NATTYPE.h> #include <linux/netfilter_ipv4/ipt_NATTYPE.h> #include <linux/atomic.h> #include <linux/atomic.h> #if !defined(NATTYPE_DEBUG) #define DEBUGP(type, args...) #else static const char * const types[] = {"TYPE_PORT_ADDRESS_RESTRICTED", static const char * const types[] = {"TYPE_PORT_ADDRESS_RESTRICTED", "TYPE_ENDPOINT_INDEPENDENT", "TYPE_ENDPOINT_INDEPENDENT", "TYPE_ADDRESS_RESTRICTED"}; "TYPE_ADDRESS_RESTRICTED"}; static const char * const modes[] = {"MODE_DNAT", "MODE_FORWARD_IN", static const char * const modes[] = {"MODE_DNAT", "MODE_FORWARD_IN", "MODE_FORWARD_OUT"}; "MODE_FORWARD_OUT"}; #define DEBUGP(args...) pr_debug(args) #define DEBUGP(args...) pr_debug(args) #endif /* netfilter NATTYPE TODO: /* netfilter NATTYPE TODO: * Add magic value checks to data structure. * Add magic value checks to data structure. Loading @@ -58,14 +55,17 @@ static const char * const modes[] = {"MODE_DNAT", "MODE_FORWARD_IN", struct ipt_nattype { struct ipt_nattype { struct list_head list; struct list_head list; struct timer_list timeout; struct timer_list timeout; unsigned char is_valid; unsigned long timeout_value; unsigned int nattype_cookie; unsigned short proto; /* Protocol: TCP or UDP */ 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 short nat_port; /* Routed NAT port */ unsigned int dest_addr; /* Original egress packets dst addr */ unsigned int dest_addr; /* Original egress packets dst addr */ unsigned short dest_port;/* Original egress packets destination port */ unsigned short dest_port;/* Original egress packets destination port */ }; }; #define NATTYPE_COOKIE 0x11abcdef /* TODO: It might be better to use a hash table for performance in /* TODO: It might be better to use a hash table for performance in * heavy traffic. * heavy traffic. */ */ Loading @@ -78,11 +78,13 @@ static DEFINE_SPINLOCK(nattype_lock); static void nattype_nte_debug_print(const struct ipt_nattype *nte, static void nattype_nte_debug_print(const struct ipt_nattype *nte, const char *s) 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, 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), ntohs(nte->nat_port), &nte->dest_addr, ntohs(nte->dest_port)); &nte->dest_addr, ntohs(nte->dest_port)); DEBUGP("Timeout[%lx], Expires[%lx]\n", nte->timeout_value, nte->timeout.expires); } } /* netfilter NATTYPE nattype_free() /* netfilter NATTYPE nattype_free() Loading @@ -90,28 +92,28 @@ static void nattype_nte_debug_print(const struct ipt_nattype *nte, */ */ static void nattype_free(struct ipt_nattype *nte) static void nattype_free(struct ipt_nattype *nte) { { nattype_nte_debug_print(nte, "free"); kfree(nte); kfree(nte); } } /* netfilter NATTYPE nattype_refresh_timer() /* netfilter NATTYPE nattype_refresh_timer() * Refresh the timer for this object. * Refresh the timer for this object. */ */ bool nattype_refresh_timer_impl(unsigned long nat_type) bool nattype_refresh_timer(unsigned long nat_type, unsigned long timeout_value) { { struct ipt_nattype *nte = (struct ipt_nattype *)nat_type; struct ipt_nattype *nte = (struct ipt_nattype *)nat_type; if (!nte) if (!nte) return false; return false; spin_lock_bh(&nattype_lock); spin_lock_bh(&nattype_lock); if (!nte->is_valid) { if (nte->nattype_cookie != NATTYPE_COOKIE) { spin_unlock_bh(&nattype_lock); spin_unlock_bh(&nattype_lock); return false; return false; } } if (del_timer(&nte->timeout)) { if (del_timer(&nte->timeout)) { nte->timeout.expires = jiffies + NATTYPE_TIMEOUT * HZ; nte->timeout.expires = timeout_value; add_timer(&nte->timeout); add_timer(&nte->timeout); spin_unlock_bh(&nattype_lock); spin_unlock_bh(&nattype_lock); nattype_nte_debug_print(nte, "refresh"); return true; return true; } } spin_unlock_bh(&nattype_lock); spin_unlock_bh(&nattype_lock); Loading Loading @@ -213,7 +215,8 @@ static bool nattype_packet_in_match(const struct ipt_nattype *nte, /* netfilter NATTYPE nattype_compare /* netfilter NATTYPE nattype_compare * Compare two entries, return true if relevant fields are the same. * 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 /* netfilter NATTYPE Protocol * compare. * compare. Loading @@ -228,16 +231,16 @@ static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2) * Since we always keep min/max values the same, * Since we always keep min/max values the same, * just compare the min values. * just compare the min values. */ */ if (n1->range.min_ip != n2->range.min_ip) { if (n1->range.min_addr.ip != n2->range.min_addr.ip) { DEBUGP("nattype_compare: r.min_ip mismatch: %pI4:%pI4\n", DEBUGP("nattype_compare: r.min_addr.ip mismatch: %pI4:%pI4\n", &n1->range.min_ip, &n2->range.min_ip); &n1->range.min_addr.ip, &n2->range.min_addr.ip); return false; return false; } } if (n1->range.min.all != n2->range.min.all) { if (n1->range.min_proto.all != n2->range.min_proto.all) { DEBUGP("nattype_compare: r.min mismatch: %d:%d\n", DEBUGP("nattype_compare: r.min mismatch: %d:%d\n", ntohs(n1->range.min.all), ntohs(n1->range.min_proto.all), ntohs(n2->range.min.all)); ntohs(n2->range.min_proto.all)); return false; return false; } } Loading @@ -250,20 +253,16 @@ static bool nattype_compare(struct ipt_nattype *n1, struct ipt_nattype *n2) return false; return false; } } /* netfilter NATTYPE /* netfilter NATTYPE Destination compare * Destination compare * Destination Comapre for Address Restricted Cone NAT. */ */ if (n1->dest_addr != n2->dest_addr) { if ((info->type == TYPE_ADDRESS_RESTRICTED) && (n1->dest_addr != n2->dest_addr)) { DEBUGP("nattype_compare: dest_addr mismatch: %pI4:%pI4\n", DEBUGP("nattype_compare: dest_addr mismatch: %pI4:%pI4\n", &n1->dest_addr, &n2->dest_addr); &n1->dest_addr, &n2->dest_addr); return false; return false; } } if (n1->dest_port != n2->dest_port) { DEBUGP("nattype_compare: dest_port mismatch: %d:%d\n", ntohs(n1->dest_port), ntohs(n2->dest_port)); return false; } return true; return true; } } Loading @@ -283,7 +282,7 @@ static unsigned int nattype_nat(struct sk_buff *skb, list_for_each_entry(nte, &nattype_list, list) { list_for_each_entry(nte, &nattype_list, list) { struct nf_conn *ct; struct nf_conn *ct; enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo; struct nf_nat_ipv4_range newrange; struct nf_nat_range newrange; unsigned int ret; unsigned int ret; if (!nattype_packet_in_match(nte, skb, par->targinfo)) if (!nattype_packet_in_match(nte, skb, par->targinfo)) Loading @@ -304,11 +303,21 @@ static unsigned int nattype_nat(struct sk_buff *skb, return XT_CONTINUE; return XT_CONTINUE; } } /* Expand the ingress conntrack /* netfilter * to include the reply as source * 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", 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; ct->nattype_entry = (unsigned long)nte; ret = nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); ret = nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); DEBUGP("Expand returned: %d\n", ret); DEBUGP("Expand returned: %d\n", ret); Loading @@ -332,12 +341,22 @@ static unsigned int nattype_forward(struct sk_buff *skb, enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo; const struct ipt_nattype_info *info = par->targinfo; const struct ipt_nattype_info *info = par->targinfo; u16 nat_port; u16 nat_port; enum ip_conntrack_dir dir; if (par->hooknum != NF_INET_FORWARD) if (par->hooknum != NF_INET_POST_ROUTING) return XT_CONTINUE; /* 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; return XT_CONTINUE; /* Ingress packet, /* netfilter * refresh the timer if we find an entry. * Ingress packet, refresh the timer if we find an entry. */ */ if (info->mode == MODE_FORWARD_IN) { if (info->mode == MODE_FORWARD_IN) { spin_lock_bh(&nattype_lock); spin_lock_bh(&nattype_lock); Loading @@ -355,7 +374,8 @@ static unsigned int nattype_forward(struct sk_buff *skb, * out and forward fail as though we never * out and forward fail as though we never * found the entry. * found the entry. */ */ if (!nattype_refresh_timer((unsigned long)nte)) if (!nattype_refresh_timer((unsigned long)nte, ct->timeout.expires)) break; break; /* netfilter NATTYPE /* netfilter NATTYPE Loading @@ -372,15 +392,9 @@ static unsigned int nattype_forward(struct sk_buff *skb, return XT_CONTINUE; return XT_CONTINUE; } } /* netfilter NATTYPE dir = CTINFO2DIR(ctinfo); * 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; nat_port = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.all; nat_port = ct->tuplehash[!dir].tuple.dst.u.all; /* netfilter NATTYPE /* netfilter NATTYPE * Allocate a new entry * Allocate a new entry Loading @@ -396,20 +410,22 @@ static unsigned int nattype_forward(struct sk_buff *skb, nte->proto = iph->protocol; nte->proto = iph->protocol; nte->nat_port = nat_port; nte->nat_port = nat_port; nte->dest_addr = iph->daddr; nte->dest_addr = iph->daddr; nte->range.min_ip = iph->saddr; nte->range.min_addr.ip = iph->saddr; nte->range.max_ip = nte->range.min_ip; nte->range.max_addr.ip = nte->range.min_addr.ip; /* netfilter NATTYPE /* netfilter NATTYPE * TOOD: Would it be better to get this information from the * TOOD: Would it be better to get this information from the * conntrack instead of the headers. * conntrack instead of the headers. */ */ if (iph->protocol == IPPROTO_TCP) { if (iph->protocol == IPPROTO_TCP) { nte->range.min.tcp.port = ((struct tcphdr *)protoh)->source; nte->range.min_proto.tcp.port = nte->range.max.tcp.port = nte->range.min.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; nte->dest_port = ((struct tcphdr *)protoh)->dest; } else if (iph->protocol == IPPROTO_UDP) { } else if (iph->protocol == IPPROTO_UDP) { nte->range.min.udp.port = ((struct udphdr *)protoh)->source; nte->range.min_proto.udp.port = nte->range.max.udp.port = nte->range.min.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->dest_port = ((struct udphdr *)protoh)->dest; } } nte->range.flags = (NF_NAT_RANGE_MAP_IPS | nte->range.flags = (NF_NAT_RANGE_MAP_IPS | Loading @@ -430,7 +446,7 @@ static unsigned int nattype_forward(struct sk_buff *skb, */ */ spin_lock_bh(&nattype_lock); spin_lock_bh(&nattype_lock); list_for_each_entry(nte2, &nattype_list, list) { list_for_each_entry(nte2, &nattype_list, list) { if (!nattype_compare(nte, nte2)) if (!nattype_compare(nte, nte2, info)) continue; continue; spin_unlock_bh(&nattype_lock); spin_unlock_bh(&nattype_lock); /* netfilter NATTYPE /* netfilter NATTYPE Loading @@ -438,7 +454,9 @@ static unsigned int nattype_forward(struct sk_buff *skb, * entry as this one is timed out and will be removed * entry as this one is timed out and will be removed * from the list shortly. * from the list shortly. */ */ if (!nattype_refresh_timer((unsigned long)nte2)) if (!nattype_refresh_timer( (unsigned long)nte2, jiffies + nte2->timeout_value)) break; break; /* netfilter NATTYPE /* netfilter NATTYPE Loading @@ -455,11 +473,12 @@ static unsigned int nattype_forward(struct sk_buff *skb, /* netfilter NATTYPE /* netfilter NATTYPE * Add the new entry to the list. * 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); add_timer(&nte->timeout); list_add(&nte->list, &nattype_list); list_add(&nte->list, &nattype_list); ct->nattype_entry = (unsigned long)nte; ct->nattype_entry = (unsigned long)nte; nte->is_valid = 1; nte->nattype_cookie = NATTYPE_COOKIE; spin_unlock_bh(&nattype_lock); spin_unlock_bh(&nattype_lock); nattype_nte_debug_print(nte, "ADD"); nattype_nte_debug_print(nte, "ADD"); return XT_CONTINUE; return XT_CONTINUE; Loading Loading @@ -549,7 +568,7 @@ static int nattype_check(const struct xt_tgchk_param *par) types[info->type], modes[info->mode]); types[info->type], modes[info->mode]); if (par->hook_mask & ~((1 << NF_INET_PRE_ROUTING) | if (par->hook_mask & ~((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_FORWARD))) { (1 << NF_INET_POST_ROUTING))) { DEBUGP("nattype_check: bad hooks %x.\n", par->hook_mask); DEBUGP("nattype_check: bad hooks %x.\n", par->hook_mask); return -EINVAL; return -EINVAL; } } Loading Loading @@ -590,7 +609,7 @@ static struct xt_target nattype = { .checkentry = nattype_check, .checkentry = nattype_check, .targetsize = sizeof(struct ipt_nattype_info), .targetsize = sizeof(struct ipt_nattype_info), .hooks = ((1 << NF_INET_PRE_ROUTING) | .hooks = ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_FORWARD)), (1 << NF_INET_POST_ROUTING)), .me = THIS_MODULE, .me = THIS_MODULE, }; }; Loading
net/ipv4/netfilter/nf_nat_masquerade_ipv4.c +6 −0 Original line number Original line Diff line number Diff line Loading @@ -68,7 +68,13 @@ nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum, newrange.max_proto = range->max_proto; newrange.max_proto = range->max_proto; /* Hand modified range to generic setup. */ /* Hand modified range to generic setup. */ #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC); return XT_CONTINUE; #else return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC); return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC); #endif } } EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv4); EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv4); Loading
net/netfilter/nf_conntrack_core.c +11 −3 Original line number Original line Diff line number Diff line Loading @@ -72,7 +72,10 @@ EXPORT_SYMBOL_GPL(nf_conntrack_expect_lock); struct hlist_nulls_head *nf_conntrack_hash __read_mostly; struct hlist_nulls_head *nf_conntrack_hash __read_mostly; EXPORT_SYMBOL_GPL(nf_conntrack_hash); EXPORT_SYMBOL_GPL(nf_conntrack_hash); bool (*nattype_refresh_timer)(unsigned long nattype) __rcu __read_mostly; bool (*nattype_refresh_timer) (unsigned long nattype, unsigned long timeout_value) __rcu __read_mostly; EXPORT_SYMBOL(nattype_refresh_timer); EXPORT_SYMBOL(nattype_refresh_timer); struct conntrack_gc_work { struct conntrack_gc_work { Loading Loading @@ -1110,6 +1113,9 @@ __nf_conntrack_alloc(struct net *net, nf_ct_zone_add(ct, zone); 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 /* Because we use RCU lookups, we set ct_general.use to zero before * this is inserted in any list. * this is inserted in any list. */ */ Loading Loading @@ -1482,7 +1488,9 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, struct nf_conn_acct *acct; struct nf_conn_acct *acct; u64 pkts; u64 pkts; #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) bool (*nattype_ref_timer)(unsigned long nattype); bool (*nattype_ref_timer) (unsigned long nattype, unsigned long timeout_value); #endif #endif NF_CT_ASSERT(skb); NF_CT_ASSERT(skb); Loading @@ -1500,7 +1508,7 @@ void __nf_ct_refresh_acct(struct nf_conn *ct, #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) nattype_ref_timer = rcu_dereference(nattype_refresh_timer); nattype_ref_timer = rcu_dereference(nattype_refresh_timer); if (nattype_ref_timer) if (nattype_ref_timer) nattype_ref_timer(ct->nattype_entry); nattype_ref_timer(ct->nattype_entry, ct->timeout.expires); #endif #endif acct: acct: Loading
net/netfilter/nf_conntrack_netlink.c +11 −0 Original line number Original line Diff line number Diff line Loading @@ -1540,12 +1540,23 @@ static int ctnetlink_change_timeout(struct nf_conn *ct, const struct nlattr * const cda[]) const struct nlattr * const cda[]) { { u_int32_t timeout = ntohl(nla_get_be32(cda[CTA_TIMEOUT])); u_int32_t timeout = ntohl(nla_get_be32(cda[CTA_TIMEOUT])); #if defined(CONFIG_IP_NF_TARGET_NATTYPE_MODULE) bool (*nattype_ref_timer) (unsigned long nattype, unsigned long timeout_value); #endif ct->timeout = nfct_time_stamp + timeout * HZ; ct->timeout = nfct_time_stamp + timeout * HZ; if (test_bit(IPS_DYING_BIT, &ct->status)) if (test_bit(IPS_DYING_BIT, &ct->status)) return -ETIME; 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; return 0; } } Loading