mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 17:13:52 +02:00
netfilter pull request nf-26-02-17
-----BEGIN PGP SIGNATURE----- iQJdBAABCABHFiEEgKkgxbID4Gn1hq6fcJGo2a1f9gAFAmmUlGEbFIAAAAAABAAO bWFudTIsMi41KzEuMTEsMiwyDRxmd0BzdHJsZW4uZGUACgkQcJGo2a1f9gAIYxAA 0AfkdXmCWMcHgWpMeW/K1R6SVxFpPLiXbvBSgQ7rUARARFQLTn7HkJGwpeq/slYp eAOnAF2e6j50dPJTAaa7hL4zMAuMe2a3zHPB03xg937FX/1wc/8kv73WCM7FkOSk yqOD/VhrbbW4Texc93wiYk+EZCjVyoQPb9wEbQkn6G1uUZddGeSllQLsYcs2/Vz0 o4vL6ouoxwIAud5Hqt63dV5IAwneCqp2g2Wg9QiwZK9oOf1l9QgN0axFXkn1z1pP I60zQwWQgalMeuQw3jiktvZF45hyUvf9tR4CHvaOlpkg0ExOOr3o6o70J1eq9WlR aIax9oRZC9N8EEel7AyFHD53E0ooI1T87kz05XLnB2Jb+vJ25smpTNLGOZMi68bD Sg6xywF3lUsHe0K1rdH+dXeY4VmN1oB8r8jxbxU15H9JiGGnO5/pVxxfq0kFhRHU Q1490qAX8Se+Pa+cj1nwBESTvAFH9jDZSbBQC6wc328l4kXOzQa+EKCrj+dae5q2 PNTG0xkvMMV3RKB15V2YZ9Ay3bA5Lf4iz8/E0pUHhCN8E/SADctfhZQLG0T3eg1K D3Ix1/iqeMDuq2t8A6uCq2bPrxKg8ijDsLWJ4ilCyirfRurlr3SrQAkMx6Tu7AnC XOYh5VBFrKywoWi/4kivXhQ1EengGUA9sev7WRC5yXo= =yncs -----END PGP SIGNATURE----- Merge tag 'nf-26-02-17' of https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf Florian Westphal says: ==================== netfilter: updates for net The following patchset contains Netfilter fixes for *net*: 1) Add missing __rcu annotations to NAT helper hook pointers in Amanda, FTP, IRC, SNMP and TFTP helpers. From Sun Jian. 2-4): - Add global spinlock to serialize nft_counter fetch+reset operations. - Use atomic64_xchg() for nft_quota reset instead of read+subtract pattern. Note AI review detects a race in this change but it isn't new. The 'racing' bit only exists to prevent constant stream of 'quota expired' notifications. - Revert commit_mutex usage in nf_tables reset path, it caused circular lock dependency. All from Brian Witte. 5) Fix uninitialized l3num value in nf_conntrack_h323 helper. 6) Fix musl libc compatibility in netfilter_bridge.h UAPI header. This change isn't nice (UAPI headers should not include libc headers), but as-is musl builds may fail due to redefinition of struct ethhdr. 7) Fix protocol checksum validation in IPVS for IPv6 with extension headers, from Julian Anastasov. 8) Fix device reference leak in IPVS when netdev goes down. Also from Julian. 9) Remove WARN_ON_ONCE when accessing forward path array, this can trigger with sufficiently long forward paths. From Pablo Neira Ayuso. 10) Fix use-after-free in nf_tables_addchain() error path, from Inseo An. * tag 'nf-26-02-17' of https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf: netfilter: nf_tables: fix use-after-free in nf_tables_addchain() net: remove WARN_ON_ONCE when accessing forward path array ipvs: do not keep dest_dst if dev is going down ipvs: skip ipv6 extension headers for csum checks include: uapi: netfilter_bridge.h: Cover for musl libc netfilter: nf_conntrack_h323: don't pass uninitialised l3num value netfilter: nf_tables: revert commit_mutex usage in reset path netfilter: nft_quota: use atomic64_xchg for reset netfilter: nft_counter: serialize reset with spinlock netfilter: annotate NAT helper hook pointers with __rcu ==================== Link: https://patch.msgid.link/20260217163233.31455-1-fw@strlen.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
284f1f176f
|
|
@ -7,7 +7,7 @@
|
|||
#include <linux/skbuff.h>
|
||||
#include <net/netfilter/nf_conntrack_expect.h>
|
||||
|
||||
extern unsigned int (*nf_nat_amanda_hook)(struct sk_buff *skb,
|
||||
extern unsigned int (__rcu *nf_nat_amanda_hook)(struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned int matchoff,
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ struct nf_ct_ftp_master {
|
|||
|
||||
/* For NAT to hook in when we find a packet which describes what other
|
||||
* connection we should expect. */
|
||||
extern unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb,
|
||||
extern unsigned int (__rcu *nf_nat_ftp_hook)(struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
enum nf_ct_ftp_type type,
|
||||
unsigned int protoff,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#define IRC_PORT 6667
|
||||
|
||||
extern unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb,
|
||||
extern unsigned int (__rcu *nf_nat_irc_hook)(struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned int matchoff,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#include <linux/netfilter.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
extern int (*nf_nat_snmp_hook)(struct sk_buff *skb,
|
||||
extern int (__rcu *nf_nat_snmp_hook)(struct sk_buff *skb,
|
||||
unsigned int protoff,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ struct tftphdr {
|
|||
#define TFTP_OPCODE_ACK 4
|
||||
#define TFTP_OPCODE_ERROR 5
|
||||
|
||||
extern unsigned int (*nf_nat_tftp_hook)(struct sk_buff *skb,
|
||||
extern unsigned int (__rcu *nf_nat_tftp_hook)(struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
struct nf_conntrack_expect *exp);
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@
|
|||
/* bridge-specific defines for netfilter.
|
||||
*/
|
||||
|
||||
#ifndef __KERNEL__
|
||||
#include <netinet/if_ether.h> /* for __UAPI_DEF_ETHHDR if defined */
|
||||
#endif
|
||||
|
||||
#include <linux/in.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
|
|
|||
|
|
@ -744,7 +744,7 @@ static struct net_device_path *dev_fwd_path(struct net_device_path_stack *stack)
|
|||
{
|
||||
int k = stack->num_paths++;
|
||||
|
||||
if (WARN_ON_ONCE(k >= NET_DEVICE_PATH_STACK_MAX))
|
||||
if (k >= NET_DEVICE_PATH_STACK_MAX)
|
||||
return NULL;
|
||||
|
||||
return &stack->path[k];
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@
|
|||
#include <net/ip_vs.h>
|
||||
|
||||
static int
|
||||
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp);
|
||||
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
|
||||
unsigned int sctphoff);
|
||||
|
||||
static int
|
||||
sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
|
||||
|
|
@ -108,7 +109,7 @@ sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
int ret;
|
||||
|
||||
/* Some checks before mangling */
|
||||
if (!sctp_csum_check(cp->af, skb, pp))
|
||||
if (!sctp_csum_check(cp->af, skb, pp, sctphoff))
|
||||
return 0;
|
||||
|
||||
/* Call application helper if needed */
|
||||
|
|
@ -156,7 +157,7 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
int ret;
|
||||
|
||||
/* Some checks before mangling */
|
||||
if (!sctp_csum_check(cp->af, skb, pp))
|
||||
if (!sctp_csum_check(cp->af, skb, pp, sctphoff))
|
||||
return 0;
|
||||
|
||||
/* Call application helper if needed */
|
||||
|
|
@ -185,19 +186,12 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
}
|
||||
|
||||
static int
|
||||
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
|
||||
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
|
||||
unsigned int sctphoff)
|
||||
{
|
||||
unsigned int sctphoff;
|
||||
struct sctphdr *sh;
|
||||
__le32 cmp, val;
|
||||
|
||||
#ifdef CONFIG_IP_VS_IPV6
|
||||
if (af == AF_INET6)
|
||||
sctphoff = sizeof(struct ipv6hdr);
|
||||
else
|
||||
#endif
|
||||
sctphoff = ip_hdrlen(skb);
|
||||
|
||||
sh = (struct sctphdr *)(skb->data + sctphoff);
|
||||
cmp = sh->checksum;
|
||||
val = sctp_compute_cksum(skb, sctphoff);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@
|
|||
#include <net/ip_vs.h>
|
||||
|
||||
static int
|
||||
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp);
|
||||
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
|
||||
unsigned int tcphoff);
|
||||
|
||||
static int
|
||||
tcp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
|
||||
|
|
@ -165,7 +166,7 @@ tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
int ret;
|
||||
|
||||
/* Some checks before mangling */
|
||||
if (!tcp_csum_check(cp->af, skb, pp))
|
||||
if (!tcp_csum_check(cp->af, skb, pp, tcphoff))
|
||||
return 0;
|
||||
|
||||
/* Call application helper if needed */
|
||||
|
|
@ -243,7 +244,7 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
int ret;
|
||||
|
||||
/* Some checks before mangling */
|
||||
if (!tcp_csum_check(cp->af, skb, pp))
|
||||
if (!tcp_csum_check(cp->af, skb, pp, tcphoff))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
|
|
@ -300,17 +301,9 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
|
||||
|
||||
static int
|
||||
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
|
||||
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
|
||||
unsigned int tcphoff)
|
||||
{
|
||||
unsigned int tcphoff;
|
||||
|
||||
#ifdef CONFIG_IP_VS_IPV6
|
||||
if (af == AF_INET6)
|
||||
tcphoff = sizeof(struct ipv6hdr);
|
||||
else
|
||||
#endif
|
||||
tcphoff = ip_hdrlen(skb);
|
||||
|
||||
switch (skb->ip_summed) {
|
||||
case CHECKSUM_NONE:
|
||||
skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0);
|
||||
|
|
@ -321,7 +314,7 @@ tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
|
|||
if (csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
|
||||
&ipv6_hdr(skb)->daddr,
|
||||
skb->len - tcphoff,
|
||||
ipv6_hdr(skb)->nexthdr,
|
||||
IPPROTO_TCP,
|
||||
skb->csum)) {
|
||||
IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
|
||||
"Failed checksum for");
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@
|
|||
#include <net/ip6_checksum.h>
|
||||
|
||||
static int
|
||||
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp);
|
||||
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
|
||||
unsigned int udphoff);
|
||||
|
||||
static int
|
||||
udp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
|
||||
|
|
@ -154,7 +155,7 @@ udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
int ret;
|
||||
|
||||
/* Some checks before mangling */
|
||||
if (!udp_csum_check(cp->af, skb, pp))
|
||||
if (!udp_csum_check(cp->af, skb, pp, udphoff))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
|
|
@ -237,7 +238,7 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
int ret;
|
||||
|
||||
/* Some checks before mangling */
|
||||
if (!udp_csum_check(cp->af, skb, pp))
|
||||
if (!udp_csum_check(cp->af, skb, pp, udphoff))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
|
|
@ -296,17 +297,10 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|||
|
||||
|
||||
static int
|
||||
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
|
||||
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
|
||||
unsigned int udphoff)
|
||||
{
|
||||
struct udphdr _udph, *uh;
|
||||
unsigned int udphoff;
|
||||
|
||||
#ifdef CONFIG_IP_VS_IPV6
|
||||
if (af == AF_INET6)
|
||||
udphoff = sizeof(struct ipv6hdr);
|
||||
else
|
||||
#endif
|
||||
udphoff = ip_hdrlen(skb);
|
||||
|
||||
uh = skb_header_pointer(skb, udphoff, sizeof(_udph), &_udph);
|
||||
if (uh == NULL)
|
||||
|
|
@ -324,7 +318,7 @@ udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
|
|||
if (csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
|
||||
&ipv6_hdr(skb)->daddr,
|
||||
skb->len - udphoff,
|
||||
ipv6_hdr(skb)->nexthdr,
|
||||
IPPROTO_UDP,
|
||||
skb->csum)) {
|
||||
IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
|
||||
"Failed checksum for");
|
||||
|
|
|
|||
|
|
@ -294,6 +294,12 @@ static inline bool decrement_ttl(struct netns_ipvs *ipvs,
|
|||
return true;
|
||||
}
|
||||
|
||||
/* rt has device that is down */
|
||||
static bool rt_dev_is_down(const struct net_device *dev)
|
||||
{
|
||||
return dev && !netif_running(dev);
|
||||
}
|
||||
|
||||
/* Get route to destination or remote server */
|
||||
static int
|
||||
__ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
|
||||
|
|
@ -309,9 +315,11 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
|
|||
|
||||
if (dest) {
|
||||
dest_dst = __ip_vs_dst_check(dest);
|
||||
if (likely(dest_dst))
|
||||
if (likely(dest_dst)) {
|
||||
rt = dst_rtable(dest_dst->dst_cache);
|
||||
else {
|
||||
if (ret_saddr)
|
||||
*ret_saddr = dest_dst->dst_saddr.ip;
|
||||
} else {
|
||||
dest_dst = ip_vs_dest_dst_alloc();
|
||||
spin_lock_bh(&dest->dst_lock);
|
||||
if (!dest_dst) {
|
||||
|
|
@ -327,14 +335,22 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
|
|||
ip_vs_dest_dst_free(dest_dst);
|
||||
goto err_unreach;
|
||||
}
|
||||
__ip_vs_dst_set(dest, dest_dst, &rt->dst, 0);
|
||||
/* It is forbidden to attach dest->dest_dst if
|
||||
* device is going down.
|
||||
*/
|
||||
if (!rt_dev_is_down(dst_dev_rcu(&rt->dst)))
|
||||
__ip_vs_dst_set(dest, dest_dst, &rt->dst, 0);
|
||||
else
|
||||
noref = 0;
|
||||
spin_unlock_bh(&dest->dst_lock);
|
||||
IP_VS_DBG(10, "new dst %pI4, src %pI4, refcnt=%d\n",
|
||||
&dest->addr.ip, &dest_dst->dst_saddr.ip,
|
||||
rcuref_read(&rt->dst.__rcuref));
|
||||
if (ret_saddr)
|
||||
*ret_saddr = dest_dst->dst_saddr.ip;
|
||||
if (!noref)
|
||||
ip_vs_dest_dst_free(dest_dst);
|
||||
}
|
||||
if (ret_saddr)
|
||||
*ret_saddr = dest_dst->dst_saddr.ip;
|
||||
} else {
|
||||
noref = 0;
|
||||
|
||||
|
|
@ -471,9 +487,11 @@ __ip_vs_get_out_rt_v6(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
|
|||
|
||||
if (dest) {
|
||||
dest_dst = __ip_vs_dst_check(dest);
|
||||
if (likely(dest_dst))
|
||||
if (likely(dest_dst)) {
|
||||
rt = dst_rt6_info(dest_dst->dst_cache);
|
||||
else {
|
||||
if (ret_saddr)
|
||||
*ret_saddr = dest_dst->dst_saddr.in6;
|
||||
} else {
|
||||
u32 cookie;
|
||||
|
||||
dest_dst = ip_vs_dest_dst_alloc();
|
||||
|
|
@ -494,14 +512,22 @@ __ip_vs_get_out_rt_v6(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
|
|||
}
|
||||
rt = dst_rt6_info(dst);
|
||||
cookie = rt6_get_cookie(rt);
|
||||
__ip_vs_dst_set(dest, dest_dst, &rt->dst, cookie);
|
||||
/* It is forbidden to attach dest->dest_dst if
|
||||
* device is going down.
|
||||
*/
|
||||
if (!rt_dev_is_down(dst_dev_rcu(&rt->dst)))
|
||||
__ip_vs_dst_set(dest, dest_dst, &rt->dst, cookie);
|
||||
else
|
||||
noref = 0;
|
||||
spin_unlock_bh(&dest->dst_lock);
|
||||
IP_VS_DBG(10, "new dst %pI6, src %pI6, refcnt=%d\n",
|
||||
&dest->addr.in6, &dest_dst->dst_saddr.in6,
|
||||
rcuref_read(&rt->dst.__rcuref));
|
||||
if (ret_saddr)
|
||||
*ret_saddr = dest_dst->dst_saddr.in6;
|
||||
if (!noref)
|
||||
ip_vs_dest_dst_free(dest_dst);
|
||||
}
|
||||
if (ret_saddr)
|
||||
*ret_saddr = dest_dst->dst_saddr.in6;
|
||||
} else {
|
||||
noref = 0;
|
||||
dst = __ip_vs_route_output_v6(net, daddr, ret_saddr, do_xfrm,
|
||||
|
|
|
|||
|
|
@ -37,13 +37,13 @@ MODULE_PARM_DESC(master_timeout, "timeout for the master connection");
|
|||
module_param(ts_algo, charp, 0400);
|
||||
MODULE_PARM_DESC(ts_algo, "textsearch algorithm to use (default kmp)");
|
||||
|
||||
unsigned int (*nf_nat_amanda_hook)(struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned int matchoff,
|
||||
unsigned int matchlen,
|
||||
struct nf_conntrack_expect *exp)
|
||||
__read_mostly;
|
||||
unsigned int (__rcu *nf_nat_amanda_hook)(struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned int matchoff,
|
||||
unsigned int matchlen,
|
||||
struct nf_conntrack_expect *exp)
|
||||
__read_mostly;
|
||||
EXPORT_SYMBOL_GPL(nf_nat_amanda_hook);
|
||||
|
||||
enum amanda_strings {
|
||||
|
|
|
|||
|
|
@ -43,13 +43,13 @@ module_param_array(ports, ushort, &ports_c, 0400);
|
|||
static bool loose;
|
||||
module_param(loose, bool, 0600);
|
||||
|
||||
unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
enum nf_ct_ftp_type type,
|
||||
unsigned int protoff,
|
||||
unsigned int matchoff,
|
||||
unsigned int matchlen,
|
||||
struct nf_conntrack_expect *exp);
|
||||
unsigned int (__rcu *nf_nat_ftp_hook)(struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
enum nf_ct_ftp_type type,
|
||||
unsigned int protoff,
|
||||
unsigned int matchoff,
|
||||
unsigned int matchlen,
|
||||
struct nf_conntrack_expect *exp);
|
||||
EXPORT_SYMBOL_GPL(nf_nat_ftp_hook);
|
||||
|
||||
static int try_rfc959(const char *, size_t, struct nf_conntrack_man *,
|
||||
|
|
|
|||
|
|
@ -1187,13 +1187,13 @@ static struct nf_conntrack_expect *find_expect(struct nf_conn *ct,
|
|||
{
|
||||
struct net *net = nf_ct_net(ct);
|
||||
struct nf_conntrack_expect *exp;
|
||||
struct nf_conntrack_tuple tuple;
|
||||
struct nf_conntrack_tuple tuple = {
|
||||
.src.l3num = nf_ct_l3num(ct),
|
||||
.dst.protonum = IPPROTO_TCP,
|
||||
.dst.u.tcp.port = port,
|
||||
};
|
||||
|
||||
memset(&tuple.src.u3, 0, sizeof(tuple.src.u3));
|
||||
tuple.src.u.tcp.port = 0;
|
||||
memcpy(&tuple.dst.u3, addr, sizeof(tuple.dst.u3));
|
||||
tuple.dst.u.tcp.port = port;
|
||||
tuple.dst.protonum = IPPROTO_TCP;
|
||||
|
||||
exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple);
|
||||
if (exp && exp->master == ct)
|
||||
|
|
|
|||
|
|
@ -30,12 +30,13 @@ static unsigned int dcc_timeout __read_mostly = 300;
|
|||
static char *irc_buffer;
|
||||
static DEFINE_SPINLOCK(irc_buffer_lock);
|
||||
|
||||
unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned int matchoff,
|
||||
unsigned int matchlen,
|
||||
struct nf_conntrack_expect *exp) __read_mostly;
|
||||
unsigned int (__rcu *nf_nat_irc_hook)(struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned int matchoff,
|
||||
unsigned int matchlen,
|
||||
struct nf_conntrack_expect *exp)
|
||||
__read_mostly;
|
||||
EXPORT_SYMBOL_GPL(nf_nat_irc_hook);
|
||||
|
||||
#define HELPER_NAME "irc"
|
||||
|
|
|
|||
|
|
@ -25,10 +25,10 @@ static unsigned int timeout __read_mostly = 30;
|
|||
module_param(timeout, uint, 0400);
|
||||
MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds");
|
||||
|
||||
int (*nf_nat_snmp_hook)(struct sk_buff *skb,
|
||||
unsigned int protoff,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo);
|
||||
int (__rcu *nf_nat_snmp_hook)(struct sk_buff *skb,
|
||||
unsigned int protoff,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo);
|
||||
EXPORT_SYMBOL_GPL(nf_nat_snmp_hook);
|
||||
|
||||
static int snmp_conntrack_help(struct sk_buff *skb, unsigned int protoff,
|
||||
|
|
|
|||
|
|
@ -32,9 +32,10 @@ static unsigned int ports_c;
|
|||
module_param_array(ports, ushort, &ports_c, 0400);
|
||||
MODULE_PARM_DESC(ports, "Port numbers of TFTP servers");
|
||||
|
||||
unsigned int (*nf_nat_tftp_hook)(struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
struct nf_conntrack_expect *exp) __read_mostly;
|
||||
unsigned int (__rcu *nf_nat_tftp_hook)(struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
struct nf_conntrack_expect *exp)
|
||||
__read_mostly;
|
||||
EXPORT_SYMBOL_GPL(nf_nat_tftp_hook);
|
||||
|
||||
static int tftp_help(struct sk_buff *skb,
|
||||
|
|
|
|||
|
|
@ -2823,6 +2823,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 policy,
|
|||
|
||||
err_register_hook:
|
||||
nft_chain_del(chain);
|
||||
synchronize_rcu();
|
||||
err_chain_add:
|
||||
nft_trans_destroy(trans);
|
||||
err_trans:
|
||||
|
|
@ -3901,23 +3902,6 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
|
|||
return skb->len;
|
||||
}
|
||||
|
||||
static int nf_tables_dumpreset_rules(struct sk_buff *skb,
|
||||
struct netlink_callback *cb)
|
||||
{
|
||||
struct nftables_pernet *nft_net = nft_pernet(sock_net(skb->sk));
|
||||
int ret;
|
||||
|
||||
/* Mutex is held is to prevent that two concurrent dump-and-reset calls
|
||||
* do not underrun counters and quotas. The commit_mutex is used for
|
||||
* the lack a better lock, this is not transaction path.
|
||||
*/
|
||||
mutex_lock(&nft_net->commit_mutex);
|
||||
ret = nf_tables_dump_rules(skb, cb);
|
||||
mutex_unlock(&nft_net->commit_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nf_tables_dump_rules_start(struct netlink_callback *cb)
|
||||
{
|
||||
struct nft_rule_dump_ctx *ctx = (void *)cb->ctx;
|
||||
|
|
@ -3937,18 +3921,12 @@ static int nf_tables_dump_rules_start(struct netlink_callback *cb)
|
|||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETRULE_RESET)
|
||||
ctx->reset = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nf_tables_dumpreset_rules_start(struct netlink_callback *cb)
|
||||
{
|
||||
struct nft_rule_dump_ctx *ctx = (void *)cb->ctx;
|
||||
|
||||
ctx->reset = true;
|
||||
|
||||
return nf_tables_dump_rules_start(cb);
|
||||
}
|
||||
|
||||
static int nf_tables_dump_rules_done(struct netlink_callback *cb)
|
||||
{
|
||||
struct nft_rule_dump_ctx *ctx = (void *)cb->ctx;
|
||||
|
|
@ -4012,6 +3990,8 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
|
|||
u32 portid = NETLINK_CB(skb).portid;
|
||||
struct net *net = info->net;
|
||||
struct sk_buff *skb2;
|
||||
bool reset = false;
|
||||
char *buf;
|
||||
|
||||
if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
|
||||
struct netlink_dump_control c = {
|
||||
|
|
@ -4025,46 +4005,15 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
|
|||
return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
|
||||
}
|
||||
|
||||
skb2 = nf_tables_getrule_single(portid, info, nla, false);
|
||||
if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETRULE_RESET)
|
||||
reset = true;
|
||||
|
||||
skb2 = nf_tables_getrule_single(portid, info, nla, reset);
|
||||
if (IS_ERR(skb2))
|
||||
return PTR_ERR(skb2);
|
||||
|
||||
return nfnetlink_unicast(skb2, net, portid);
|
||||
}
|
||||
|
||||
static int nf_tables_getrule_reset(struct sk_buff *skb,
|
||||
const struct nfnl_info *info,
|
||||
const struct nlattr * const nla[])
|
||||
{
|
||||
struct nftables_pernet *nft_net = nft_pernet(info->net);
|
||||
u32 portid = NETLINK_CB(skb).portid;
|
||||
struct net *net = info->net;
|
||||
struct sk_buff *skb2;
|
||||
char *buf;
|
||||
|
||||
if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
|
||||
struct netlink_dump_control c = {
|
||||
.start= nf_tables_dumpreset_rules_start,
|
||||
.dump = nf_tables_dumpreset_rules,
|
||||
.done = nf_tables_dump_rules_done,
|
||||
.module = THIS_MODULE,
|
||||
.data = (void *)nla,
|
||||
};
|
||||
|
||||
return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
|
||||
}
|
||||
|
||||
if (!try_module_get(THIS_MODULE))
|
||||
return -EINVAL;
|
||||
rcu_read_unlock();
|
||||
mutex_lock(&nft_net->commit_mutex);
|
||||
skb2 = nf_tables_getrule_single(portid, info, nla, true);
|
||||
mutex_unlock(&nft_net->commit_mutex);
|
||||
rcu_read_lock();
|
||||
module_put(THIS_MODULE);
|
||||
|
||||
if (IS_ERR(skb2))
|
||||
return PTR_ERR(skb2);
|
||||
if (!reset)
|
||||
return nfnetlink_unicast(skb2, net, portid);
|
||||
|
||||
buf = kasprintf(GFP_ATOMIC, "%.*s:%u",
|
||||
nla_len(nla[NFTA_RULE_TABLE]),
|
||||
|
|
@ -6324,6 +6273,10 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
nla_nest_end(skb, nest);
|
||||
nlmsg_end(skb, nlh);
|
||||
|
||||
if (dump_ctx->reset && args.iter.count > args.iter.skip)
|
||||
audit_log_nft_set_reset(table, cb->seq,
|
||||
args.iter.count - args.iter.skip);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
if (args.iter.err && args.iter.err != -EMSGSIZE)
|
||||
|
|
@ -6339,26 +6292,6 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
return -ENOSPC;
|
||||
}
|
||||
|
||||
static int nf_tables_dumpreset_set(struct sk_buff *skb,
|
||||
struct netlink_callback *cb)
|
||||
{
|
||||
struct nftables_pernet *nft_net = nft_pernet(sock_net(skb->sk));
|
||||
struct nft_set_dump_ctx *dump_ctx = cb->data;
|
||||
int ret, skip = cb->args[0];
|
||||
|
||||
mutex_lock(&nft_net->commit_mutex);
|
||||
|
||||
ret = nf_tables_dump_set(skb, cb);
|
||||
|
||||
if (cb->args[0] > skip)
|
||||
audit_log_nft_set_reset(dump_ctx->ctx.table, cb->seq,
|
||||
cb->args[0] - skip);
|
||||
|
||||
mutex_unlock(&nft_net->commit_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nf_tables_dump_set_start(struct netlink_callback *cb)
|
||||
{
|
||||
struct nft_set_dump_ctx *dump_ctx = cb->data;
|
||||
|
|
@ -6602,8 +6535,13 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
|
|||
{
|
||||
struct netlink_ext_ack *extack = info->extack;
|
||||
struct nft_set_dump_ctx dump_ctx;
|
||||
int rem, err = 0, nelems = 0;
|
||||
struct net *net = info->net;
|
||||
struct nlattr *attr;
|
||||
int rem, err = 0;
|
||||
bool reset = false;
|
||||
|
||||
if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETSETELEM_RESET)
|
||||
reset = true;
|
||||
|
||||
if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
|
||||
struct netlink_dump_control c = {
|
||||
|
|
@ -6613,7 +6551,7 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
|
|||
.module = THIS_MODULE,
|
||||
};
|
||||
|
||||
err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, false);
|
||||
err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, reset);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
|
@ -6624,75 +6562,21 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
|
|||
if (!nla[NFTA_SET_ELEM_LIST_ELEMENTS])
|
||||
return -EINVAL;
|
||||
|
||||
err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, false);
|
||||
err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, reset);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
|
||||
err = nft_get_set_elem(&dump_ctx.ctx, dump_ctx.set, attr, false);
|
||||
if (err < 0) {
|
||||
NL_SET_BAD_ATTR(extack, attr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nf_tables_getsetelem_reset(struct sk_buff *skb,
|
||||
const struct nfnl_info *info,
|
||||
const struct nlattr * const nla[])
|
||||
{
|
||||
struct nftables_pernet *nft_net = nft_pernet(info->net);
|
||||
struct netlink_ext_ack *extack = info->extack;
|
||||
struct nft_set_dump_ctx dump_ctx;
|
||||
int rem, err = 0, nelems = 0;
|
||||
struct nlattr *attr;
|
||||
|
||||
if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
|
||||
struct netlink_dump_control c = {
|
||||
.start = nf_tables_dump_set_start,
|
||||
.dump = nf_tables_dumpreset_set,
|
||||
.done = nf_tables_dump_set_done,
|
||||
.module = THIS_MODULE,
|
||||
};
|
||||
|
||||
err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, true);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
c.data = &dump_ctx;
|
||||
return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
|
||||
}
|
||||
|
||||
if (!nla[NFTA_SET_ELEM_LIST_ELEMENTS])
|
||||
return -EINVAL;
|
||||
|
||||
if (!try_module_get(THIS_MODULE))
|
||||
return -EINVAL;
|
||||
rcu_read_unlock();
|
||||
mutex_lock(&nft_net->commit_mutex);
|
||||
rcu_read_lock();
|
||||
|
||||
err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, true);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
|
||||
nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
|
||||
err = nft_get_set_elem(&dump_ctx.ctx, dump_ctx.set, attr, true);
|
||||
err = nft_get_set_elem(&dump_ctx.ctx, dump_ctx.set, attr, reset);
|
||||
if (err < 0) {
|
||||
NL_SET_BAD_ATTR(extack, attr);
|
||||
break;
|
||||
}
|
||||
nelems++;
|
||||
}
|
||||
audit_log_nft_set_reset(dump_ctx.ctx.table, nft_base_seq(info->net), nelems);
|
||||
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
mutex_unlock(&nft_net->commit_mutex);
|
||||
rcu_read_lock();
|
||||
module_put(THIS_MODULE);
|
||||
if (reset)
|
||||
audit_log_nft_set_reset(dump_ctx.ctx.table, nft_base_seq(net),
|
||||
nelems);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
@ -8564,19 +8448,6 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
return skb->len;
|
||||
}
|
||||
|
||||
static int nf_tables_dumpreset_obj(struct sk_buff *skb,
|
||||
struct netlink_callback *cb)
|
||||
{
|
||||
struct nftables_pernet *nft_net = nft_pernet(sock_net(skb->sk));
|
||||
int ret;
|
||||
|
||||
mutex_lock(&nft_net->commit_mutex);
|
||||
ret = nf_tables_dump_obj(skb, cb);
|
||||
mutex_unlock(&nft_net->commit_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nf_tables_dump_obj_start(struct netlink_callback *cb)
|
||||
{
|
||||
struct nft_obj_dump_ctx *ctx = (void *)cb->ctx;
|
||||
|
|
@ -8593,18 +8464,12 @@ static int nf_tables_dump_obj_start(struct netlink_callback *cb)
|
|||
if (nla[NFTA_OBJ_TYPE])
|
||||
ctx->type = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
|
||||
|
||||
if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
|
||||
ctx->reset = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nf_tables_dumpreset_obj_start(struct netlink_callback *cb)
|
||||
{
|
||||
struct nft_obj_dump_ctx *ctx = (void *)cb->ctx;
|
||||
|
||||
ctx->reset = true;
|
||||
|
||||
return nf_tables_dump_obj_start(cb);
|
||||
}
|
||||
|
||||
static int nf_tables_dump_obj_done(struct netlink_callback *cb)
|
||||
{
|
||||
struct nft_obj_dump_ctx *ctx = (void *)cb->ctx;
|
||||
|
|
@ -8665,7 +8530,10 @@ static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info,
|
|||
const struct nlattr * const nla[])
|
||||
{
|
||||
u32 portid = NETLINK_CB(skb).portid;
|
||||
struct net *net = info->net;
|
||||
struct sk_buff *skb2;
|
||||
bool reset = false;
|
||||
char *buf;
|
||||
|
||||
if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
|
||||
struct netlink_dump_control c = {
|
||||
|
|
@ -8679,46 +8547,15 @@ static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info,
|
|||
return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
|
||||
}
|
||||
|
||||
skb2 = nf_tables_getobj_single(portid, info, nla, false);
|
||||
if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
|
||||
reset = true;
|
||||
|
||||
skb2 = nf_tables_getobj_single(portid, info, nla, reset);
|
||||
if (IS_ERR(skb2))
|
||||
return PTR_ERR(skb2);
|
||||
|
||||
return nfnetlink_unicast(skb2, info->net, portid);
|
||||
}
|
||||
|
||||
static int nf_tables_getobj_reset(struct sk_buff *skb,
|
||||
const struct nfnl_info *info,
|
||||
const struct nlattr * const nla[])
|
||||
{
|
||||
struct nftables_pernet *nft_net = nft_pernet(info->net);
|
||||
u32 portid = NETLINK_CB(skb).portid;
|
||||
struct net *net = info->net;
|
||||
struct sk_buff *skb2;
|
||||
char *buf;
|
||||
|
||||
if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
|
||||
struct netlink_dump_control c = {
|
||||
.start = nf_tables_dumpreset_obj_start,
|
||||
.dump = nf_tables_dumpreset_obj,
|
||||
.done = nf_tables_dump_obj_done,
|
||||
.module = THIS_MODULE,
|
||||
.data = (void *)nla,
|
||||
};
|
||||
|
||||
return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
|
||||
}
|
||||
|
||||
if (!try_module_get(THIS_MODULE))
|
||||
return -EINVAL;
|
||||
rcu_read_unlock();
|
||||
mutex_lock(&nft_net->commit_mutex);
|
||||
skb2 = nf_tables_getobj_single(portid, info, nla, true);
|
||||
mutex_unlock(&nft_net->commit_mutex);
|
||||
rcu_read_lock();
|
||||
module_put(THIS_MODULE);
|
||||
|
||||
if (IS_ERR(skb2))
|
||||
return PTR_ERR(skb2);
|
||||
if (!reset)
|
||||
return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
|
||||
|
||||
buf = kasprintf(GFP_ATOMIC, "%.*s:%u",
|
||||
nla_len(nla[NFTA_OBJ_TABLE]),
|
||||
|
|
@ -10037,7 +9874,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
|
|||
.policy = nft_rule_policy,
|
||||
},
|
||||
[NFT_MSG_GETRULE_RESET] = {
|
||||
.call = nf_tables_getrule_reset,
|
||||
.call = nf_tables_getrule,
|
||||
.type = NFNL_CB_RCU,
|
||||
.attr_count = NFTA_RULE_MAX,
|
||||
.policy = nft_rule_policy,
|
||||
|
|
@ -10091,7 +9928,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
|
|||
.policy = nft_set_elem_list_policy,
|
||||
},
|
||||
[NFT_MSG_GETSETELEM_RESET] = {
|
||||
.call = nf_tables_getsetelem_reset,
|
||||
.call = nf_tables_getsetelem,
|
||||
.type = NFNL_CB_RCU,
|
||||
.attr_count = NFTA_SET_ELEM_LIST_MAX,
|
||||
.policy = nft_set_elem_list_policy,
|
||||
|
|
@ -10137,7 +9974,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
|
|||
.policy = nft_obj_policy,
|
||||
},
|
||||
[NFT_MSG_GETOBJ_RESET] = {
|
||||
.call = nf_tables_getobj_reset,
|
||||
.call = nf_tables_getobj,
|
||||
.type = NFNL_CB_RCU,
|
||||
.attr_count = NFTA_OBJ_MAX,
|
||||
.policy = nft_obj_policy,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@ struct nft_counter_percpu_priv {
|
|||
|
||||
static DEFINE_PER_CPU(struct u64_stats_sync, nft_counter_sync);
|
||||
|
||||
/* control plane only: sync fetch+reset */
|
||||
static DEFINE_SPINLOCK(nft_counter_lock);
|
||||
|
||||
static inline void nft_counter_do_eval(struct nft_counter_percpu_priv *priv,
|
||||
struct nft_regs *regs,
|
||||
const struct nft_pktinfo *pkt)
|
||||
|
|
@ -148,13 +151,25 @@ static void nft_counter_fetch(struct nft_counter_percpu_priv *priv,
|
|||
}
|
||||
}
|
||||
|
||||
static void nft_counter_fetch_and_reset(struct nft_counter_percpu_priv *priv,
|
||||
struct nft_counter_tot *total)
|
||||
{
|
||||
spin_lock(&nft_counter_lock);
|
||||
nft_counter_fetch(priv, total);
|
||||
nft_counter_reset(priv, total);
|
||||
spin_unlock(&nft_counter_lock);
|
||||
}
|
||||
|
||||
static int nft_counter_do_dump(struct sk_buff *skb,
|
||||
struct nft_counter_percpu_priv *priv,
|
||||
bool reset)
|
||||
{
|
||||
struct nft_counter_tot total;
|
||||
|
||||
nft_counter_fetch(priv, &total);
|
||||
if (unlikely(reset))
|
||||
nft_counter_fetch_and_reset(priv, &total);
|
||||
else
|
||||
nft_counter_fetch(priv, &total);
|
||||
|
||||
if (nla_put_be64(skb, NFTA_COUNTER_BYTES, cpu_to_be64(total.bytes),
|
||||
NFTA_COUNTER_PAD) ||
|
||||
|
|
@ -162,9 +177,6 @@ static int nft_counter_do_dump(struct sk_buff *skb,
|
|||
NFTA_COUNTER_PAD))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (reset)
|
||||
nft_counter_reset(priv, &total);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
|
|
|
|||
|
|
@ -140,11 +140,16 @@ static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv,
|
|||
u64 consumed, consumed_cap, quota;
|
||||
u32 flags = priv->flags;
|
||||
|
||||
/* Since we inconditionally increment consumed quota for each packet
|
||||
/* Since we unconditionally increment consumed quota for each packet
|
||||
* that we see, don't go over the quota boundary in what we send to
|
||||
* userspace.
|
||||
*/
|
||||
consumed = atomic64_read(priv->consumed);
|
||||
if (reset) {
|
||||
consumed = atomic64_xchg(priv->consumed, 0);
|
||||
clear_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags);
|
||||
} else {
|
||||
consumed = atomic64_read(priv->consumed);
|
||||
}
|
||||
quota = atomic64_read(&priv->quota);
|
||||
if (consumed >= quota) {
|
||||
consumed_cap = quota;
|
||||
|
|
@ -160,10 +165,6 @@ static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv,
|
|||
nla_put_be32(skb, NFTA_QUOTA_FLAGS, htonl(flags)))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (reset) {
|
||||
atomic64_sub(consumed, priv->consumed);
|
||||
clear_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags);
|
||||
}
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user