netfilter pull request 26-06-10
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEjF9xRqF1emXiQiqU1w0aZmrPKyEFAmopiokACgkQ1w0aZmrP
KyGBoA//W6EXg8MCgQGojXZ4+41fPpJ6opw7t65e26/CIwTBgtOiX/no4WOJcOk/
J6WBk2sHIg+RgPPzzOLfzAeyVf7MfbnXvBnEMselFGOtd1o5LeikdcskuMIQ2GP/
v7a3C49Xueyp5ChjdArTbYcaREnAFVnmPGdsaE90D64SHNlmuiyIsRtEut+XUfuz
Tl+JNCV2RCdSAl36MqnwAF8sBpj9ndnekNz8E5UONwgA7sowPM6KsGbYqCJrQXxa
qDqbj9fme8BmLWc8gwQ37yD5iBGxc7LdVlyavIJ9uSi2Gp/jnDSsuyUm5WDo84wm
R65jYmkXh9ZHr8OU/qYg5Mb0LBsSfNRzcE4WZIqb71WQ45IqA53kXam/2W0CuflN
g9tPfAqboI9A11Mq3LSwwFWfa3L2xJIi1LFpzGThNTZa9vFoqhXZG0PCqXBKiDdo
KsEmU4vtMFqga8tOFDJMgKHAxr/jPWhEZp1ZgIy3xAM2s9xC56Qe1g8mwcBFeZR7
n/YEFGpWFa83EnXGow1gdhUQHu+PYbiwQQy1tSVaZ+kg5WhA3ahnJfIopS2qIrHq
NN1RP8m85YjSZGzF/gvq+BEuuYZsebeaFxYLDha0zrhqXA3vlRZvVxoySlJtW/bk
m/05GsIb7ySpAyOjejJ9fokymzjD1op+0o69AnEqvg1IXUmE0oM=
=Rg2q
-----END PGP SIGNATURE-----
Merge tag 'nf-26-06-10' 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) Revalidate bridge ports, add missing NULL checks to fetch the bridge
device by the port. From Florian Westphal.
2) Fix netdevice refcount leak in the error path of nft_fwd hardware
offload function, also from Florian.
3) Unregister helper expectfn callback on conntrack helper module
removal, otherwise dangling pointer remains in place,
from Weiming Shi.
4) Fix possible pointer infoleak in getsockopt() IPT_SO_GET_ENTRIES,
From Kyle Zeng.
5) Validate that device MAC header is present before nf_syslog
accesses it. From Xiang Mei.
6-8) Three patches to address a possible infoleak of stale stack
data in three nf_tables expressions, due to mismatch in the
_init() and _eval() function which is possible since 14fb07130c.
From Davide Ornaghi and Florian Westphal.
netfilter pull request 26-06-10
* tag 'nf-26-06-10' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf:
netfilter: nft_meta_bridge: fix stale stack leak via IIFHWADDR register
netfilter: nft_fib: fix stale stack leak via the OIFNAME register
netfilter: nft_exthdr: fix register tracking for F_PRESENT flag
netfilter: nf_log: validate MAC header was set before dumping it
netfilter: x_tables: avoid leaking percpu counter pointers
netfilter: nf_conntrack: destroy stale expectfn expectations on unregister
netfilter: nf_tables_offload: drop device refcount on error
netfilter: revalidate bridge ports
====================
Link: https://patch.msgid.link/20260610161629.214092-1-pablo@netfilter.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
64ced6c088
19 changed files with 151 additions and 51 deletions
|
|
@ -39,7 +39,9 @@ ebt_dnat_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
|||
dev = xt_in(par);
|
||||
break;
|
||||
case NF_BR_PRE_ROUTING:
|
||||
dev = br_port_get_rcu(xt_in(par))->br->dev;
|
||||
dev = netdev_master_upper_dev_get_rcu(xt_in(par));
|
||||
if (!dev) /* bridge port removed? */
|
||||
return EBT_DROP;
|
||||
break;
|
||||
default:
|
||||
dev = NULL;
|
||||
|
|
|
|||
|
|
@ -24,12 +24,18 @@ ebt_redirect_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
|||
if (skb_ensure_writable(skb, 0))
|
||||
return EBT_DROP;
|
||||
|
||||
if (xt_hooknum(par) != NF_BR_BROUTING)
|
||||
/* rcu_read_lock()ed by nf_hook_thresh */
|
||||
ether_addr_copy(eth_hdr(skb)->h_dest,
|
||||
br_port_get_rcu(xt_in(par))->br->dev->dev_addr);
|
||||
else
|
||||
if (xt_hooknum(par) != NF_BR_BROUTING) {
|
||||
const struct net_device *dev;
|
||||
|
||||
dev = netdev_master_upper_dev_get_rcu(xt_in(par));
|
||||
if (!dev)
|
||||
return EBT_DROP;
|
||||
|
||||
ether_addr_copy(eth_hdr(skb)->h_dest, dev->dev_addr);
|
||||
} else {
|
||||
ether_addr_copy(eth_hdr(skb)->h_dest, xt_in(par)->dev_addr);
|
||||
}
|
||||
|
||||
skb->pkt_type = PACKET_HOST;
|
||||
return info->target;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr,
|
|||
if (!br_dev)
|
||||
goto err;
|
||||
|
||||
/* ETH_ALEN (6) is shorter than the destination register span (8) */
|
||||
dest[1] = 0;
|
||||
memcpy(dest, br_dev->dev_addr, ETH_ALEN);
|
||||
return;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -702,14 +702,12 @@ static int copy_entries_to_user(unsigned int total_size,
|
|||
const struct xt_entry_target *t;
|
||||
|
||||
e = loc_cpu_entry + off;
|
||||
if (copy_to_user(userptr + off, e, sizeof(*e))) {
|
||||
ret = -EFAULT;
|
||||
goto free_counters;
|
||||
}
|
||||
if (copy_to_user(userptr + off
|
||||
if (copy_to_user(userptr + off, e,
|
||||
offsetof(struct arpt_entry, counters)) ||
|
||||
copy_to_user(userptr + off
|
||||
+ offsetof(struct arpt_entry, counters),
|
||||
&counters[num],
|
||||
sizeof(counters[num])) != 0) {
|
||||
sizeof(counters[num]))) {
|
||||
ret = -EFAULT;
|
||||
goto free_counters;
|
||||
}
|
||||
|
|
@ -1327,9 +1325,8 @@ static int compat_copy_entry_to_user(struct arpt_entry *e, void __user **dstptr,
|
|||
|
||||
origsize = *size;
|
||||
ce = *dstptr;
|
||||
if (copy_to_user(ce, e, sizeof(struct arpt_entry)) != 0 ||
|
||||
copy_to_user(&ce->counters, &counters[i],
|
||||
sizeof(counters[i])) != 0)
|
||||
if (copy_to_user(ce, e, offsetof(struct compat_arpt_entry, counters)) ||
|
||||
copy_to_user(&ce->counters, &counters[i], sizeof(counters[i])))
|
||||
return -EFAULT;
|
||||
|
||||
*dstptr += sizeof(struct compat_arpt_entry);
|
||||
|
|
|
|||
|
|
@ -832,14 +832,12 @@ copy_entries_to_user(unsigned int total_size,
|
|||
const struct xt_entry_target *t;
|
||||
|
||||
e = loc_cpu_entry + off;
|
||||
if (copy_to_user(userptr + off, e, sizeof(*e))) {
|
||||
ret = -EFAULT;
|
||||
goto free_counters;
|
||||
}
|
||||
if (copy_to_user(userptr + off
|
||||
if (copy_to_user(userptr + off, e,
|
||||
offsetof(struct ipt_entry, counters)) ||
|
||||
copy_to_user(userptr + off
|
||||
+ offsetof(struct ipt_entry, counters),
|
||||
&counters[num],
|
||||
sizeof(counters[num])) != 0) {
|
||||
sizeof(counters[num]))) {
|
||||
ret = -EFAULT;
|
||||
goto free_counters;
|
||||
}
|
||||
|
|
@ -1228,9 +1226,8 @@ compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
|
|||
|
||||
origsize = *size;
|
||||
ce = *dstptr;
|
||||
if (copy_to_user(ce, e, sizeof(struct ipt_entry)) != 0 ||
|
||||
copy_to_user(&ce->counters, &counters[i],
|
||||
sizeof(counters[i])) != 0)
|
||||
if (copy_to_user(ce, e, offsetof(struct compat_ipt_entry, counters)) ||
|
||||
copy_to_user(&ce->counters, &counters[i], sizeof(counters[i])))
|
||||
return -EFAULT;
|
||||
|
||||
*dstptr += sizeof(struct compat_ipt_entry);
|
||||
|
|
|
|||
|
|
@ -555,6 +555,8 @@ static void __exit nf_nat_h323_fini(void)
|
|||
nf_ct_helper_expectfn_unregister(&q931_nat);
|
||||
nf_ct_helper_expectfn_unregister(&callforwarding_nat);
|
||||
synchronize_rcu();
|
||||
nf_ct_helper_expectfn_destroy(&q931_nat);
|
||||
nf_ct_helper_expectfn_destroy(&callforwarding_nat);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
|
|||
fl4.saddr = get_saddr(iph->daddr);
|
||||
}
|
||||
|
||||
*dest = 0;
|
||||
nft_fib_store_result(dest, priv, NULL);
|
||||
|
||||
if (fib_lookup(nft_net(pkt), &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE))
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -848,14 +848,12 @@ copy_entries_to_user(unsigned int total_size,
|
|||
const struct xt_entry_target *t;
|
||||
|
||||
e = loc_cpu_entry + off;
|
||||
if (copy_to_user(userptr + off, e, sizeof(*e))) {
|
||||
ret = -EFAULT;
|
||||
goto free_counters;
|
||||
}
|
||||
if (copy_to_user(userptr + off
|
||||
if (copy_to_user(userptr + off, e,
|
||||
offsetof(struct ip6t_entry, counters)) ||
|
||||
copy_to_user(userptr + off
|
||||
+ offsetof(struct ip6t_entry, counters),
|
||||
&counters[num],
|
||||
sizeof(counters[num])) != 0) {
|
||||
sizeof(counters[num]))) {
|
||||
ret = -EFAULT;
|
||||
goto free_counters;
|
||||
}
|
||||
|
|
@ -1244,9 +1242,8 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr,
|
|||
|
||||
origsize = *size;
|
||||
ce = *dstptr;
|
||||
if (copy_to_user(ce, e, sizeof(struct ip6t_entry)) != 0 ||
|
||||
copy_to_user(&ce->counters, &counters[i],
|
||||
sizeof(counters[i])) != 0)
|
||||
if (copy_to_user(ce, e, offsetof(struct compat_ip6t_entry, counters)) ||
|
||||
copy_to_user(&ce->counters, &counters[i], sizeof(counters[i])))
|
||||
return -EFAULT;
|
||||
|
||||
*dstptr += sizeof(struct compat_ip6t_entry);
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,
|
|||
|
||||
lookup_flags = nft_fib6_flowi_init(&fl6, priv, pkt, oif, iph);
|
||||
|
||||
*dest = 0;
|
||||
nft_fib_store_result(dest, priv, NULL);
|
||||
ret = nft_fib6_lookup(nft_net(pkt), &fl6, &res, lookup_flags);
|
||||
if (ret || res.fib6_flags & (RTF_REJECT | RTF_ANYCAST | RTF_LOCAL))
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -283,6 +283,25 @@ void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_unregister);
|
||||
|
||||
static bool expect_iter_expectfn(struct nf_conntrack_expect *exp, void *data)
|
||||
{
|
||||
const struct nf_ct_helper_expectfn *n = data;
|
||||
|
||||
/* Relies on registered expectfn descriptors having unique ->expectfn
|
||||
* pointers, which holds for the in-tree NAT helpers.
|
||||
*/
|
||||
return exp->expectfn == n->expectfn;
|
||||
}
|
||||
|
||||
/* Destroy expectations still pointing at @n->expectfn; call after the
|
||||
* caller's RCU grace period so none outlives the (often modular) callback.
|
||||
*/
|
||||
void nf_ct_helper_expectfn_destroy(const struct nf_ct_helper_expectfn *n)
|
||||
{
|
||||
nf_ct_expect_iterate_destroy(expect_iter_expectfn, (void *)n);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_destroy);
|
||||
|
||||
/* Caller should hold the rcu lock */
|
||||
struct nf_ct_helper_expectfn *
|
||||
nf_ct_helper_expectfn_find_by_name(const char *name)
|
||||
|
|
|
|||
|
|
@ -74,16 +74,18 @@ int nft_fwd_dup_netdev_offload(struct nft_offload_ctx *ctx,
|
|||
struct flow_action_entry *entry;
|
||||
struct net_device *dev;
|
||||
|
||||
/* nft_flow_rule_destroy() releases the reference on this device. */
|
||||
dev = dev_get_by_index(ctx->net, oif);
|
||||
if (!dev)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
entry = nft_flow_action_entry_next(ctx, flow);
|
||||
if (!entry)
|
||||
if (!entry) {
|
||||
dev_put(dev);
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
entry->id = id;
|
||||
/* nft_flow_rule_destroy() releases the reference on this device. */
|
||||
entry->dev = dev;
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -815,8 +815,8 @@ static void dump_mac_header(struct nf_log_buf *m,
|
|||
|
||||
fallback:
|
||||
nf_log_buf_add(m, "MAC=");
|
||||
if (dev->hard_header_len &&
|
||||
skb->mac_header != skb->network_header) {
|
||||
if (dev->hard_header_len && skb_mac_header_was_set(skb) &&
|
||||
skb_mac_header_len(skb) != 0) {
|
||||
const unsigned char *p = skb_mac_header(skb);
|
||||
unsigned int i;
|
||||
|
||||
|
|
|
|||
|
|
@ -1341,6 +1341,7 @@ static int __init nf_nat_init(void)
|
|||
RCU_INIT_POINTER(nf_nat_hook, NULL);
|
||||
nf_ct_helper_expectfn_unregister(&follow_master_nat);
|
||||
synchronize_net();
|
||||
nf_ct_helper_expectfn_destroy(&follow_master_nat);
|
||||
unregister_pernet_subsys(&nat_net_ops);
|
||||
kvfree(nf_nat_bysource);
|
||||
}
|
||||
|
|
@ -1358,6 +1359,7 @@ static void __exit nf_nat_cleanup(void)
|
|||
RCU_INIT_POINTER(nf_nat_hook, NULL);
|
||||
|
||||
synchronize_net();
|
||||
nf_ct_helper_expectfn_destroy(&follow_master_nat);
|
||||
kvfree(nf_nat_bysource);
|
||||
unregister_pernet_subsys(&nat_net_ops);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -655,6 +655,7 @@ static void __exit nf_nat_sip_fini(void)
|
|||
RCU_INIT_POINTER(nf_nat_sip_hooks, NULL);
|
||||
nf_ct_helper_expectfn_unregister(&sip_nat);
|
||||
synchronize_rcu();
|
||||
nf_ct_helper_expectfn_destroy(&sip_nat);
|
||||
}
|
||||
|
||||
static const struct nf_nat_sip_hooks sip_hooks = {
|
||||
|
|
|
|||
|
|
@ -451,6 +451,23 @@ nla_put_failure:
|
|||
return -1;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
|
||||
static int nflog_put_master_ifindex(struct sk_buff *nlskb, int attr,
|
||||
const struct net_device *dev)
|
||||
{
|
||||
const struct net_device *upper;
|
||||
|
||||
if (dev && !netif_is_bridge_port(dev))
|
||||
return 0;
|
||||
|
||||
upper = netdev_master_upper_dev_get_rcu((struct net_device *)dev);
|
||||
if (upper && nla_put_be32(nlskb, attr, htonl(upper->ifindex)))
|
||||
return -EMSGSIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This is an inline function, we don't really care about a long
|
||||
* list of arguments */
|
||||
static inline int
|
||||
|
|
@ -505,8 +522,7 @@ __build_packet_message(struct nfnl_log_net *log,
|
|||
/* rcu_read_lock()ed by nf_hook_thresh or
|
||||
* nf_log_packet.
|
||||
*/
|
||||
nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV,
|
||||
htonl(br_port_get_rcu(indev)->br->dev->ifindex)))
|
||||
nflog_put_master_ifindex(inst->skb, NFULA_IFINDEX_INDEV, indev))
|
||||
goto nla_put_failure;
|
||||
} else {
|
||||
int physinif;
|
||||
|
|
@ -542,8 +558,7 @@ __build_packet_message(struct nfnl_log_net *log,
|
|||
/* rcu_read_lock()ed by nf_hook_thresh or
|
||||
* nf_log_packet.
|
||||
*/
|
||||
nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV,
|
||||
htonl(br_port_get_rcu(outdev)->br->dev->ifindex)))
|
||||
nflog_put_master_ifindex(inst->skb, NFULA_IFINDEX_OUTDEV, outdev))
|
||||
goto nla_put_failure;
|
||||
} else {
|
||||
struct net_device *physoutdev;
|
||||
|
|
|
|||
|
|
@ -440,10 +440,47 @@ static bool nf_ct_drop_unconfirmed(const struct nf_queue_entry *entry, bool *is_
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool nf_bridge_port_valid(const struct net_device *dev)
|
||||
{
|
||||
if (!dev)
|
||||
return true;
|
||||
|
||||
return netif_is_bridge_port(dev);
|
||||
}
|
||||
|
||||
/* queued skbs leave rcu protection. We bump device refcount so that
|
||||
* the device cannot go away. However, while packet was out the port
|
||||
* could have been removed from the bridge.
|
||||
*
|
||||
* Ensure in+outdev are still part of a bridge at reinject time.
|
||||
*
|
||||
* The device rx_handler_data could even be pointing at data that is
|
||||
* not a net_bridge_port structure.
|
||||
*/
|
||||
static bool nf_bridge_ports_valid(const struct nf_queue_entry *entry)
|
||||
{
|
||||
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
|
||||
if (!nf_bridge_port_valid(entry->physin) ||
|
||||
!nf_bridge_port_valid(entry->physout))
|
||||
return false;
|
||||
#endif
|
||||
if (entry->state.pf != PF_BRIDGE)
|
||||
return true;
|
||||
|
||||
if (!nf_bridge_port_valid(entry->state.in) ||
|
||||
!nf_bridge_port_valid(entry->state.out))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void nfqnl_reinject(struct nf_queue_entry *entry, unsigned int verdict)
|
||||
{
|
||||
const struct nf_ct_hook *ct_hook;
|
||||
|
||||
if (!nf_bridge_ports_valid(entry))
|
||||
verdict = NF_DROP;
|
||||
|
||||
if (verdict == NF_ACCEPT ||
|
||||
verdict == NF_REPEAT ||
|
||||
verdict == NF_STOP) {
|
||||
|
|
@ -636,6 +673,23 @@ static int nf_queue_checksum_help(struct sk_buff *entskb)
|
|||
return skb_checksum_help(entskb);
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
|
||||
static int nfqnl_put_master_ifindex(struct sk_buff *nlskb, int attr,
|
||||
const struct net_device *dev)
|
||||
{
|
||||
const struct net_device *upper;
|
||||
|
||||
if (dev && !netif_is_bridge_port(dev))
|
||||
return 0;
|
||||
|
||||
upper = netdev_master_upper_dev_get_rcu((struct net_device *)dev);
|
||||
if (upper && nla_put_be32(nlskb, attr, htonl(upper->ifindex)))
|
||||
return -EMSGSIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct sk_buff *
|
||||
nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
|
||||
struct nf_queue_entry *entry,
|
||||
|
|
@ -771,10 +825,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
|
|||
* netfilter_bridge) */
|
||||
if (nla_put_be32(skb, NFQA_IFINDEX_PHYSINDEV,
|
||||
htonl(indev->ifindex)) ||
|
||||
/* this is the bridge group "brX" */
|
||||
/* rcu_read_lock()ed by __nf_queue */
|
||||
nla_put_be32(skb, NFQA_IFINDEX_INDEV,
|
||||
htonl(br_port_get_rcu(indev)->br->dev->ifindex)))
|
||||
nfqnl_put_master_ifindex(skb, NFQA_IFINDEX_INDEV, indev))
|
||||
goto nla_put_failure;
|
||||
} else {
|
||||
int physinif;
|
||||
|
|
@ -805,10 +856,7 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
|
|||
* netfilter_bridge) */
|
||||
if (nla_put_be32(skb, NFQA_IFINDEX_PHYSOUTDEV,
|
||||
htonl(outdev->ifindex)) ||
|
||||
/* this is the bridge group "brX" */
|
||||
/* rcu_read_lock()ed by __nf_queue */
|
||||
nla_put_be32(skb, NFQA_IFINDEX_OUTDEV,
|
||||
htonl(br_port_get_rcu(outdev)->br->dev->ifindex)))
|
||||
nfqnl_put_master_ifindex(skb, NFQA_IFINDEX_OUTDEV, outdev))
|
||||
goto nla_put_failure;
|
||||
} else {
|
||||
int physoutif;
|
||||
|
|
|
|||
|
|
@ -532,6 +532,9 @@ static int nft_exthdr_init(const struct nft_ctx *ctx,
|
|||
return err;
|
||||
}
|
||||
|
||||
if ((flags & NFT_EXTHDR_F_PRESENT) && len != 1)
|
||||
return -EINVAL;
|
||||
|
||||
priv->type = nla_get_u8(tb[NFTA_EXTHDR_TYPE]);
|
||||
priv->offset = offset;
|
||||
priv->len = len;
|
||||
|
|
|
|||
|
|
@ -107,6 +107,12 @@ int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (priv->flags & NFTA_FIB_F_PRESENT) {
|
||||
if (priv->result != NFT_FIB_RESULT_OIF)
|
||||
return -EINVAL;
|
||||
len = sizeof(u8);
|
||||
}
|
||||
|
||||
err = nft_parse_register_store(ctx, tb[NFTA_FIB_DREG], &priv->dreg,
|
||||
NULL, NFT_DATA_VALUE, len);
|
||||
if (err < 0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue