summaryrefslogtreecommitdiffstats
path: root/kernel/net
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/net')
-rw-r--r--kernel/net/netfilter/ipset/ip_set_core.c49
1 files changed, 32 insertions, 17 deletions
diff --git a/kernel/net/netfilter/ipset/ip_set_core.c b/kernel/net/netfilter/ipset/ip_set_core.c
index e367f3b..1f506e6 100644
--- a/kernel/net/netfilter/ipset/ip_set_core.c
+++ b/kernel/net/netfilter/ipset/ip_set_core.c
@@ -1490,31 +1490,40 @@ ip_set_dump_policy[IPSET_ATTR_CMD_MAX + 1] = {
};
static int
-dump_init(struct netlink_callback *cb, struct ip_set_net *inst)
+ip_set_dump_start(struct netlink_callback *cb)
{
struct nlmsghdr *nlh = nlmsg_hdr(cb->skb);
int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
struct nlattr *cda[IPSET_ATTR_CMD_MAX + 1];
struct nlattr *attr = (void *)nlh + min_len;
+ struct sk_buff *skb = cb->skb;
+ struct ip_set_net *inst = ip_set_pernet(sock_net(skb->sk));
u32 dump_type;
- ip_set_id_t index;
int ret;
ret = NLA_PARSE(cda, IPSET_ATTR_CMD_MAX, attr,
nlh->nlmsg_len - min_len,
ip_set_dump_policy, NULL);
if (ret)
- return ret;
+ goto error;
cb->args[IPSET_CB_PROTO] = nla_get_u8(cda[IPSET_ATTR_PROTOCOL]);
if (cda[IPSET_ATTR_SETNAME]) {
+ ip_set_id_t index;
struct ip_set *set;
+#if HAVE_NETLINK_DUMP_START_ARGS != 4
+ read_lock_bh(&ip_set_ref_lock);
+#endif
set = find_set_and_id(inst, nla_data(cda[IPSET_ATTR_SETNAME]),
&index);
- if (!set)
- return -ENOENT;
-
+#if HAVE_NETLINK_DUMP_START_ARGS != 4
+ read_unlock_bh(&ip_set_ref_lock);
+#endif
+ if (!set) {
+ ret = -ENOENT;
+ goto error;
+ }
dump_type = DUMP_ONE;
cb->args[IPSET_CB_INDEX] = index;
} else {
@@ -1530,10 +1539,17 @@ dump_init(struct netlink_callback *cb, struct ip_set_net *inst)
cb->args[IPSET_CB_DUMP] = dump_type;
return 0;
+
+error:
+ /* We have to create and send the error message manually :-( */
+ if (nlh->nlmsg_flags & NLM_F_ACK) {
+ NETLINK_ACK(cb->skb, nlh, ret, NULL);
+ }
+ return ret;
}
static int
-ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
+ip_set_dump_do(struct sk_buff *skb, struct netlink_callback *cb)
{
ip_set_id_t index = IPSET_INVALID_ID, max;
struct ip_set *set = NULL;
@@ -1545,16 +1561,14 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
int ret = 0;
if (!cb->args[IPSET_CB_DUMP]) {
- ret = dump_init(cb, inst);
+#if HAVE_NETLINK_DUMP_START_ARGS == 4
+ return -EINVAL;
+#else
+ ret = ip_set_dump_start(cb);
if (ret < 0) {
- nlh = nlmsg_hdr(cb->skb);
- /* We have to create and send the error message
- * manually :-(
- */
- if (nlh->nlmsg_flags & NLM_F_ACK)
- NETLINK_ACK(cb->skb, nlh, ret, NULL);
return ret;
}
+#endif
}
if (cb->args[IPSET_CB_INDEX] >= inst->ip_set_max)
@@ -1692,16 +1706,17 @@ IPSET_CBFN(ip_set_dump, struct net *net, struct sock *ctnl,
#if HAVE_NETLINK_DUMP_START_ARGS == 5
return netlink_dump_start(ctnl, skb, nlh,
- ip_set_dump_start,
+ ip_set_dump_do,
ip_set_dump_done);
#elif HAVE_NETLINK_DUMP_START_ARGS == 6
return netlink_dump_start(ctnl, skb, nlh,
- ip_set_dump_start,
+ ip_set_dump_do,
ip_set_dump_done, 0);
#else
{
struct netlink_dump_control c = {
- .dump = ip_set_dump_start,
+ .start = ip_set_dump_start,
+ .dump = ip_set_dump_do,
.done = ip_set_dump_done,
};
return netlink_dump_start(ctnl, skb, nlh, &c);