Commit 9a3cd877 authored by Paolo Abeni's avatar Paolo Abeni

Merge tag 'nf-24-10-09' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf

Pablo Neira Ayuso says:

====================
Netfilter fixes for net

The following patchset contains Netfilter fixes for net:

1) Restrict xtables extensions to families that are safe, syzbot found
   a way to combine ebtables with extensions that are never used by
   userspace tools. From Florian Westphal.

2) Set l3mdev inconditionally whenever possible in nft_fib to fix lookup
   mismatch, also from Florian.

netfilter pull request 24-10-09

* tag 'nf-24-10-09' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf:
  selftests: netfilter: conntrack_vrf.sh: add fib test case
  netfilter: fib: check correct rtable in vrf setups
  netfilter: xtables: avoid NFPROTO_UNSPEC where needed
====================

Link: https://patch.msgid.link/20241009213858.3565808-1-pablo@netfilter.orgSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents ac888d58 c6a0862b
...@@ -65,6 +65,7 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs, ...@@ -65,6 +65,7 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
.flowi4_scope = RT_SCOPE_UNIVERSE, .flowi4_scope = RT_SCOPE_UNIVERSE,
.flowi4_iif = LOOPBACK_IFINDEX, .flowi4_iif = LOOPBACK_IFINDEX,
.flowi4_uid = sock_net_uid(nft_net(pkt), NULL), .flowi4_uid = sock_net_uid(nft_net(pkt), NULL),
.flowi4_l3mdev = l3mdev_master_ifindex_rcu(nft_in(pkt)),
}; };
const struct net_device *oif; const struct net_device *oif;
const struct net_device *found; const struct net_device *found;
...@@ -83,9 +84,6 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs, ...@@ -83,9 +84,6 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
else else
oif = NULL; oif = NULL;
if (priv->flags & NFTA_FIB_F_IIF)
fl4.flowi4_l3mdev = l3mdev_master_ifindex_rcu(oif);
if (nft_hook(pkt) == NF_INET_PRE_ROUTING && if (nft_hook(pkt) == NF_INET_PRE_ROUTING &&
nft_fib_is_loopback(pkt->skb, nft_in(pkt))) { nft_fib_is_loopback(pkt->skb, nft_in(pkt))) {
nft_fib_store_result(dest, priv, nft_in(pkt)); nft_fib_store_result(dest, priv, nft_in(pkt));
......
...@@ -41,8 +41,6 @@ static int nft_fib6_flowi_init(struct flowi6 *fl6, const struct nft_fib *priv, ...@@ -41,8 +41,6 @@ static int nft_fib6_flowi_init(struct flowi6 *fl6, const struct nft_fib *priv,
if (ipv6_addr_type(&fl6->daddr) & IPV6_ADDR_LINKLOCAL) { if (ipv6_addr_type(&fl6->daddr) & IPV6_ADDR_LINKLOCAL) {
lookup_flags |= RT6_LOOKUP_F_IFACE; lookup_flags |= RT6_LOOKUP_F_IFACE;
fl6->flowi6_oif = get_ifindex(dev ? dev : pkt->skb->dev); fl6->flowi6_oif = get_ifindex(dev ? dev : pkt->skb->dev);
} else if (priv->flags & NFTA_FIB_F_IIF) {
fl6->flowi6_l3mdev = l3mdev_master_ifindex_rcu(dev);
} }
if (ipv6_addr_type(&fl6->saddr) & IPV6_ADDR_UNICAST) if (ipv6_addr_type(&fl6->saddr) & IPV6_ADDR_UNICAST)
...@@ -75,6 +73,8 @@ static u32 __nft_fib6_eval_type(const struct nft_fib *priv, ...@@ -75,6 +73,8 @@ static u32 __nft_fib6_eval_type(const struct nft_fib *priv,
else if (priv->flags & NFTA_FIB_F_OIF) else if (priv->flags & NFTA_FIB_F_OIF)
dev = nft_out(pkt); dev = nft_out(pkt);
fl6.flowi6_l3mdev = l3mdev_master_ifindex_rcu(dev);
nft_fib6_flowi_init(&fl6, priv, pkt, dev, iph); nft_fib6_flowi_init(&fl6, priv, pkt, dev, iph);
if (dev && nf_ipv6_chk_addr(nft_net(pkt), &fl6.daddr, dev, true)) if (dev && nf_ipv6_chk_addr(nft_net(pkt), &fl6.daddr, dev, true))
...@@ -165,6 +165,7 @@ void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs, ...@@ -165,6 +165,7 @@ void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,
.flowi6_iif = LOOPBACK_IFINDEX, .flowi6_iif = LOOPBACK_IFINDEX,
.flowi6_proto = pkt->tprot, .flowi6_proto = pkt->tprot,
.flowi6_uid = sock_net_uid(nft_net(pkt), NULL), .flowi6_uid = sock_net_uid(nft_net(pkt), NULL),
.flowi6_l3mdev = l3mdev_master_ifindex_rcu(nft_in(pkt)),
}; };
struct rt6_info *rt; struct rt6_info *rt;
int lookup_flags; int lookup_flags;
......
...@@ -63,24 +63,37 @@ static int checksum_tg_check(const struct xt_tgchk_param *par) ...@@ -63,24 +63,37 @@ static int checksum_tg_check(const struct xt_tgchk_param *par)
return 0; return 0;
} }
static struct xt_target checksum_tg_reg __read_mostly = { static struct xt_target checksum_tg_reg[] __read_mostly = {
.name = "CHECKSUM", {
.family = NFPROTO_UNSPEC, .name = "CHECKSUM",
.target = checksum_tg, .family = NFPROTO_IPV4,
.targetsize = sizeof(struct xt_CHECKSUM_info), .target = checksum_tg,
.table = "mangle", .targetsize = sizeof(struct xt_CHECKSUM_info),
.checkentry = checksum_tg_check, .table = "mangle",
.me = THIS_MODULE, .checkentry = checksum_tg_check,
.me = THIS_MODULE,
},
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
{
.name = "CHECKSUM",
.family = NFPROTO_IPV6,
.target = checksum_tg,
.targetsize = sizeof(struct xt_CHECKSUM_info),
.table = "mangle",
.checkentry = checksum_tg_check,
.me = THIS_MODULE,
},
#endif
}; };
static int __init checksum_tg_init(void) static int __init checksum_tg_init(void)
{ {
return xt_register_target(&checksum_tg_reg); return xt_register_targets(checksum_tg_reg, ARRAY_SIZE(checksum_tg_reg));
} }
static void __exit checksum_tg_exit(void) static void __exit checksum_tg_exit(void)
{ {
xt_unregister_target(&checksum_tg_reg); xt_unregister_targets(checksum_tg_reg, ARRAY_SIZE(checksum_tg_reg));
} }
module_init(checksum_tg_init); module_init(checksum_tg_init);
......
...@@ -38,9 +38,9 @@ static struct xt_target classify_tg_reg[] __read_mostly = { ...@@ -38,9 +38,9 @@ static struct xt_target classify_tg_reg[] __read_mostly = {
{ {
.name = "CLASSIFY", .name = "CLASSIFY",
.revision = 0, .revision = 0,
.family = NFPROTO_UNSPEC, .family = NFPROTO_IPV4,
.hooks = (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_FORWARD) | .hooks = (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_FORWARD) |
(1 << NF_INET_POST_ROUTING), (1 << NF_INET_POST_ROUTING),
.target = classify_tg, .target = classify_tg,
.targetsize = sizeof(struct xt_classify_target_info), .targetsize = sizeof(struct xt_classify_target_info),
.me = THIS_MODULE, .me = THIS_MODULE,
...@@ -54,6 +54,18 @@ static struct xt_target classify_tg_reg[] __read_mostly = { ...@@ -54,6 +54,18 @@ static struct xt_target classify_tg_reg[] __read_mostly = {
.targetsize = sizeof(struct xt_classify_target_info), .targetsize = sizeof(struct xt_classify_target_info),
.me = THIS_MODULE, .me = THIS_MODULE,
}, },
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
{
.name = "CLASSIFY",
.revision = 0,
.family = NFPROTO_IPV6,
.hooks = (1 << NF_INET_LOCAL_OUT) | (1 << NF_INET_FORWARD) |
(1 << NF_INET_POST_ROUTING),
.target = classify_tg,
.targetsize = sizeof(struct xt_classify_target_info),
.me = THIS_MODULE,
},
#endif
}; };
static int __init classify_tg_init(void) static int __init classify_tg_init(void)
......
...@@ -114,25 +114,39 @@ static void connsecmark_tg_destroy(const struct xt_tgdtor_param *par) ...@@ -114,25 +114,39 @@ static void connsecmark_tg_destroy(const struct xt_tgdtor_param *par)
nf_ct_netns_put(par->net, par->family); nf_ct_netns_put(par->net, par->family);
} }
static struct xt_target connsecmark_tg_reg __read_mostly = { static struct xt_target connsecmark_tg_reg[] __read_mostly = {
.name = "CONNSECMARK", {
.revision = 0, .name = "CONNSECMARK",
.family = NFPROTO_UNSPEC, .revision = 0,
.checkentry = connsecmark_tg_check, .family = NFPROTO_IPV4,
.destroy = connsecmark_tg_destroy, .checkentry = connsecmark_tg_check,
.target = connsecmark_tg, .destroy = connsecmark_tg_destroy,
.targetsize = sizeof(struct xt_connsecmark_target_info), .target = connsecmark_tg,
.me = THIS_MODULE, .targetsize = sizeof(struct xt_connsecmark_target_info),
.me = THIS_MODULE,
},
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
{
.name = "CONNSECMARK",
.revision = 0,
.family = NFPROTO_IPV6,
.checkentry = connsecmark_tg_check,
.destroy = connsecmark_tg_destroy,
.target = connsecmark_tg,
.targetsize = sizeof(struct xt_connsecmark_target_info),
.me = THIS_MODULE,
},
#endif
}; };
static int __init connsecmark_tg_init(void) static int __init connsecmark_tg_init(void)
{ {
return xt_register_target(&connsecmark_tg_reg); return xt_register_targets(connsecmark_tg_reg, ARRAY_SIZE(connsecmark_tg_reg));
} }
static void __exit connsecmark_tg_exit(void) static void __exit connsecmark_tg_exit(void)
{ {
xt_unregister_target(&connsecmark_tg_reg); xt_unregister_targets(connsecmark_tg_reg, ARRAY_SIZE(connsecmark_tg_reg));
} }
module_init(connsecmark_tg_init); module_init(connsecmark_tg_init);
......
...@@ -313,10 +313,30 @@ static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) ...@@ -313,10 +313,30 @@ static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par)
xt_ct_tg_destroy(par, par->targinfo); xt_ct_tg_destroy(par, par->targinfo);
} }
static unsigned int
notrack_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
/* Previously seen (loopback)? Ignore. */
if (skb->_nfct != 0)
return XT_CONTINUE;
nf_ct_set(skb, NULL, IP_CT_UNTRACKED);
return XT_CONTINUE;
}
static struct xt_target xt_ct_tg_reg[] __read_mostly = { static struct xt_target xt_ct_tg_reg[] __read_mostly = {
{
.name = "NOTRACK",
.revision = 0,
.family = NFPROTO_IPV4,
.target = notrack_tg,
.table = "raw",
.me = THIS_MODULE,
},
{ {
.name = "CT", .name = "CT",
.family = NFPROTO_UNSPEC, .family = NFPROTO_IPV4,
.targetsize = sizeof(struct xt_ct_target_info), .targetsize = sizeof(struct xt_ct_target_info),
.usersize = offsetof(struct xt_ct_target_info, ct), .usersize = offsetof(struct xt_ct_target_info, ct),
.checkentry = xt_ct_tg_check_v0, .checkentry = xt_ct_tg_check_v0,
...@@ -327,7 +347,7 @@ static struct xt_target xt_ct_tg_reg[] __read_mostly = { ...@@ -327,7 +347,7 @@ static struct xt_target xt_ct_tg_reg[] __read_mostly = {
}, },
{ {
.name = "CT", .name = "CT",
.family = NFPROTO_UNSPEC, .family = NFPROTO_IPV4,
.revision = 1, .revision = 1,
.targetsize = sizeof(struct xt_ct_target_info_v1), .targetsize = sizeof(struct xt_ct_target_info_v1),
.usersize = offsetof(struct xt_ct_target_info, ct), .usersize = offsetof(struct xt_ct_target_info, ct),
...@@ -339,7 +359,7 @@ static struct xt_target xt_ct_tg_reg[] __read_mostly = { ...@@ -339,7 +359,7 @@ static struct xt_target xt_ct_tg_reg[] __read_mostly = {
}, },
{ {
.name = "CT", .name = "CT",
.family = NFPROTO_UNSPEC, .family = NFPROTO_IPV4,
.revision = 2, .revision = 2,
.targetsize = sizeof(struct xt_ct_target_info_v1), .targetsize = sizeof(struct xt_ct_target_info_v1),
.usersize = offsetof(struct xt_ct_target_info, ct), .usersize = offsetof(struct xt_ct_target_info, ct),
...@@ -349,49 +369,61 @@ static struct xt_target xt_ct_tg_reg[] __read_mostly = { ...@@ -349,49 +369,61 @@ static struct xt_target xt_ct_tg_reg[] __read_mostly = {
.table = "raw", .table = "raw",
.me = THIS_MODULE, .me = THIS_MODULE,
}, },
}; #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
{
static unsigned int .name = "NOTRACK",
notrack_tg(struct sk_buff *skb, const struct xt_action_param *par) .revision = 0,
{ .family = NFPROTO_IPV6,
/* Previously seen (loopback)? Ignore. */ .target = notrack_tg,
if (skb->_nfct != 0) .table = "raw",
return XT_CONTINUE; .me = THIS_MODULE,
},
nf_ct_set(skb, NULL, IP_CT_UNTRACKED); {
.name = "CT",
return XT_CONTINUE; .family = NFPROTO_IPV6,
} .targetsize = sizeof(struct xt_ct_target_info),
.usersize = offsetof(struct xt_ct_target_info, ct),
static struct xt_target notrack_tg_reg __read_mostly = { .checkentry = xt_ct_tg_check_v0,
.name = "NOTRACK", .destroy = xt_ct_tg_destroy_v0,
.revision = 0, .target = xt_ct_target_v0,
.family = NFPROTO_UNSPEC, .table = "raw",
.target = notrack_tg, .me = THIS_MODULE,
.table = "raw", },
.me = THIS_MODULE, {
.name = "CT",
.family = NFPROTO_IPV6,
.revision = 1,
.targetsize = sizeof(struct xt_ct_target_info_v1),
.usersize = offsetof(struct xt_ct_target_info, ct),
.checkentry = xt_ct_tg_check_v1,
.destroy = xt_ct_tg_destroy_v1,
.target = xt_ct_target_v1,
.table = "raw",
.me = THIS_MODULE,
},
{
.name = "CT",
.family = NFPROTO_IPV6,
.revision = 2,
.targetsize = sizeof(struct xt_ct_target_info_v1),
.usersize = offsetof(struct xt_ct_target_info, ct),
.checkentry = xt_ct_tg_check_v2,
.destroy = xt_ct_tg_destroy_v1,
.target = xt_ct_target_v1,
.table = "raw",
.me = THIS_MODULE,
},
#endif
}; };
static int __init xt_ct_tg_init(void) static int __init xt_ct_tg_init(void)
{ {
int ret; return xt_register_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
ret = xt_register_target(&notrack_tg_reg);
if (ret < 0)
return ret;
ret = xt_register_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
if (ret < 0) {
xt_unregister_target(&notrack_tg_reg);
return ret;
}
return 0;
} }
static void __exit xt_ct_tg_exit(void) static void __exit xt_ct_tg_exit(void)
{ {
xt_unregister_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg)); xt_unregister_targets(xt_ct_tg_reg, ARRAY_SIZE(xt_ct_tg_reg));
xt_unregister_target(&notrack_tg_reg);
} }
module_init(xt_ct_tg_init); module_init(xt_ct_tg_init);
......
...@@ -458,28 +458,49 @@ static void idletimer_tg_destroy_v1(const struct xt_tgdtor_param *par) ...@@ -458,28 +458,49 @@ static void idletimer_tg_destroy_v1(const struct xt_tgdtor_param *par)
static struct xt_target idletimer_tg[] __read_mostly = { static struct xt_target idletimer_tg[] __read_mostly = {
{ {
.name = "IDLETIMER", .name = "IDLETIMER",
.family = NFPROTO_UNSPEC, .family = NFPROTO_IPV4,
.target = idletimer_tg_target, .target = idletimer_tg_target,
.targetsize = sizeof(struct idletimer_tg_info), .targetsize = sizeof(struct idletimer_tg_info),
.usersize = offsetof(struct idletimer_tg_info, timer), .usersize = offsetof(struct idletimer_tg_info, timer),
.checkentry = idletimer_tg_checkentry, .checkentry = idletimer_tg_checkentry,
.destroy = idletimer_tg_destroy, .destroy = idletimer_tg_destroy,
.me = THIS_MODULE, .me = THIS_MODULE,
}, },
{ {
.name = "IDLETIMER", .name = "IDLETIMER",
.family = NFPROTO_UNSPEC, .family = NFPROTO_IPV4,
.revision = 1, .revision = 1,
.target = idletimer_tg_target_v1, .target = idletimer_tg_target_v1,
.targetsize = sizeof(struct idletimer_tg_info_v1), .targetsize = sizeof(struct idletimer_tg_info_v1),
.usersize = offsetof(struct idletimer_tg_info_v1, timer), .usersize = offsetof(struct idletimer_tg_info_v1, timer),
.checkentry = idletimer_tg_checkentry_v1, .checkentry = idletimer_tg_checkentry_v1,
.destroy = idletimer_tg_destroy_v1, .destroy = idletimer_tg_destroy_v1,
.me = THIS_MODULE, .me = THIS_MODULE,
}, },
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
{
.name = "IDLETIMER",
.family = NFPROTO_IPV6,
.target = idletimer_tg_target,
.targetsize = sizeof(struct idletimer_tg_info),
.usersize = offsetof(struct idletimer_tg_info, timer),
.checkentry = idletimer_tg_checkentry,
.destroy = idletimer_tg_destroy,
.me = THIS_MODULE,
},
{
.name = "IDLETIMER",
.family = NFPROTO_IPV6,
.revision = 1,
.target = idletimer_tg_target_v1,
.targetsize = sizeof(struct idletimer_tg_info_v1),
.usersize = offsetof(struct idletimer_tg_info_v1, timer),
.checkentry = idletimer_tg_checkentry_v1,
.destroy = idletimer_tg_destroy_v1,
.me = THIS_MODULE,
},
#endif
}; };
static struct class *idletimer_tg_class; static struct class *idletimer_tg_class;
......
...@@ -175,26 +175,41 @@ static void led_tg_destroy(const struct xt_tgdtor_param *par) ...@@ -175,26 +175,41 @@ static void led_tg_destroy(const struct xt_tgdtor_param *par)
kfree(ledinternal); kfree(ledinternal);
} }
static struct xt_target led_tg_reg __read_mostly = { static struct xt_target led_tg_reg[] __read_mostly = {
.name = "LED", {
.revision = 0, .name = "LED",
.family = NFPROTO_UNSPEC, .revision = 0,
.target = led_tg, .family = NFPROTO_IPV4,
.targetsize = sizeof(struct xt_led_info), .target = led_tg,
.usersize = offsetof(struct xt_led_info, internal_data), .targetsize = sizeof(struct xt_led_info),
.checkentry = led_tg_check, .usersize = offsetof(struct xt_led_info, internal_data),
.destroy = led_tg_destroy, .checkentry = led_tg_check,
.me = THIS_MODULE, .destroy = led_tg_destroy,
.me = THIS_MODULE,
},
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
{
.name = "LED",
.revision = 0,
.family = NFPROTO_IPV6,
.target = led_tg,
.targetsize = sizeof(struct xt_led_info),
.usersize = offsetof(struct xt_led_info, internal_data),
.checkentry = led_tg_check,
.destroy = led_tg_destroy,
.me = THIS_MODULE,
},
#endif
}; };
static int __init led_tg_init(void) static int __init led_tg_init(void)
{ {
return xt_register_target(&led_tg_reg); return xt_register_targets(led_tg_reg, ARRAY_SIZE(led_tg_reg));
} }
static void __exit led_tg_exit(void) static void __exit led_tg_exit(void)
{ {
xt_unregister_target(&led_tg_reg); xt_unregister_targets(led_tg_reg, ARRAY_SIZE(led_tg_reg));
} }
module_init(led_tg_init); module_init(led_tg_init);
......
...@@ -64,25 +64,39 @@ static void nflog_tg_destroy(const struct xt_tgdtor_param *par) ...@@ -64,25 +64,39 @@ static void nflog_tg_destroy(const struct xt_tgdtor_param *par)
nf_logger_put(par->family, NF_LOG_TYPE_ULOG); nf_logger_put(par->family, NF_LOG_TYPE_ULOG);
} }
static struct xt_target nflog_tg_reg __read_mostly = { static struct xt_target nflog_tg_reg[] __read_mostly = {
.name = "NFLOG", {
.revision = 0, .name = "NFLOG",
.family = NFPROTO_UNSPEC, .revision = 0,
.checkentry = nflog_tg_check, .family = NFPROTO_IPV4,
.destroy = nflog_tg_destroy, .checkentry = nflog_tg_check,
.target = nflog_tg, .destroy = nflog_tg_destroy,
.targetsize = sizeof(struct xt_nflog_info), .target = nflog_tg,
.me = THIS_MODULE, .targetsize = sizeof(struct xt_nflog_info),
.me = THIS_MODULE,
},
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
{
.name = "NFLOG",
.revision = 0,
.family = NFPROTO_IPV4,
.checkentry = nflog_tg_check,
.destroy = nflog_tg_destroy,
.target = nflog_tg,
.targetsize = sizeof(struct xt_nflog_info),
.me = THIS_MODULE,
},
#endif
}; };
static int __init nflog_tg_init(void) static int __init nflog_tg_init(void)
{ {
return xt_register_target(&nflog_tg_reg); return xt_register_targets(nflog_tg_reg, ARRAY_SIZE(nflog_tg_reg));
} }
static void __exit nflog_tg_exit(void) static void __exit nflog_tg_exit(void)
{ {
xt_unregister_target(&nflog_tg_reg); xt_unregister_targets(nflog_tg_reg, ARRAY_SIZE(nflog_tg_reg));
} }
module_init(nflog_tg_init); module_init(nflog_tg_init);
......
...@@ -179,16 +179,31 @@ static void xt_rateest_tg_destroy(const struct xt_tgdtor_param *par) ...@@ -179,16 +179,31 @@ static void xt_rateest_tg_destroy(const struct xt_tgdtor_param *par)
xt_rateest_put(par->net, info->est); xt_rateest_put(par->net, info->est);
} }
static struct xt_target xt_rateest_tg_reg __read_mostly = { static struct xt_target xt_rateest_tg_reg[] __read_mostly = {
.name = "RATEEST", {
.revision = 0, .name = "RATEEST",
.family = NFPROTO_UNSPEC, .revision = 0,
.target = xt_rateest_tg, .family = NFPROTO_IPV4,
.checkentry = xt_rateest_tg_checkentry, .target = xt_rateest_tg,
.destroy = xt_rateest_tg_destroy, .checkentry = xt_rateest_tg_checkentry,
.targetsize = sizeof(struct xt_rateest_target_info), .destroy = xt_rateest_tg_destroy,
.usersize = offsetof(struct xt_rateest_target_info, est), .targetsize = sizeof(struct xt_rateest_target_info),
.me = THIS_MODULE, .usersize = offsetof(struct xt_rateest_target_info, est),
.me = THIS_MODULE,
},
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
{
.name = "RATEEST",
.revision = 0,
.family = NFPROTO_IPV6,
.target = xt_rateest_tg,
.checkentry = xt_rateest_tg_checkentry,
.destroy = xt_rateest_tg_destroy,
.targetsize = sizeof(struct xt_rateest_target_info),
.usersize = offsetof(struct xt_rateest_target_info, est),
.me = THIS_MODULE,
},
#endif
}; };
static __net_init int xt_rateest_net_init(struct net *net) static __net_init int xt_rateest_net_init(struct net *net)
...@@ -214,12 +229,12 @@ static int __init xt_rateest_tg_init(void) ...@@ -214,12 +229,12 @@ static int __init xt_rateest_tg_init(void)
if (err) if (err)
return err; return err;
return xt_register_target(&xt_rateest_tg_reg); return xt_register_targets(xt_rateest_tg_reg, ARRAY_SIZE(xt_rateest_tg_reg));
} }
static void __exit xt_rateest_tg_fini(void) static void __exit xt_rateest_tg_fini(void)
{ {
xt_unregister_target(&xt_rateest_tg_reg); xt_unregister_targets(xt_rateest_tg_reg, ARRAY_SIZE(xt_rateest_tg_reg));
unregister_pernet_subsys(&xt_rateest_net_ops); unregister_pernet_subsys(&xt_rateest_net_ops);
} }
......
...@@ -157,7 +157,7 @@ static struct xt_target secmark_tg_reg[] __read_mostly = { ...@@ -157,7 +157,7 @@ static struct xt_target secmark_tg_reg[] __read_mostly = {
{ {
.name = "SECMARK", .name = "SECMARK",
.revision = 0, .revision = 0,
.family = NFPROTO_UNSPEC, .family = NFPROTO_IPV4,
.checkentry = secmark_tg_check_v0, .checkentry = secmark_tg_check_v0,
.destroy = secmark_tg_destroy, .destroy = secmark_tg_destroy,
.target = secmark_tg_v0, .target = secmark_tg_v0,
...@@ -167,7 +167,7 @@ static struct xt_target secmark_tg_reg[] __read_mostly = { ...@@ -167,7 +167,7 @@ static struct xt_target secmark_tg_reg[] __read_mostly = {
{ {
.name = "SECMARK", .name = "SECMARK",
.revision = 1, .revision = 1,
.family = NFPROTO_UNSPEC, .family = NFPROTO_IPV4,
.checkentry = secmark_tg_check_v1, .checkentry = secmark_tg_check_v1,
.destroy = secmark_tg_destroy, .destroy = secmark_tg_destroy,
.target = secmark_tg_v1, .target = secmark_tg_v1,
...@@ -175,6 +175,29 @@ static struct xt_target secmark_tg_reg[] __read_mostly = { ...@@ -175,6 +175,29 @@ static struct xt_target secmark_tg_reg[] __read_mostly = {
.usersize = offsetof(struct xt_secmark_target_info_v1, secid), .usersize = offsetof(struct xt_secmark_target_info_v1, secid),
.me = THIS_MODULE, .me = THIS_MODULE,
}, },
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
{
.name = "SECMARK",
.revision = 0,
.family = NFPROTO_IPV6,
.checkentry = secmark_tg_check_v0,
.destroy = secmark_tg_destroy,
.target = secmark_tg_v0,
.targetsize = sizeof(struct xt_secmark_target_info),
.me = THIS_MODULE,
},
{
.name = "SECMARK",
.revision = 1,
.family = NFPROTO_IPV6,
.checkentry = secmark_tg_check_v1,
.destroy = secmark_tg_destroy,
.target = secmark_tg_v1,
.targetsize = sizeof(struct xt_secmark_target_info_v1),
.usersize = offsetof(struct xt_secmark_target_info_v1, secid),
.me = THIS_MODULE,
},
#endif
}; };
static int __init secmark_tg_init(void) static int __init secmark_tg_init(void)
......
...@@ -29,25 +29,38 @@ trace_tg(struct sk_buff *skb, const struct xt_action_param *par) ...@@ -29,25 +29,38 @@ trace_tg(struct sk_buff *skb, const struct xt_action_param *par)
return XT_CONTINUE; return XT_CONTINUE;
} }
static struct xt_target trace_tg_reg __read_mostly = { static struct xt_target trace_tg_reg[] __read_mostly = {
.name = "TRACE", {
.revision = 0, .name = "TRACE",
.family = NFPROTO_UNSPEC, .revision = 0,
.table = "raw", .family = NFPROTO_IPV4,
.target = trace_tg, .table = "raw",
.checkentry = trace_tg_check, .target = trace_tg,
.destroy = trace_tg_destroy, .checkentry = trace_tg_check,
.me = THIS_MODULE, .destroy = trace_tg_destroy,
.me = THIS_MODULE,
},
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
{
.name = "TRACE",
.revision = 0,
.family = NFPROTO_IPV6,
.table = "raw",
.target = trace_tg,
.checkentry = trace_tg_check,
.destroy = trace_tg_destroy,
},
#endif
}; };
static int __init trace_tg_init(void) static int __init trace_tg_init(void)
{ {
return xt_register_target(&trace_tg_reg); return xt_register_targets(trace_tg_reg, ARRAY_SIZE(trace_tg_reg));
} }
static void __exit trace_tg_exit(void) static void __exit trace_tg_exit(void)
{ {
xt_unregister_target(&trace_tg_reg); xt_unregister_targets(trace_tg_reg, ARRAY_SIZE(trace_tg_reg));
} }
module_init(trace_tg_init); module_init(trace_tg_init);
......
...@@ -208,13 +208,24 @@ static struct xt_match addrtype_mt_reg[] __read_mostly = { ...@@ -208,13 +208,24 @@ static struct xt_match addrtype_mt_reg[] __read_mostly = {
}, },
{ {
.name = "addrtype", .name = "addrtype",
.family = NFPROTO_UNSPEC, .family = NFPROTO_IPV4,
.revision = 1, .revision = 1,
.match = addrtype_mt_v1, .match = addrtype_mt_v1,
.checkentry = addrtype_mt_checkentry_v1, .checkentry = addrtype_mt_checkentry_v1,
.matchsize = sizeof(struct xt_addrtype_info_v1), .matchsize = sizeof(struct xt_addrtype_info_v1),
.me = THIS_MODULE .me = THIS_MODULE
} },
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
{
.name = "addrtype",
.family = NFPROTO_IPV6,
.revision = 1,
.match = addrtype_mt_v1,
.checkentry = addrtype_mt_checkentry_v1,
.matchsize = sizeof(struct xt_addrtype_info_v1),
.me = THIS_MODULE
},
#endif
}; };
static int __init addrtype_mt_init(void) static int __init addrtype_mt_init(void)
......
...@@ -146,24 +146,37 @@ static void xt_cluster_mt_destroy(const struct xt_mtdtor_param *par) ...@@ -146,24 +146,37 @@ static void xt_cluster_mt_destroy(const struct xt_mtdtor_param *par)
nf_ct_netns_put(par->net, par->family); nf_ct_netns_put(par->net, par->family);
} }
static struct xt_match xt_cluster_match __read_mostly = { static struct xt_match xt_cluster_match[] __read_mostly = {
.name = "cluster", {
.family = NFPROTO_UNSPEC, .name = "cluster",
.match = xt_cluster_mt, .family = NFPROTO_IPV4,
.checkentry = xt_cluster_mt_checkentry, .match = xt_cluster_mt,
.matchsize = sizeof(struct xt_cluster_match_info), .checkentry = xt_cluster_mt_checkentry,
.destroy = xt_cluster_mt_destroy, .matchsize = sizeof(struct xt_cluster_match_info),
.me = THIS_MODULE, .destroy = xt_cluster_mt_destroy,
.me = THIS_MODULE,
},
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
{
.name = "cluster",
.family = NFPROTO_IPV6,
.match = xt_cluster_mt,
.checkentry = xt_cluster_mt_checkentry,
.matchsize = sizeof(struct xt_cluster_match_info),
.destroy = xt_cluster_mt_destroy,
.me = THIS_MODULE,
},
#endif
}; };
static int __init xt_cluster_mt_init(void) static int __init xt_cluster_mt_init(void)
{ {
return xt_register_match(&xt_cluster_match); return xt_register_matches(xt_cluster_match, ARRAY_SIZE(xt_cluster_match));
} }
static void __exit xt_cluster_mt_fini(void) static void __exit xt_cluster_mt_fini(void)
{ {
xt_unregister_match(&xt_cluster_match); xt_unregister_matches(xt_cluster_match, ARRAY_SIZE(xt_cluster_match));
} }
MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
......
...@@ -111,9 +111,11 @@ static int connbytes_mt_check(const struct xt_mtchk_param *par) ...@@ -111,9 +111,11 @@ static int connbytes_mt_check(const struct xt_mtchk_param *par)
return -EINVAL; return -EINVAL;
ret = nf_ct_netns_get(par->net, par->family); ret = nf_ct_netns_get(par->net, par->family);
if (ret < 0) if (ret < 0) {
pr_info_ratelimited("cannot load conntrack support for proto=%u\n", pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
par->family); par->family);
return ret;
}
/* /*
* This filter cannot function correctly unless connection tracking * This filter cannot function correctly unless connection tracking
......
...@@ -117,26 +117,41 @@ static void connlimit_mt_destroy(const struct xt_mtdtor_param *par) ...@@ -117,26 +117,41 @@ static void connlimit_mt_destroy(const struct xt_mtdtor_param *par)
nf_ct_netns_put(par->net, par->family); nf_ct_netns_put(par->net, par->family);
} }
static struct xt_match connlimit_mt_reg __read_mostly = { static struct xt_match connlimit_mt_reg[] __read_mostly = {
.name = "connlimit", {
.revision = 1, .name = "connlimit",
.family = NFPROTO_UNSPEC, .revision = 1,
.checkentry = connlimit_mt_check, .family = NFPROTO_IPV4,
.match = connlimit_mt, .checkentry = connlimit_mt_check,
.matchsize = sizeof(struct xt_connlimit_info), .match = connlimit_mt,
.usersize = offsetof(struct xt_connlimit_info, data), .matchsize = sizeof(struct xt_connlimit_info),
.destroy = connlimit_mt_destroy, .usersize = offsetof(struct xt_connlimit_info, data),
.me = THIS_MODULE, .destroy = connlimit_mt_destroy,
.me = THIS_MODULE,
},
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
{
.name = "connlimit",
.revision = 1,
.family = NFPROTO_IPV6,
.checkentry = connlimit_mt_check,
.match = connlimit_mt,
.matchsize = sizeof(struct xt_connlimit_info),
.usersize = offsetof(struct xt_connlimit_info, data),
.destroy = connlimit_mt_destroy,
.me = THIS_MODULE,
},
#endif
}; };
static int __init connlimit_mt_init(void) static int __init connlimit_mt_init(void)
{ {
return xt_register_match(&connlimit_mt_reg); return xt_register_matches(connlimit_mt_reg, ARRAY_SIZE(connlimit_mt_reg));
} }
static void __exit connlimit_mt_exit(void) static void __exit connlimit_mt_exit(void)
{ {
xt_unregister_match(&connlimit_mt_reg); xt_unregister_matches(connlimit_mt_reg, ARRAY_SIZE(connlimit_mt_reg));
} }
module_init(connlimit_mt_init); module_init(connlimit_mt_init);
......
...@@ -151,7 +151,7 @@ static struct xt_target connmark_tg_reg[] __read_mostly = { ...@@ -151,7 +151,7 @@ static struct xt_target connmark_tg_reg[] __read_mostly = {
{ {
.name = "CONNMARK", .name = "CONNMARK",
.revision = 1, .revision = 1,
.family = NFPROTO_UNSPEC, .family = NFPROTO_IPV4,
.checkentry = connmark_tg_check, .checkentry = connmark_tg_check,
.target = connmark_tg, .target = connmark_tg,
.targetsize = sizeof(struct xt_connmark_tginfo1), .targetsize = sizeof(struct xt_connmark_tginfo1),
...@@ -161,13 +161,35 @@ static struct xt_target connmark_tg_reg[] __read_mostly = { ...@@ -161,13 +161,35 @@ static struct xt_target connmark_tg_reg[] __read_mostly = {
{ {
.name = "CONNMARK", .name = "CONNMARK",
.revision = 2, .revision = 2,
.family = NFPROTO_UNSPEC, .family = NFPROTO_IPV4,
.checkentry = connmark_tg_check, .checkentry = connmark_tg_check,
.target = connmark_tg_v2, .target = connmark_tg_v2,
.targetsize = sizeof(struct xt_connmark_tginfo2), .targetsize = sizeof(struct xt_connmark_tginfo2),
.destroy = connmark_tg_destroy, .destroy = connmark_tg_destroy,
.me = THIS_MODULE, .me = THIS_MODULE,
} },
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
{
.name = "CONNMARK",
.revision = 1,
.family = NFPROTO_IPV6,
.checkentry = connmark_tg_check,
.target = connmark_tg,
.targetsize = sizeof(struct xt_connmark_tginfo1),
.destroy = connmark_tg_destroy,
.me = THIS_MODULE,
},
{
.name = "CONNMARK",
.revision = 2,
.family = NFPROTO_IPV6,
.checkentry = connmark_tg_check,
.target = connmark_tg_v2,
.targetsize = sizeof(struct xt_connmark_tginfo2),
.destroy = connmark_tg_destroy,
.me = THIS_MODULE,
},
#endif
}; };
static struct xt_match connmark_mt_reg __read_mostly = { static struct xt_match connmark_mt_reg __read_mostly = {
......
...@@ -39,13 +39,35 @@ mark_mt(const struct sk_buff *skb, struct xt_action_param *par) ...@@ -39,13 +39,35 @@ mark_mt(const struct sk_buff *skb, struct xt_action_param *par)
return ((skb->mark & info->mask) == info->mark) ^ info->invert; return ((skb->mark & info->mask) == info->mark) ^ info->invert;
} }
static struct xt_target mark_tg_reg __read_mostly = { static struct xt_target mark_tg_reg[] __read_mostly = {
.name = "MARK", {
.revision = 2, .name = "MARK",
.family = NFPROTO_UNSPEC, .revision = 2,
.target = mark_tg, .family = NFPROTO_IPV4,
.targetsize = sizeof(struct xt_mark_tginfo2), .target = mark_tg,
.me = THIS_MODULE, .targetsize = sizeof(struct xt_mark_tginfo2),
.me = THIS_MODULE,
},
#if IS_ENABLED(CONFIG_IP_NF_ARPTABLES)
{
.name = "MARK",
.revision = 2,
.family = NFPROTO_ARP,
.target = mark_tg,
.targetsize = sizeof(struct xt_mark_tginfo2),
.me = THIS_MODULE,
},
#endif
#if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
{
.name = "MARK",
.revision = 2,
.family = NFPROTO_IPV4,
.target = mark_tg,
.targetsize = sizeof(struct xt_mark_tginfo2),
.me = THIS_MODULE,
},
#endif
}; };
static struct xt_match mark_mt_reg __read_mostly = { static struct xt_match mark_mt_reg __read_mostly = {
...@@ -61,12 +83,12 @@ static int __init mark_mt_init(void) ...@@ -61,12 +83,12 @@ static int __init mark_mt_init(void)
{ {
int ret; int ret;
ret = xt_register_target(&mark_tg_reg); ret = xt_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = xt_register_match(&mark_mt_reg); ret = xt_register_match(&mark_mt_reg);
if (ret < 0) { if (ret < 0) {
xt_unregister_target(&mark_tg_reg); xt_unregister_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
return ret; return ret;
} }
return 0; return 0;
...@@ -75,7 +97,7 @@ static int __init mark_mt_init(void) ...@@ -75,7 +97,7 @@ static int __init mark_mt_init(void)
static void __exit mark_mt_exit(void) static void __exit mark_mt_exit(void)
{ {
xt_unregister_match(&mark_mt_reg); xt_unregister_match(&mark_mt_reg);
xt_unregister_target(&mark_tg_reg); xt_unregister_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
} }
module_init(mark_mt_init); module_init(mark_mt_init);
......
...@@ -32,6 +32,7 @@ source lib.sh ...@@ -32,6 +32,7 @@ source lib.sh
IP0=172.30.30.1 IP0=172.30.30.1
IP1=172.30.30.2 IP1=172.30.30.2
DUMMYNET=10.9.9
PFXL=30 PFXL=30
ret=0 ret=0
...@@ -54,6 +55,7 @@ setup_ns ns0 ns1 ...@@ -54,6 +55,7 @@ setup_ns ns0 ns1
ip netns exec "$ns0" sysctl -q -w net.ipv4.conf.default.rp_filter=0 ip netns exec "$ns0" sysctl -q -w net.ipv4.conf.default.rp_filter=0
ip netns exec "$ns0" sysctl -q -w net.ipv4.conf.all.rp_filter=0 ip netns exec "$ns0" sysctl -q -w net.ipv4.conf.all.rp_filter=0
ip netns exec "$ns0" sysctl -q -w net.ipv4.conf.all.rp_filter=0 ip netns exec "$ns0" sysctl -q -w net.ipv4.conf.all.rp_filter=0
ip netns exec "$ns0" sysctl -q -w net.ipv4.conf.all.forwarding=1
if ! ip link add veth0 netns "$ns0" type veth peer name veth0 netns "$ns1" > /dev/null 2>&1; then if ! ip link add veth0 netns "$ns0" type veth peer name veth0 netns "$ns1" > /dev/null 2>&1; then
echo "SKIP: Could not add veth device" echo "SKIP: Could not add veth device"
...@@ -65,13 +67,18 @@ if ! ip -net "$ns0" li add tvrf type vrf table 9876; then ...@@ -65,13 +67,18 @@ if ! ip -net "$ns0" li add tvrf type vrf table 9876; then
exit $ksft_skip exit $ksft_skip
fi fi
ip -net "$ns0" link add dummy0 type dummy
ip -net "$ns0" li set veth0 master tvrf ip -net "$ns0" li set veth0 master tvrf
ip -net "$ns0" li set dummy0 master tvrf
ip -net "$ns0" li set tvrf up ip -net "$ns0" li set tvrf up
ip -net "$ns0" li set veth0 up ip -net "$ns0" li set veth0 up
ip -net "$ns0" li set dummy0 up
ip -net "$ns1" li set veth0 up ip -net "$ns1" li set veth0 up
ip -net "$ns0" addr add $IP0/$PFXL dev veth0 ip -net "$ns0" addr add $IP0/$PFXL dev veth0
ip -net "$ns1" addr add $IP1/$PFXL dev veth0 ip -net "$ns1" addr add $IP1/$PFXL dev veth0
ip -net "$ns0" addr add $DUMMYNET.1/$PFXL dev dummy0
listener_ready() listener_ready()
{ {
...@@ -212,9 +219,35 @@ EOF ...@@ -212,9 +219,35 @@ EOF
fi fi
} }
test_fib()
{
ip netns exec "$ns0" nft -f - <<EOF
flush ruleset
table ip t {
counter fibcount { }
chain prerouting {
type filter hook prerouting priority 0;
meta iifname veth0 ip daddr $DUMMYNET.2 fib daddr oif dummy0 counter name fibcount notrack
}
}
EOF
ip -net "$ns1" route add 10.9.9.0/24 via "$IP0" dev veth0
ip netns exec "$ns1" ping -q -w 1 -c 1 "$DUMMYNET".2 > /dev/null
if ip netns exec "$ns0" nft list counter t fibcount | grep -q "packets 1"; then
echo "PASS: fib lookup returned exepected output interface"
else
echo "FAIL: fib lookup did not return exepected output interface"
ret=1
return
fi
}
test_ct_zone_in test_ct_zone_in
test_masquerade_vrf "default" test_masquerade_vrf "default"
test_masquerade_vrf "pfifo" test_masquerade_vrf "pfifo"
test_masquerade_veth test_masquerade_veth
test_fib
exit $ret exit $ret
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment