Skip to content

Commit

Permalink
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/gi…
Browse files Browse the repository at this point in the history
…t/pablo/nf-next

Pablo Neira Ayuso says:

====================
This is another batch containing Netfilter/IPVS updates for your net-next
tree, they are:

* Six patches to make the ipt_CLUSTERIP target support netnamespace,
  from Gao feng.

* Two cleanups for the nf_conntrack_acct infrastructure, introducing
  a new structure to encapsulate conntrack counters, from Holger
  Eitzenberger.

* Fix missing verdict in SCTP support for IPVS, from Daniel Borkmann.

* Skip checksum recalculation in SCTP support for IPVS, also from
  Daniel Borkmann.

* Fix behavioural change in xt_socket after IP early demux, from
  Florian Westphal.

* Fix bogus large memory allocation in the bitmap port set type in ipset,
  from Jozsef Kadlecsik.

* Fix possible compilation issues in the hash netnet set type in ipset,
  also from Jozsef Kadlecsik.

* Define constants to identify netlink callback data in ipset dumps,
  again from Jozsef Kadlecsik.

* Use sock_gen_put() in xt_socket to replace xt_socket_put_sk,
  from Eric Dumazet.

* Improvements for the SH scheduler in IPVS, from Alexander Frolkin.

* Remove extra delay due to unneeded rcu barrier in IPVS net namespace
  cleanup path, from Julian Anastasov.

* Save some cycles in ip6t_REJECT by skipping checksum validation in
  packets leaving from our stack, from Stanislav Fomichev.

* Fix IPVS_CMD_ATTR_MAX definition in IPVS, larger that required, from
  Julian Anastasov.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Nov 5, 2013
2 parents 6fcf018 + 4542fa4 commit 72c39a0
Show file tree
Hide file tree
Showing 25 changed files with 305 additions and 198 deletions.
10 changes: 10 additions & 0 deletions include/linux/netfilter/ipset/ip_set.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,16 @@ ip_set_init_counter(struct ip_set_counter *counter,
atomic64_set(&(counter)->packets, (long long)(ext->packets));
}

/* Netlink CB args */
enum {
IPSET_CB_NET = 0,
IPSET_CB_DUMP,
IPSET_CB_INDEX,
IPSET_CB_ARG0,
IPSET_CB_ARG1,
IPSET_CB_ARG2,
};

/* register and unregister set references */
extern ip_set_id_t ip_set_get_byname(struct net *net,
const char *name, struct ip_set **set);
Expand Down
6 changes: 6 additions & 0 deletions include/net/ip_vs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1442,6 +1442,12 @@ static inline void ip_vs_dest_put(struct ip_vs_dest *dest)
atomic_dec(&dest->refcnt);
}

static inline void ip_vs_dest_put_and_free(struct ip_vs_dest *dest)
{
if (atomic_dec_return(&dest->refcnt) < 0)
kfree(dest);
}

/*
* IPVS sync daemon data and function prototypes
* (from ip_vs_sync.c)
Expand Down
10 changes: 7 additions & 3 deletions include/net/netfilter/nf_conntrack_acct.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,21 @@ struct nf_conn_counter {
atomic64_t bytes;
};

struct nf_conn_acct {
struct nf_conn_counter counter[IP_CT_DIR_MAX];
};

static inline
struct nf_conn_counter *nf_conn_acct_find(const struct nf_conn *ct)
struct nf_conn_acct *nf_conn_acct_find(const struct nf_conn *ct)
{
return nf_ct_ext_find(ct, NF_CT_EXT_ACCT);
}

static inline
struct nf_conn_counter *nf_ct_acct_ext_add(struct nf_conn *ct, gfp_t gfp)
struct nf_conn_acct *nf_ct_acct_ext_add(struct nf_conn *ct, gfp_t gfp)
{
struct net *net = nf_ct_net(ct);
struct nf_conn_counter *acct;
struct nf_conn_acct *acct;

if (!net->ct.sysctl_acct)
return NULL;
Expand Down
2 changes: 1 addition & 1 deletion include/net/netfilter/nf_conntrack_extend.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ enum nf_ct_ext_id {
#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help
#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat
#define NF_CT_EXT_SEQADJ_TYPE struct nf_conn_seqadj
#define NF_CT_EXT_ACCT_TYPE struct nf_conn_counter
#define NF_CT_EXT_ACCT_TYPE struct nf_conn_acct
#define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache
#define NF_CT_EXT_ZONE_TYPE struct nf_conntrack_zone
#define NF_CT_EXT_TSTAMP_TYPE struct nf_conn_tstamp
Expand Down
2 changes: 1 addition & 1 deletion include/uapi/linux/ip_vs.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ enum {
__IPVS_CMD_ATTR_MAX,
};

#define IPVS_CMD_ATTR_MAX (__IPVS_SVC_ATTR_MAX - 1)
#define IPVS_CMD_ATTR_MAX (__IPVS_CMD_ATTR_MAX - 1)

/*
* Attributes used to describe a service
Expand Down
2 changes: 2 additions & 0 deletions net/bridge/br_netfilter.c
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,8 @@ static struct net_device *setup_pre_routing(struct sk_buff *skb)
else if (skb->protocol == htons(ETH_P_PPP_SES))
nf_bridge->mask |= BRNF_PPPoE;

/* Must drop socket now because of tproxy. */
skb_orphan(skb);
return skb->dev;
}

Expand Down
110 changes: 75 additions & 35 deletions net/ipv4/netfilter/ipt_CLUSTERIP.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <linux/netfilter_ipv4/ipt_CLUSTERIP.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
#include <net/checksum.h>
#include <net/ip.h>

Expand Down Expand Up @@ -57,15 +58,21 @@ struct clusterip_config {
struct rcu_head rcu;
};

static LIST_HEAD(clusterip_configs);
#ifdef CONFIG_PROC_FS
static const struct file_operations clusterip_proc_fops;
#endif

/* clusterip_lock protects the clusterip_configs list */
static DEFINE_SPINLOCK(clusterip_lock);
static int clusterip_net_id __read_mostly;

struct clusterip_net {
struct list_head configs;
/* lock protects the configs list */
spinlock_t lock;

#ifdef CONFIG_PROC_FS
static const struct file_operations clusterip_proc_fops;
static struct proc_dir_entry *clusterip_procdir;
struct proc_dir_entry *procdir;
#endif
};

static inline void
clusterip_config_get(struct clusterip_config *c)
Expand All @@ -92,10 +99,13 @@ clusterip_config_put(struct clusterip_config *c)
static inline void
clusterip_config_entry_put(struct clusterip_config *c)
{
struct net *net = dev_net(c->dev);
struct clusterip_net *cn = net_generic(net, clusterip_net_id);

local_bh_disable();
if (atomic_dec_and_lock(&c->entries, &clusterip_lock)) {
if (atomic_dec_and_lock(&c->entries, &cn->lock)) {
list_del_rcu(&c->list);
spin_unlock(&clusterip_lock);
spin_unlock(&cn->lock);
local_bh_enable();

dev_mc_del(c->dev, c->clustermac);
Expand All @@ -113,11 +123,12 @@ clusterip_config_entry_put(struct clusterip_config *c)
}

static struct clusterip_config *
__clusterip_config_find(__be32 clusterip)
__clusterip_config_find(struct net *net, __be32 clusterip)
{
struct clusterip_config *c;
struct clusterip_net *cn = net_generic(net, clusterip_net_id);

list_for_each_entry_rcu(c, &clusterip_configs, list) {
list_for_each_entry_rcu(c, &cn->configs, list) {
if (c->clusterip == clusterip)
return c;
}
Expand All @@ -126,12 +137,12 @@ __clusterip_config_find(__be32 clusterip)
}

static inline struct clusterip_config *
clusterip_config_find_get(__be32 clusterip, int entry)
clusterip_config_find_get(struct net *net, __be32 clusterip, int entry)
{
struct clusterip_config *c;

rcu_read_lock_bh();
c = __clusterip_config_find(clusterip);
c = __clusterip_config_find(net, clusterip);
if (c) {
if (unlikely(!atomic_inc_not_zero(&c->refcount)))
c = NULL;
Expand All @@ -158,6 +169,7 @@ clusterip_config_init(const struct ipt_clusterip_tgt_info *i, __be32 ip,
struct net_device *dev)
{
struct clusterip_config *c;
struct clusterip_net *cn = net_generic(dev_net(dev), clusterip_net_id);

c = kzalloc(sizeof(*c), GFP_ATOMIC);
if (!c)
Expand All @@ -180,7 +192,7 @@ clusterip_config_init(const struct ipt_clusterip_tgt_info *i, __be32 ip,
/* create proc dir entry */
sprintf(buffer, "%pI4", &ip);
c->pde = proc_create_data(buffer, S_IWUSR|S_IRUSR,
clusterip_procdir,
cn->procdir,
&clusterip_proc_fops, c);
if (!c->pde) {
kfree(c);
Expand All @@ -189,9 +201,9 @@ clusterip_config_init(const struct ipt_clusterip_tgt_info *i, __be32 ip,
}
#endif

spin_lock_bh(&clusterip_lock);
list_add_rcu(&c->list, &clusterip_configs);
spin_unlock_bh(&clusterip_lock);
spin_lock_bh(&cn->lock);
list_add_rcu(&c->list, &cn->configs);
spin_unlock_bh(&cn->lock);

return c;
}
Expand Down Expand Up @@ -370,7 +382,7 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par)

/* FIXME: further sanity checks */

config = clusterip_config_find_get(e->ip.dst.s_addr, 1);
config = clusterip_config_find_get(par->net, e->ip.dst.s_addr, 1);
if (!config) {
if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) {
pr_info("no config found for %pI4, need 'new'\n",
Expand All @@ -384,7 +396,7 @@ static int clusterip_tg_check(const struct xt_tgchk_param *par)
return -EINVAL;
}

dev = dev_get_by_name(&init_net, e->ip.iniface);
dev = dev_get_by_name(par->net, e->ip.iniface);
if (!dev) {
pr_info("no such interface %s\n",
e->ip.iniface);
Expand Down Expand Up @@ -492,6 +504,7 @@ arp_mangle(const struct nf_hook_ops *ops,
struct arphdr *arp = arp_hdr(skb);
struct arp_payload *payload;
struct clusterip_config *c;
struct net *net = dev_net(in ? in : out);

/* we don't care about non-ethernet and non-ipv4 ARP */
if (arp->ar_hrd != htons(ARPHRD_ETHER) ||
Expand All @@ -508,7 +521,7 @@ arp_mangle(const struct nf_hook_ops *ops,

/* if there is no clusterip configuration for the arp reply's
* source ip, we don't want to mangle it */
c = clusterip_config_find_get(payload->src_ip, 0);
c = clusterip_config_find_get(net, payload->src_ip, 0);
if (!c)
return NF_ACCEPT;

Expand Down Expand Up @@ -698,48 +711,75 @@ static const struct file_operations clusterip_proc_fops = {

#endif /* CONFIG_PROC_FS */

static int clusterip_net_init(struct net *net)
{
struct clusterip_net *cn = net_generic(net, clusterip_net_id);

INIT_LIST_HEAD(&cn->configs);

spin_lock_init(&cn->lock);

#ifdef CONFIG_PROC_FS
cn->procdir = proc_mkdir("ipt_CLUSTERIP", net->proc_net);
if (!cn->procdir) {
pr_err("Unable to proc dir entry\n");
return -ENOMEM;
}
#endif /* CONFIG_PROC_FS */

return 0;
}

static void clusterip_net_exit(struct net *net)
{
#ifdef CONFIG_PROC_FS
struct clusterip_net *cn = net_generic(net, clusterip_net_id);
proc_remove(cn->procdir);
#endif
}

static struct pernet_operations clusterip_net_ops = {
.init = clusterip_net_init,
.exit = clusterip_net_exit,
.id = &clusterip_net_id,
.size = sizeof(struct clusterip_net),
};

static int __init clusterip_tg_init(void)
{
int ret;

ret = xt_register_target(&clusterip_tg_reg);
ret = register_pernet_subsys(&clusterip_net_ops);
if (ret < 0)
return ret;

ret = xt_register_target(&clusterip_tg_reg);
if (ret < 0)
goto cleanup_subsys;

ret = nf_register_hook(&cip_arp_ops);
if (ret < 0)
goto cleanup_target;

#ifdef CONFIG_PROC_FS
clusterip_procdir = proc_mkdir("ipt_CLUSTERIP", init_net.proc_net);
if (!clusterip_procdir) {
pr_err("Unable to proc dir entry\n");
ret = -ENOMEM;
goto cleanup_hook;
}
#endif /* CONFIG_PROC_FS */

pr_info("ClusterIP Version %s loaded successfully\n",
CLUSTERIP_VERSION);

return 0;

#ifdef CONFIG_PROC_FS
cleanup_hook:
nf_unregister_hook(&cip_arp_ops);
#endif /* CONFIG_PROC_FS */
cleanup_target:
xt_unregister_target(&clusterip_tg_reg);
cleanup_subsys:
unregister_pernet_subsys(&clusterip_net_ops);
return ret;
}

static void __exit clusterip_tg_exit(void)
{
pr_info("ClusterIP Version %s unloading\n", CLUSTERIP_VERSION);
#ifdef CONFIG_PROC_FS
proc_remove(clusterip_procdir);
#endif

nf_unregister_hook(&cip_arp_ops);
xt_unregister_target(&clusterip_tg_reg);
unregister_pernet_subsys(&clusterip_net_ops);

/* Wait for completion of call_rcu_bh()'s (clusterip_config_rcu_free) */
rcu_barrier_bh();
Expand Down
7 changes: 3 additions & 4 deletions net/ipv6/netfilter/ip6t_REJECT.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ MODULE_DESCRIPTION("Xtables: packet \"rejection\" target for IPv6");
MODULE_LICENSE("GPL");

/* Send RST reply */
static void send_reset(struct net *net, struct sk_buff *oldskb)
static void send_reset(struct net *net, struct sk_buff *oldskb, int hook)
{
struct sk_buff *nskb;
struct tcphdr otcph, *tcph;
Expand Down Expand Up @@ -88,8 +88,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb)
}

/* Check checksum. */
if (csum_ipv6_magic(&oip6h->saddr, &oip6h->daddr, otcplen, IPPROTO_TCP,
skb_checksum(oldskb, tcphoff, otcplen, 0))) {
if (nf_ip6_checksum(oldskb, hook, tcphoff, IPPROTO_TCP)) {
pr_debug("TCP checksum is invalid\n");
return;
}
Expand Down Expand Up @@ -227,7 +226,7 @@ reject_tg6(struct sk_buff *skb, const struct xt_action_param *par)
/* Do nothing */
break;
case IP6T_TCP_RESET:
send_reset(net, skb);
send_reset(net, skb, par->hooknum);
break;
default:
net_info_ratelimited("case %u not handled yet\n", reject->with);
Expand Down
11 changes: 6 additions & 5 deletions net/netfilter/ipset/ip_set_bitmap_gen.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,13 +198,14 @@ mtype_list(const struct ip_set *set,
struct mtype *map = set->data;
struct nlattr *adt, *nested;
void *x;
u32 id, first = cb->args[2];
u32 id, first = cb->args[IPSET_CB_ARG0];

adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
if (!adt)
return -EMSGSIZE;
for (; cb->args[2] < map->elements; cb->args[2]++) {
id = cb->args[2];
for (; cb->args[IPSET_CB_ARG0] < map->elements;
cb->args[IPSET_CB_ARG0]++) {
id = cb->args[IPSET_CB_ARG0];
x = get_ext(set, map, id);
if (!test_bit(id, map->members) ||
(SET_WITH_TIMEOUT(set) &&
Expand All @@ -231,14 +232,14 @@ mtype_list(const struct ip_set *set,
ipset_nest_end(skb, adt);

/* Set listing finished */
cb->args[2] = 0;
cb->args[IPSET_CB_ARG0] = 0;

return 0;

nla_put_failure:
nla_nest_cancel(skb, nested);
if (unlikely(id == first)) {
cb->args[2] = 0;
cb->args[IPSET_CB_ARG0] = 0;
return -EMSGSIZE;
}
ipset_nest_end(skb, adt);
Expand Down
2 changes: 1 addition & 1 deletion net/netfilter/ipset/ip_set_bitmap_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ bitmap_port_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
return -ENOMEM;

map->elements = last_port - first_port + 1;
map->memsize = map->elements * sizeof(unsigned long);
map->memsize = bitmap_bytes(0, map->elements);
set->variant = &bitmap_port;
set->dsize = ip_set_elem_len(set, tb, 0);
if (!init_map_port(set, map, first_port, last_port)) {
Expand Down
Loading

0 comments on commit 72c39a0

Please sign in to comment.