Commit 93302880 authored by Jozsef Kadlecsik's avatar Jozsef Kadlecsik Committed by Pablo Neira Ayuso

netfilter: ipset: Use netlink callback dump args only

Instead of cb->data, use callback dump args only and introduce symbolic
names instead of plain numbers at accessing the argument members.
Signed-off-by: default avatarJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent d86946d2
...@@ -316,6 +316,16 @@ ip_set_init_counter(struct ip_set_counter *counter, ...@@ -316,6 +316,16 @@ ip_set_init_counter(struct ip_set_counter *counter,
atomic64_set(&(counter)->packets, (long long)(ext->packets)); 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 */ /* register and unregister set references */
extern ip_set_id_t ip_set_get_byname(struct net *net, extern ip_set_id_t ip_set_get_byname(struct net *net,
const char *name, struct ip_set **set); const char *name, struct ip_set **set);
......
...@@ -198,13 +198,14 @@ mtype_list(const struct ip_set *set, ...@@ -198,13 +198,14 @@ mtype_list(const struct ip_set *set,
struct mtype *map = set->data; struct mtype *map = set->data;
struct nlattr *adt, *nested; struct nlattr *adt, *nested;
void *x; void *x;
u32 id, first = cb->args[2]; u32 id, first = cb->args[IPSET_CB_ARG0];
adt = ipset_nest_start(skb, IPSET_ATTR_ADT); adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
if (!adt) if (!adt)
return -EMSGSIZE; return -EMSGSIZE;
for (; cb->args[2] < map->elements; cb->args[2]++) { for (; cb->args[IPSET_CB_ARG0] < map->elements;
id = cb->args[2]; cb->args[IPSET_CB_ARG0]++) {
id = cb->args[IPSET_CB_ARG0];
x = get_ext(set, map, id); x = get_ext(set, map, id);
if (!test_bit(id, map->members) || if (!test_bit(id, map->members) ||
(SET_WITH_TIMEOUT(set) && (SET_WITH_TIMEOUT(set) &&
...@@ -231,14 +232,14 @@ mtype_list(const struct ip_set *set, ...@@ -231,14 +232,14 @@ mtype_list(const struct ip_set *set,
ipset_nest_end(skb, adt); ipset_nest_end(skb, adt);
/* Set listing finished */ /* Set listing finished */
cb->args[2] = 0; cb->args[IPSET_CB_ARG0] = 0;
return 0; return 0;
nla_put_failure: nla_put_failure:
nla_nest_cancel(skb, nested); nla_nest_cancel(skb, nested);
if (unlikely(id == first)) { if (unlikely(id == first)) {
cb->args[2] = 0; cb->args[IPSET_CB_ARG0] = 0;
return -EMSGSIZE; return -EMSGSIZE;
} }
ipset_nest_end(skb, adt); ipset_nest_end(skb, adt);
......
...@@ -1182,10 +1182,12 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb, ...@@ -1182,10 +1182,12 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb,
static int static int
ip_set_dump_done(struct netlink_callback *cb) ip_set_dump_done(struct netlink_callback *cb)
{ {
struct ip_set_net *inst = (struct ip_set_net *)cb->data; struct ip_set_net *inst = (struct ip_set_net *)cb->args[IPSET_CB_NET];
if (cb->args[2]) { if (cb->args[IPSET_CB_ARG0]) {
pr_debug("release set %s\n", nfnl_set(inst, cb->args[1])->name); pr_debug("release set %s\n",
__ip_set_put_byindex(inst, (ip_set_id_t) cb->args[1]); nfnl_set(inst, cb->args[IPSET_CB_INDEX])->name);
__ip_set_put_byindex(inst,
(ip_set_id_t) cb->args[IPSET_CB_INDEX]);
} }
return 0; return 0;
} }
...@@ -1203,7 +1205,7 @@ dump_attrs(struct nlmsghdr *nlh) ...@@ -1203,7 +1205,7 @@ dump_attrs(struct nlmsghdr *nlh)
} }
static int static int
dump_init(struct netlink_callback *cb) dump_init(struct netlink_callback *cb, struct ip_set_net *inst)
{ {
struct nlmsghdr *nlh = nlmsg_hdr(cb->skb); struct nlmsghdr *nlh = nlmsg_hdr(cb->skb);
int min_len = nlmsg_total_size(sizeof(struct nfgenmsg)); int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
...@@ -1211,15 +1213,15 @@ dump_init(struct netlink_callback *cb) ...@@ -1211,15 +1213,15 @@ dump_init(struct netlink_callback *cb)
struct nlattr *attr = (void *)nlh + min_len; struct nlattr *attr = (void *)nlh + min_len;
u32 dump_type; u32 dump_type;
ip_set_id_t index; ip_set_id_t index;
struct ip_set_net *inst = (struct ip_set_net *)cb->data;
/* Second pass, so parser can't fail */ /* Second pass, so parser can't fail */
nla_parse(cda, IPSET_ATTR_CMD_MAX, nla_parse(cda, IPSET_ATTR_CMD_MAX,
attr, nlh->nlmsg_len - min_len, ip_set_setname_policy); attr, nlh->nlmsg_len - min_len, ip_set_setname_policy);
/* cb->args[0] : dump single set/all sets /* cb->args[IPSET_CB_NET]: net namespace
* [1] : set index * [IPSET_CB_DUMP]: dump single set/all sets
* [..]: type specific * [IPSET_CB_INDEX]: set index
* [IPSET_CB_ARG0]: type specific
*/ */
if (cda[IPSET_ATTR_SETNAME]) { if (cda[IPSET_ATTR_SETNAME]) {
...@@ -1231,7 +1233,7 @@ dump_init(struct netlink_callback *cb) ...@@ -1231,7 +1233,7 @@ dump_init(struct netlink_callback *cb)
return -ENOENT; return -ENOENT;
dump_type = DUMP_ONE; dump_type = DUMP_ONE;
cb->args[1] = index; cb->args[IPSET_CB_INDEX] = index;
} else } else
dump_type = DUMP_ALL; dump_type = DUMP_ALL;
...@@ -1239,7 +1241,8 @@ dump_init(struct netlink_callback *cb) ...@@ -1239,7 +1241,8 @@ dump_init(struct netlink_callback *cb)
u32 f = ip_set_get_h32(cda[IPSET_ATTR_FLAGS]); u32 f = ip_set_get_h32(cda[IPSET_ATTR_FLAGS]);
dump_type |= (f << 16); dump_type |= (f << 16);
} }
cb->args[0] = dump_type; cb->args[IPSET_CB_NET] = (unsigned long)inst;
cb->args[IPSET_CB_DUMP] = dump_type;
return 0; return 0;
} }
...@@ -1251,12 +1254,12 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1251,12 +1254,12 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
struct ip_set *set = NULL; struct ip_set *set = NULL;
struct nlmsghdr *nlh = NULL; struct nlmsghdr *nlh = NULL;
unsigned int flags = NETLINK_CB(cb->skb).portid ? NLM_F_MULTI : 0; unsigned int flags = NETLINK_CB(cb->skb).portid ? NLM_F_MULTI : 0;
struct ip_set_net *inst = ip_set_pernet(sock_net(skb->sk));
u32 dump_type, dump_flags; u32 dump_type, dump_flags;
int ret = 0; int ret = 0;
struct ip_set_net *inst = (struct ip_set_net *)cb->data;
if (!cb->args[0]) { if (!cb->args[IPSET_CB_DUMP]) {
ret = dump_init(cb); ret = dump_init(cb, inst);
if (ret < 0) { if (ret < 0) {
nlh = nlmsg_hdr(cb->skb); nlh = nlmsg_hdr(cb->skb);
/* We have to create and send the error message /* We have to create and send the error message
...@@ -1267,17 +1270,18 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1267,17 +1270,18 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
} }
} }
if (cb->args[1] >= inst->ip_set_max) if (cb->args[IPSET_CB_INDEX] >= inst->ip_set_max)
goto out; goto out;
dump_type = DUMP_TYPE(cb->args[0]); dump_type = DUMP_TYPE(cb->args[IPSET_CB_DUMP]);
dump_flags = DUMP_FLAGS(cb->args[0]); dump_flags = DUMP_FLAGS(cb->args[IPSET_CB_DUMP]);
max = dump_type == DUMP_ONE ? cb->args[1] + 1 : inst->ip_set_max; max = dump_type == DUMP_ONE ? cb->args[IPSET_CB_INDEX] + 1
: inst->ip_set_max;
dump_last: dump_last:
pr_debug("args[0]: %u %u args[1]: %ld\n", pr_debug("dump type, flag: %u %u index: %ld\n",
dump_type, dump_flags, cb->args[1]); dump_type, dump_flags, cb->args[IPSET_CB_INDEX]);
for (; cb->args[1] < max; cb->args[1]++) { for (; cb->args[IPSET_CB_INDEX] < max; cb->args[IPSET_CB_INDEX]++) {
index = (ip_set_id_t) cb->args[1]; index = (ip_set_id_t) cb->args[IPSET_CB_INDEX];
set = nfnl_set(inst, index); set = nfnl_set(inst, index);
if (set == NULL) { if (set == NULL) {
if (dump_type == DUMP_ONE) { if (dump_type == DUMP_ONE) {
...@@ -1294,7 +1298,7 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1294,7 +1298,7 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
!!(set->type->features & IPSET_DUMP_LAST))) !!(set->type->features & IPSET_DUMP_LAST)))
continue; continue;
pr_debug("List set: %s\n", set->name); pr_debug("List set: %s\n", set->name);
if (!cb->args[2]) { if (!cb->args[IPSET_CB_ARG0]) {
/* Start listing: make sure set won't be destroyed */ /* Start listing: make sure set won't be destroyed */
pr_debug("reference set\n"); pr_debug("reference set\n");
__ip_set_get(set); __ip_set_get(set);
...@@ -1311,7 +1315,7 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1311,7 +1315,7 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
goto nla_put_failure; goto nla_put_failure;
if (dump_flags & IPSET_FLAG_LIST_SETNAME) if (dump_flags & IPSET_FLAG_LIST_SETNAME)
goto next_set; goto next_set;
switch (cb->args[2]) { switch (cb->args[IPSET_CB_ARG0]) {
case 0: case 0:
/* Core header data */ /* Core header data */
if (nla_put_string(skb, IPSET_ATTR_TYPENAME, if (nla_put_string(skb, IPSET_ATTR_TYPENAME,
...@@ -1331,7 +1335,7 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1331,7 +1335,7 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
read_lock_bh(&set->lock); read_lock_bh(&set->lock);
ret = set->variant->list(set, skb, cb); ret = set->variant->list(set, skb, cb);
read_unlock_bh(&set->lock); read_unlock_bh(&set->lock);
if (!cb->args[2]) if (!cb->args[IPSET_CB_ARG0])
/* Set is done, proceed with next one */ /* Set is done, proceed with next one */
goto next_set; goto next_set;
goto release_refcount; goto release_refcount;
...@@ -1340,8 +1344,8 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1340,8 +1344,8 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
/* If we dump all sets, continue with dumping last ones */ /* If we dump all sets, continue with dumping last ones */
if (dump_type == DUMP_ALL) { if (dump_type == DUMP_ALL) {
dump_type = DUMP_LAST; dump_type = DUMP_LAST;
cb->args[0] = dump_type | (dump_flags << 16); cb->args[IPSET_CB_DUMP] = dump_type | (dump_flags << 16);
cb->args[1] = 0; cb->args[IPSET_CB_INDEX] = 0;
goto dump_last; goto dump_last;
} }
goto out; goto out;
...@@ -1350,15 +1354,15 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -1350,15 +1354,15 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
ret = -EFAULT; ret = -EFAULT;
next_set: next_set:
if (dump_type == DUMP_ONE) if (dump_type == DUMP_ONE)
cb->args[1] = IPSET_INVALID_ID; cb->args[IPSET_CB_INDEX] = IPSET_INVALID_ID;
else else
cb->args[1]++; cb->args[IPSET_CB_INDEX]++;
release_refcount: release_refcount:
/* If there was an error or set is done, release set */ /* If there was an error or set is done, release set */
if (ret || !cb->args[2]) { if (ret || !cb->args[IPSET_CB_ARG0]) {
pr_debug("release set %s\n", nfnl_set(inst, index)->name); pr_debug("release set %s\n", nfnl_set(inst, index)->name);
__ip_set_put_byindex(inst, index); __ip_set_put_byindex(inst, index);
cb->args[2] = 0; cb->args[IPSET_CB_ARG0] = 0;
} }
out: out:
if (nlh) { if (nlh) {
...@@ -1375,8 +1379,6 @@ ip_set_dump(struct sock *ctnl, struct sk_buff *skb, ...@@ -1375,8 +1379,6 @@ ip_set_dump(struct sock *ctnl, struct sk_buff *skb,
const struct nlmsghdr *nlh, const struct nlmsghdr *nlh,
const struct nlattr * const attr[]) const struct nlattr * const attr[])
{ {
struct ip_set_net *inst = ip_set_pernet(sock_net(ctnl));
if (unlikely(protocol_failed(attr))) if (unlikely(protocol_failed(attr)))
return -IPSET_ERR_PROTOCOL; return -IPSET_ERR_PROTOCOL;
...@@ -1384,7 +1386,6 @@ ip_set_dump(struct sock *ctnl, struct sk_buff *skb, ...@@ -1384,7 +1386,6 @@ ip_set_dump(struct sock *ctnl, struct sk_buff *skb,
struct netlink_dump_control c = { struct netlink_dump_control c = {
.dump = ip_set_dump_start, .dump = ip_set_dump_start,
.done = ip_set_dump_done, .done = ip_set_dump_done,
.data = (void *)inst
}; };
return netlink_dump_start(ctnl, skb, nlh, &c); return netlink_dump_start(ctnl, skb, nlh, &c);
} }
...@@ -1961,7 +1962,6 @@ static int __net_init ...@@ -1961,7 +1962,6 @@ static int __net_init
ip_set_net_init(struct net *net) ip_set_net_init(struct net *net)
{ {
struct ip_set_net *inst = ip_set_pernet(net); struct ip_set_net *inst = ip_set_pernet(net);
struct ip_set **list; struct ip_set **list;
inst->ip_set_max = max_sets ? max_sets : CONFIG_IP_SET_MAX; inst->ip_set_max = max_sets ? max_sets : CONFIG_IP_SET_MAX;
......
...@@ -931,7 +931,7 @@ mtype_list(const struct ip_set *set, ...@@ -931,7 +931,7 @@ mtype_list(const struct ip_set *set,
struct nlattr *atd, *nested; struct nlattr *atd, *nested;
const struct hbucket *n; const struct hbucket *n;
const struct mtype_elem *e; const struct mtype_elem *e;
u32 first = cb->args[2]; u32 first = cb->args[IPSET_CB_ARG0];
/* We assume that one hash bucket fills into one page */ /* We assume that one hash bucket fills into one page */
void *incomplete; void *incomplete;
int i; int i;
...@@ -940,20 +940,22 @@ mtype_list(const struct ip_set *set, ...@@ -940,20 +940,22 @@ mtype_list(const struct ip_set *set,
if (!atd) if (!atd)
return -EMSGSIZE; return -EMSGSIZE;
pr_debug("list hash set %s\n", set->name); pr_debug("list hash set %s\n", set->name);
for (; cb->args[2] < jhash_size(t->htable_bits); cb->args[2]++) { for (; cb->args[IPSET_CB_ARG0] < jhash_size(t->htable_bits);
cb->args[IPSET_CB_ARG0]++) {
incomplete = skb_tail_pointer(skb); incomplete = skb_tail_pointer(skb);
n = hbucket(t, cb->args[2]); n = hbucket(t, cb->args[IPSET_CB_ARG0]);
pr_debug("cb->args[2]: %lu, t %p n %p\n", cb->args[2], t, n); pr_debug("cb->arg bucket: %lu, t %p n %p\n",
cb->args[IPSET_CB_ARG0], t, n);
for (i = 0; i < n->pos; i++) { for (i = 0; i < n->pos; i++) {
e = ahash_data(n, i, set->dsize); e = ahash_data(n, i, set->dsize);
if (SET_WITH_TIMEOUT(set) && if (SET_WITH_TIMEOUT(set) &&
ip_set_timeout_expired(ext_timeout(e, set))) ip_set_timeout_expired(ext_timeout(e, set)))
continue; continue;
pr_debug("list hash %lu hbucket %p i %u, data %p\n", pr_debug("list hash %lu hbucket %p i %u, data %p\n",
cb->args[2], n, i, e); cb->args[IPSET_CB_ARG0], n, i, e);
nested = ipset_nest_start(skb, IPSET_ATTR_DATA); nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
if (!nested) { if (!nested) {
if (cb->args[2] == first) { if (cb->args[IPSET_CB_ARG0] == first) {
nla_nest_cancel(skb, atd); nla_nest_cancel(skb, atd);
return -EMSGSIZE; return -EMSGSIZE;
} else } else
...@@ -968,16 +970,16 @@ mtype_list(const struct ip_set *set, ...@@ -968,16 +970,16 @@ mtype_list(const struct ip_set *set,
} }
ipset_nest_end(skb, atd); ipset_nest_end(skb, atd);
/* Set listing finished */ /* Set listing finished */
cb->args[2] = 0; cb->args[IPSET_CB_ARG0] = 0;
return 0; return 0;
nla_put_failure: nla_put_failure:
nlmsg_trim(skb, incomplete); nlmsg_trim(skb, incomplete);
if (unlikely(first == cb->args[2])) { if (unlikely(first == cb->args[IPSET_CB_ARG0])) {
pr_warning("Can't list set %s: one bucket does not fit into " pr_warning("Can't list set %s: one bucket does not fit into "
"a message. Please report it!\n", set->name); "a message. Please report it!\n", set->name);
cb->args[2] = 0; cb->args[IPSET_CB_ARG0] = 0;
return -EMSGSIZE; return -EMSGSIZE;
} }
ipset_nest_end(skb, atd); ipset_nest_end(skb, atd);
......
...@@ -490,14 +490,15 @@ list_set_list(const struct ip_set *set, ...@@ -490,14 +490,15 @@ list_set_list(const struct ip_set *set,
{ {
const struct list_set *map = set->data; const struct list_set *map = set->data;
struct nlattr *atd, *nested; struct nlattr *atd, *nested;
u32 i, first = cb->args[2]; u32 i, first = cb->args[IPSET_CB_ARG0];
const struct set_elem *e; const struct set_elem *e;
atd = ipset_nest_start(skb, IPSET_ATTR_ADT); atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
if (!atd) if (!atd)
return -EMSGSIZE; return -EMSGSIZE;
for (; cb->args[2] < map->size; cb->args[2]++) { for (; cb->args[IPSET_CB_ARG0] < map->size;
i = cb->args[2]; cb->args[IPSET_CB_ARG0]++) {
i = cb->args[IPSET_CB_ARG0];
e = list_set_elem(set, map, i); e = list_set_elem(set, map, i);
if (e->id == IPSET_INVALID_ID) if (e->id == IPSET_INVALID_ID)
goto finish; goto finish;
...@@ -522,13 +523,13 @@ list_set_list(const struct ip_set *set, ...@@ -522,13 +523,13 @@ list_set_list(const struct ip_set *set,
finish: finish:
ipset_nest_end(skb, atd); ipset_nest_end(skb, atd);
/* Set listing finished */ /* Set listing finished */
cb->args[2] = 0; cb->args[IPSET_CB_ARG0] = 0;
return 0; return 0;
nla_put_failure: nla_put_failure:
nla_nest_cancel(skb, nested); nla_nest_cancel(skb, nested);
if (unlikely(i == first)) { if (unlikely(i == first)) {
cb->args[2] = 0; cb->args[IPSET_CB_ARG0] = 0;
return -EMSGSIZE; return -EMSGSIZE;
} }
ipset_nest_end(skb, atd); ipset_nest_end(skb, atd);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment