mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-15 16:53:54 +08:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
Pablo Neira Ayuso says: ==================== Netfilter/IPVS updates for net-next The following patchset contains Netfilter/IPVS updates for your net-next tree. A couple of new features for nf_tables, and unsorted cleanups and incremental updates for the Netfilter tree. More specifically, they are: 1) Allow to check for TCP option presence via nft_exthdr, patch from Phil Sutter. 2) Add symmetric hash support to nft_hash, from Laura Garcia Liebana. 3) Use pr_cont() in ebt_log, from Joe Perches. 4) Remove some dead code in arp_tables reported via static analysis tool, from Colin Ian King. 5) Consolidate nf_tables expression validation, from Liping Zhang. 6) Consolidate set lookup via nft_set_lookup(). 7) Remove unnecessary rcu read lock side in bridge netfilter, from Florian Westphal. 8) Remove unused variable in nf_reject_ipv4, from Tahee Yoo. 9) Pass nft_ctx struct to object initialization indirections, from Florian Westphal. 10) Add code to integrate conntrack helper into nf_tables, also from Florian. 11) Allow to check if interface index or name exists via NFTA_FIB_F_PRESENT, from Phil Sutter. 12) Simplify resolve_normal_ct(), from Florian. 13) Use per-limit spinlock in nft_limit and xt_limit, from Liping Zhang. 14) Use rwlock in nft_set_rbtree set, also from Liping Zhang. 15) One patch to remove a useless printk at netns init path in ipvs, and several patches to document IPVS knobs. 16) Use refcount_t for reference counter in the Netfilter/IPVS code, from Elena Reshetova. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
41e95736b3
@ -175,6 +175,14 @@ nat_icmp_send - BOOLEAN
|
||||
for VS/NAT when the load balancer receives packets from real
|
||||
servers but the connection entries don't exist.
|
||||
|
||||
pmtu_disc - BOOLEAN
|
||||
0 - disabled
|
||||
not 0 - enabled (default)
|
||||
|
||||
By default, reject with FRAG_NEEDED all DF packets that exceed
|
||||
the PMTU, irrespective of the forwarding method. For TUN method
|
||||
the flag can be disabled to fragment such packets.
|
||||
|
||||
secure_tcp - INTEGER
|
||||
0 - disabled (default)
|
||||
|
||||
@ -185,15 +193,59 @@ secure_tcp - INTEGER
|
||||
The value definition is the same as that of drop_entry and
|
||||
drop_packet.
|
||||
|
||||
sync_threshold - INTEGER
|
||||
default 3
|
||||
sync_threshold - vector of 2 INTEGERs: sync_threshold, sync_period
|
||||
default 3 50
|
||||
|
||||
It sets synchronization threshold, which is the minimum number
|
||||
of incoming packets that a connection needs to receive before
|
||||
the connection will be synchronized. A connection will be
|
||||
synchronized, every time the number of its incoming packets
|
||||
modulus 50 equals the threshold. The range of the threshold is
|
||||
from 0 to 49.
|
||||
It sets synchronization threshold, which is the minimum number
|
||||
of incoming packets that a connection needs to receive before
|
||||
the connection will be synchronized. A connection will be
|
||||
synchronized, every time the number of its incoming packets
|
||||
modulus sync_period equals the threshold. The range of the
|
||||
threshold is from 0 to sync_period.
|
||||
|
||||
When sync_period and sync_refresh_period are 0, send sync only
|
||||
for state changes or only once when pkts matches sync_threshold
|
||||
|
||||
sync_refresh_period - UNSIGNED INTEGER
|
||||
default 0
|
||||
|
||||
In seconds, difference in reported connection timer that triggers
|
||||
new sync message. It can be used to avoid sync messages for the
|
||||
specified period (or half of the connection timeout if it is lower)
|
||||
if connection state is not changed since last sync.
|
||||
|
||||
This is useful for normal connections with high traffic to reduce
|
||||
sync rate. Additionally, retry sync_retries times with period of
|
||||
sync_refresh_period/8.
|
||||
|
||||
sync_retries - INTEGER
|
||||
default 0
|
||||
|
||||
Defines sync retries with period of sync_refresh_period/8. Useful
|
||||
to protect against loss of sync messages. The range of the
|
||||
sync_retries is from 0 to 3.
|
||||
|
||||
sync_qlen_max - UNSIGNED LONG
|
||||
|
||||
Hard limit for queued sync messages that are not sent yet. It
|
||||
defaults to 1/32 of the memory pages but actually represents
|
||||
number of messages. It will protect us from allocating large
|
||||
parts of memory when the sending rate is lower than the queuing
|
||||
rate.
|
||||
|
||||
sync_sock_size - INTEGER
|
||||
default 0
|
||||
|
||||
Configuration of SNDBUF (master) or RCVBUF (slave) socket limit.
|
||||
Default value is 0 (preserve system defaults).
|
||||
|
||||
sync_ports - INTEGER
|
||||
default 1
|
||||
|
||||
The number of threads that master and backup servers can use for
|
||||
sync traffic. Every thread will use single UDP port, thread 0 will
|
||||
use the default port 8848 while last thread will use port
|
||||
8848+sync_ports-1.
|
||||
|
||||
snat_reroute - BOOLEAN
|
||||
0 - disabled
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include <linux/list.h> /* for struct list_head */
|
||||
#include <linux/spinlock.h> /* for struct rwlock_t */
|
||||
#include <linux/atomic.h> /* for struct atomic_t */
|
||||
#include <linux/refcount.h> /* for struct refcount_t */
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/bug.h>
|
||||
@ -525,7 +527,7 @@ struct ip_vs_conn {
|
||||
struct netns_ipvs *ipvs;
|
||||
|
||||
/* counter and timer */
|
||||
atomic_t refcnt; /* reference count */
|
||||
refcount_t refcnt; /* reference count */
|
||||
struct timer_list timer; /* Expiration timer */
|
||||
volatile unsigned long timeout; /* timeout */
|
||||
|
||||
@ -667,7 +669,7 @@ struct ip_vs_dest {
|
||||
atomic_t conn_flags; /* flags to copy to conn */
|
||||
atomic_t weight; /* server weight */
|
||||
|
||||
atomic_t refcnt; /* reference counter */
|
||||
refcount_t refcnt; /* reference counter */
|
||||
struct ip_vs_stats stats; /* statistics */
|
||||
unsigned long idle_start; /* start time, jiffies */
|
||||
|
||||
@ -1211,14 +1213,14 @@ struct ip_vs_conn * ip_vs_conn_out_get_proto(struct netns_ipvs *ipvs, int af,
|
||||
*/
|
||||
static inline bool __ip_vs_conn_get(struct ip_vs_conn *cp)
|
||||
{
|
||||
return atomic_inc_not_zero(&cp->refcnt);
|
||||
return refcount_inc_not_zero(&cp->refcnt);
|
||||
}
|
||||
|
||||
/* put back the conn without restarting its timer */
|
||||
static inline void __ip_vs_conn_put(struct ip_vs_conn *cp)
|
||||
{
|
||||
smp_mb__before_atomic();
|
||||
atomic_dec(&cp->refcnt);
|
||||
refcount_dec(&cp->refcnt);
|
||||
}
|
||||
void ip_vs_conn_put(struct ip_vs_conn *cp);
|
||||
void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport);
|
||||
@ -1410,18 +1412,18 @@ void ip_vs_try_bind_dest(struct ip_vs_conn *cp);
|
||||
|
||||
static inline void ip_vs_dest_hold(struct ip_vs_dest *dest)
|
||||
{
|
||||
atomic_inc(&dest->refcnt);
|
||||
refcount_inc(&dest->refcnt);
|
||||
}
|
||||
|
||||
static inline void ip_vs_dest_put(struct ip_vs_dest *dest)
|
||||
{
|
||||
smp_mb__before_atomic();
|
||||
atomic_dec(&dest->refcnt);
|
||||
refcount_dec(&dest->refcnt);
|
||||
}
|
||||
|
||||
static inline void ip_vs_dest_put_and_free(struct ip_vs_dest *dest)
|
||||
{
|
||||
if (atomic_dec_and_test(&dest->refcnt))
|
||||
if (refcount_dec_and_test(&dest->refcnt))
|
||||
kfree(dest);
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,8 @@
|
||||
#ifndef _NF_CONNTRACK_EXPECT_H
|
||||
#define _NF_CONNTRACK_EXPECT_H
|
||||
|
||||
#include <linux/refcount.h>
|
||||
|
||||
#include <net/netfilter/nf_conntrack.h>
|
||||
#include <net/netfilter/nf_conntrack_zones.h>
|
||||
|
||||
@ -37,7 +39,7 @@ struct nf_conntrack_expect {
|
||||
struct timer_list timeout;
|
||||
|
||||
/* Usage count. */
|
||||
atomic_t use;
|
||||
refcount_t use;
|
||||
|
||||
/* Flags */
|
||||
unsigned int flags;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <net/net_namespace.h>
|
||||
#include <linux/netfilter/nf_conntrack_common.h>
|
||||
#include <linux/netfilter/nf_conntrack_tuple_common.h>
|
||||
#include <linux/refcount.h>
|
||||
#include <net/netfilter/nf_conntrack.h>
|
||||
#include <net/netfilter/nf_conntrack_extend.h>
|
||||
|
||||
@ -12,7 +13,7 @@
|
||||
struct ctnl_timeout {
|
||||
struct list_head head;
|
||||
struct rcu_head rcu_head;
|
||||
atomic_t refcnt;
|
||||
refcount_t refcnt;
|
||||
char name[CTNL_TIMEOUT_NAME_MAX];
|
||||
__u16 l3num;
|
||||
struct nf_conntrack_l4proto *l4proto;
|
||||
|
@ -385,10 +385,11 @@ static inline struct nft_set *nft_set_container_of(const void *priv)
|
||||
return (void *)priv - offsetof(struct nft_set, data);
|
||||
}
|
||||
|
||||
struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
|
||||
const struct nlattr *nla, u8 genmask);
|
||||
struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
|
||||
const struct nlattr *nla, u8 genmask);
|
||||
struct nft_set *nft_set_lookup(const struct net *net,
|
||||
const struct nft_table *table,
|
||||
const struct nlattr *nla_set_name,
|
||||
const struct nlattr *nla_set_id,
|
||||
u8 genmask);
|
||||
|
||||
static inline unsigned long nft_set_gc_interval(const struct nft_set *set)
|
||||
{
|
||||
@ -1016,7 +1017,8 @@ struct nft_object_type {
|
||||
unsigned int maxattr;
|
||||
struct module *owner;
|
||||
const struct nla_policy *policy;
|
||||
int (*init)(const struct nlattr * const tb[],
|
||||
int (*init)(const struct nft_ctx *ctx,
|
||||
const struct nlattr *const tb[],
|
||||
struct nft_object *obj);
|
||||
void (*destroy)(struct nft_object *obj);
|
||||
int (*dump)(struct sk_buff *skb,
|
||||
|
@ -32,6 +32,6 @@ void nft_fib6_eval_type(const struct nft_expr *expr, struct nft_regs *regs,
|
||||
void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,
|
||||
const struct nft_pktinfo *pkt);
|
||||
|
||||
void nft_fib_store_result(void *reg, enum nft_fib_result r,
|
||||
void nft_fib_store_result(void *reg, const struct nft_fib *priv,
|
||||
const struct nft_pktinfo *pkt, int index);
|
||||
#endif
|
||||
|
@ -815,6 +815,17 @@ enum nft_rt_keys {
|
||||
NFT_RT_NEXTHOP6,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nft_hash_types - nf_tables hash expression types
|
||||
*
|
||||
* @NFT_HASH_JENKINS: Jenkins Hash
|
||||
* @NFT_HASH_SYM: Symmetric Hash
|
||||
*/
|
||||
enum nft_hash_types {
|
||||
NFT_HASH_JENKINS,
|
||||
NFT_HASH_SYM,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum nft_hash_attributes - nf_tables hash expression netlink attributes
|
||||
*
|
||||
@ -824,6 +835,7 @@ enum nft_rt_keys {
|
||||
* @NFTA_HASH_MODULUS: modulus value (NLA_U32)
|
||||
* @NFTA_HASH_SEED: seed value (NLA_U32)
|
||||
* @NFTA_HASH_OFFSET: add this offset value to hash result (NLA_U32)
|
||||
* @NFTA_HASH_TYPE: hash operation (NLA_U32: nft_hash_types)
|
||||
*/
|
||||
enum nft_hash_attributes {
|
||||
NFTA_HASH_UNSPEC,
|
||||
@ -833,6 +845,7 @@ enum nft_hash_attributes {
|
||||
NFTA_HASH_MODULUS,
|
||||
NFTA_HASH_SEED,
|
||||
NFTA_HASH_OFFSET,
|
||||
NFTA_HASH_TYPE,
|
||||
__NFTA_HASH_MAX,
|
||||
};
|
||||
#define NFTA_HASH_MAX (__NFTA_HASH_MAX - 1)
|
||||
@ -1244,12 +1257,23 @@ enum nft_fib_flags {
|
||||
NFTA_FIB_F_MARK = 1 << 2, /* use skb->mark */
|
||||
NFTA_FIB_F_IIF = 1 << 3, /* restrict to iif */
|
||||
NFTA_FIB_F_OIF = 1 << 4, /* restrict to oif */
|
||||
NFTA_FIB_F_PRESENT = 1 << 5, /* check existence only */
|
||||
};
|
||||
|
||||
enum nft_ct_helper_attributes {
|
||||
NFTA_CT_HELPER_UNSPEC,
|
||||
NFTA_CT_HELPER_NAME,
|
||||
NFTA_CT_HELPER_L3PROTO,
|
||||
NFTA_CT_HELPER_L4PROTO,
|
||||
__NFTA_CT_HELPER_MAX,
|
||||
};
|
||||
#define NFTA_CT_HELPER_MAX (__NFTA_CT_HELPER_MAX - 1)
|
||||
|
||||
#define NFT_OBJECT_UNSPEC 0
|
||||
#define NFT_OBJECT_COUNTER 1
|
||||
#define NFT_OBJECT_QUOTA 2
|
||||
#define __NFT_OBJECT_MAX 3
|
||||
#define NFT_OBJECT_CT_HELPER 3
|
||||
#define __NFT_OBJECT_MAX 4
|
||||
#define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1)
|
||||
|
||||
/**
|
||||
|
@ -995,13 +995,10 @@ int br_nf_hook_thresh(unsigned int hook, struct net *net,
|
||||
if (!elem)
|
||||
return okfn(net, sk, skb);
|
||||
|
||||
/* We may already have this, but read-locks nest anyway */
|
||||
rcu_read_lock();
|
||||
nf_hook_state_init(&state, hook, NFPROTO_BRIDGE, indev, outdev,
|
||||
sk, net, okfn);
|
||||
|
||||
ret = nf_hook_slow(skb, &state, elem);
|
||||
rcu_read_unlock();
|
||||
if (ret == 1)
|
||||
ret = okfn(net, sk, skb);
|
||||
|
||||
|
@ -62,10 +62,10 @@ print_ports(const struct sk_buff *skb, uint8_t protocol, int offset)
|
||||
pptr = skb_header_pointer(skb, offset,
|
||||
sizeof(_ports), &_ports);
|
||||
if (pptr == NULL) {
|
||||
printk(" INCOMPLETE TCP/UDP header");
|
||||
pr_cont(" INCOMPLETE TCP/UDP header");
|
||||
return;
|
||||
}
|
||||
printk(" SPT=%u DPT=%u", ntohs(pptr->src), ntohs(pptr->dst));
|
||||
pr_cont(" SPT=%u DPT=%u", ntohs(pptr->src), ntohs(pptr->dst));
|
||||
}
|
||||
}
|
||||
|
||||
@ -100,11 +100,11 @@ ebt_log_packet(struct net *net, u_int8_t pf, unsigned int hooknum,
|
||||
|
||||
ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
|
||||
if (ih == NULL) {
|
||||
printk(" INCOMPLETE IP header");
|
||||
pr_cont(" INCOMPLETE IP header");
|
||||
goto out;
|
||||
}
|
||||
printk(" IP SRC=%pI4 IP DST=%pI4, IP tos=0x%02X, IP proto=%d",
|
||||
&ih->saddr, &ih->daddr, ih->tos, ih->protocol);
|
||||
pr_cont(" IP SRC=%pI4 IP DST=%pI4, IP tos=0x%02X, IP proto=%d",
|
||||
&ih->saddr, &ih->daddr, ih->tos, ih->protocol);
|
||||
print_ports(skb, ih->protocol, ih->ihl*4);
|
||||
goto out;
|
||||
}
|
||||
@ -120,11 +120,11 @@ ebt_log_packet(struct net *net, u_int8_t pf, unsigned int hooknum,
|
||||
|
||||
ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
|
||||
if (ih == NULL) {
|
||||
printk(" INCOMPLETE IPv6 header");
|
||||
pr_cont(" INCOMPLETE IPv6 header");
|
||||
goto out;
|
||||
}
|
||||
printk(" IPv6 SRC=%pI6 IPv6 DST=%pI6, IPv6 priority=0x%01X, Next Header=%d",
|
||||
&ih->saddr, &ih->daddr, ih->priority, ih->nexthdr);
|
||||
pr_cont(" IPv6 SRC=%pI6 IPv6 DST=%pI6, IPv6 priority=0x%01X, Next Header=%d",
|
||||
&ih->saddr, &ih->daddr, ih->priority, ih->nexthdr);
|
||||
nexthdr = ih->nexthdr;
|
||||
offset_ph = ipv6_skip_exthdr(skb, sizeof(_iph), &nexthdr, &frag_off);
|
||||
if (offset_ph == -1)
|
||||
@ -142,12 +142,12 @@ ebt_log_packet(struct net *net, u_int8_t pf, unsigned int hooknum,
|
||||
|
||||
ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
|
||||
if (ah == NULL) {
|
||||
printk(" INCOMPLETE ARP header");
|
||||
pr_cont(" INCOMPLETE ARP header");
|
||||
goto out;
|
||||
}
|
||||
printk(" ARP HTYPE=%d, PTYPE=0x%04x, OPCODE=%d",
|
||||
ntohs(ah->ar_hrd), ntohs(ah->ar_pro),
|
||||
ntohs(ah->ar_op));
|
||||
pr_cont(" ARP HTYPE=%d, PTYPE=0x%04x, OPCODE=%d",
|
||||
ntohs(ah->ar_hrd), ntohs(ah->ar_pro),
|
||||
ntohs(ah->ar_op));
|
||||
|
||||
/* If it's for Ethernet and the lengths are OK,
|
||||
* then log the ARP payload
|
||||
@ -161,17 +161,17 @@ ebt_log_packet(struct net *net, u_int8_t pf, unsigned int hooknum,
|
||||
ap = skb_header_pointer(skb, sizeof(_arph),
|
||||
sizeof(_arpp), &_arpp);
|
||||
if (ap == NULL) {
|
||||
printk(" INCOMPLETE ARP payload");
|
||||
pr_cont(" INCOMPLETE ARP payload");
|
||||
goto out;
|
||||
}
|
||||
printk(" ARP MAC SRC=%pM ARP IP SRC=%pI4 ARP MAC DST=%pM ARP IP DST=%pI4",
|
||||
ap->mac_src, ap->ip_src, ap->mac_dst, ap->ip_dst);
|
||||
pr_cont(" ARP MAC SRC=%pM ARP IP SRC=%pI4 ARP MAC DST=%pM ARP IP DST=%pI4",
|
||||
ap->mac_src, ap->ip_src,
|
||||
ap->mac_dst, ap->ip_dst);
|
||||
}
|
||||
}
|
||||
out:
|
||||
printk("\n");
|
||||
pr_cont("\n");
|
||||
spin_unlock_bh(&ebt_log_lock);
|
||||
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
|
@ -375,11 +375,7 @@ static int nft_reject_bridge_init(const struct nft_ctx *ctx,
|
||||
const struct nlattr * const tb[])
|
||||
{
|
||||
struct nft_reject *priv = nft_expr_priv(expr);
|
||||
int icmp_code, err;
|
||||
|
||||
err = nft_reject_bridge_validate(ctx, expr, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
int icmp_code;
|
||||
|
||||
if (tb[NFTA_REJECT_TYPE] == NULL)
|
||||
return -EINVAL;
|
||||
|
@ -562,8 +562,6 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0,
|
||||
XT_ERROR_TARGET) == 0)
|
||||
++newinfo->stacksize;
|
||||
}
|
||||
if (ret != 0)
|
||||
goto out_free;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (i != repl->num_entries)
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <linux/icmp.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/refcount.h>
|
||||
#include <linux/netfilter_arp.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
@ -40,8 +41,8 @@ MODULE_DESCRIPTION("Xtables: CLUSTERIP target");
|
||||
|
||||
struct clusterip_config {
|
||||
struct list_head list; /* list of all configs */
|
||||
atomic_t refcount; /* reference count */
|
||||
atomic_t entries; /* number of entries/rules
|
||||
refcount_t refcount; /* reference count */
|
||||
refcount_t entries; /* number of entries/rules
|
||||
* referencing us */
|
||||
|
||||
__be32 clusterip; /* the IP address */
|
||||
@ -77,7 +78,7 @@ struct clusterip_net {
|
||||
static inline void
|
||||
clusterip_config_get(struct clusterip_config *c)
|
||||
{
|
||||
atomic_inc(&c->refcount);
|
||||
refcount_inc(&c->refcount);
|
||||
}
|
||||
|
||||
|
||||
@ -89,7 +90,7 @@ static void clusterip_config_rcu_free(struct rcu_head *head)
|
||||
static inline void
|
||||
clusterip_config_put(struct clusterip_config *c)
|
||||
{
|
||||
if (atomic_dec_and_test(&c->refcount))
|
||||
if (refcount_dec_and_test(&c->refcount))
|
||||
call_rcu_bh(&c->rcu, clusterip_config_rcu_free);
|
||||
}
|
||||
|
||||
@ -103,7 +104,7 @@ clusterip_config_entry_put(struct clusterip_config *c)
|
||||
struct clusterip_net *cn = net_generic(net, clusterip_net_id);
|
||||
|
||||
local_bh_disable();
|
||||
if (atomic_dec_and_lock(&c->entries, &cn->lock)) {
|
||||
if (refcount_dec_and_lock(&c->entries, &cn->lock)) {
|
||||
list_del_rcu(&c->list);
|
||||
spin_unlock(&cn->lock);
|
||||
local_bh_enable();
|
||||
@ -149,10 +150,10 @@ clusterip_config_find_get(struct net *net, __be32 clusterip, int entry)
|
||||
c = NULL;
|
||||
else
|
||||
#endif
|
||||
if (unlikely(!atomic_inc_not_zero(&c->refcount)))
|
||||
if (unlikely(!refcount_inc_not_zero(&c->refcount)))
|
||||
c = NULL;
|
||||
else if (entry)
|
||||
atomic_inc(&c->entries);
|
||||
refcount_inc(&c->entries);
|
||||
}
|
||||
rcu_read_unlock_bh();
|
||||
|
||||
@ -188,8 +189,8 @@ clusterip_config_init(const struct ipt_clusterip_tgt_info *i, __be32 ip,
|
||||
clusterip_config_init_nodelist(c, i);
|
||||
c->hash_mode = i->hash_mode;
|
||||
c->hash_initval = i->hash_initval;
|
||||
atomic_set(&c->refcount, 1);
|
||||
atomic_set(&c->entries, 1);
|
||||
refcount_set(&c->refcount, 1);
|
||||
refcount_set(&c->entries, 1);
|
||||
|
||||
spin_lock_bh(&cn->lock);
|
||||
if (__clusterip_config_find(net, ip)) {
|
||||
|
@ -998,18 +998,6 @@ err_id_free:
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static void hex_dump(const unsigned char *buf, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (i && !(i % 16))
|
||||
printk("\n");
|
||||
printk("%02x ", *(buf + i));
|
||||
}
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse and mangle SNMP message according to mapping.
|
||||
* (And this is the fucking 'basic' method).
|
||||
@ -1026,7 +1014,8 @@ static int snmp_parse_mangle(unsigned char *msg,
|
||||
struct snmp_object *obj;
|
||||
|
||||
if (debug > 1)
|
||||
hex_dump(msg, len);
|
||||
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_NONE, 16, 1,
|
||||
msg, len, 0);
|
||||
|
||||
asn1_open(&ctx, msg, len);
|
||||
|
||||
|
@ -104,7 +104,6 @@ EXPORT_SYMBOL_GPL(nf_reject_ip_tcphdr_put);
|
||||
void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)
|
||||
{
|
||||
struct sk_buff *nskb;
|
||||
const struct iphdr *oiph;
|
||||
struct iphdr *niph;
|
||||
const struct tcphdr *oth;
|
||||
struct tcphdr _oth;
|
||||
@ -116,8 +115,6 @@ void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook)
|
||||
if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
|
||||
return;
|
||||
|
||||
oiph = ip_hdr(oldskb);
|
||||
|
||||
nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct tcphdr) +
|
||||
LL_MAX_HEADER, GFP_ATOMIC);
|
||||
if (!nskb)
|
||||
|
@ -90,7 +90,7 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
|
||||
|
||||
if (nft_hook(pkt) == NF_INET_PRE_ROUTING &&
|
||||
nft_fib_is_loopback(pkt->skb, nft_in(pkt))) {
|
||||
nft_fib_store_result(dest, priv->result, pkt,
|
||||
nft_fib_store_result(dest, priv, pkt,
|
||||
nft_in(pkt)->ifindex);
|
||||
return;
|
||||
}
|
||||
@ -99,7 +99,7 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
|
||||
if (ipv4_is_zeronet(iph->saddr)) {
|
||||
if (ipv4_is_lbcast(iph->daddr) ||
|
||||
ipv4_is_local_multicast(iph->daddr)) {
|
||||
nft_fib_store_result(dest, priv->result, pkt,
|
||||
nft_fib_store_result(dest, priv, pkt,
|
||||
get_ifindex(pkt->skb->dev));
|
||||
return;
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,
|
||||
|
||||
if (nft_hook(pkt) == NF_INET_PRE_ROUTING &&
|
||||
nft_fib_is_loopback(pkt->skb, nft_in(pkt))) {
|
||||
nft_fib_store_result(dest, priv->result, pkt,
|
||||
nft_fib_store_result(dest, priv, pkt,
|
||||
nft_in(pkt)->ifindex);
|
||||
return;
|
||||
}
|
||||
|
@ -181,7 +181,7 @@ static inline int ip_vs_conn_hash(struct ip_vs_conn *cp)
|
||||
|
||||
if (!(cp->flags & IP_VS_CONN_F_HASHED)) {
|
||||
cp->flags |= IP_VS_CONN_F_HASHED;
|
||||
atomic_inc(&cp->refcnt);
|
||||
refcount_inc(&cp->refcnt);
|
||||
hlist_add_head_rcu(&cp->c_list, &ip_vs_conn_tab[hash]);
|
||||
ret = 1;
|
||||
} else {
|
||||
@ -215,7 +215,7 @@ static inline int ip_vs_conn_unhash(struct ip_vs_conn *cp)
|
||||
if (cp->flags & IP_VS_CONN_F_HASHED) {
|
||||
hlist_del_rcu(&cp->c_list);
|
||||
cp->flags &= ~IP_VS_CONN_F_HASHED;
|
||||
atomic_dec(&cp->refcnt);
|
||||
refcount_dec(&cp->refcnt);
|
||||
ret = 1;
|
||||
} else
|
||||
ret = 0;
|
||||
@ -242,13 +242,13 @@ static inline bool ip_vs_conn_unlink(struct ip_vs_conn *cp)
|
||||
if (cp->flags & IP_VS_CONN_F_HASHED) {
|
||||
ret = false;
|
||||
/* Decrease refcnt and unlink conn only if we are last user */
|
||||
if (atomic_cmpxchg(&cp->refcnt, 1, 0) == 1) {
|
||||
if (refcount_dec_if_one(&cp->refcnt)) {
|
||||
hlist_del_rcu(&cp->c_list);
|
||||
cp->flags &= ~IP_VS_CONN_F_HASHED;
|
||||
ret = true;
|
||||
}
|
||||
} else
|
||||
ret = atomic_read(&cp->refcnt) ? false : true;
|
||||
ret = refcount_read(&cp->refcnt) ? false : true;
|
||||
|
||||
spin_unlock(&cp->lock);
|
||||
ct_write_unlock_bh(hash);
|
||||
@ -475,7 +475,7 @@ static void __ip_vs_conn_put_timer(struct ip_vs_conn *cp)
|
||||
void ip_vs_conn_put(struct ip_vs_conn *cp)
|
||||
{
|
||||
if ((cp->flags & IP_VS_CONN_F_ONE_PACKET) &&
|
||||
(atomic_read(&cp->refcnt) == 1) &&
|
||||
(refcount_read(&cp->refcnt) == 1) &&
|
||||
!timer_pending(&cp->timer))
|
||||
/* expire connection immediately */
|
||||
__ip_vs_conn_put_notimer(cp);
|
||||
@ -617,8 +617,8 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest)
|
||||
IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
|
||||
IP_VS_DBG_ADDR(cp->daf, &cp->daddr), ntohs(cp->dport),
|
||||
ip_vs_fwd_tag(cp), cp->state,
|
||||
cp->flags, atomic_read(&cp->refcnt),
|
||||
atomic_read(&dest->refcnt));
|
||||
cp->flags, refcount_read(&cp->refcnt),
|
||||
refcount_read(&dest->refcnt));
|
||||
|
||||
/* Update the connection counters */
|
||||
if (!(flags & IP_VS_CONN_F_TEMPLATE)) {
|
||||
@ -714,8 +714,8 @@ static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp)
|
||||
IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
|
||||
IP_VS_DBG_ADDR(cp->daf, &cp->daddr), ntohs(cp->dport),
|
||||
ip_vs_fwd_tag(cp), cp->state,
|
||||
cp->flags, atomic_read(&cp->refcnt),
|
||||
atomic_read(&dest->refcnt));
|
||||
cp->flags, refcount_read(&cp->refcnt),
|
||||
refcount_read(&dest->refcnt));
|
||||
|
||||
/* Update the connection counters */
|
||||
if (!(cp->flags & IP_VS_CONN_F_TEMPLATE)) {
|
||||
@ -863,10 +863,10 @@ static void ip_vs_conn_expire(unsigned long data)
|
||||
|
||||
expire_later:
|
||||
IP_VS_DBG(7, "delayed: conn->refcnt=%d conn->n_control=%d\n",
|
||||
atomic_read(&cp->refcnt),
|
||||
refcount_read(&cp->refcnt),
|
||||
atomic_read(&cp->n_control));
|
||||
|
||||
atomic_inc(&cp->refcnt);
|
||||
refcount_inc(&cp->refcnt);
|
||||
cp->timeout = 60*HZ;
|
||||
|
||||
if (ipvs->sync_state & IP_VS_STATE_MASTER)
|
||||
@ -941,7 +941,7 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p, int dest_af,
|
||||
* it in the table, so that other thread run ip_vs_random_dropentry
|
||||
* but cannot drop this entry.
|
||||
*/
|
||||
atomic_set(&cp->refcnt, 1);
|
||||
refcount_set(&cp->refcnt, 1);
|
||||
|
||||
cp->control = NULL;
|
||||
atomic_set(&cp->n_control, 0);
|
||||
|
@ -542,7 +542,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
|
||||
IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport),
|
||||
IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
|
||||
IP_VS_DBG_ADDR(cp->daf, &cp->daddr), ntohs(cp->dport),
|
||||
cp->flags, atomic_read(&cp->refcnt));
|
||||
cp->flags, refcount_read(&cp->refcnt));
|
||||
|
||||
ip_vs_conn_stats(cp, svc);
|
||||
return cp;
|
||||
@ -1193,7 +1193,7 @@ struct ip_vs_conn *ip_vs_new_conn_out(struct ip_vs_service *svc,
|
||||
IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport),
|
||||
IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
|
||||
IP_VS_DBG_ADDR(cp->af, &cp->daddr), ntohs(cp->dport),
|
||||
cp->flags, atomic_read(&cp->refcnt));
|
||||
cp->flags, refcount_read(&cp->refcnt));
|
||||
LeaveFunction(12);
|
||||
return cp;
|
||||
}
|
||||
@ -2231,8 +2231,6 @@ static int __net_init __ip_vs_init(struct net *net)
|
||||
if (ip_vs_sync_net_init(ipvs) < 0)
|
||||
goto sync_fail;
|
||||
|
||||
printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d\n",
|
||||
sizeof(struct netns_ipvs), ipvs->gen);
|
||||
return 0;
|
||||
/*
|
||||
* Error handling
|
||||
|
@ -699,7 +699,7 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, int dest_af,
|
||||
dest->vfwmark,
|
||||
IP_VS_DBG_ADDR(dest->af, &dest->addr),
|
||||
ntohs(dest->port),
|
||||
atomic_read(&dest->refcnt));
|
||||
refcount_read(&dest->refcnt));
|
||||
if (dest->af == dest_af &&
|
||||
ip_vs_addr_equal(dest_af, &dest->addr, daddr) &&
|
||||
dest->port == dport &&
|
||||
@ -934,7 +934,7 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
|
||||
atomic_set(&dest->activeconns, 0);
|
||||
atomic_set(&dest->inactconns, 0);
|
||||
atomic_set(&dest->persistconns, 0);
|
||||
atomic_set(&dest->refcnt, 1);
|
||||
refcount_set(&dest->refcnt, 1);
|
||||
|
||||
INIT_HLIST_NODE(&dest->d_list);
|
||||
spin_lock_init(&dest->dst_lock);
|
||||
@ -998,7 +998,7 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
|
||||
IP_VS_DBG_BUF(3, "Get destination %s:%u from trash, "
|
||||
"dest->refcnt=%d, service %u/%s:%u\n",
|
||||
IP_VS_DBG_ADDR(udest->af, &daddr), ntohs(dport),
|
||||
atomic_read(&dest->refcnt),
|
||||
refcount_read(&dest->refcnt),
|
||||
dest->vfwmark,
|
||||
IP_VS_DBG_ADDR(svc->af, &dest->vaddr),
|
||||
ntohs(dest->vport));
|
||||
@ -1074,7 +1074,7 @@ static void __ip_vs_del_dest(struct netns_ipvs *ipvs, struct ip_vs_dest *dest,
|
||||
spin_lock_bh(&ipvs->dest_trash_lock);
|
||||
IP_VS_DBG_BUF(3, "Moving dest %s:%u into trash, dest->refcnt=%d\n",
|
||||
IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port),
|
||||
atomic_read(&dest->refcnt));
|
||||
refcount_read(&dest->refcnt));
|
||||
if (list_empty(&ipvs->dest_trash) && !cleanup)
|
||||
mod_timer(&ipvs->dest_trash_timer,
|
||||
jiffies + (IP_VS_DEST_TRASH_PERIOD >> 1));
|
||||
@ -1157,7 +1157,7 @@ static void ip_vs_dest_trash_expire(unsigned long data)
|
||||
|
||||
spin_lock(&ipvs->dest_trash_lock);
|
||||
list_for_each_entry_safe(dest, next, &ipvs->dest_trash, t_list) {
|
||||
if (atomic_read(&dest->refcnt) > 1)
|
||||
if (refcount_read(&dest->refcnt) > 1)
|
||||
continue;
|
||||
if (dest->idle_start) {
|
||||
if (time_before(now, dest->idle_start +
|
||||
@ -1545,7 +1545,7 @@ ip_vs_forget_dev(struct ip_vs_dest *dest, struct net_device *dev)
|
||||
dev->name,
|
||||
IP_VS_DBG_ADDR(dest->af, &dest->addr),
|
||||
ntohs(dest->port),
|
||||
atomic_read(&dest->refcnt));
|
||||
refcount_read(&dest->refcnt));
|
||||
__ip_vs_dst_cache_reset(dest);
|
||||
}
|
||||
spin_unlock_bh(&dest->dst_lock);
|
||||
|
@ -448,7 +448,7 @@ __ip_vs_lblc_schedule(struct ip_vs_service *svc)
|
||||
IP_VS_DBG_ADDR(least->af, &least->addr),
|
||||
ntohs(least->port),
|
||||
atomic_read(&least->activeconns),
|
||||
atomic_read(&least->refcnt),
|
||||
refcount_read(&least->refcnt),
|
||||
atomic_read(&least->weight), loh);
|
||||
|
||||
return least;
|
||||
|
@ -204,7 +204,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set)
|
||||
IP_VS_DBG_ADDR(least->af, &least->addr),
|
||||
ntohs(least->port),
|
||||
atomic_read(&least->activeconns),
|
||||
atomic_read(&least->refcnt),
|
||||
refcount_read(&least->refcnt),
|
||||
atomic_read(&least->weight), loh);
|
||||
return least;
|
||||
}
|
||||
@ -249,7 +249,7 @@ static inline struct ip_vs_dest *ip_vs_dest_set_max(struct ip_vs_dest_set *set)
|
||||
__func__,
|
||||
IP_VS_DBG_ADDR(most->af, &most->addr), ntohs(most->port),
|
||||
atomic_read(&most->activeconns),
|
||||
atomic_read(&most->refcnt),
|
||||
refcount_read(&most->refcnt),
|
||||
atomic_read(&most->weight), moh);
|
||||
return most;
|
||||
}
|
||||
@ -612,7 +612,7 @@ __ip_vs_lblcr_schedule(struct ip_vs_service *svc)
|
||||
IP_VS_DBG_ADDR(least->af, &least->addr),
|
||||
ntohs(least->port),
|
||||
atomic_read(&least->activeconns),
|
||||
atomic_read(&least->refcnt),
|
||||
refcount_read(&least->refcnt),
|
||||
atomic_read(&least->weight), loh);
|
||||
|
||||
return least;
|
||||
|
@ -110,7 +110,7 @@ ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
|
||||
IP_VS_DBG_ADDR(least->af, &least->addr),
|
||||
ntohs(least->port),
|
||||
atomic_read(&least->activeconns),
|
||||
atomic_read(&least->refcnt),
|
||||
refcount_read(&least->refcnt),
|
||||
atomic_read(&least->weight), loh);
|
||||
|
||||
return least;
|
||||
|
@ -447,7 +447,7 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
|
||||
ntohs(cp->cport),
|
||||
sctp_state_name(cp->state),
|
||||
sctp_state_name(next_state),
|
||||
atomic_read(&cp->refcnt));
|
||||
refcount_read(&cp->refcnt));
|
||||
if (dest) {
|
||||
if (!(cp->flags & IP_VS_CONN_F_INACTIVE) &&
|
||||
(next_state != IP_VS_SCTP_S_ESTABLISHED)) {
|
||||
|
@ -557,7 +557,7 @@ set_tcp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
|
||||
ntohs(cp->cport),
|
||||
tcp_state_name(cp->state),
|
||||
tcp_state_name(new_state),
|
||||
atomic_read(&cp->refcnt));
|
||||
refcount_read(&cp->refcnt));
|
||||
|
||||
if (dest) {
|
||||
if (!(cp->flags & IP_VS_CONN_F_INACTIVE) &&
|
||||
|
@ -97,7 +97,7 @@ stop:
|
||||
"activeconns %d refcnt %d weight %d\n",
|
||||
IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port),
|
||||
atomic_read(&dest->activeconns),
|
||||
atomic_read(&dest->refcnt), atomic_read(&dest->weight));
|
||||
refcount_read(&dest->refcnt), atomic_read(&dest->weight));
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
|
||||
IP_VS_DBG_ADDR(least->af, &least->addr),
|
||||
ntohs(least->port),
|
||||
atomic_read(&least->activeconns),
|
||||
atomic_read(&least->refcnt),
|
||||
refcount_read(&least->refcnt),
|
||||
atomic_read(&least->weight), loh);
|
||||
|
||||
return least;
|
||||
|
@ -83,7 +83,7 @@ ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
|
||||
IP_VS_DBG_ADDR(least->af, &least->addr),
|
||||
ntohs(least->port),
|
||||
atomic_read(&least->activeconns),
|
||||
atomic_read(&least->refcnt),
|
||||
refcount_read(&least->refcnt),
|
||||
atomic_read(&least->weight), loh);
|
||||
|
||||
return least;
|
||||
|
@ -218,7 +218,7 @@ found:
|
||||
"activeconns %d refcnt %d weight %d\n",
|
||||
IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port),
|
||||
atomic_read(&dest->activeconns),
|
||||
atomic_read(&dest->refcnt),
|
||||
refcount_read(&dest->refcnt),
|
||||
atomic_read(&dest->weight));
|
||||
mark->cl = dest;
|
||||
|
||||
|
@ -1129,7 +1129,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_free);
|
||||
|
||||
/* Allocate a new conntrack: we return -ENOMEM if classification
|
||||
failed due to stress. Otherwise it really is unclassifiable. */
|
||||
static struct nf_conntrack_tuple_hash *
|
||||
static noinline struct nf_conntrack_tuple_hash *
|
||||
init_conntrack(struct net *net, struct nf_conn *tmpl,
|
||||
const struct nf_conntrack_tuple *tuple,
|
||||
struct nf_conntrack_l3proto *l3proto,
|
||||
@ -1237,21 +1237,20 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
|
||||
return &ct->tuplehash[IP_CT_DIR_ORIGINAL];
|
||||
}
|
||||
|
||||
/* On success, returns conntrack ptr, sets skb->_nfct | ctinfo */
|
||||
static inline struct nf_conn *
|
||||
/* On success, returns 0, sets skb->_nfct | ctinfo */
|
||||
static int
|
||||
resolve_normal_ct(struct net *net, struct nf_conn *tmpl,
|
||||
struct sk_buff *skb,
|
||||
unsigned int dataoff,
|
||||
u_int16_t l3num,
|
||||
u_int8_t protonum,
|
||||
struct nf_conntrack_l3proto *l3proto,
|
||||
struct nf_conntrack_l4proto *l4proto,
|
||||
int *set_reply,
|
||||
enum ip_conntrack_info *ctinfo)
|
||||
struct nf_conntrack_l4proto *l4proto)
|
||||
{
|
||||
const struct nf_conntrack_zone *zone;
|
||||
struct nf_conntrack_tuple tuple;
|
||||
struct nf_conntrack_tuple_hash *h;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
struct nf_conntrack_zone tmp;
|
||||
struct nf_conn *ct;
|
||||
u32 hash;
|
||||
@ -1260,7 +1259,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl,
|
||||
dataoff, l3num, protonum, net, &tuple, l3proto,
|
||||
l4proto)) {
|
||||
pr_debug("Can't get tuple\n");
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* look for tuple match */
|
||||
@ -1271,33 +1270,30 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl,
|
||||
h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto,
|
||||
skb, dataoff, hash);
|
||||
if (!h)
|
||||
return NULL;
|
||||
return 0;
|
||||
if (IS_ERR(h))
|
||||
return (void *)h;
|
||||
return PTR_ERR(h);
|
||||
}
|
||||
ct = nf_ct_tuplehash_to_ctrack(h);
|
||||
|
||||
/* It exists; we have (non-exclusive) reference. */
|
||||
if (NF_CT_DIRECTION(h) == IP_CT_DIR_REPLY) {
|
||||
*ctinfo = IP_CT_ESTABLISHED_REPLY;
|
||||
/* Please set reply bit if this packet OK */
|
||||
*set_reply = 1;
|
||||
ctinfo = IP_CT_ESTABLISHED_REPLY;
|
||||
} else {
|
||||
/* Once we've had two way comms, always ESTABLISHED. */
|
||||
if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
|
||||
pr_debug("normal packet for %p\n", ct);
|
||||
*ctinfo = IP_CT_ESTABLISHED;
|
||||
ctinfo = IP_CT_ESTABLISHED;
|
||||
} else if (test_bit(IPS_EXPECTED_BIT, &ct->status)) {
|
||||
pr_debug("related packet for %p\n", ct);
|
||||
*ctinfo = IP_CT_RELATED;
|
||||
ctinfo = IP_CT_RELATED;
|
||||
} else {
|
||||
pr_debug("new packet for %p\n", ct);
|
||||
*ctinfo = IP_CT_NEW;
|
||||
ctinfo = IP_CT_NEW;
|
||||
}
|
||||
*set_reply = 0;
|
||||
}
|
||||
nf_ct_set(skb, ct, *ctinfo);
|
||||
return ct;
|
||||
nf_ct_set(skb, ct, ctinfo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
@ -1311,7 +1307,6 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
|
||||
unsigned int *timeouts;
|
||||
unsigned int dataoff;
|
||||
u_int8_t protonum;
|
||||
int set_reply = 0;
|
||||
int ret;
|
||||
|
||||
tmpl = nf_ct_get(skb, &ctinfo);
|
||||
@ -1354,23 +1349,22 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
|
||||
goto out;
|
||||
}
|
||||
repeat:
|
||||
ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum,
|
||||
l3proto, l4proto, &set_reply, &ctinfo);
|
||||
if (!ct) {
|
||||
/* Not valid part of a connection */
|
||||
NF_CT_STAT_INC_ATOMIC(net, invalid);
|
||||
ret = NF_ACCEPT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (IS_ERR(ct)) {
|
||||
ret = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum,
|
||||
l3proto, l4proto);
|
||||
if (ret < 0) {
|
||||
/* Too stressed to deal. */
|
||||
NF_CT_STAT_INC_ATOMIC(net, drop);
|
||||
ret = NF_DROP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
NF_CT_ASSERT(skb_nfct(skb));
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
if (!ct) {
|
||||
/* Not valid part of a connection */
|
||||
NF_CT_STAT_INC_ATOMIC(net, invalid);
|
||||
ret = NF_ACCEPT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Decide what timeout policy we want to apply to this flow. */
|
||||
timeouts = nf_ct_timeout_lookup(net, ct, l4proto);
|
||||
@ -1395,7 +1389,8 @@ repeat:
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (set_reply && !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status))
|
||||
if (ctinfo == IP_CT_ESTABLISHED_REPLY &&
|
||||
!test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status))
|
||||
nf_conntrack_event_cache(IPCT_REPLY, ct);
|
||||
out:
|
||||
if (tmpl)
|
||||
|
@ -133,7 +133,7 @@ nf_ct_expect_find_get(struct net *net,
|
||||
|
||||
rcu_read_lock();
|
||||
i = __nf_ct_expect_find(net, zone, tuple);
|
||||
if (i && !atomic_inc_not_zero(&i->use))
|
||||
if (i && !refcount_inc_not_zero(&i->use))
|
||||
i = NULL;
|
||||
rcu_read_unlock();
|
||||
|
||||
@ -186,7 +186,7 @@ nf_ct_find_expectation(struct net *net,
|
||||
return NULL;
|
||||
|
||||
if (exp->flags & NF_CT_EXPECT_PERMANENT) {
|
||||
atomic_inc(&exp->use);
|
||||
refcount_inc(&exp->use);
|
||||
return exp;
|
||||
} else if (del_timer(&exp->timeout)) {
|
||||
nf_ct_unlink_expect(exp);
|
||||
@ -275,7 +275,7 @@ struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me)
|
||||
return NULL;
|
||||
|
||||
new->master = me;
|
||||
atomic_set(&new->use, 1);
|
||||
refcount_set(&new->use, 1);
|
||||
return new;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_ct_expect_alloc);
|
||||
@ -348,7 +348,7 @@ static void nf_ct_expect_free_rcu(struct rcu_head *head)
|
||||
|
||||
void nf_ct_expect_put(struct nf_conntrack_expect *exp)
|
||||
{
|
||||
if (atomic_dec_and_test(&exp->use))
|
||||
if (refcount_dec_and_test(&exp->use))
|
||||
call_rcu(&exp->rcu, nf_ct_expect_free_rcu);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_ct_expect_put);
|
||||
@ -361,7 +361,7 @@ static void nf_ct_expect_insert(struct nf_conntrack_expect *exp)
|
||||
unsigned int h = nf_ct_expect_dst_hash(net, &exp->tuple);
|
||||
|
||||
/* two references : one for hash insert, one for the timer */
|
||||
atomic_add(2, &exp->use);
|
||||
refcount_add(2, &exp->use);
|
||||
|
||||
hlist_add_head(&exp->lnode, &master_help->expectations);
|
||||
master_help->expecting[exp->class]++;
|
||||
|
@ -2693,7 +2693,7 @@ restart:
|
||||
cb->nlh->nlmsg_seq,
|
||||
IPCTNL_MSG_EXP_NEW,
|
||||
exp) < 0) {
|
||||
if (!atomic_inc_not_zero(&exp->use))
|
||||
if (!refcount_inc_not_zero(&exp->use))
|
||||
continue;
|
||||
cb->args[1] = (unsigned long)exp;
|
||||
goto out;
|
||||
@ -2739,7 +2739,7 @@ restart:
|
||||
cb->nlh->nlmsg_seq,
|
||||
IPCTNL_MSG_EXP_NEW,
|
||||
exp) < 0) {
|
||||
if (!atomic_inc_not_zero(&exp->use))
|
||||
if (!refcount_inc_not_zero(&exp->use))
|
||||
continue;
|
||||
cb->args[1] = (unsigned long)exp;
|
||||
goto out;
|
||||
|
@ -1772,8 +1772,19 @@ static int nf_tables_newexpr(const struct nft_ctx *ctx,
|
||||
goto err1;
|
||||
}
|
||||
|
||||
if (ops->validate) {
|
||||
const struct nft_data *data = NULL;
|
||||
|
||||
err = ops->validate(ctx, expr, &data);
|
||||
if (err < 0)
|
||||
goto err2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
if (ops->destroy)
|
||||
ops->destroy(ctx, expr);
|
||||
err1:
|
||||
expr->ops = NULL;
|
||||
return err;
|
||||
@ -2523,8 +2534,8 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net,
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
|
||||
const struct nlattr *nla, u8 genmask)
|
||||
static struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
|
||||
const struct nlattr *nla, u8 genmask)
|
||||
{
|
||||
struct nft_set *set;
|
||||
|
||||
@ -2538,11 +2549,10 @@ struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
|
||||
}
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_tables_set_lookup);
|
||||
|
||||
struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
|
||||
const struct nlattr *nla,
|
||||
u8 genmask)
|
||||
static struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
|
||||
const struct nlattr *nla,
|
||||
u8 genmask)
|
||||
{
|
||||
struct nft_trans *trans;
|
||||
u32 id = ntohl(nla_get_be32(nla));
|
||||
@ -2557,7 +2567,25 @@ struct nft_set *nf_tables_set_lookup_byid(const struct net *net,
|
||||
}
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_tables_set_lookup_byid);
|
||||
|
||||
struct nft_set *nft_set_lookup(const struct net *net,
|
||||
const struct nft_table *table,
|
||||
const struct nlattr *nla_set_name,
|
||||
const struct nlattr *nla_set_id,
|
||||
u8 genmask)
|
||||
{
|
||||
struct nft_set *set;
|
||||
|
||||
set = nf_tables_set_lookup(table, nla_set_name, genmask);
|
||||
if (IS_ERR(set)) {
|
||||
if (!nla_set_id)
|
||||
return set;
|
||||
|
||||
set = nf_tables_set_lookup_byid(net, nla_set_id, genmask);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nft_set_lookup);
|
||||
|
||||
static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set,
|
||||
const char *name)
|
||||
@ -4067,7 +4095,8 @@ static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = {
|
||||
[NFTA_OBJ_DATA] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
static struct nft_object *nft_obj_init(const struct nft_object_type *type,
|
||||
static struct nft_object *nft_obj_init(const struct nft_ctx *ctx,
|
||||
const struct nft_object_type *type,
|
||||
const struct nlattr *attr)
|
||||
{
|
||||
struct nlattr *tb[type->maxattr + 1];
|
||||
@ -4087,7 +4116,7 @@ static struct nft_object *nft_obj_init(const struct nft_object_type *type,
|
||||
if (obj == NULL)
|
||||
goto err1;
|
||||
|
||||
err = type->init((const struct nlattr * const *)tb, obj);
|
||||
err = type->init(ctx, (const struct nlattr * const *)tb, obj);
|
||||
if (err < 0)
|
||||
goto err2;
|
||||
|
||||
@ -4195,7 +4224,7 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
|
||||
if (IS_ERR(type))
|
||||
return PTR_ERR(type);
|
||||
|
||||
obj = nft_obj_init(type, nla[NFTA_OBJ_DATA]);
|
||||
obj = nft_obj_init(&ctx, type, nla[NFTA_OBJ_DATA]);
|
||||
if (IS_ERR(obj)) {
|
||||
err = PTR_ERR(obj);
|
||||
goto err1;
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/refcount.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rculist.h>
|
||||
#include <linux/slab.h>
|
||||
@ -32,7 +33,7 @@ struct nf_acct {
|
||||
atomic64_t bytes;
|
||||
unsigned long flags;
|
||||
struct list_head head;
|
||||
atomic_t refcnt;
|
||||
refcount_t refcnt;
|
||||
char name[NFACCT_NAME_MAX];
|
||||
struct rcu_head rcu_head;
|
||||
char data[0];
|
||||
@ -123,7 +124,7 @@ static int nfnl_acct_new(struct net *net, struct sock *nfnl,
|
||||
atomic64_set(&nfacct->pkts,
|
||||
be64_to_cpu(nla_get_be64(tb[NFACCT_PKTS])));
|
||||
}
|
||||
atomic_set(&nfacct->refcnt, 1);
|
||||
refcount_set(&nfacct->refcnt, 1);
|
||||
list_add_tail_rcu(&nfacct->head, &net->nfnl_acct_list);
|
||||
return 0;
|
||||
}
|
||||
@ -166,7 +167,7 @@ nfnl_acct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
|
||||
NFACCT_PAD) ||
|
||||
nla_put_be64(skb, NFACCT_BYTES, cpu_to_be64(bytes),
|
||||
NFACCT_PAD) ||
|
||||
nla_put_be32(skb, NFACCT_USE, htonl(atomic_read(&acct->refcnt))))
|
||||
nla_put_be32(skb, NFACCT_USE, htonl(refcount_read(&acct->refcnt))))
|
||||
goto nla_put_failure;
|
||||
if (acct->flags & NFACCT_F_QUOTA) {
|
||||
u64 *quota = (u64 *)acct->data;
|
||||
@ -329,7 +330,7 @@ static int nfnl_acct_try_del(struct nf_acct *cur)
|
||||
/* We want to avoid races with nfnl_acct_put. So only when the current
|
||||
* refcnt is 1, we decrease it to 0.
|
||||
*/
|
||||
if (atomic_cmpxchg(&cur->refcnt, 1, 0) == 1) {
|
||||
if (refcount_dec_if_one(&cur->refcnt)) {
|
||||
/* We are protected by nfnl mutex. */
|
||||
list_del_rcu(&cur->head);
|
||||
kfree_rcu(cur, rcu_head);
|
||||
@ -413,7 +414,7 @@ struct nf_acct *nfnl_acct_find_get(struct net *net, const char *acct_name)
|
||||
if (!try_module_get(THIS_MODULE))
|
||||
goto err;
|
||||
|
||||
if (!atomic_inc_not_zero(&cur->refcnt)) {
|
||||
if (!refcount_inc_not_zero(&cur->refcnt)) {
|
||||
module_put(THIS_MODULE);
|
||||
goto err;
|
||||
}
|
||||
@ -429,7 +430,7 @@ EXPORT_SYMBOL_GPL(nfnl_acct_find_get);
|
||||
|
||||
void nfnl_acct_put(struct nf_acct *acct)
|
||||
{
|
||||
if (atomic_dec_and_test(&acct->refcnt))
|
||||
if (refcount_dec_and_test(&acct->refcnt))
|
||||
kfree_rcu(acct, rcu_head);
|
||||
|
||||
module_put(THIS_MODULE);
|
||||
@ -502,7 +503,7 @@ static void __net_exit nfnl_acct_net_exit(struct net *net)
|
||||
list_for_each_entry_safe(cur, tmp, &net->nfnl_acct_list, head) {
|
||||
list_del_rcu(&cur->head);
|
||||
|
||||
if (atomic_dec_and_test(&cur->refcnt))
|
||||
if (refcount_dec_and_test(&cur->refcnt))
|
||||
kfree_rcu(cur, rcu_head);
|
||||
}
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ static int cttimeout_new_timeout(struct net *net, struct sock *ctnl,
|
||||
strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME]));
|
||||
timeout->l3num = l3num;
|
||||
timeout->l4proto = l4proto;
|
||||
atomic_set(&timeout->refcnt, 1);
|
||||
refcount_set(&timeout->refcnt, 1);
|
||||
list_add_tail_rcu(&timeout->head, &net->nfct_timeout_list);
|
||||
|
||||
return 0;
|
||||
@ -172,7 +172,7 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
|
||||
nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num)) ||
|
||||
nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4proto->l4proto) ||
|
||||
nla_put_be32(skb, CTA_TIMEOUT_USE,
|
||||
htonl(atomic_read(&timeout->refcnt))))
|
||||
htonl(refcount_read(&timeout->refcnt))))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) {
|
||||
@ -339,7 +339,7 @@ static int ctnl_timeout_try_del(struct net *net, struct ctnl_timeout *timeout)
|
||||
/* We want to avoid races with ctnl_timeout_put. So only when the
|
||||
* current refcnt is 1, we decrease it to 0.
|
||||
*/
|
||||
if (atomic_cmpxchg(&timeout->refcnt, 1, 0) == 1) {
|
||||
if (refcount_dec_if_one(&timeout->refcnt)) {
|
||||
/* We are protected by nfnl mutex. */
|
||||
list_del_rcu(&timeout->head);
|
||||
nf_ct_l4proto_put(timeout->l4proto);
|
||||
@ -536,7 +536,7 @@ ctnl_timeout_find_get(struct net *net, const char *name)
|
||||
if (!try_module_get(THIS_MODULE))
|
||||
goto err;
|
||||
|
||||
if (!atomic_inc_not_zero(&timeout->refcnt)) {
|
||||
if (!refcount_inc_not_zero(&timeout->refcnt)) {
|
||||
module_put(THIS_MODULE);
|
||||
goto err;
|
||||
}
|
||||
@ -550,7 +550,7 @@ err:
|
||||
|
||||
static void ctnl_timeout_put(struct ctnl_timeout *timeout)
|
||||
{
|
||||
if (atomic_dec_and_test(&timeout->refcnt))
|
||||
if (refcount_dec_and_test(&timeout->refcnt))
|
||||
kfree_rcu(timeout, rcu_head);
|
||||
|
||||
module_put(THIS_MODULE);
|
||||
@ -601,7 +601,7 @@ static void __net_exit cttimeout_net_exit(struct net *net)
|
||||
list_del_rcu(&cur->head);
|
||||
nf_ct_l4proto_put(cur->l4proto);
|
||||
|
||||
if (atomic_dec_and_test(&cur->refcnt))
|
||||
if (refcount_dec_and_test(&cur->refcnt))
|
||||
kfree_rcu(cur, rcu_head);
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,8 @@
|
||||
#include <net/netfilter/nfnetlink_log.h>
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/refcount.h>
|
||||
|
||||
|
||||
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
|
||||
#include "../bridge/br_private.h"
|
||||
@ -57,7 +59,7 @@
|
||||
struct nfulnl_instance {
|
||||
struct hlist_node hlist; /* global list of instances */
|
||||
spinlock_t lock;
|
||||
atomic_t use; /* use count */
|
||||
refcount_t use; /* use count */
|
||||
|
||||
unsigned int qlen; /* number of nlmsgs in skb */
|
||||
struct sk_buff *skb; /* pre-allocatd skb */
|
||||
@ -115,7 +117,7 @@ __instance_lookup(struct nfnl_log_net *log, u_int16_t group_num)
|
||||
static inline void
|
||||
instance_get(struct nfulnl_instance *inst)
|
||||
{
|
||||
atomic_inc(&inst->use);
|
||||
refcount_inc(&inst->use);
|
||||
}
|
||||
|
||||
static struct nfulnl_instance *
|
||||
@ -125,7 +127,7 @@ instance_lookup_get(struct nfnl_log_net *log, u_int16_t group_num)
|
||||
|
||||
rcu_read_lock_bh();
|
||||
inst = __instance_lookup(log, group_num);
|
||||
if (inst && !atomic_inc_not_zero(&inst->use))
|
||||
if (inst && !refcount_inc_not_zero(&inst->use))
|
||||
inst = NULL;
|
||||
rcu_read_unlock_bh();
|
||||
|
||||
@ -145,7 +147,7 @@ static void nfulnl_instance_free_rcu(struct rcu_head *head)
|
||||
static void
|
||||
instance_put(struct nfulnl_instance *inst)
|
||||
{
|
||||
if (inst && atomic_dec_and_test(&inst->use))
|
||||
if (inst && refcount_dec_and_test(&inst->use))
|
||||
call_rcu_bh(&inst->rcu, nfulnl_instance_free_rcu);
|
||||
}
|
||||
|
||||
@ -180,7 +182,7 @@ instance_create(struct net *net, u_int16_t group_num,
|
||||
INIT_HLIST_NODE(&inst->hlist);
|
||||
spin_lock_init(&inst->lock);
|
||||
/* needs to be two, since we _put() after creation */
|
||||
atomic_set(&inst->use, 2);
|
||||
refcount_set(&inst->use, 2);
|
||||
|
||||
setup_timer(&inst->timer, nfulnl_timer, (unsigned long)inst);
|
||||
|
||||
@ -1031,7 +1033,7 @@ static int seq_show(struct seq_file *s, void *v)
|
||||
inst->group_num,
|
||||
inst->peer_portid, inst->qlen,
|
||||
inst->copy_mode, inst->copy_range,
|
||||
inst->flushtimeout, atomic_read(&inst->use));
|
||||
inst->flushtimeout, refcount_read(&inst->use));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -230,10 +230,6 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
union nft_entry e = {};
|
||||
int ret;
|
||||
|
||||
ret = nft_compat_chain_validate_dependency(target->table, ctx->chain);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
target_compat_from_user(target, nla_data(tb[NFTA_TARGET_INFO]), info);
|
||||
|
||||
if (ctx->nla[NFTA_RULE_COMPAT]) {
|
||||
@ -419,10 +415,6 @@ nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
union nft_entry e = {};
|
||||
int ret;
|
||||
|
||||
ret = nft_compat_chain_validate_dependency(match->table, ctx->chain);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
match_compat_from_user(match, nla_data(tb[NFTA_MATCH_INFO]), info);
|
||||
|
||||
if (ctx->nla[NFTA_RULE_COMPAT]) {
|
||||
|
@ -82,7 +82,8 @@ static int nft_counter_do_init(const struct nlattr * const tb[],
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nft_counter_obj_init(const struct nlattr * const tb[],
|
||||
static int nft_counter_obj_init(const struct nft_ctx *ctx,
|
||||
const struct nlattr * const tb[],
|
||||
struct nft_object *obj)
|
||||
{
|
||||
struct nft_counter_percpu_priv *priv = nft_obj_data(obj);
|
||||
|
@ -32,6 +32,12 @@ struct nft_ct {
|
||||
};
|
||||
};
|
||||
|
||||
struct nft_ct_helper_obj {
|
||||
struct nf_conntrack_helper *helper4;
|
||||
struct nf_conntrack_helper *helper6;
|
||||
u8 l4proto;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_NF_CONNTRACK_ZONES
|
||||
static DEFINE_PER_CPU(struct nf_conn *, nft_ct_pcpu_template);
|
||||
static unsigned int nft_ct_pcpu_template_refcnt __read_mostly;
|
||||
@ -730,6 +736,162 @@ static struct nft_expr_type nft_notrack_type __read_mostly = {
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int nft_ct_helper_obj_init(const struct nft_ctx *ctx,
|
||||
const struct nlattr * const tb[],
|
||||
struct nft_object *obj)
|
||||
{
|
||||
struct nft_ct_helper_obj *priv = nft_obj_data(obj);
|
||||
struct nf_conntrack_helper *help4, *help6;
|
||||
char name[NF_CT_HELPER_NAME_LEN];
|
||||
int family = ctx->afi->family;
|
||||
|
||||
if (!tb[NFTA_CT_HELPER_NAME] || !tb[NFTA_CT_HELPER_L4PROTO])
|
||||
return -EINVAL;
|
||||
|
||||
priv->l4proto = nla_get_u8(tb[NFTA_CT_HELPER_L4PROTO]);
|
||||
if (!priv->l4proto)
|
||||
return -ENOENT;
|
||||
|
||||
nla_strlcpy(name, tb[NFTA_CT_HELPER_NAME], sizeof(name));
|
||||
|
||||
if (tb[NFTA_CT_HELPER_L3PROTO])
|
||||
family = ntohs(nla_get_be16(tb[NFTA_CT_HELPER_L3PROTO]));
|
||||
|
||||
help4 = NULL;
|
||||
help6 = NULL;
|
||||
|
||||
switch (family) {
|
||||
case NFPROTO_IPV4:
|
||||
if (ctx->afi->family == NFPROTO_IPV6)
|
||||
return -EINVAL;
|
||||
|
||||
help4 = nf_conntrack_helper_try_module_get(name, family,
|
||||
priv->l4proto);
|
||||
break;
|
||||
case NFPROTO_IPV6:
|
||||
if (ctx->afi->family == NFPROTO_IPV4)
|
||||
return -EINVAL;
|
||||
|
||||
help6 = nf_conntrack_helper_try_module_get(name, family,
|
||||
priv->l4proto);
|
||||
break;
|
||||
case NFPROTO_NETDEV: /* fallthrough */
|
||||
case NFPROTO_BRIDGE: /* same */
|
||||
case NFPROTO_INET:
|
||||
help4 = nf_conntrack_helper_try_module_get(name, NFPROTO_IPV4,
|
||||
priv->l4proto);
|
||||
help6 = nf_conntrack_helper_try_module_get(name, NFPROTO_IPV6,
|
||||
priv->l4proto);
|
||||
break;
|
||||
default:
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
/* && is intentional; only error if INET found neither ipv4 or ipv6 */
|
||||
if (!help4 && !help6)
|
||||
return -ENOENT;
|
||||
|
||||
priv->helper4 = help4;
|
||||
priv->helper6 = help6;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nft_ct_helper_obj_destroy(struct nft_object *obj)
|
||||
{
|
||||
struct nft_ct_helper_obj *priv = nft_obj_data(obj);
|
||||
|
||||
if (priv->helper4)
|
||||
module_put(priv->helper4->me);
|
||||
if (priv->helper6)
|
||||
module_put(priv->helper6->me);
|
||||
}
|
||||
|
||||
static void nft_ct_helper_obj_eval(struct nft_object *obj,
|
||||
struct nft_regs *regs,
|
||||
const struct nft_pktinfo *pkt)
|
||||
{
|
||||
const struct nft_ct_helper_obj *priv = nft_obj_data(obj);
|
||||
struct nf_conn *ct = (struct nf_conn *)skb_nfct(pkt->skb);
|
||||
struct nf_conntrack_helper *to_assign = NULL;
|
||||
struct nf_conn_help *help;
|
||||
|
||||
if (!ct ||
|
||||
nf_ct_is_confirmed(ct) ||
|
||||
nf_ct_is_template(ct) ||
|
||||
priv->l4proto != nf_ct_protonum(ct))
|
||||
return;
|
||||
|
||||
switch (nf_ct_l3num(ct)) {
|
||||
case NFPROTO_IPV4:
|
||||
to_assign = priv->helper4;
|
||||
break;
|
||||
case NFPROTO_IPV6:
|
||||
to_assign = priv->helper6;
|
||||
break;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!to_assign)
|
||||
return;
|
||||
|
||||
if (test_bit(IPS_HELPER_BIT, &ct->status))
|
||||
return;
|
||||
|
||||
help = nf_ct_helper_ext_add(ct, to_assign, GFP_ATOMIC);
|
||||
if (help) {
|
||||
rcu_assign_pointer(help->helper, to_assign);
|
||||
set_bit(IPS_HELPER_BIT, &ct->status);
|
||||
}
|
||||
}
|
||||
|
||||
static int nft_ct_helper_obj_dump(struct sk_buff *skb,
|
||||
struct nft_object *obj, bool reset)
|
||||
{
|
||||
const struct nft_ct_helper_obj *priv = nft_obj_data(obj);
|
||||
const struct nf_conntrack_helper *helper = priv->helper4;
|
||||
u16 family;
|
||||
|
||||
if (nla_put_string(skb, NFTA_CT_HELPER_NAME, helper->name))
|
||||
return -1;
|
||||
|
||||
if (nla_put_u8(skb, NFTA_CT_HELPER_L4PROTO, priv->l4proto))
|
||||
return -1;
|
||||
|
||||
if (priv->helper4 && priv->helper6)
|
||||
family = NFPROTO_INET;
|
||||
else if (priv->helper6)
|
||||
family = NFPROTO_IPV6;
|
||||
else
|
||||
family = NFPROTO_IPV4;
|
||||
|
||||
if (nla_put_be16(skb, NFTA_CT_HELPER_L3PROTO, htons(family)))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct nla_policy nft_ct_helper_policy[NFTA_CT_HELPER_MAX + 1] = {
|
||||
[NFTA_CT_HELPER_NAME] = { .type = NLA_STRING,
|
||||
.len = NF_CT_HELPER_NAME_LEN - 1 },
|
||||
[NFTA_CT_HELPER_L3PROTO] = { .type = NLA_U16 },
|
||||
[NFTA_CT_HELPER_L4PROTO] = { .type = NLA_U8 },
|
||||
};
|
||||
|
||||
static struct nft_object_type nft_ct_helper_obj __read_mostly = {
|
||||
.type = NFT_OBJECT_CT_HELPER,
|
||||
.size = sizeof(struct nft_ct_helper_obj),
|
||||
.maxattr = NFTA_CT_HELPER_MAX,
|
||||
.policy = nft_ct_helper_policy,
|
||||
.eval = nft_ct_helper_obj_eval,
|
||||
.init = nft_ct_helper_obj_init,
|
||||
.destroy = nft_ct_helper_obj_destroy,
|
||||
.dump = nft_ct_helper_obj_dump,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init nft_ct_module_init(void)
|
||||
{
|
||||
int err;
|
||||
@ -744,7 +906,14 @@ static int __init nft_ct_module_init(void)
|
||||
if (err < 0)
|
||||
goto err1;
|
||||
|
||||
err = nft_register_obj(&nft_ct_helper_obj);
|
||||
if (err < 0)
|
||||
goto err2;
|
||||
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
nft_unregister_expr(&nft_notrack_type);
|
||||
err1:
|
||||
nft_unregister_expr(&nft_ct_type);
|
||||
return err;
|
||||
@ -752,6 +921,7 @@ err1:
|
||||
|
||||
static void __exit nft_ct_module_exit(void)
|
||||
{
|
||||
nft_unregister_obj(&nft_ct_helper_obj);
|
||||
nft_unregister_expr(&nft_notrack_type);
|
||||
nft_unregister_expr(&nft_ct_type);
|
||||
}
|
||||
@ -763,3 +933,4 @@ MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
|
||||
MODULE_ALIAS_NFT_EXPR("ct");
|
||||
MODULE_ALIAS_NFT_EXPR("notrack");
|
||||
MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_CT_HELPER);
|
||||
|
@ -133,16 +133,10 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
|
||||
priv->invert = true;
|
||||
}
|
||||
|
||||
set = nf_tables_set_lookup(ctx->table, tb[NFTA_DYNSET_SET_NAME],
|
||||
genmask);
|
||||
if (IS_ERR(set)) {
|
||||
if (tb[NFTA_DYNSET_SET_ID])
|
||||
set = nf_tables_set_lookup_byid(ctx->net,
|
||||
tb[NFTA_DYNSET_SET_ID],
|
||||
genmask);
|
||||
if (IS_ERR(set))
|
||||
return PTR_ERR(set);
|
||||
}
|
||||
set = nft_set_lookup(ctx->net, ctx->table, tb[NFTA_DYNSET_SET_NAME],
|
||||
tb[NFTA_DYNSET_SET_ID], genmask);
|
||||
if (IS_ERR(set))
|
||||
return PTR_ERR(set);
|
||||
|
||||
if (set->ops->update == NULL)
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -98,14 +98,21 @@ static void nft_exthdr_tcp_eval(const struct nft_expr *expr,
|
||||
goto err;
|
||||
|
||||
offset = i + priv->offset;
|
||||
dest[priv->len / NFT_REG32_SIZE] = 0;
|
||||
memcpy(dest, opt + offset, priv->len);
|
||||
if (priv->flags & NFT_EXTHDR_F_PRESENT) {
|
||||
*dest = 1;
|
||||
} else {
|
||||
dest[priv->len / NFT_REG32_SIZE] = 0;
|
||||
memcpy(dest, opt + offset, priv->len);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
err:
|
||||
regs->verdict.code = NFT_BREAK;
|
||||
if (priv->flags & NFT_EXTHDR_F_PRESENT)
|
||||
*dest = 0;
|
||||
else
|
||||
regs->verdict.code = NFT_BREAK;
|
||||
}
|
||||
|
||||
static const struct nla_policy nft_exthdr_policy[NFTA_EXTHDR_MAX + 1] = {
|
||||
|
@ -24,7 +24,8 @@ const struct nla_policy nft_fib_policy[NFTA_FIB_MAX + 1] = {
|
||||
EXPORT_SYMBOL(nft_fib_policy);
|
||||
|
||||
#define NFTA_FIB_F_ALL (NFTA_FIB_F_SADDR | NFTA_FIB_F_DADDR | \
|
||||
NFTA_FIB_F_MARK | NFTA_FIB_F_IIF | NFTA_FIB_F_OIF)
|
||||
NFTA_FIB_F_MARK | NFTA_FIB_F_IIF | NFTA_FIB_F_OIF | \
|
||||
NFTA_FIB_F_PRESENT)
|
||||
|
||||
int nft_fib_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
const struct nft_data **data)
|
||||
@ -112,7 +113,7 @@ int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return nft_fib_validate(ctx, expr, NULL);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nft_fib_init);
|
||||
|
||||
@ -133,19 +134,22 @@ int nft_fib_dump(struct sk_buff *skb, const struct nft_expr *expr)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nft_fib_dump);
|
||||
|
||||
void nft_fib_store_result(void *reg, enum nft_fib_result r,
|
||||
void nft_fib_store_result(void *reg, const struct nft_fib *priv,
|
||||
const struct nft_pktinfo *pkt, int index)
|
||||
{
|
||||
struct net_device *dev;
|
||||
u32 *dreg = reg;
|
||||
|
||||
switch (r) {
|
||||
switch (priv->result) {
|
||||
case NFT_FIB_RESULT_OIF:
|
||||
*dreg = index;
|
||||
*dreg = (priv->flags & NFTA_FIB_F_PRESENT) ? !!index : index;
|
||||
break;
|
||||
case NFT_FIB_RESULT_OIFNAME:
|
||||
dev = dev_get_by_index_rcu(nft_net(pkt), index);
|
||||
strncpy(reg, dev ? dev->name : "", IFNAMSIZ);
|
||||
if (priv->flags & NFTA_FIB_F_PRESENT)
|
||||
*dreg = !!dev;
|
||||
else
|
||||
strncpy(reg, dev ? dev->name : "", IFNAMSIZ);
|
||||
break;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <net/netfilter/nf_tables_core.h>
|
||||
#include <linux/jhash.h>
|
||||
|
||||
struct nft_hash {
|
||||
struct nft_jhash {
|
||||
enum nft_registers sreg:8;
|
||||
enum nft_registers dreg:8;
|
||||
u8 len;
|
||||
@ -26,11 +26,11 @@ struct nft_hash {
|
||||
u32 offset;
|
||||
};
|
||||
|
||||
static void nft_hash_eval(const struct nft_expr *expr,
|
||||
struct nft_regs *regs,
|
||||
const struct nft_pktinfo *pkt)
|
||||
static void nft_jhash_eval(const struct nft_expr *expr,
|
||||
struct nft_regs *regs,
|
||||
const struct nft_pktinfo *pkt)
|
||||
{
|
||||
struct nft_hash *priv = nft_expr_priv(expr);
|
||||
struct nft_jhash *priv = nft_expr_priv(expr);
|
||||
const void *data = ®s->data[priv->sreg];
|
||||
u32 h;
|
||||
|
||||
@ -38,6 +38,25 @@ static void nft_hash_eval(const struct nft_expr *expr,
|
||||
regs->data[priv->dreg] = h + priv->offset;
|
||||
}
|
||||
|
||||
struct nft_symhash {
|
||||
enum nft_registers dreg:8;
|
||||
u32 modulus;
|
||||
u32 offset;
|
||||
};
|
||||
|
||||
static void nft_symhash_eval(const struct nft_expr *expr,
|
||||
struct nft_regs *regs,
|
||||
const struct nft_pktinfo *pkt)
|
||||
{
|
||||
struct nft_symhash *priv = nft_expr_priv(expr);
|
||||
struct sk_buff *skb = pkt->skb;
|
||||
u32 h;
|
||||
|
||||
h = reciprocal_scale(__skb_get_hash_symmetric(skb), priv->modulus);
|
||||
|
||||
regs->data[priv->dreg] = h + priv->offset;
|
||||
}
|
||||
|
||||
static const struct nla_policy nft_hash_policy[NFTA_HASH_MAX + 1] = {
|
||||
[NFTA_HASH_SREG] = { .type = NLA_U32 },
|
||||
[NFTA_HASH_DREG] = { .type = NLA_U32 },
|
||||
@ -45,13 +64,14 @@ static const struct nla_policy nft_hash_policy[NFTA_HASH_MAX + 1] = {
|
||||
[NFTA_HASH_MODULUS] = { .type = NLA_U32 },
|
||||
[NFTA_HASH_SEED] = { .type = NLA_U32 },
|
||||
[NFTA_HASH_OFFSET] = { .type = NLA_U32 },
|
||||
[NFTA_HASH_TYPE] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int nft_hash_init(const struct nft_ctx *ctx,
|
||||
const struct nft_expr *expr,
|
||||
const struct nlattr * const tb[])
|
||||
static int nft_jhash_init(const struct nft_ctx *ctx,
|
||||
const struct nft_expr *expr,
|
||||
const struct nlattr * const tb[])
|
||||
{
|
||||
struct nft_hash *priv = nft_expr_priv(expr);
|
||||
struct nft_jhash *priv = nft_expr_priv(expr);
|
||||
u32 len;
|
||||
int err;
|
||||
|
||||
@ -92,10 +112,36 @@ static int nft_hash_init(const struct nft_ctx *ctx,
|
||||
NFT_DATA_VALUE, sizeof(u32));
|
||||
}
|
||||
|
||||
static int nft_hash_dump(struct sk_buff *skb,
|
||||
const struct nft_expr *expr)
|
||||
static int nft_symhash_init(const struct nft_ctx *ctx,
|
||||
const struct nft_expr *expr,
|
||||
const struct nlattr * const tb[])
|
||||
{
|
||||
const struct nft_hash *priv = nft_expr_priv(expr);
|
||||
struct nft_symhash *priv = nft_expr_priv(expr);
|
||||
|
||||
if (!tb[NFTA_HASH_DREG] ||
|
||||
!tb[NFTA_HASH_MODULUS])
|
||||
return -EINVAL;
|
||||
|
||||
if (tb[NFTA_HASH_OFFSET])
|
||||
priv->offset = ntohl(nla_get_be32(tb[NFTA_HASH_OFFSET]));
|
||||
|
||||
priv->dreg = nft_parse_register(tb[NFTA_HASH_DREG]);
|
||||
|
||||
priv->modulus = ntohl(nla_get_be32(tb[NFTA_HASH_MODULUS]));
|
||||
if (priv->modulus <= 1)
|
||||
return -ERANGE;
|
||||
|
||||
if (priv->offset + priv->modulus - 1 < priv->offset)
|
||||
return -EOVERFLOW;
|
||||
|
||||
return nft_validate_register_store(ctx, priv->dreg, NULL,
|
||||
NFT_DATA_VALUE, sizeof(u32));
|
||||
}
|
||||
|
||||
static int nft_jhash_dump(struct sk_buff *skb,
|
||||
const struct nft_expr *expr)
|
||||
{
|
||||
const struct nft_jhash *priv = nft_expr_priv(expr);
|
||||
|
||||
if (nft_dump_register(skb, NFTA_HASH_SREG, priv->sreg))
|
||||
goto nla_put_failure;
|
||||
@ -110,6 +156,28 @@ static int nft_hash_dump(struct sk_buff *skb,
|
||||
if (priv->offset != 0)
|
||||
if (nla_put_be32(skb, NFTA_HASH_OFFSET, htonl(priv->offset)))
|
||||
goto nla_put_failure;
|
||||
if (nla_put_be32(skb, NFTA_HASH_TYPE, htonl(NFT_HASH_JENKINS)))
|
||||
goto nla_put_failure;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int nft_symhash_dump(struct sk_buff *skb,
|
||||
const struct nft_expr *expr)
|
||||
{
|
||||
const struct nft_symhash *priv = nft_expr_priv(expr);
|
||||
|
||||
if (nft_dump_register(skb, NFTA_HASH_DREG, priv->dreg))
|
||||
goto nla_put_failure;
|
||||
if (nla_put_be32(skb, NFTA_HASH_MODULUS, htonl(priv->modulus)))
|
||||
goto nla_put_failure;
|
||||
if (priv->offset != 0)
|
||||
if (nla_put_be32(skb, NFTA_HASH_OFFSET, htonl(priv->offset)))
|
||||
goto nla_put_failure;
|
||||
if (nla_put_be32(skb, NFTA_HASH_TYPE, htonl(NFT_HASH_SYM)))
|
||||
goto nla_put_failure;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
@ -117,17 +185,46 @@ nla_put_failure:
|
||||
}
|
||||
|
||||
static struct nft_expr_type nft_hash_type;
|
||||
static const struct nft_expr_ops nft_hash_ops = {
|
||||
static const struct nft_expr_ops nft_jhash_ops = {
|
||||
.type = &nft_hash_type,
|
||||
.size = NFT_EXPR_SIZE(sizeof(struct nft_hash)),
|
||||
.eval = nft_hash_eval,
|
||||
.init = nft_hash_init,
|
||||
.dump = nft_hash_dump,
|
||||
.size = NFT_EXPR_SIZE(sizeof(struct nft_jhash)),
|
||||
.eval = nft_jhash_eval,
|
||||
.init = nft_jhash_init,
|
||||
.dump = nft_jhash_dump,
|
||||
};
|
||||
|
||||
static const struct nft_expr_ops nft_symhash_ops = {
|
||||
.type = &nft_hash_type,
|
||||
.size = NFT_EXPR_SIZE(sizeof(struct nft_symhash)),
|
||||
.eval = nft_symhash_eval,
|
||||
.init = nft_symhash_init,
|
||||
.dump = nft_symhash_dump,
|
||||
};
|
||||
|
||||
static const struct nft_expr_ops *
|
||||
nft_hash_select_ops(const struct nft_ctx *ctx,
|
||||
const struct nlattr * const tb[])
|
||||
{
|
||||
u32 type;
|
||||
|
||||
if (!tb[NFTA_HASH_TYPE])
|
||||
return &nft_jhash_ops;
|
||||
|
||||
type = ntohl(nla_get_be32(tb[NFTA_HASH_TYPE]));
|
||||
switch (type) {
|
||||
case NFT_HASH_SYM:
|
||||
return &nft_symhash_ops;
|
||||
case NFT_HASH_JENKINS:
|
||||
return &nft_jhash_ops;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
}
|
||||
|
||||
static struct nft_expr_type nft_hash_type __read_mostly = {
|
||||
.name = "hash",
|
||||
.ops = &nft_hash_ops,
|
||||
.select_ops = &nft_hash_select_ops,
|
||||
.policy = nft_hash_policy,
|
||||
.maxattr = NFTA_HASH_MAX,
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -17,9 +17,8 @@
|
||||
#include <linux/netfilter/nf_tables.h>
|
||||
#include <net/netfilter/nf_tables.h>
|
||||
|
||||
static DEFINE_SPINLOCK(limit_lock);
|
||||
|
||||
struct nft_limit {
|
||||
spinlock_t lock;
|
||||
u64 last;
|
||||
u64 tokens;
|
||||
u64 tokens_max;
|
||||
@ -34,7 +33,7 @@ static inline bool nft_limit_eval(struct nft_limit *limit, u64 cost)
|
||||
u64 now, tokens;
|
||||
s64 delta;
|
||||
|
||||
spin_lock_bh(&limit_lock);
|
||||
spin_lock_bh(&limit->lock);
|
||||
now = ktime_get_ns();
|
||||
tokens = limit->tokens + now - limit->last;
|
||||
if (tokens > limit->tokens_max)
|
||||
@ -44,11 +43,11 @@ static inline bool nft_limit_eval(struct nft_limit *limit, u64 cost)
|
||||
delta = tokens - cost;
|
||||
if (delta >= 0) {
|
||||
limit->tokens = delta;
|
||||
spin_unlock_bh(&limit_lock);
|
||||
spin_unlock_bh(&limit->lock);
|
||||
return limit->invert;
|
||||
}
|
||||
limit->tokens = tokens;
|
||||
spin_unlock_bh(&limit_lock);
|
||||
spin_unlock_bh(&limit->lock);
|
||||
return !limit->invert;
|
||||
}
|
||||
|
||||
@ -86,6 +85,7 @@ static int nft_limit_init(struct nft_limit *limit,
|
||||
limit->invert = true;
|
||||
}
|
||||
limit->last = ktime_get_ns();
|
||||
spin_lock_init(&limit->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -71,16 +71,10 @@ static int nft_lookup_init(const struct nft_ctx *ctx,
|
||||
tb[NFTA_LOOKUP_SREG] == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
set = nf_tables_set_lookup(ctx->table, tb[NFTA_LOOKUP_SET], genmask);
|
||||
if (IS_ERR(set)) {
|
||||
if (tb[NFTA_LOOKUP_SET_ID]) {
|
||||
set = nf_tables_set_lookup_byid(ctx->net,
|
||||
tb[NFTA_LOOKUP_SET_ID],
|
||||
genmask);
|
||||
}
|
||||
if (IS_ERR(set))
|
||||
return PTR_ERR(set);
|
||||
}
|
||||
set = nft_set_lookup(ctx->net, ctx->table, tb[NFTA_LOOKUP_SET],
|
||||
tb[NFTA_LOOKUP_SET_ID], genmask);
|
||||
if (IS_ERR(set))
|
||||
return PTR_ERR(set);
|
||||
|
||||
if (set->flags & NFT_SET_EVAL)
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -46,10 +46,6 @@ int nft_masq_init(const struct nft_ctx *ctx,
|
||||
struct nft_masq *priv = nft_expr_priv(expr);
|
||||
int err;
|
||||
|
||||
err = nft_masq_validate(ctx, expr, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (tb[NFTA_MASQ_FLAGS]) {
|
||||
priv->flags = ntohl(nla_get_be32(tb[NFTA_MASQ_FLAGS]));
|
||||
if (priv->flags & ~NF_NAT_RANGE_MASK)
|
||||
|
@ -370,10 +370,6 @@ int nft_meta_set_init(const struct nft_ctx *ctx,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
err = nft_meta_set_validate(ctx, expr, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
priv->sreg = nft_parse_register(tb[NFTA_META_SREG]);
|
||||
err = nft_validate_register_load(priv->sreg, len);
|
||||
if (err < 0)
|
||||
|
@ -138,10 +138,6 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = nft_nat_validate(ctx, expr, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[NFTA_NAT_FAMILY] == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -116,16 +116,10 @@ static int nft_objref_map_init(const struct nft_ctx *ctx,
|
||||
struct nft_set *set;
|
||||
int err;
|
||||
|
||||
set = nf_tables_set_lookup(ctx->table, tb[NFTA_OBJREF_SET_NAME], genmask);
|
||||
if (IS_ERR(set)) {
|
||||
if (tb[NFTA_OBJREF_SET_ID]) {
|
||||
set = nf_tables_set_lookup_byid(ctx->net,
|
||||
tb[NFTA_OBJREF_SET_ID],
|
||||
genmask);
|
||||
}
|
||||
if (IS_ERR(set))
|
||||
return PTR_ERR(set);
|
||||
}
|
||||
set = nft_set_lookup(ctx->net, ctx->table, tb[NFTA_OBJREF_SET_NAME],
|
||||
tb[NFTA_OBJREF_SET_ID], genmask);
|
||||
if (IS_ERR(set))
|
||||
return PTR_ERR(set);
|
||||
|
||||
if (!(set->flags & NFT_SET_OBJECT))
|
||||
return -EINVAL;
|
||||
|
@ -99,7 +99,8 @@ static int nft_quota_do_init(const struct nlattr * const tb[],
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nft_quota_obj_init(const struct nlattr * const tb[],
|
||||
static int nft_quota_obj_init(const struct nft_ctx *ctx,
|
||||
const struct nlattr * const tb[],
|
||||
struct nft_object *obj)
|
||||
{
|
||||
struct nft_quota *priv = nft_obj_data(obj);
|
||||
|
@ -47,10 +47,6 @@ int nft_redir_init(const struct nft_ctx *ctx,
|
||||
unsigned int plen;
|
||||
int err;
|
||||
|
||||
err = nft_redir_validate(ctx, expr, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all);
|
||||
if (tb[NFTA_REDIR_REG_PROTO_MIN]) {
|
||||
priv->sreg_proto_min =
|
||||
|
@ -42,11 +42,6 @@ int nft_reject_init(const struct nft_ctx *ctx,
|
||||
const struct nlattr * const tb[])
|
||||
{
|
||||
struct nft_reject *priv = nft_expr_priv(expr);
|
||||
int err;
|
||||
|
||||
err = nft_reject_validate(ctx, expr, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[NFTA_REJECT_TYPE] == NULL)
|
||||
return -EINVAL;
|
||||
|
@ -66,11 +66,7 @@ static int nft_reject_inet_init(const struct nft_ctx *ctx,
|
||||
const struct nlattr * const tb[])
|
||||
{
|
||||
struct nft_reject *priv = nft_expr_priv(expr);
|
||||
int icmp_code, err;
|
||||
|
||||
err = nft_reject_validate(ctx, expr, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
int icmp_code;
|
||||
|
||||
if (tb[NFTA_REJECT_TYPE] == NULL)
|
||||
return -EINVAL;
|
||||
|
@ -18,9 +18,8 @@
|
||||
#include <linux/netfilter/nf_tables.h>
|
||||
#include <net/netfilter/nf_tables.h>
|
||||
|
||||
static DEFINE_SPINLOCK(nft_rbtree_lock);
|
||||
|
||||
struct nft_rbtree {
|
||||
rwlock_t lock;
|
||||
struct rb_root root;
|
||||
};
|
||||
|
||||
@ -44,14 +43,14 @@ static bool nft_rbtree_equal(const struct nft_set *set, const void *this,
|
||||
static bool nft_rbtree_lookup(const struct net *net, const struct nft_set *set,
|
||||
const u32 *key, const struct nft_set_ext **ext)
|
||||
{
|
||||
const struct nft_rbtree *priv = nft_set_priv(set);
|
||||
struct nft_rbtree *priv = nft_set_priv(set);
|
||||
const struct nft_rbtree_elem *rbe, *interval = NULL;
|
||||
u8 genmask = nft_genmask_cur(net);
|
||||
const struct rb_node *parent;
|
||||
const void *this;
|
||||
int d;
|
||||
|
||||
spin_lock_bh(&nft_rbtree_lock);
|
||||
read_lock_bh(&priv->lock);
|
||||
parent = priv->root.rb_node;
|
||||
while (parent != NULL) {
|
||||
rbe = rb_entry(parent, struct nft_rbtree_elem, node);
|
||||
@ -75,7 +74,7 @@ static bool nft_rbtree_lookup(const struct net *net, const struct nft_set *set,
|
||||
}
|
||||
if (nft_rbtree_interval_end(rbe))
|
||||
goto out;
|
||||
spin_unlock_bh(&nft_rbtree_lock);
|
||||
read_unlock_bh(&priv->lock);
|
||||
|
||||
*ext = &rbe->ext;
|
||||
return true;
|
||||
@ -85,12 +84,12 @@ static bool nft_rbtree_lookup(const struct net *net, const struct nft_set *set,
|
||||
if (set->flags & NFT_SET_INTERVAL && interval != NULL &&
|
||||
nft_set_elem_active(&interval->ext, genmask) &&
|
||||
!nft_rbtree_interval_end(interval)) {
|
||||
spin_unlock_bh(&nft_rbtree_lock);
|
||||
read_unlock_bh(&priv->lock);
|
||||
*ext = &interval->ext;
|
||||
return true;
|
||||
}
|
||||
out:
|
||||
spin_unlock_bh(&nft_rbtree_lock);
|
||||
read_unlock_bh(&priv->lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -140,12 +139,13 @@ static int nft_rbtree_insert(const struct net *net, const struct nft_set *set,
|
||||
const struct nft_set_elem *elem,
|
||||
struct nft_set_ext **ext)
|
||||
{
|
||||
struct nft_rbtree *priv = nft_set_priv(set);
|
||||
struct nft_rbtree_elem *rbe = elem->priv;
|
||||
int err;
|
||||
|
||||
spin_lock_bh(&nft_rbtree_lock);
|
||||
write_lock_bh(&priv->lock);
|
||||
err = __nft_rbtree_insert(net, set, rbe, ext);
|
||||
spin_unlock_bh(&nft_rbtree_lock);
|
||||
write_unlock_bh(&priv->lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -157,9 +157,9 @@ static void nft_rbtree_remove(const struct net *net,
|
||||
struct nft_rbtree *priv = nft_set_priv(set);
|
||||
struct nft_rbtree_elem *rbe = elem->priv;
|
||||
|
||||
spin_lock_bh(&nft_rbtree_lock);
|
||||
write_lock_bh(&priv->lock);
|
||||
rb_erase(&rbe->node, &priv->root);
|
||||
spin_unlock_bh(&nft_rbtree_lock);
|
||||
write_unlock_bh(&priv->lock);
|
||||
}
|
||||
|
||||
static void nft_rbtree_activate(const struct net *net,
|
||||
@ -224,12 +224,12 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx,
|
||||
struct nft_set *set,
|
||||
struct nft_set_iter *iter)
|
||||
{
|
||||
const struct nft_rbtree *priv = nft_set_priv(set);
|
||||
struct nft_rbtree *priv = nft_set_priv(set);
|
||||
struct nft_rbtree_elem *rbe;
|
||||
struct nft_set_elem elem;
|
||||
struct rb_node *node;
|
||||
|
||||
spin_lock_bh(&nft_rbtree_lock);
|
||||
read_lock_bh(&priv->lock);
|
||||
for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) {
|
||||
rbe = rb_entry(node, struct nft_rbtree_elem, node);
|
||||
|
||||
@ -242,13 +242,13 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx,
|
||||
|
||||
iter->err = iter->fn(ctx, set, iter, &elem);
|
||||
if (iter->err < 0) {
|
||||
spin_unlock_bh(&nft_rbtree_lock);
|
||||
read_unlock_bh(&priv->lock);
|
||||
return;
|
||||
}
|
||||
cont:
|
||||
iter->count++;
|
||||
}
|
||||
spin_unlock_bh(&nft_rbtree_lock);
|
||||
read_unlock_bh(&priv->lock);
|
||||
}
|
||||
|
||||
static unsigned int nft_rbtree_privsize(const struct nlattr * const nla[])
|
||||
@ -262,6 +262,7 @@ static int nft_rbtree_init(const struct nft_set *set,
|
||||
{
|
||||
struct nft_rbtree *priv = nft_set_priv(set);
|
||||
|
||||
rwlock_init(&priv->lock);
|
||||
priv->root = RB_ROOT;
|
||||
return 0;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <linux/netfilter/xt_limit.h>
|
||||
|
||||
struct xt_limit_priv {
|
||||
spinlock_t lock;
|
||||
unsigned long prev;
|
||||
uint32_t credit;
|
||||
};
|
||||
@ -32,8 +33,6 @@ MODULE_ALIAS("ip6t_limit");
|
||||
* see net/sched/sch_tbf.c in the linux source tree
|
||||
*/
|
||||
|
||||
static DEFINE_SPINLOCK(limit_lock);
|
||||
|
||||
/* Rusty: This is my (non-mathematically-inclined) understanding of
|
||||
this algorithm. The `average rate' in jiffies becomes your initial
|
||||
amount of credit `credit' and the most credit you can ever have
|
||||
@ -72,7 +71,7 @@ limit_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
struct xt_limit_priv *priv = r->master;
|
||||
unsigned long now = jiffies;
|
||||
|
||||
spin_lock_bh(&limit_lock);
|
||||
spin_lock_bh(&priv->lock);
|
||||
priv->credit += (now - xchg(&priv->prev, now)) * CREDITS_PER_JIFFY;
|
||||
if (priv->credit > r->credit_cap)
|
||||
priv->credit = r->credit_cap;
|
||||
@ -80,11 +79,11 @@ limit_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
if (priv->credit >= r->cost) {
|
||||
/* We're not limited. */
|
||||
priv->credit -= r->cost;
|
||||
spin_unlock_bh(&limit_lock);
|
||||
spin_unlock_bh(&priv->lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&limit_lock);
|
||||
spin_unlock_bh(&priv->lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -126,6 +125,8 @@ static int limit_mt_check(const struct xt_mtchk_param *par)
|
||||
r->credit_cap = priv->credit; /* Credits full. */
|
||||
r->cost = user2credits(r->avg);
|
||||
}
|
||||
spin_lock_init(&priv->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user