Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 188bab3a authored by Harald Welte's avatar Harald Welte Committed by David S. Miller
Browse files

[NETFILTER]: Fix invalid module autoloading by splitting iptable_nat



When you've enabled conntrack and NAT as a module (standard case in all
distributions), and you've also enabled the new conntrack netlink
interface, loading ip_conntrack_netlink.ko will auto-load iptable_nat.ko.
This causes a huge performance penalty, since for every packet you iterate
the nat code, even if you don't want it.

This patch splits iptable_nat.ko into the NAT core (ip_nat.ko) and the
iptables frontend (iptable_nat.ko).  Threfore, ip_conntrack_netlink.ko will
only pull ip_nat.ko, but not the frontend.  ip_nat.ko will "only" allocate
some resources, but not affect runtime performance.

This separation is also a nice step in anticipation of new packet filters
(nf-hipac, ipset, pkttables) being able to use the NAT core.

Signed-off-by: default avatarHarald Welte <laforge@netfilter.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b85daee0
Loading
Loading
Loading
Loading
+5 −7
Original line number Original line Diff line number Diff line
@@ -5,15 +5,13 @@


/* This header used to share core functionality between the standalone
/* This header used to share core functionality between the standalone
   NAT module, and the compatibility layer's use of NAT for masquerading. */
   NAT module, and the compatibility layer's use of NAT for masquerading. */
extern int ip_nat_init(void);
extern void ip_nat_cleanup(void);


extern unsigned int nat_packet(struct ip_conntrack *ct,
extern unsigned int ip_nat_packet(struct ip_conntrack *ct,
			       enum ip_conntrack_info conntrackinfo,
			       enum ip_conntrack_info conntrackinfo,
			       unsigned int hooknum,
			       unsigned int hooknum,
			       struct sk_buff **pskb);
			       struct sk_buff **pskb);


extern int icmp_reply_translation(struct sk_buff **pskb,
extern int ip_nat_icmp_reply_translation(struct sk_buff **pskb,
					 struct ip_conntrack *ct,
					 struct ip_conntrack *ct,
					 enum ip_nat_manip_type manip,
					 enum ip_nat_manip_type manip,
					 enum ip_conntrack_dir dir);
					 enum ip_conntrack_dir dir);
+3 −2
Original line number Original line Diff line number Diff line
@@ -4,7 +4,8 @@


# objects for the standalone - connection tracking / NAT
# objects for the standalone - connection tracking / NAT
ip_conntrack-objs	:= ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o
ip_conntrack-objs	:= ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o
iptable_nat-objs	:= ip_nat_standalone.o ip_nat_rule.o ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o
ip_nat-objs	:= ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o
iptable_nat-objs	:= ip_nat_rule.o ip_nat_standalone.o


ip_conntrack_pptp-objs	:= ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o
ip_conntrack_pptp-objs	:= ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o
ip_nat_pptp-objs	:= ip_nat_helper_pptp.o ip_nat_proto_gre.o
ip_nat_pptp-objs	:= ip_nat_helper_pptp.o ip_nat_proto_gre.o
@@ -40,7 +41,7 @@ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
# the three instances of ip_tables
# the three instances of ip_tables
obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o ip_nat.o
obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o


# matches
# matches
+24 −11
Original line number Original line Diff line number Diff line
@@ -74,12 +74,14 @@ ip_nat_proto_find_get(u_int8_t protonum)


	return p;
	return p;
}
}
EXPORT_SYMBOL_GPL(ip_nat_proto_find_get);


void
void
ip_nat_proto_put(struct ip_nat_protocol *p)
ip_nat_proto_put(struct ip_nat_protocol *p)
{
{
	module_put(p->me);
	module_put(p->me);
}
}
EXPORT_SYMBOL_GPL(ip_nat_proto_put);


/* We keep an extra hash for each conntrack, for fast searching. */
/* We keep an extra hash for each conntrack, for fast searching. */
static inline unsigned int
static inline unsigned int
@@ -111,6 +113,7 @@ ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
	return csum_fold(csum_partial((char *)diffs, sizeof(diffs),
	return csum_fold(csum_partial((char *)diffs, sizeof(diffs),
				      oldcheck^0xFFFF));
				      oldcheck^0xFFFF));
}
}
EXPORT_SYMBOL(ip_nat_cheat_check);


/* Is this tuple already taken? (not by us) */
/* Is this tuple already taken? (not by us) */
int
int
@@ -127,6 +130,7 @@ ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
	invert_tuplepr(&reply, tuple);
	invert_tuplepr(&reply, tuple);
	return ip_conntrack_tuple_taken(&reply, ignored_conntrack);
	return ip_conntrack_tuple_taken(&reply, ignored_conntrack);
}
}
EXPORT_SYMBOL(ip_nat_used_tuple);


/* If we source map this tuple so reply looks like reply_tuple, will
/* If we source map this tuple so reply looks like reply_tuple, will
 * that meet the constraints of range. */
 * that meet the constraints of range. */
@@ -347,6 +351,7 @@ ip_nat_setup_info(struct ip_conntrack *conntrack,


	return NF_ACCEPT;
	return NF_ACCEPT;
}
}
EXPORT_SYMBOL(ip_nat_setup_info);


/* Returns true if succeeded. */
/* Returns true if succeeded. */
static int
static int
@@ -387,7 +392,7 @@ manip_pkt(u_int16_t proto,
}
}


/* Do packet manipulations according to ip_nat_setup_info. */
/* Do packet manipulations according to ip_nat_setup_info. */
unsigned int nat_packet(struct ip_conntrack *ct,
unsigned int ip_nat_packet(struct ip_conntrack *ct,
			   enum ip_conntrack_info ctinfo,
			   enum ip_conntrack_info ctinfo,
			   unsigned int hooknum,
			   unsigned int hooknum,
			   struct sk_buff **pskb)
			   struct sk_buff **pskb)
@@ -417,9 +422,10 @@ unsigned int nat_packet(struct ip_conntrack *ct,
	}
	}
	return NF_ACCEPT;
	return NF_ACCEPT;
}
}
EXPORT_SYMBOL_GPL(ip_nat_packet);


/* Dir is direction ICMP is coming from (opposite to packet it contains) */
/* Dir is direction ICMP is coming from (opposite to packet it contains) */
int icmp_reply_translation(struct sk_buff **pskb,
int ip_nat_icmp_reply_translation(struct sk_buff **pskb,
				  struct ip_conntrack *ct,
				  struct ip_conntrack *ct,
				  enum ip_nat_manip_type manip,
				  enum ip_nat_manip_type manip,
				  enum ip_conntrack_dir dir)
				  enum ip_conntrack_dir dir)
@@ -509,6 +515,7 @@ int icmp_reply_translation(struct sk_buff **pskb,


	return 1;
	return 1;
}
}
EXPORT_SYMBOL_GPL(ip_nat_icmp_reply_translation);


/* Protocol registration. */
/* Protocol registration. */
int ip_nat_protocol_register(struct ip_nat_protocol *proto)
int ip_nat_protocol_register(struct ip_nat_protocol *proto)
@@ -525,6 +532,7 @@ int ip_nat_protocol_register(struct ip_nat_protocol *proto)
	write_unlock_bh(&ip_nat_lock);
	write_unlock_bh(&ip_nat_lock);
	return ret;
	return ret;
}
}
EXPORT_SYMBOL(ip_nat_protocol_register);


/* Noone stores the protocol anywhere; simply delete it. */
/* Noone stores the protocol anywhere; simply delete it. */
void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
@@ -536,6 +544,7 @@ void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
	/* Someone could be still looking at the proto in a bh. */
	/* Someone could be still looking at the proto in a bh. */
	synchronize_net();
	synchronize_net();
}
}
EXPORT_SYMBOL(ip_nat_protocol_unregister);


#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
    defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
    defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
@@ -582,7 +591,7 @@ EXPORT_SYMBOL_GPL(ip_nat_port_nfattr_to_range);
EXPORT_SYMBOL_GPL(ip_nat_port_range_to_nfattr);
EXPORT_SYMBOL_GPL(ip_nat_port_range_to_nfattr);
#endif
#endif


int __init ip_nat_init(void)
static int __init ip_nat_init(void)
{
{
	size_t i;
	size_t i;


@@ -624,10 +633,14 @@ static int clean_nat(struct ip_conntrack *i, void *data)
	return 0;
	return 0;
}
}


/* Not __exit: called from ip_nat_standalone.c:init_or_cleanup() --RR */
static void __exit ip_nat_cleanup(void)
void ip_nat_cleanup(void)
{
{
	ip_ct_iterate_cleanup(&clean_nat, NULL);
	ip_ct_iterate_cleanup(&clean_nat, NULL);
	ip_conntrack_destroyed = NULL;
	ip_conntrack_destroyed = NULL;
	vfree(bysource);
	vfree(bysource);
}
}

MODULE_LICENSE("GPL");

module_init(ip_nat_init);
module_exit(ip_nat_cleanup);
+4 −0
Original line number Original line Diff line number Diff line
@@ -199,6 +199,7 @@ ip_nat_mangle_tcp_packet(struct sk_buff **pskb,
	}
	}
	return 1;
	return 1;
}
}
EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);
			
			
/* Generic function for mangling variable-length address changes inside
/* Generic function for mangling variable-length address changes inside
 * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
 * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
@@ -256,6 +257,7 @@ ip_nat_mangle_udp_packet(struct sk_buff **pskb,


	return 1;
	return 1;
}
}
EXPORT_SYMBOL(ip_nat_mangle_udp_packet);


/* Adjust one found SACK option including checksum correction */
/* Adjust one found SACK option including checksum correction */
static void
static void
@@ -399,6 +401,7 @@ ip_nat_seq_adjust(struct sk_buff **pskb,


	return 1;
	return 1;
}
}
EXPORT_SYMBOL(ip_nat_seq_adjust);


/* Setup NAT on this expected conntrack so it follows master. */
/* Setup NAT on this expected conntrack so it follows master. */
/* If we fail to get a free NAT slot, we'll get dropped on confirm */
/* If we fail to get a free NAT slot, we'll get dropped on confirm */
@@ -425,3 +428,4 @@ void ip_nat_follow_master(struct ip_conntrack *ct,
	/* hook doesn't matter, but it has to do destination manip */
	/* hook doesn't matter, but it has to do destination manip */
	ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
	ip_nat_setup_info(ct, &range, NF_IP_PRE_ROUTING);
}
}
EXPORT_SYMBOL(ip_nat_follow_master);
+4 −21
Original line number Original line Diff line number Diff line
@@ -108,7 +108,7 @@ ip_nat_fn(unsigned int hooknum,
	case IP_CT_RELATED:
	case IP_CT_RELATED:
	case IP_CT_RELATED+IP_CT_IS_REPLY:
	case IP_CT_RELATED+IP_CT_IS_REPLY:
		if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
		if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP) {
			if (!icmp_reply_translation(pskb, ct, maniptype,
			if (!ip_nat_icmp_reply_translation(pskb, ct, maniptype,
							   CTINFO2DIR(ctinfo)))
							   CTINFO2DIR(ctinfo)))
				return NF_DROP;
				return NF_DROP;
			else
			else
@@ -152,7 +152,7 @@ ip_nat_fn(unsigned int hooknum,
	}
	}


	IP_NF_ASSERT(info);
	IP_NF_ASSERT(info);
	return nat_packet(ct, ctinfo, hooknum, pskb);
	return ip_nat_packet(ct, ctinfo, hooknum, pskb);
}
}


static unsigned int
static unsigned int
@@ -325,15 +325,10 @@ static int init_or_cleanup(int init)
		printk("ip_nat_init: can't setup rules.\n");
		printk("ip_nat_init: can't setup rules.\n");
		goto cleanup_nothing;
		goto cleanup_nothing;
	}
	}
	ret = ip_nat_init();
	if (ret < 0) {
		printk("ip_nat_init: can't setup rules.\n");
		goto cleanup_rule_init;
	}
	ret = nf_register_hook(&ip_nat_in_ops);
	ret = nf_register_hook(&ip_nat_in_ops);
	if (ret < 0) {
	if (ret < 0) {
		printk("ip_nat_init: can't register in hook.\n");
		printk("ip_nat_init: can't register in hook.\n");
		goto cleanup_nat;
		goto cleanup_rule_init;
	}
	}
	ret = nf_register_hook(&ip_nat_out_ops);
	ret = nf_register_hook(&ip_nat_out_ops);
	if (ret < 0) {
	if (ret < 0) {
@@ -374,8 +369,6 @@ static int init_or_cleanup(int init)
	nf_unregister_hook(&ip_nat_out_ops);
	nf_unregister_hook(&ip_nat_out_ops);
 cleanup_inops:
 cleanup_inops:
	nf_unregister_hook(&ip_nat_in_ops);
	nf_unregister_hook(&ip_nat_in_ops);
 cleanup_nat:
	ip_nat_cleanup();
 cleanup_rule_init:
 cleanup_rule_init:
	ip_nat_rule_cleanup();
	ip_nat_rule_cleanup();
 cleanup_nothing:
 cleanup_nothing:
@@ -395,14 +388,4 @@ static void __exit fini(void)
module_init(init);
module_init(init);
module_exit(fini);
module_exit(fini);


EXPORT_SYMBOL(ip_nat_setup_info);
EXPORT_SYMBOL(ip_nat_protocol_register);
EXPORT_SYMBOL(ip_nat_protocol_unregister);
EXPORT_SYMBOL_GPL(ip_nat_proto_find_get);
EXPORT_SYMBOL_GPL(ip_nat_proto_put);
EXPORT_SYMBOL(ip_nat_cheat_check);
EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);
EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
EXPORT_SYMBOL(ip_nat_used_tuple);
EXPORT_SYMBOL(ip_nat_follow_master);
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL");