Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== Netfilter/nftables/IPVS fixes for net The following patchset contains Netfilter/IPVS fixes, mostly nftables fixes, most relevantly they are: * Fix a crash in the h323 conntrack NAT helper due to expectation list corruption, from Alexey Dobriyan. * A couple of RCU race fixes for conntrack, one manifests by hitting BUG_ON in nf_nat_setup_info() and the destroy path, patches from Andrey Vagin and me. * Dump direction attribute in nft_ct only if it is set, from Arturo Borrero. * Fix IPVS bug in its own connection tracking system that may lead to copying only 4 bytes of the IPv6 address when initializing the ip_vs_conn object, from Michal Kubecek. * Fix -EBUSY errors in nftables when deleting the rules, chain and tables in a row due mixture of asynchronous and synchronous object releasing, from me. * Three fixes for the nf_tables set infrastructure when using intervals and mappings, from me. * Four patches to fixing the nf_tables log, reject and ct expressions from the new inet table, from Patrick McHardy. * Fix memory overrun in the map that is used to dynamically allocate names from anonymous sets, also from Patrick. * Fix a potential oops if you dump a set with NFPROTO_UNSPEC and a table name, from Patrick McHardy. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
f41f031960
|
@ -284,6 +284,8 @@ extern unsigned int nf_conntrack_max;
|
|||
extern unsigned int nf_conntrack_hash_rnd;
|
||||
void init_nf_conntrack_hash_rnd(void);
|
||||
|
||||
void nf_conntrack_tmpl_insert(struct net *net, struct nf_conn *tmpl);
|
||||
|
||||
#define NF_CT_STAT_INC(net, count) __this_cpu_inc((net)->ct.stat->count)
|
||||
#define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count)
|
||||
|
||||
|
|
|
@ -252,6 +252,7 @@ void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
|
|||
* @owner: module reference
|
||||
* @policy: netlink attribute policy
|
||||
* @maxattr: highest netlink attribute number
|
||||
* @family: address family for AF-specific types
|
||||
*/
|
||||
struct nft_expr_type {
|
||||
const struct nft_expr_ops *(*select_ops)(const struct nft_ctx *,
|
||||
|
@ -262,6 +263,7 @@ struct nft_expr_type {
|
|||
struct module *owner;
|
||||
const struct nla_policy *policy;
|
||||
unsigned int maxattr;
|
||||
u8 family;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -320,7 +322,6 @@ static inline void *nft_expr_priv(const struct nft_expr *expr)
|
|||
* struct nft_rule - nf_tables rule
|
||||
*
|
||||
* @list: used internally
|
||||
* @rcu_head: used internally for rcu
|
||||
* @handle: rule handle
|
||||
* @genmask: generation mask
|
||||
* @dlen: length of expression data
|
||||
|
@ -328,7 +329,6 @@ static inline void *nft_expr_priv(const struct nft_expr *expr)
|
|||
*/
|
||||
struct nft_rule {
|
||||
struct list_head list;
|
||||
struct rcu_head rcu_head;
|
||||
u64 handle:46,
|
||||
genmask:2,
|
||||
dlen:16;
|
||||
|
@ -389,7 +389,6 @@ enum nft_chain_flags {
|
|||
*
|
||||
* @rules: list of rules in the chain
|
||||
* @list: used internally
|
||||
* @rcu_head: used internally
|
||||
* @net: net namespace that this chain belongs to
|
||||
* @table: table that this chain belongs to
|
||||
* @handle: chain handle
|
||||
|
@ -401,7 +400,6 @@ enum nft_chain_flags {
|
|||
struct nft_chain {
|
||||
struct list_head rules;
|
||||
struct list_head list;
|
||||
struct rcu_head rcu_head;
|
||||
struct net *net;
|
||||
struct nft_table *table;
|
||||
u64 handle;
|
||||
|
@ -529,6 +527,9 @@ void nft_unregister_expr(struct nft_expr_type *);
|
|||
#define MODULE_ALIAS_NFT_CHAIN(family, name) \
|
||||
MODULE_ALIAS("nft-chain-" __stringify(family) "-" name)
|
||||
|
||||
#define MODULE_ALIAS_NFT_AF_EXPR(family, name) \
|
||||
MODULE_ALIAS("nft-expr-" __stringify(family) "-" name)
|
||||
|
||||
#define MODULE_ALIAS_NFT_EXPR(name) \
|
||||
MODULE_ALIAS("nft-expr-" name)
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef _NFT_REJECT_H_
|
||||
#define _NFT_REJECT_H_
|
||||
|
||||
struct nft_reject {
|
||||
enum nft_reject_types type:8;
|
||||
u8 icmp_code;
|
||||
};
|
||||
|
||||
extern const struct nla_policy nft_reject_policy[];
|
||||
|
||||
int nft_reject_init(const struct nft_ctx *ctx,
|
||||
const struct nft_expr *expr,
|
||||
const struct nlattr * const tb[]);
|
||||
|
||||
int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr);
|
||||
|
||||
void nft_reject_ipv4_eval(const struct nft_expr *expr,
|
||||
struct nft_data data[NFT_REG_MAX + 1],
|
||||
const struct nft_pktinfo *pkt);
|
||||
|
||||
void nft_reject_ipv6_eval(const struct nft_expr *expr,
|
||||
struct nft_data data[NFT_REG_MAX + 1],
|
||||
const struct nft_pktinfo *pkt);
|
||||
|
||||
#endif
|
|
@ -61,6 +61,11 @@ config NFT_CHAIN_NAT_IPV4
|
|||
packet transformations such as the source, destination address and
|
||||
source and destination ports.
|
||||
|
||||
config NFT_REJECT_IPV4
|
||||
depends on NF_TABLES_IPV4
|
||||
default NFT_REJECT
|
||||
tristate
|
||||
|
||||
config NF_TABLES_ARP
|
||||
depends on NF_TABLES
|
||||
tristate "ARP nf_tables support"
|
||||
|
|
|
@ -30,6 +30,7 @@ obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
|
|||
obj-$(CONFIG_NF_TABLES_IPV4) += nf_tables_ipv4.o
|
||||
obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV4) += nft_chain_route_ipv4.o
|
||||
obj-$(CONFIG_NFT_CHAIN_NAT_IPV4) += nft_chain_nat_ipv4.o
|
||||
obj-$(CONFIG_NFT_REJECT_IPV4) += nft_reject_ipv4.o
|
||||
obj-$(CONFIG_NF_TABLES_ARP) += nf_tables_arp.o
|
||||
|
||||
# generic IP tables
|
||||
|
|
|
@ -229,7 +229,10 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
|
|||
ret = nf_ct_expect_related(rtcp_exp);
|
||||
if (ret == 0)
|
||||
break;
|
||||
else if (ret != -EBUSY) {
|
||||
else if (ret == -EBUSY) {
|
||||
nf_ct_unexpect_related(rtp_exp);
|
||||
continue;
|
||||
} else if (ret < 0) {
|
||||
nf_ct_unexpect_related(rtp_exp);
|
||||
nated_port = 0;
|
||||
break;
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
|
||||
* Copyright (c) 2013 Eric Leblond <eric@regit.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Development of this code funded by Astaro AG (http://www.astaro.com/)
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter/nf_tables.h>
|
||||
#include <net/netfilter/nf_tables.h>
|
||||
#include <net/icmp.h>
|
||||
#include <net/netfilter/ipv4/nf_reject.h>
|
||||
#include <net/netfilter/nft_reject.h>
|
||||
|
||||
void nft_reject_ipv4_eval(const struct nft_expr *expr,
|
||||
struct nft_data data[NFT_REG_MAX + 1],
|
||||
const struct nft_pktinfo *pkt)
|
||||
{
|
||||
struct nft_reject *priv = nft_expr_priv(expr);
|
||||
|
||||
switch (priv->type) {
|
||||
case NFT_REJECT_ICMP_UNREACH:
|
||||
nf_send_unreach(pkt->skb, priv->icmp_code);
|
||||
break;
|
||||
case NFT_REJECT_TCP_RST:
|
||||
nf_send_reset(pkt->skb, pkt->ops->hooknum);
|
||||
break;
|
||||
}
|
||||
|
||||
data[NFT_REG_VERDICT].verdict = NF_DROP;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nft_reject_ipv4_eval);
|
||||
|
||||
static struct nft_expr_type nft_reject_ipv4_type;
|
||||
static const struct nft_expr_ops nft_reject_ipv4_ops = {
|
||||
.type = &nft_reject_ipv4_type,
|
||||
.size = NFT_EXPR_SIZE(sizeof(struct nft_reject)),
|
||||
.eval = nft_reject_ipv4_eval,
|
||||
.init = nft_reject_init,
|
||||
.dump = nft_reject_dump,
|
||||
};
|
||||
|
||||
static struct nft_expr_type nft_reject_ipv4_type __read_mostly = {
|
||||
.family = NFPROTO_IPV4,
|
||||
.name = "reject",
|
||||
.ops = &nft_reject_ipv4_ops,
|
||||
.policy = nft_reject_policy,
|
||||
.maxattr = NFTA_REJECT_MAX,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init nft_reject_ipv4_module_init(void)
|
||||
{
|
||||
return nft_register_expr(&nft_reject_ipv4_type);
|
||||
}
|
||||
|
||||
static void __exit nft_reject_ipv4_module_exit(void)
|
||||
{
|
||||
nft_unregister_expr(&nft_reject_ipv4_type);
|
||||
}
|
||||
|
||||
module_init(nft_reject_ipv4_module_init);
|
||||
module_exit(nft_reject_ipv4_module_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
|
||||
MODULE_ALIAS_NFT_AF_EXPR(AF_INET, "reject");
|
|
@ -50,6 +50,11 @@ config NFT_CHAIN_NAT_IPV6
|
|||
packet transformations such as the source, destination address and
|
||||
source and destination ports.
|
||||
|
||||
config NFT_REJECT_IPV6
|
||||
depends on NF_TABLES_IPV6
|
||||
default NFT_REJECT
|
||||
tristate
|
||||
|
||||
config IP6_NF_IPTABLES
|
||||
tristate "IP6 tables support (required for filtering)"
|
||||
depends on INET && IPV6
|
||||
|
|
|
@ -27,6 +27,7 @@ obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o
|
|||
obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o
|
||||
obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o
|
||||
obj-$(CONFIG_NFT_CHAIN_NAT_IPV6) += nft_chain_nat_ipv6.o
|
||||
obj-$(CONFIG_NFT_REJECT_IPV6) += nft_reject_ipv6.o
|
||||
|
||||
# matches
|
||||
obj-$(CONFIG_IP6_NF_MATCH_AH) += ip6t_ah.o
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
|
||||
* Copyright (c) 2013 Eric Leblond <eric@regit.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Development of this code funded by Astaro AG (http://www.astaro.com/)
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter/nf_tables.h>
|
||||
#include <net/netfilter/nf_tables.h>
|
||||
#include <net/netfilter/nft_reject.h>
|
||||
#include <net/netfilter/ipv6/nf_reject.h>
|
||||
|
||||
void nft_reject_ipv6_eval(const struct nft_expr *expr,
|
||||
struct nft_data data[NFT_REG_MAX + 1],
|
||||
const struct nft_pktinfo *pkt)
|
||||
{
|
||||
struct nft_reject *priv = nft_expr_priv(expr);
|
||||
struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out);
|
||||
|
||||
switch (priv->type) {
|
||||
case NFT_REJECT_ICMP_UNREACH:
|
||||
nf_send_unreach6(net, pkt->skb, priv->icmp_code,
|
||||
pkt->ops->hooknum);
|
||||
break;
|
||||
case NFT_REJECT_TCP_RST:
|
||||
nf_send_reset6(net, pkt->skb, pkt->ops->hooknum);
|
||||
break;
|
||||
}
|
||||
|
||||
data[NFT_REG_VERDICT].verdict = NF_DROP;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nft_reject_ipv6_eval);
|
||||
|
||||
static struct nft_expr_type nft_reject_ipv6_type;
|
||||
static const struct nft_expr_ops nft_reject_ipv6_ops = {
|
||||
.type = &nft_reject_ipv6_type,
|
||||
.size = NFT_EXPR_SIZE(sizeof(struct nft_reject)),
|
||||
.eval = nft_reject_ipv6_eval,
|
||||
.init = nft_reject_init,
|
||||
.dump = nft_reject_dump,
|
||||
};
|
||||
|
||||
static struct nft_expr_type nft_reject_ipv6_type __read_mostly = {
|
||||
.family = NFPROTO_IPV6,
|
||||
.name = "reject",
|
||||
.ops = &nft_reject_ipv6_ops,
|
||||
.policy = nft_reject_policy,
|
||||
.maxattr = NFTA_REJECT_MAX,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init nft_reject_ipv6_module_init(void)
|
||||
{
|
||||
return nft_register_expr(&nft_reject_ipv6_type);
|
||||
}
|
||||
|
||||
static void __exit nft_reject_ipv6_module_exit(void)
|
||||
{
|
||||
nft_unregister_expr(&nft_reject_ipv6_type);
|
||||
}
|
||||
|
||||
module_init(nft_reject_ipv6_module_init);
|
||||
module_exit(nft_reject_ipv6_module_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
|
||||
MODULE_ALIAS_NFT_AF_EXPR(AF_INET6, "reject");
|
|
@ -513,7 +513,6 @@ config NFT_QUEUE
|
|||
|
||||
config NFT_REJECT
|
||||
depends on NF_TABLES
|
||||
depends on NF_TABLES_IPV6 || !NF_TABLES_IPV6
|
||||
default m if NETFILTER_ADVANCED=n
|
||||
tristate "Netfilter nf_tables reject support"
|
||||
help
|
||||
|
@ -521,6 +520,11 @@ config NFT_REJECT
|
|||
explicitly deny and notify via TCP reset/ICMP informational errors
|
||||
unallowed traffic.
|
||||
|
||||
config NFT_REJECT_INET
|
||||
depends on NF_TABLES_INET
|
||||
default NFT_REJECT
|
||||
tristate
|
||||
|
||||
config NFT_COMPAT
|
||||
depends on NF_TABLES
|
||||
depends on NETFILTER_XTABLES
|
||||
|
|
|
@ -79,6 +79,7 @@ obj-$(CONFIG_NFT_LIMIT) += nft_limit.o
|
|||
obj-$(CONFIG_NFT_NAT) += nft_nat.o
|
||||
obj-$(CONFIG_NFT_QUEUE) += nft_queue.o
|
||||
obj-$(CONFIG_NFT_REJECT) += nft_reject.o
|
||||
obj-$(CONFIG_NFT_REJECT_INET) += nft_reject_inet.o
|
||||
obj-$(CONFIG_NFT_RBTREE) += nft_rbtree.o
|
||||
obj-$(CONFIG_NFT_HASH) += nft_hash.o
|
||||
obj-$(CONFIG_NFT_COUNTER) += nft_counter.o
|
||||
|
|
|
@ -871,11 +871,11 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p,
|
|||
cp->protocol = p->protocol;
|
||||
ip_vs_addr_set(p->af, &cp->caddr, p->caddr);
|
||||
cp->cport = p->cport;
|
||||
ip_vs_addr_set(p->af, &cp->vaddr, p->vaddr);
|
||||
cp->vport = p->vport;
|
||||
/* proto should only be IPPROTO_IP if d_addr is a fwmark */
|
||||
/* proto should only be IPPROTO_IP if p->vaddr is a fwmark */
|
||||
ip_vs_addr_set(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af,
|
||||
&cp->daddr, daddr);
|
||||
&cp->vaddr, p->vaddr);
|
||||
cp->vport = p->vport;
|
||||
ip_vs_addr_set(p->af, &cp->daddr, daddr);
|
||||
cp->dport = dport;
|
||||
cp->flags = flags;
|
||||
cp->fwmark = fwmark;
|
||||
|
|
|
@ -312,6 +312,21 @@ static void death_by_timeout(unsigned long ul_conntrack)
|
|||
nf_ct_delete((struct nf_conn *)ul_conntrack, 0, 0);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
nf_ct_key_equal(struct nf_conntrack_tuple_hash *h,
|
||||
const struct nf_conntrack_tuple *tuple,
|
||||
u16 zone)
|
||||
{
|
||||
struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
|
||||
|
||||
/* A conntrack can be recreated with the equal tuple,
|
||||
* so we need to check that the conntrack is confirmed
|
||||
*/
|
||||
return nf_ct_tuple_equal(tuple, &h->tuple) &&
|
||||
nf_ct_zone(ct) == zone &&
|
||||
nf_ct_is_confirmed(ct);
|
||||
}
|
||||
|
||||
/*
|
||||
* Warning :
|
||||
* - Caller must take a reference on returned object
|
||||
|
@ -333,8 +348,7 @@ ____nf_conntrack_find(struct net *net, u16 zone,
|
|||
local_bh_disable();
|
||||
begin:
|
||||
hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[bucket], hnnode) {
|
||||
if (nf_ct_tuple_equal(tuple, &h->tuple) &&
|
||||
nf_ct_zone(nf_ct_tuplehash_to_ctrack(h)) == zone) {
|
||||
if (nf_ct_key_equal(h, tuple, zone)) {
|
||||
NF_CT_STAT_INC(net, found);
|
||||
local_bh_enable();
|
||||
return h;
|
||||
|
@ -372,8 +386,7 @@ begin:
|
|||
!atomic_inc_not_zero(&ct->ct_general.use)))
|
||||
h = NULL;
|
||||
else {
|
||||
if (unlikely(!nf_ct_tuple_equal(tuple, &h->tuple) ||
|
||||
nf_ct_zone(ct) != zone)) {
|
||||
if (unlikely(!nf_ct_key_equal(h, tuple, zone))) {
|
||||
nf_ct_put(ct);
|
||||
goto begin;
|
||||
}
|
||||
|
@ -435,7 +448,9 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct)
|
|||
goto out;
|
||||
|
||||
add_timer(&ct->timeout);
|
||||
nf_conntrack_get(&ct->ct_general);
|
||||
smp_wmb();
|
||||
/* The caller holds a reference to this object */
|
||||
atomic_set(&ct->ct_general.use, 2);
|
||||
__nf_conntrack_hash_insert(ct, hash, repl_hash);
|
||||
NF_CT_STAT_INC(net, insert);
|
||||
spin_unlock_bh(&nf_conntrack_lock);
|
||||
|
@ -449,6 +464,21 @@ out:
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(nf_conntrack_hash_check_insert);
|
||||
|
||||
/* deletion from this larval template list happens via nf_ct_put() */
|
||||
void nf_conntrack_tmpl_insert(struct net *net, struct nf_conn *tmpl)
|
||||
{
|
||||
__set_bit(IPS_TEMPLATE_BIT, &tmpl->status);
|
||||
__set_bit(IPS_CONFIRMED_BIT, &tmpl->status);
|
||||
nf_conntrack_get(&tmpl->ct_general);
|
||||
|
||||
spin_lock_bh(&nf_conntrack_lock);
|
||||
/* Overload tuple linked list to put us in template list. */
|
||||
hlist_nulls_add_head_rcu(&tmpl->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
|
||||
&net->ct.tmpl);
|
||||
spin_unlock_bh(&nf_conntrack_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_conntrack_tmpl_insert);
|
||||
|
||||
/* Confirm a connection given skb; places it in hash table */
|
||||
int
|
||||
__nf_conntrack_confirm(struct sk_buff *skb)
|
||||
|
@ -720,11 +750,10 @@ __nf_conntrack_alloc(struct net *net, u16 zone,
|
|||
nf_ct_zone->id = zone;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* changes to lookup keys must be done before setting refcnt to 1
|
||||
/* Because we use RCU lookups, we set ct_general.use to zero before
|
||||
* this is inserted in any list.
|
||||
*/
|
||||
smp_wmb();
|
||||
atomic_set(&ct->ct_general.use, 1);
|
||||
atomic_set(&ct->ct_general.use, 0);
|
||||
return ct;
|
||||
|
||||
#ifdef CONFIG_NF_CONNTRACK_ZONES
|
||||
|
@ -748,6 +777,11 @@ void nf_conntrack_free(struct nf_conn *ct)
|
|||
{
|
||||
struct net *net = nf_ct_net(ct);
|
||||
|
||||
/* A freed object has refcnt == 0, that's
|
||||
* the golden rule for SLAB_DESTROY_BY_RCU
|
||||
*/
|
||||
NF_CT_ASSERT(atomic_read(&ct->ct_general.use) == 0);
|
||||
|
||||
nf_ct_ext_destroy(ct);
|
||||
nf_ct_ext_free(ct);
|
||||
kmem_cache_free(net->ct.nf_conntrack_cachep, ct);
|
||||
|
@ -843,6 +877,9 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
|
|||
NF_CT_STAT_INC(net, new);
|
||||
}
|
||||
|
||||
/* Now it is inserted into the unconfirmed list, bump refcount */
|
||||
nf_conntrack_get(&ct->ct_general);
|
||||
|
||||
/* Overload tuple linked list to put us in unconfirmed list. */
|
||||
hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
|
||||
&net->ct.unconfirmed);
|
||||
|
|
|
@ -363,9 +363,8 @@ static int __net_init synproxy_net_init(struct net *net)
|
|||
goto err2;
|
||||
if (!nfct_synproxy_ext_add(ct))
|
||||
goto err2;
|
||||
__set_bit(IPS_TEMPLATE_BIT, &ct->status);
|
||||
__set_bit(IPS_CONFIRMED_BIT, &ct->status);
|
||||
|
||||
nf_conntrack_tmpl_insert(net, ct);
|
||||
snet->tmpl = ct;
|
||||
|
||||
snet->stats = alloc_percpu(struct synproxy_stats);
|
||||
|
@ -390,7 +389,7 @@ static void __net_exit synproxy_net_exit(struct net *net)
|
|||
{
|
||||
struct synproxy_net *snet = synproxy_pernet(net);
|
||||
|
||||
nf_conntrack_free(snet->tmpl);
|
||||
nf_ct_put(snet->tmpl);
|
||||
synproxy_proc_exit(net);
|
||||
free_percpu(snet->stats);
|
||||
}
|
||||
|
|
|
@ -1008,10 +1008,8 @@ notify:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void nf_tables_rcu_chain_destroy(struct rcu_head *head)
|
||||
static void nf_tables_chain_destroy(struct nft_chain *chain)
|
||||
{
|
||||
struct nft_chain *chain = container_of(head, struct nft_chain, rcu_head);
|
||||
|
||||
BUG_ON(chain->use > 0);
|
||||
|
||||
if (chain->flags & NFT_BASE_CHAIN) {
|
||||
|
@ -1045,7 +1043,7 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb,
|
|||
if (IS_ERR(chain))
|
||||
return PTR_ERR(chain);
|
||||
|
||||
if (!list_empty(&chain->rules))
|
||||
if (!list_empty(&chain->rules) || chain->use > 0)
|
||||
return -EBUSY;
|
||||
|
||||
list_del(&chain->list);
|
||||
|
@ -1059,7 +1057,9 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb,
|
|||
family);
|
||||
|
||||
/* Make sure all rule references are gone before this is released */
|
||||
call_rcu(&chain->rcu_head, nf_tables_rcu_chain_destroy);
|
||||
synchronize_rcu();
|
||||
|
||||
nf_tables_chain_destroy(chain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1114,35 +1114,45 @@ void nft_unregister_expr(struct nft_expr_type *type)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(nft_unregister_expr);
|
||||
|
||||
static const struct nft_expr_type *__nft_expr_type_get(struct nlattr *nla)
|
||||
static const struct nft_expr_type *__nft_expr_type_get(u8 family,
|
||||
struct nlattr *nla)
|
||||
{
|
||||
const struct nft_expr_type *type;
|
||||
|
||||
list_for_each_entry(type, &nf_tables_expressions, list) {
|
||||
if (!nla_strcmp(nla, type->name))
|
||||
if (!nla_strcmp(nla, type->name) &&
|
||||
(!type->family || type->family == family))
|
||||
return type;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct nft_expr_type *nft_expr_type_get(struct nlattr *nla)
|
||||
static const struct nft_expr_type *nft_expr_type_get(u8 family,
|
||||
struct nlattr *nla)
|
||||
{
|
||||
const struct nft_expr_type *type;
|
||||
|
||||
if (nla == NULL)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
type = __nft_expr_type_get(nla);
|
||||
type = __nft_expr_type_get(family, nla);
|
||||
if (type != NULL && try_module_get(type->owner))
|
||||
return type;
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
if (type == NULL) {
|
||||
nfnl_unlock(NFNL_SUBSYS_NFTABLES);
|
||||
request_module("nft-expr-%u-%.*s", family,
|
||||
nla_len(nla), (char *)nla_data(nla));
|
||||
nfnl_lock(NFNL_SUBSYS_NFTABLES);
|
||||
if (__nft_expr_type_get(family, nla))
|
||||
return ERR_PTR(-EAGAIN);
|
||||
|
||||
nfnl_unlock(NFNL_SUBSYS_NFTABLES);
|
||||
request_module("nft-expr-%.*s",
|
||||
nla_len(nla), (char *)nla_data(nla));
|
||||
nfnl_lock(NFNL_SUBSYS_NFTABLES);
|
||||
if (__nft_expr_type_get(nla))
|
||||
if (__nft_expr_type_get(family, nla))
|
||||
return ERR_PTR(-EAGAIN);
|
||||
}
|
||||
#endif
|
||||
|
@ -1193,7 +1203,7 @@ static int nf_tables_expr_parse(const struct nft_ctx *ctx,
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
type = nft_expr_type_get(tb[NFTA_EXPR_NAME]);
|
||||
type = nft_expr_type_get(ctx->afi->family, tb[NFTA_EXPR_NAME]);
|
||||
if (IS_ERR(type))
|
||||
return PTR_ERR(type);
|
||||
|
||||
|
@ -1521,9 +1531,8 @@ err:
|
|||
return err;
|
||||
}
|
||||
|
||||
static void nf_tables_rcu_rule_destroy(struct rcu_head *head)
|
||||
static void nf_tables_rule_destroy(struct nft_rule *rule)
|
||||
{
|
||||
struct nft_rule *rule = container_of(head, struct nft_rule, rcu_head);
|
||||
struct nft_expr *expr;
|
||||
|
||||
/*
|
||||
|
@ -1538,11 +1547,6 @@ static void nf_tables_rcu_rule_destroy(struct rcu_head *head)
|
|||
kfree(rule);
|
||||
}
|
||||
|
||||
static void nf_tables_rule_destroy(struct nft_rule *rule)
|
||||
{
|
||||
call_rcu(&rule->rcu_head, nf_tables_rcu_rule_destroy);
|
||||
}
|
||||
|
||||
#define NFT_RULE_MAXEXPRS 128
|
||||
|
||||
static struct nft_expr_info *info;
|
||||
|
@ -1809,9 +1813,6 @@ static int nf_tables_commit(struct sk_buff *skb)
|
|||
synchronize_rcu();
|
||||
|
||||
list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) {
|
||||
/* Delete this rule from the dirty list */
|
||||
list_del(&rupd->list);
|
||||
|
||||
/* This rule was inactive in the past and just became active.
|
||||
* Clear the next bit of the genmask since its meaning has
|
||||
* changed, now it is the future.
|
||||
|
@ -1822,6 +1823,7 @@ static int nf_tables_commit(struct sk_buff *skb)
|
|||
rupd->chain, rupd->rule,
|
||||
NFT_MSG_NEWRULE, 0,
|
||||
rupd->family);
|
||||
list_del(&rupd->list);
|
||||
kfree(rupd);
|
||||
continue;
|
||||
}
|
||||
|
@ -1831,7 +1833,15 @@ static int nf_tables_commit(struct sk_buff *skb)
|
|||
nf_tables_rule_notify(skb, rupd->nlh, rupd->table, rupd->chain,
|
||||
rupd->rule, NFT_MSG_DELRULE, 0,
|
||||
rupd->family);
|
||||
}
|
||||
|
||||
/* Make sure we don't see any packet traversing old rules */
|
||||
synchronize_rcu();
|
||||
|
||||
/* Now we can safely release unused old rules */
|
||||
list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) {
|
||||
nf_tables_rule_destroy(rupd->rule);
|
||||
list_del(&rupd->list);
|
||||
kfree(rupd);
|
||||
}
|
||||
|
||||
|
@ -1844,20 +1854,26 @@ static int nf_tables_abort(struct sk_buff *skb)
|
|||
struct nft_rule_trans *rupd, *tmp;
|
||||
|
||||
list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) {
|
||||
/* Delete all rules from the dirty list */
|
||||
list_del(&rupd->list);
|
||||
|
||||
if (!nft_rule_is_active_next(net, rupd->rule)) {
|
||||
nft_rule_clear(net, rupd->rule);
|
||||
list_del(&rupd->list);
|
||||
kfree(rupd);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This rule is inactive, get rid of it */
|
||||
list_del_rcu(&rupd->rule->list);
|
||||
}
|
||||
|
||||
/* Make sure we don't see any packet accessing aborted rules */
|
||||
synchronize_rcu();
|
||||
|
||||
list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) {
|
||||
nf_tables_rule_destroy(rupd->rule);
|
||||
list_del(&rupd->list);
|
||||
kfree(rupd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1943,6 +1959,9 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx,
|
|||
}
|
||||
|
||||
if (nla[NFTA_SET_TABLE] != NULL) {
|
||||
if (afi == NULL)
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
table = nf_tables_table_lookup(afi, nla[NFTA_SET_TABLE]);
|
||||
if (IS_ERR(table))
|
||||
return PTR_ERR(table);
|
||||
|
@ -1989,13 +2008,13 @@ static int nf_tables_set_alloc_name(struct nft_ctx *ctx, struct nft_set *set,
|
|||
|
||||
if (!sscanf(i->name, name, &tmp))
|
||||
continue;
|
||||
if (tmp < 0 || tmp > BITS_PER_LONG * PAGE_SIZE)
|
||||
if (tmp < 0 || tmp >= BITS_PER_BYTE * PAGE_SIZE)
|
||||
continue;
|
||||
|
||||
set_bit(tmp, inuse);
|
||||
}
|
||||
|
||||
n = find_first_zero_bit(inuse, BITS_PER_LONG * PAGE_SIZE);
|
||||
n = find_first_zero_bit(inuse, BITS_PER_BYTE * PAGE_SIZE);
|
||||
free_page((unsigned long)inuse);
|
||||
}
|
||||
|
||||
|
@ -2428,6 +2447,8 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb,
|
|||
struct nft_ctx ctx;
|
||||
int err;
|
||||
|
||||
if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
|
||||
return -EAFNOSUPPORT;
|
||||
if (nla[NFTA_SET_TABLE] == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -2435,9 +2456,6 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb,
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (nfmsg->nfgen_family == NFPROTO_UNSPEC)
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME]);
|
||||
if (IS_ERR(set))
|
||||
return PTR_ERR(set);
|
||||
|
@ -2723,6 +2741,9 @@ static int nft_add_set_elem(const struct nft_ctx *ctx, struct nft_set *set,
|
|||
if (nla[NFTA_SET_ELEM_DATA] == NULL &&
|
||||
!(elem.flags & NFT_SET_ELEM_INTERVAL_END))
|
||||
return -EINVAL;
|
||||
if (nla[NFTA_SET_ELEM_DATA] != NULL &&
|
||||
elem.flags & NFT_SET_ELEM_INTERVAL_END)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (nla[NFTA_SET_ELEM_DATA] != NULL)
|
||||
return -EINVAL;
|
||||
|
@ -2977,6 +2998,9 @@ static int nf_tables_loop_check_setelem(const struct nft_ctx *ctx,
|
|||
const struct nft_set_iter *iter,
|
||||
const struct nft_set_elem *elem)
|
||||
{
|
||||
if (elem->flags & NFT_SET_ELEM_INTERVAL_END)
|
||||
return 0;
|
||||
|
||||
switch (elem->data.verdict) {
|
||||
case NFT_JUMP:
|
||||
case NFT_GOTO:
|
||||
|
|
|
@ -103,9 +103,9 @@ static struct nf_loginfo trace_loginfo = {
|
|||
},
|
||||
};
|
||||
|
||||
static inline void nft_trace_packet(const struct nft_pktinfo *pkt,
|
||||
const struct nft_chain *chain,
|
||||
int rulenum, enum nft_trace type)
|
||||
static void nft_trace_packet(const struct nft_pktinfo *pkt,
|
||||
const struct nft_chain *chain,
|
||||
int rulenum, enum nft_trace type)
|
||||
{
|
||||
struct net *net = dev_net(pkt->in ? pkt->in : pkt->out);
|
||||
|
||||
|
|
|
@ -226,6 +226,7 @@ static int nft_ct_init_validate_get(const struct nft_expr *expr,
|
|||
if (tb[NFTA_CT_DIRECTION] != NULL)
|
||||
return -EINVAL;
|
||||
break;
|
||||
case NFT_CT_L3PROTOCOL:
|
||||
case NFT_CT_PROTOCOL:
|
||||
case NFT_CT_SRC:
|
||||
case NFT_CT_DST:
|
||||
|
@ -311,8 +312,19 @@ static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr)
|
|||
goto nla_put_failure;
|
||||
if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key)))
|
||||
goto nla_put_failure;
|
||||
if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
|
||||
goto nla_put_failure;
|
||||
|
||||
switch (priv->key) {
|
||||
case NFT_CT_PROTOCOL:
|
||||
case NFT_CT_SRC:
|
||||
case NFT_CT_DST:
|
||||
case NFT_CT_PROTO_SRC:
|
||||
case NFT_CT_PROTO_DST:
|
||||
if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
|
||||
goto nla_put_failure;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
|
|
|
@ -23,7 +23,6 @@ static const char *nft_log_null_prefix = "";
|
|||
struct nft_log {
|
||||
struct nf_loginfo loginfo;
|
||||
char *prefix;
|
||||
int family;
|
||||
};
|
||||
|
||||
static void nft_log_eval(const struct nft_expr *expr,
|
||||
|
@ -33,7 +32,7 @@ static void nft_log_eval(const struct nft_expr *expr,
|
|||
const struct nft_log *priv = nft_expr_priv(expr);
|
||||
struct net *net = dev_net(pkt->in ? pkt->in : pkt->out);
|
||||
|
||||
nf_log_packet(net, priv->family, pkt->ops->hooknum, pkt->skb, pkt->in,
|
||||
nf_log_packet(net, pkt->ops->pf, pkt->ops->hooknum, pkt->skb, pkt->in,
|
||||
pkt->out, &priv->loginfo, "%s", priv->prefix);
|
||||
}
|
||||
|
||||
|
@ -52,8 +51,6 @@ static int nft_log_init(const struct nft_ctx *ctx,
|
|||
struct nf_loginfo *li = &priv->loginfo;
|
||||
const struct nlattr *nla;
|
||||
|
||||
priv->family = ctx->afi->family;
|
||||
|
||||
nla = tb[NFTA_LOG_PREFIX];
|
||||
if (nla != NULL) {
|
||||
priv->prefix = kmalloc(nla_len(nla) + 1, GFP_KERNEL);
|
||||
|
|
|
@ -25,7 +25,6 @@ struct nft_queue {
|
|||
u16 queuenum;
|
||||
u16 queues_total;
|
||||
u16 flags;
|
||||
u8 family;
|
||||
};
|
||||
|
||||
static void nft_queue_eval(const struct nft_expr *expr,
|
||||
|
@ -43,7 +42,7 @@ static void nft_queue_eval(const struct nft_expr *expr,
|
|||
queue = priv->queuenum + cpu % priv->queues_total;
|
||||
} else {
|
||||
queue = nfqueue_hash(pkt->skb, queue,
|
||||
priv->queues_total, priv->family,
|
||||
priv->queues_total, pkt->ops->pf,
|
||||
jhash_initval);
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +70,6 @@ static int nft_queue_init(const struct nft_ctx *ctx,
|
|||
return -EINVAL;
|
||||
|
||||
init_hashrandom(&jhash_initval);
|
||||
priv->family = ctx->afi->family;
|
||||
priv->queuenum = ntohs(nla_get_be16(tb[NFTA_QUEUE_NUM]));
|
||||
|
||||
if (tb[NFTA_QUEUE_TOTAL] != NULL)
|
||||
|
|
|
@ -69,8 +69,10 @@ static void nft_rbtree_elem_destroy(const struct nft_set *set,
|
|||
struct nft_rbtree_elem *rbe)
|
||||
{
|
||||
nft_data_uninit(&rbe->key, NFT_DATA_VALUE);
|
||||
if (set->flags & NFT_SET_MAP)
|
||||
if (set->flags & NFT_SET_MAP &&
|
||||
!(rbe->flags & NFT_SET_ELEM_INTERVAL_END))
|
||||
nft_data_uninit(rbe->data, set->dtype);
|
||||
|
||||
kfree(rbe);
|
||||
}
|
||||
|
||||
|
@ -108,7 +110,8 @@ static int nft_rbtree_insert(const struct nft_set *set,
|
|||
int err;
|
||||
|
||||
size = sizeof(*rbe);
|
||||
if (set->flags & NFT_SET_MAP)
|
||||
if (set->flags & NFT_SET_MAP &&
|
||||
!(elem->flags & NFT_SET_ELEM_INTERVAL_END))
|
||||
size += sizeof(rbe->data[0]);
|
||||
|
||||
rbe = kzalloc(size, GFP_KERNEL);
|
||||
|
@ -117,7 +120,8 @@ static int nft_rbtree_insert(const struct nft_set *set,
|
|||
|
||||
rbe->flags = elem->flags;
|
||||
nft_data_copy(&rbe->key, &elem->key);
|
||||
if (set->flags & NFT_SET_MAP)
|
||||
if (set->flags & NFT_SET_MAP &&
|
||||
!(rbe->flags & NFT_SET_ELEM_INTERVAL_END))
|
||||
nft_data_copy(rbe->data, &elem->data);
|
||||
|
||||
err = __nft_rbtree_insert(set, rbe);
|
||||
|
@ -153,7 +157,8 @@ static int nft_rbtree_get(const struct nft_set *set, struct nft_set_elem *elem)
|
|||
parent = parent->rb_right;
|
||||
else {
|
||||
elem->cookie = rbe;
|
||||
if (set->flags & NFT_SET_MAP)
|
||||
if (set->flags & NFT_SET_MAP &&
|
||||
!(rbe->flags & NFT_SET_ELEM_INTERVAL_END))
|
||||
nft_data_copy(&elem->data, rbe->data);
|
||||
elem->flags = rbe->flags;
|
||||
return 0;
|
||||
|
@ -177,7 +182,8 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx,
|
|||
|
||||
rbe = rb_entry(node, struct nft_rbtree_elem, node);
|
||||
nft_data_copy(&elem.key, &rbe->key);
|
||||
if (set->flags & NFT_SET_MAP)
|
||||
if (set->flags & NFT_SET_MAP &&
|
||||
!(rbe->flags & NFT_SET_ELEM_INTERVAL_END))
|
||||
nft_data_copy(&elem.data, rbe->data);
|
||||
elem.flags = rbe->flags;
|
||||
|
||||
|
|
|
@ -16,65 +16,23 @@
|
|||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter/nf_tables.h>
|
||||
#include <net/netfilter/nf_tables.h>
|
||||
#include <net/icmp.h>
|
||||
#include <net/netfilter/ipv4/nf_reject.h>
|
||||
#include <net/netfilter/nft_reject.h>
|
||||
|
||||
#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
|
||||
#include <net/netfilter/ipv6/nf_reject.h>
|
||||
#endif
|
||||
|
||||
struct nft_reject {
|
||||
enum nft_reject_types type:8;
|
||||
u8 icmp_code;
|
||||
u8 family;
|
||||
};
|
||||
|
||||
static void nft_reject_eval(const struct nft_expr *expr,
|
||||
struct nft_data data[NFT_REG_MAX + 1],
|
||||
const struct nft_pktinfo *pkt)
|
||||
{
|
||||
struct nft_reject *priv = nft_expr_priv(expr);
|
||||
#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
|
||||
struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out);
|
||||
#endif
|
||||
switch (priv->type) {
|
||||
case NFT_REJECT_ICMP_UNREACH:
|
||||
if (priv->family == NFPROTO_IPV4)
|
||||
nf_send_unreach(pkt->skb, priv->icmp_code);
|
||||
#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
|
||||
else if (priv->family == NFPROTO_IPV6)
|
||||
nf_send_unreach6(net, pkt->skb, priv->icmp_code,
|
||||
pkt->ops->hooknum);
|
||||
#endif
|
||||
break;
|
||||
case NFT_REJECT_TCP_RST:
|
||||
if (priv->family == NFPROTO_IPV4)
|
||||
nf_send_reset(pkt->skb, pkt->ops->hooknum);
|
||||
#if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
|
||||
else if (priv->family == NFPROTO_IPV6)
|
||||
nf_send_reset6(net, pkt->skb, pkt->ops->hooknum);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
data[NFT_REG_VERDICT].verdict = NF_DROP;
|
||||
}
|
||||
|
||||
static const struct nla_policy nft_reject_policy[NFTA_REJECT_MAX + 1] = {
|
||||
const struct nla_policy nft_reject_policy[NFTA_REJECT_MAX + 1] = {
|
||||
[NFTA_REJECT_TYPE] = { .type = NLA_U32 },
|
||||
[NFTA_REJECT_ICMP_CODE] = { .type = NLA_U8 },
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(nft_reject_policy);
|
||||
|
||||
static int nft_reject_init(const struct nft_ctx *ctx,
|
||||
const struct nft_expr *expr,
|
||||
const struct nlattr * const tb[])
|
||||
int nft_reject_init(const struct nft_ctx *ctx,
|
||||
const struct nft_expr *expr,
|
||||
const struct nlattr * const tb[])
|
||||
{
|
||||
struct nft_reject *priv = nft_expr_priv(expr);
|
||||
|
||||
if (tb[NFTA_REJECT_TYPE] == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
priv->family = ctx->afi->family;
|
||||
priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE]));
|
||||
switch (priv->type) {
|
||||
case NFT_REJECT_ICMP_UNREACH:
|
||||
|
@ -89,8 +47,9 @@ static int nft_reject_init(const struct nft_ctx *ctx,
|
|||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nft_reject_init);
|
||||
|
||||
static int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr)
|
||||
int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr)
|
||||
{
|
||||
const struct nft_reject *priv = nft_expr_priv(expr);
|
||||
|
||||
|
@ -109,37 +68,7 @@ static int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr)
|
|||
nla_put_failure:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct nft_expr_type nft_reject_type;
|
||||
static const struct nft_expr_ops nft_reject_ops = {
|
||||
.type = &nft_reject_type,
|
||||
.size = NFT_EXPR_SIZE(sizeof(struct nft_reject)),
|
||||
.eval = nft_reject_eval,
|
||||
.init = nft_reject_init,
|
||||
.dump = nft_reject_dump,
|
||||
};
|
||||
|
||||
static struct nft_expr_type nft_reject_type __read_mostly = {
|
||||
.name = "reject",
|
||||
.ops = &nft_reject_ops,
|
||||
.policy = nft_reject_policy,
|
||||
.maxattr = NFTA_REJECT_MAX,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init nft_reject_module_init(void)
|
||||
{
|
||||
return nft_register_expr(&nft_reject_type);
|
||||
}
|
||||
|
||||
static void __exit nft_reject_module_exit(void)
|
||||
{
|
||||
nft_unregister_expr(&nft_reject_type);
|
||||
}
|
||||
|
||||
module_init(nft_reject_module_init);
|
||||
module_exit(nft_reject_module_exit);
|
||||
EXPORT_SYMBOL_GPL(nft_reject_dump);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
|
||||
MODULE_ALIAS_NFT_EXPR("reject");
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2014 Patrick McHardy <kaber@trash.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter/nf_tables.h>
|
||||
#include <net/netfilter/nf_tables.h>
|
||||
#include <net/netfilter/nft_reject.h>
|
||||
|
||||
static void nft_reject_inet_eval(const struct nft_expr *expr,
|
||||
struct nft_data data[NFT_REG_MAX + 1],
|
||||
const struct nft_pktinfo *pkt)
|
||||
{
|
||||
switch (pkt->ops->pf) {
|
||||
case NFPROTO_IPV4:
|
||||
nft_reject_ipv4_eval(expr, data, pkt);
|
||||
case NFPROTO_IPV6:
|
||||
nft_reject_ipv6_eval(expr, data, pkt);
|
||||
}
|
||||
}
|
||||
|
||||
static struct nft_expr_type nft_reject_inet_type;
|
||||
static const struct nft_expr_ops nft_reject_inet_ops = {
|
||||
.type = &nft_reject_inet_type,
|
||||
.size = NFT_EXPR_SIZE(sizeof(struct nft_reject)),
|
||||
.eval = nft_reject_inet_eval,
|
||||
.init = nft_reject_init,
|
||||
.dump = nft_reject_dump,
|
||||
};
|
||||
|
||||
static struct nft_expr_type nft_reject_inet_type __read_mostly = {
|
||||
.family = NFPROTO_INET,
|
||||
.name = "reject",
|
||||
.ops = &nft_reject_inet_ops,
|
||||
.policy = nft_reject_policy,
|
||||
.maxattr = NFTA_REJECT_MAX,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init nft_reject_inet_module_init(void)
|
||||
{
|
||||
return nft_register_expr(&nft_reject_inet_type);
|
||||
}
|
||||
|
||||
static void __exit nft_reject_inet_module_exit(void)
|
||||
{
|
||||
nft_unregister_expr(&nft_reject_inet_type);
|
||||
}
|
||||
|
||||
module_init(nft_reject_inet_module_init);
|
||||
module_exit(nft_reject_inet_module_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
|
||||
MODULE_ALIAS_NFT_AF_EXPR(1, "reject");
|
|
@ -228,12 +228,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
|
|||
goto err3;
|
||||
}
|
||||
|
||||
__set_bit(IPS_TEMPLATE_BIT, &ct->status);
|
||||
__set_bit(IPS_CONFIRMED_BIT, &ct->status);
|
||||
|
||||
/* Overload tuple linked list to put us in template list. */
|
||||
hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
|
||||
&par->net->ct.tmpl);
|
||||
nf_conntrack_tmpl_insert(par->net, ct);
|
||||
out:
|
||||
info->ct = ct;
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue