|
@@ -238,29 +238,33 @@ static const struct nla_policy filter_policy[NFACCT_FILTER_MAX + 1] = {
|
|
|
[NFACCT_FILTER_VALUE] = { .type = NLA_U32 },
|
|
|
};
|
|
|
|
|
|
-static struct nfacct_filter *
|
|
|
-nfacct_filter_alloc(const struct nlattr * const attr)
|
|
|
+static int nfnl_acct_start(struct netlink_callback *cb)
|
|
|
{
|
|
|
- struct nfacct_filter *filter;
|
|
|
+ const struct nlattr *const attr = cb->data;
|
|
|
struct nlattr *tb[NFACCT_FILTER_MAX + 1];
|
|
|
+ struct nfacct_filter *filter;
|
|
|
int err;
|
|
|
|
|
|
+ if (!attr)
|
|
|
+ return 0;
|
|
|
+
|
|
|
err = nla_parse_nested(tb, NFACCT_FILTER_MAX, attr, filter_policy,
|
|
|
NULL);
|
|
|
if (err < 0)
|
|
|
- return ERR_PTR(err);
|
|
|
+ return err;
|
|
|
|
|
|
if (!tb[NFACCT_FILTER_MASK] || !tb[NFACCT_FILTER_VALUE])
|
|
|
- return ERR_PTR(-EINVAL);
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
filter = kzalloc(sizeof(struct nfacct_filter), GFP_KERNEL);
|
|
|
if (!filter)
|
|
|
- return ERR_PTR(-ENOMEM);
|
|
|
+ return -ENOMEM;
|
|
|
|
|
|
filter->mask = ntohl(nla_get_be32(tb[NFACCT_FILTER_MASK]));
|
|
|
filter->value = ntohl(nla_get_be32(tb[NFACCT_FILTER_VALUE]));
|
|
|
+ cb->data = filter;
|
|
|
|
|
|
- return filter;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
static int nfnl_acct_get(struct net *net, struct sock *nfnl,
|
|
@@ -275,18 +279,11 @@ static int nfnl_acct_get(struct net *net, struct sock *nfnl,
|
|
|
if (nlh->nlmsg_flags & NLM_F_DUMP) {
|
|
|
struct netlink_dump_control c = {
|
|
|
.dump = nfnl_acct_dump,
|
|
|
+ .start = nfnl_acct_start,
|
|
|
.done = nfnl_acct_done,
|
|
|
+ .data = (void *)tb[NFACCT_FILTER],
|
|
|
};
|
|
|
|
|
|
- if (tb[NFACCT_FILTER]) {
|
|
|
- struct nfacct_filter *filter;
|
|
|
-
|
|
|
- filter = nfacct_filter_alloc(tb[NFACCT_FILTER]);
|
|
|
- if (IS_ERR(filter))
|
|
|
- return PTR_ERR(filter);
|
|
|
-
|
|
|
- c.data = filter;
|
|
|
- }
|
|
|
return netlink_dump_start(nfnl, skb, nlh, &c);
|
|
|
}
|
|
|
|