autoload nf_nat_proto_{dccp,sctp,udplite}.ko on invocation of checkentry() callback, if rule matches DCCP, SCTP or UDPLITE protocols. This avoids situations where, after a SNAT/DNAT rule with specified sport/dport is created, no port translation is done unless the user manually loads nf_nat_proto_{dccp,udplite,sctp}.ko with insmod/modprobe commands. Suggested-by: Florian Westphal <fw@xxxxxxxxx> Signed-off-by: Davide Caratti <dcaratti@xxxxxxxxxx> --- net/netfilter/xt_nat.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/net/netfilter/xt_nat.c b/net/netfilter/xt_nat.c index bea7464..b78023d 100644 --- a/net/netfilter/xt_nat.c +++ b/net/netfilter/xt_nat.c @@ -13,6 +13,44 @@ #include <linux/netfilter.h> #include <linux/netfilter/x_tables.h> #include <net/netfilter/nf_nat_core.h> +#include <net/netfilter/nf_nat_l4proto.h> +#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter_ipv6/ip6_tables.h> + +static void xt_nat_probe_proto(const struct xt_tgchk_param *par) +{ + const struct ip6t_ip6 *i6; + const struct ipt_ip *i; + u8 proto, l4proto; + + switch (par->family) { + case NFPROTO_IPV4: + i = (const struct ipt_ip *)par->entryinfo; + if (i->invflags & IPT_INV_PROTO) + return; + proto = i->proto; + break; + case NFPROTO_IPV6: + i6 = (const struct ip6t_ip6 *)par->entryinfo; + if (i6->invflags & IP6T_INV_PROTO) + return; + proto = i6->proto; + break; + default: + return; + } + + switch (proto) { + case IPPROTO_UDPLITE: + case IPPROTO_SCTP: + case IPPROTO_DCCP: + rcu_read_lock(); + l4proto = __nf_nat_l4proto_find(par->family, proto)->l4proto; + rcu_read_unlock(); + if (!l4proto) + request_module("nf-nat-l4-%u", proto); + } +} static int xt_nat_checkentry_v0(const struct xt_tgchk_param *par) { @@ -23,6 +61,13 @@ static int xt_nat_checkentry_v0(const struct xt_tgchk_param *par) par->target->name); return -EINVAL; } + xt_nat_probe_proto(par); + return 0; +} + +static int xt_nat_checkentry_v1(const struct xt_tgchk_param *par) +{ + xt_nat_probe_proto(par); return 0; } @@ -129,6 +174,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { { .name = "SNAT", .revision = 1, + .checkentry = xt_nat_checkentry_v1, .target = xt_snat_target_v1, .targetsize = sizeof(struct nf_nat_range), .table = "nat", @@ -139,6 +185,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = { { .name = "DNAT", .revision = 1, + .checkentry = xt_nat_checkentry_v1, .target = xt_dnat_target_v1, .targetsize = sizeof(struct nf_nat_range), .table = "nat", -- 2.5.5 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html