blob: c8c303c3386fbca9aaf1c5e4aa94f5985da05bab [file] [log] [blame]
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
2 * Patrick Schaaf <bof@bof.de>
Jozsef Kadlecsik075e64c2013-04-27 14:28:55 +02003 * Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10/* Kernel module for IP set management */
11
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/moduleparam.h>
15#include <linux/ip.h>
16#include <linux/skbuff.h>
17#include <linux/spinlock.h>
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +010018#include <linux/rculist.h>
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +010019#include <net/netlink.h>
20
21#include <linux/netfilter.h>
Jozsef Kadlecsikb66554c2011-06-16 18:56:47 +020022#include <linux/netfilter/x_tables.h>
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +010023#include <linux/netfilter/nfnetlink.h>
24#include <linux/netfilter/ipset/ip_set.h>
25
26static LIST_HEAD(ip_set_type_list); /* all registered set types */
27static DEFINE_MUTEX(ip_set_type_mutex); /* protects ip_set_type_list */
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +020028static DEFINE_RWLOCK(ip_set_ref_lock); /* protects the set refs */
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +010029
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +000030static struct ip_set * __rcu *ip_set_list; /* all individual sets */
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +010031static ip_set_id_t ip_set_max = CONFIG_IP_SET_MAX; /* max number of sets */
32
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +000033#define IP_SET_INC 64
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +010034#define STREQ(a, b) (strncmp(a, b, IPSET_MAXNAMELEN) == 0)
35
36static unsigned int max_sets;
37
38module_param(max_sets, int, 0600);
39MODULE_PARM_DESC(max_sets, "maximal number of sets");
40MODULE_LICENSE("GPL");
41MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
42MODULE_DESCRIPTION("core IP set support");
43MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET);
44
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +000045/* When the nfnl mutex is held: */
46#define nfnl_dereference(p) \
47 rcu_dereference_protected(p, 1)
48#define nfnl_set(id) \
49 nfnl_dereference(ip_set_list)[id]
50
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +010051/*
52 * The set types are implemented in modules and registered set types
53 * can be found in ip_set_type_list. Adding/deleting types is
54 * serialized by ip_set_type_mutex.
55 */
56
57static inline void
58ip_set_type_lock(void)
59{
60 mutex_lock(&ip_set_type_mutex);
61}
62
63static inline void
64ip_set_type_unlock(void)
65{
66 mutex_unlock(&ip_set_type_mutex);
67}
68
69/* Register and deregister settype */
70
71static struct ip_set_type *
72find_set_type(const char *name, u8 family, u8 revision)
73{
74 struct ip_set_type *type;
75
76 list_for_each_entry_rcu(type, &ip_set_type_list, list)
77 if (STREQ(type->name, name) &&
Jozsef Kadlecsik3ace95c2012-09-21 22:01:45 +020078 (type->family == family ||
79 type->family == NFPROTO_UNSPEC) &&
Jozsef Kadlecsikf1e00b32011-06-16 18:51:41 +020080 revision >= type->revision_min &&
81 revision <= type->revision_max)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +010082 return type;
83 return NULL;
84}
85
86/* Unlock, try to load a set type module and lock again */
Jozsef Kadlecsik088067f2012-01-17 10:39:05 +010087static bool
88load_settype(const char *name)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +010089{
Pablo Neira Ayusoc14b78e2013-02-05 01:50:26 +010090 nfnl_unlock(NFNL_SUBSYS_IPSET);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +010091 pr_debug("try to load ip_set_%s\n", name);
92 if (request_module("ip_set_%s", name) < 0) {
93 pr_warning("Can't find ip_set type %s\n", name);
Pablo Neira Ayusoc14b78e2013-02-05 01:50:26 +010094 nfnl_lock(NFNL_SUBSYS_IPSET);
Jozsef Kadlecsik088067f2012-01-17 10:39:05 +010095 return false;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +010096 }
Pablo Neira Ayusoc14b78e2013-02-05 01:50:26 +010097 nfnl_lock(NFNL_SUBSYS_IPSET);
Jozsef Kadlecsik088067f2012-01-17 10:39:05 +010098 return true;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +010099}
100
101/* Find a set type and reference it */
Jozsef Kadlecsik088067f2012-01-17 10:39:05 +0100102#define find_set_type_get(name, family, revision, found) \
103 __find_set_type_get(name, family, revision, found, false)
104
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100105static int
Jozsef Kadlecsik088067f2012-01-17 10:39:05 +0100106__find_set_type_get(const char *name, u8 family, u8 revision,
107 struct ip_set_type **found, bool retry)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100108{
Jozsef Kadlecsik5c1aba42011-03-20 15:35:01 +0100109 struct ip_set_type *type;
110 int err;
111
Jozsef Kadlecsik088067f2012-01-17 10:39:05 +0100112 if (retry && !load_settype(name))
113 return -IPSET_ERR_FIND_TYPE;
114
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100115 rcu_read_lock();
116 *found = find_set_type(name, family, revision);
117 if (*found) {
Jozsef Kadlecsik5c1aba42011-03-20 15:35:01 +0100118 err = !try_module_get((*found)->me) ? -EFAULT : 0;
119 goto unlock;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100120 }
Jozsef Kadlecsik088067f2012-01-17 10:39:05 +0100121 /* Make sure the type is already loaded
122 * but we don't support the revision */
Jozsef Kadlecsik5c1aba42011-03-20 15:35:01 +0100123 list_for_each_entry_rcu(type, &ip_set_type_list, list)
124 if (STREQ(type->name, name)) {
125 err = -IPSET_ERR_FIND_TYPE;
126 goto unlock;
127 }
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100128 rcu_read_unlock();
129
Jozsef Kadlecsik088067f2012-01-17 10:39:05 +0100130 return retry ? -IPSET_ERR_FIND_TYPE :
131 __find_set_type_get(name, family, revision, found, true);
Jozsef Kadlecsik5c1aba42011-03-20 15:35:01 +0100132
133unlock:
134 rcu_read_unlock();
135 return err;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100136}
137
138/* Find a given set type by name and family.
139 * If we succeeded, the supported minimal and maximum revisions are
140 * filled out.
141 */
Jozsef Kadlecsik088067f2012-01-17 10:39:05 +0100142#define find_set_type_minmax(name, family, min, max) \
143 __find_set_type_minmax(name, family, min, max, false)
144
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100145static int
Jozsef Kadlecsik088067f2012-01-17 10:39:05 +0100146__find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max,
147 bool retry)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100148{
149 struct ip_set_type *type;
150 bool found = false;
151
Jozsef Kadlecsik088067f2012-01-17 10:39:05 +0100152 if (retry && !load_settype(name))
153 return -IPSET_ERR_FIND_TYPE;
154
Jozsef Kadlecsik5c1aba42011-03-20 15:35:01 +0100155 *min = 255; *max = 0;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100156 rcu_read_lock();
157 list_for_each_entry_rcu(type, &ip_set_type_list, list)
158 if (STREQ(type->name, name) &&
Jozsef Kadlecsik3ace95c2012-09-21 22:01:45 +0200159 (type->family == family ||
160 type->family == NFPROTO_UNSPEC)) {
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100161 found = true;
Jozsef Kadlecsikf1e00b32011-06-16 18:51:41 +0200162 if (type->revision_min < *min)
163 *min = type->revision_min;
164 if (type->revision_max > *max)
165 *max = type->revision_max;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100166 }
167 rcu_read_unlock();
168 if (found)
169 return 0;
170
Jozsef Kadlecsik088067f2012-01-17 10:39:05 +0100171 return retry ? -IPSET_ERR_FIND_TYPE :
172 __find_set_type_minmax(name, family, min, max, true);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100173}
174
Jan Engelhardtc15f1c82012-02-14 00:24:10 +0100175#define family_name(f) ((f) == NFPROTO_IPV4 ? "inet" : \
176 (f) == NFPROTO_IPV6 ? "inet6" : "any")
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100177
178/* Register a set type structure. The type is identified by
179 * the unique triple of name, family and revision.
180 */
181int
182ip_set_type_register(struct ip_set_type *type)
183{
184 int ret = 0;
185
186 if (type->protocol != IPSET_PROTOCOL) {
Jozsef Kadlecsikf1e00b32011-06-16 18:51:41 +0200187 pr_warning("ip_set type %s, family %s, revision %u:%u uses "
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100188 "wrong protocol version %u (want %u)\n",
189 type->name, family_name(type->family),
Jozsef Kadlecsikf1e00b32011-06-16 18:51:41 +0200190 type->revision_min, type->revision_max,
191 type->protocol, IPSET_PROTOCOL);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100192 return -EINVAL;
193 }
194
195 ip_set_type_lock();
Jozsef Kadlecsikf1e00b32011-06-16 18:51:41 +0200196 if (find_set_type(type->name, type->family, type->revision_min)) {
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100197 /* Duplicate! */
Jozsef Kadlecsikf1e00b32011-06-16 18:51:41 +0200198 pr_warning("ip_set type %s, family %s with revision min %u "
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100199 "already registered!\n", type->name,
Jozsef Kadlecsikf1e00b32011-06-16 18:51:41 +0200200 family_name(type->family), type->revision_min);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100201 ret = -EINVAL;
202 goto unlock;
203 }
204 list_add_rcu(&type->list, &ip_set_type_list);
Jozsef Kadlecsikf1e00b32011-06-16 18:51:41 +0200205 pr_debug("type %s, family %s, revision %u:%u registered.\n",
206 type->name, family_name(type->family),
207 type->revision_min, type->revision_max);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100208unlock:
209 ip_set_type_unlock();
210 return ret;
211}
212EXPORT_SYMBOL_GPL(ip_set_type_register);
213
214/* Unregister a set type. There's a small race with ip_set_create */
215void
216ip_set_type_unregister(struct ip_set_type *type)
217{
218 ip_set_type_lock();
Jozsef Kadlecsikf1e00b32011-06-16 18:51:41 +0200219 if (!find_set_type(type->name, type->family, type->revision_min)) {
220 pr_warning("ip_set type %s, family %s with revision min %u "
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100221 "not registered\n", type->name,
Jozsef Kadlecsikf1e00b32011-06-16 18:51:41 +0200222 family_name(type->family), type->revision_min);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100223 goto unlock;
224 }
225 list_del_rcu(&type->list);
Jozsef Kadlecsikf1e00b32011-06-16 18:51:41 +0200226 pr_debug("type %s, family %s with revision min %u unregistered.\n",
227 type->name, family_name(type->family), type->revision_min);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100228unlock:
229 ip_set_type_unlock();
230
231 synchronize_rcu();
232}
233EXPORT_SYMBOL_GPL(ip_set_type_unregister);
234
235/* Utility functions */
236void *
237ip_set_alloc(size_t size)
238{
239 void *members = NULL;
240
241 if (size < KMALLOC_MAX_SIZE)
242 members = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
243
244 if (members) {
245 pr_debug("%p: allocated with kmalloc\n", members);
246 return members;
247 }
248
249 members = vzalloc(size);
250 if (!members)
251 return NULL;
252 pr_debug("%p: allocated with vmalloc\n", members);
253
254 return members;
255}
256EXPORT_SYMBOL_GPL(ip_set_alloc);
257
258void
259ip_set_free(void *members)
260{
261 pr_debug("%p: free with %s\n", members,
262 is_vmalloc_addr(members) ? "vfree" : "kfree");
263 if (is_vmalloc_addr(members))
264 vfree(members);
265 else
266 kfree(members);
267}
268EXPORT_SYMBOL_GPL(ip_set_free);
269
270static inline bool
271flag_nested(const struct nlattr *nla)
272{
273 return nla->nla_type & NLA_F_NESTED;
274}
275
276static const struct nla_policy ipaddr_policy[IPSET_ATTR_IPADDR_MAX + 1] = {
277 [IPSET_ATTR_IPADDR_IPV4] = { .type = NLA_U32 },
278 [IPSET_ATTR_IPADDR_IPV6] = { .type = NLA_BINARY,
279 .len = sizeof(struct in6_addr) },
280};
281
282int
283ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr)
284{
285 struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1];
286
287 if (unlikely(!flag_nested(nla)))
288 return -IPSET_ERR_PROTOCOL;
Patrick McHardy8da560c2011-02-01 16:27:25 +0100289 if (nla_parse_nested(tb, IPSET_ATTR_IPADDR_MAX, nla, ipaddr_policy))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100290 return -IPSET_ERR_PROTOCOL;
291 if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV4)))
292 return -IPSET_ERR_PROTOCOL;
293
294 *ipaddr = nla_get_be32(tb[IPSET_ATTR_IPADDR_IPV4]);
295 return 0;
296}
297EXPORT_SYMBOL_GPL(ip_set_get_ipaddr4);
298
299int
300ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr)
301{
302 struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1];
303
304 if (unlikely(!flag_nested(nla)))
305 return -IPSET_ERR_PROTOCOL;
306
Patrick McHardy8da560c2011-02-01 16:27:25 +0100307 if (nla_parse_nested(tb, IPSET_ATTR_IPADDR_MAX, nla, ipaddr_policy))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100308 return -IPSET_ERR_PROTOCOL;
309 if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV6)))
310 return -IPSET_ERR_PROTOCOL;
311
312 memcpy(ipaddr, nla_data(tb[IPSET_ATTR_IPADDR_IPV6]),
313 sizeof(struct in6_addr));
314 return 0;
315}
316EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6);
317
Jozsef Kadlecsik075e64c2013-04-27 14:28:55 +0200318int
319ip_set_get_extensions(struct ip_set *set, struct nlattr *tb[],
320 struct ip_set_ext *ext)
321{
322 if (tb[IPSET_ATTR_TIMEOUT]) {
323 if (!(set->extensions & IPSET_EXT_TIMEOUT))
324 return -IPSET_ERR_TIMEOUT;
325 ext->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
326 }
Jozsef Kadlecsik34d666d2013-04-27 14:38:56 +0200327 if (tb[IPSET_ATTR_BYTES] || tb[IPSET_ATTR_PACKETS]) {
328 if (!(set->extensions & IPSET_EXT_COUNTER))
329 return -IPSET_ERR_COUNTER;
330 if (tb[IPSET_ATTR_BYTES])
331 ext->bytes = be64_to_cpu(nla_get_be64(
332 tb[IPSET_ATTR_BYTES]));
333 if (tb[IPSET_ATTR_PACKETS])
334 ext->packets = be64_to_cpu(nla_get_be64(
335 tb[IPSET_ATTR_PACKETS]));
336 }
Jozsef Kadlecsik075e64c2013-04-27 14:28:55 +0200337 return 0;
338}
339EXPORT_SYMBOL_GPL(ip_set_get_extensions);
340
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100341/*
342 * Creating/destroying/renaming/swapping affect the existence and
343 * the properties of a set. All of these can be executed from userspace
344 * only and serialized by the nfnl mutex indirectly from nfnetlink.
345 *
346 * Sets are identified by their index in ip_set_list and the index
347 * is used by the external references (set/SET netfilter modules).
348 *
349 * The set behind an index may change by swapping only, from userspace.
350 */
351
352static inline void
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000353__ip_set_get(struct ip_set *set)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100354{
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200355 write_lock_bh(&ip_set_ref_lock);
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000356 set->ref++;
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200357 write_unlock_bh(&ip_set_ref_lock);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100358}
359
360static inline void
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000361__ip_set_put(struct ip_set *set)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100362{
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200363 write_lock_bh(&ip_set_ref_lock);
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000364 BUG_ON(set->ref == 0);
365 set->ref--;
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200366 write_unlock_bh(&ip_set_ref_lock);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100367}
368
369/*
370 * Add, del and test set entries from kernel.
371 *
372 * The set behind the index must exist and must be referenced
373 * so it can't be destroyed (or changed) under our foot.
374 */
375
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000376static inline struct ip_set *
377ip_set_rcu_get(ip_set_id_t index)
378{
379 struct ip_set *set;
380
381 rcu_read_lock();
382 /* ip_set_list itself needs to be protected */
383 set = rcu_dereference(ip_set_list)[index];
384 rcu_read_unlock();
385
386 return set;
387}
388
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100389int
390ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
Jozsef Kadlecsik075e64c2013-04-27 14:28:55 +0200391 const struct xt_action_param *par, struct ip_set_adt_opt *opt)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100392{
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000393 struct ip_set *set = ip_set_rcu_get(index);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100394 int ret = 0;
395
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200396 BUG_ON(set == NULL);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100397 pr_debug("set %s, index %u\n", set->name, index);
398
Jozsef Kadlecsikac8cc922011-06-16 18:42:40 +0200399 if (opt->dim < set->type->dimension ||
Jan Engelhardtc15f1c82012-02-14 00:24:10 +0100400 !(opt->family == set->family || set->family == NFPROTO_UNSPEC))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100401 return 0;
402
403 read_lock_bh(&set->lock);
Jozsef Kadlecsikb66554c2011-06-16 18:56:47 +0200404 ret = set->variant->kadt(set, skb, par, IPSET_TEST, opt);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100405 read_unlock_bh(&set->lock);
406
407 if (ret == -EAGAIN) {
408 /* Type requests element to be completed */
409 pr_debug("element must be competed, ADD is triggered\n");
410 write_lock_bh(&set->lock);
Jozsef Kadlecsikb66554c2011-06-16 18:56:47 +0200411 set->variant->kadt(set, skb, par, IPSET_ADD, opt);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100412 write_unlock_bh(&set->lock);
413 ret = 1;
Jozsef Kadlecsik3e0304a2012-09-21 22:02:36 +0200414 } else {
415 /* --return-nomatch: invert matched element */
Jozsef Kadlecsik6e017812013-04-27 14:40:50 +0200416 if ((opt->cmdflags & IPSET_FLAG_RETURN_NOMATCH) &&
Jozsef Kadlecsik3e0304a2012-09-21 22:02:36 +0200417 (set->type->features & IPSET_TYPE_NOMATCH) &&
418 (ret > 0 || ret == -ENOTEMPTY))
419 ret = -ret;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100420 }
421
422 /* Convert error codes to nomatch */
423 return (ret < 0 ? 0 : ret);
424}
425EXPORT_SYMBOL_GPL(ip_set_test);
426
427int
428ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
Jozsef Kadlecsik075e64c2013-04-27 14:28:55 +0200429 const struct xt_action_param *par, struct ip_set_adt_opt *opt)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100430{
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000431 struct ip_set *set = ip_set_rcu_get(index);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100432 int ret;
433
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200434 BUG_ON(set == NULL);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100435 pr_debug("set %s, index %u\n", set->name, index);
436
Jozsef Kadlecsikac8cc922011-06-16 18:42:40 +0200437 if (opt->dim < set->type->dimension ||
Jan Engelhardtc15f1c82012-02-14 00:24:10 +0100438 !(opt->family == set->family || set->family == NFPROTO_UNSPEC))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100439 return 0;
440
441 write_lock_bh(&set->lock);
Jozsef Kadlecsikb66554c2011-06-16 18:56:47 +0200442 ret = set->variant->kadt(set, skb, par, IPSET_ADD, opt);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100443 write_unlock_bh(&set->lock);
444
445 return ret;
446}
447EXPORT_SYMBOL_GPL(ip_set_add);
448
449int
450ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
Jozsef Kadlecsik075e64c2013-04-27 14:28:55 +0200451 const struct xt_action_param *par, struct ip_set_adt_opt *opt)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100452{
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000453 struct ip_set *set = ip_set_rcu_get(index);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100454 int ret = 0;
455
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200456 BUG_ON(set == NULL);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100457 pr_debug("set %s, index %u\n", set->name, index);
458
Jozsef Kadlecsikac8cc922011-06-16 18:42:40 +0200459 if (opt->dim < set->type->dimension ||
Jan Engelhardtc15f1c82012-02-14 00:24:10 +0100460 !(opt->family == set->family || set->family == NFPROTO_UNSPEC))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100461 return 0;
462
463 write_lock_bh(&set->lock);
Jozsef Kadlecsikb66554c2011-06-16 18:56:47 +0200464 ret = set->variant->kadt(set, skb, par, IPSET_DEL, opt);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100465 write_unlock_bh(&set->lock);
466
467 return ret;
468}
469EXPORT_SYMBOL_GPL(ip_set_del);
470
471/*
472 * Find set by name, reference it once. The reference makes sure the
473 * thing pointed to, does not go away under our feet.
474 *
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100475 */
476ip_set_id_t
477ip_set_get_byname(const char *name, struct ip_set **set)
478{
479 ip_set_id_t i, index = IPSET_INVALID_ID;
480 struct ip_set *s;
481
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000482 rcu_read_lock();
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100483 for (i = 0; i < ip_set_max; i++) {
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000484 s = rcu_dereference(ip_set_list)[i];
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100485 if (s != NULL && STREQ(s->name, name)) {
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000486 __ip_set_get(s);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100487 index = i;
488 *set = s;
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000489 break;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100490 }
491 }
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000492 rcu_read_unlock();
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100493
494 return index;
495}
496EXPORT_SYMBOL_GPL(ip_set_get_byname);
497
498/*
499 * If the given set pointer points to a valid set, decrement
500 * reference count by 1. The caller shall not assume the index
501 * to be valid, after calling this function.
502 *
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100503 */
504void
505ip_set_put_byindex(ip_set_id_t index)
506{
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000507 struct ip_set *set;
508
509 rcu_read_lock();
510 set = rcu_dereference(ip_set_list)[index];
511 if (set != NULL)
512 __ip_set_put(set);
513 rcu_read_unlock();
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100514}
515EXPORT_SYMBOL_GPL(ip_set_put_byindex);
516
517/*
518 * Get the name of a set behind a set index.
519 * We assume the set is referenced, so it does exist and
520 * can't be destroyed. The set cannot be renamed due to
521 * the referencing either.
522 *
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100523 */
524const char *
525ip_set_name_byindex(ip_set_id_t index)
526{
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000527 const struct ip_set *set = ip_set_rcu_get(index);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100528
529 BUG_ON(set == NULL);
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200530 BUG_ON(set->ref == 0);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100531
532 /* Referenced, so it's safe */
533 return set->name;
534}
535EXPORT_SYMBOL_GPL(ip_set_name_byindex);
536
537/*
538 * Routines to call by external subsystems, which do not
539 * call nfnl_lock for us.
540 */
541
542/*
543 * Find set by name, reference it once. The reference makes sure the
544 * thing pointed to, does not go away under our feet.
545 *
546 * The nfnl mutex is used in the function.
547 */
548ip_set_id_t
549ip_set_nfnl_get(const char *name)
550{
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000551 ip_set_id_t i, index = IPSET_INVALID_ID;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100552 struct ip_set *s;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100553
Pablo Neira Ayusoc14b78e2013-02-05 01:50:26 +0100554 nfnl_lock(NFNL_SUBSYS_IPSET);
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000555 for (i = 0; i < ip_set_max; i++) {
556 s = nfnl_set(i);
557 if (s != NULL && STREQ(s->name, name)) {
558 __ip_set_get(s);
559 index = i;
560 break;
561 }
562 }
Pablo Neira Ayusoc14b78e2013-02-05 01:50:26 +0100563 nfnl_unlock(NFNL_SUBSYS_IPSET);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100564
565 return index;
566}
567EXPORT_SYMBOL_GPL(ip_set_nfnl_get);
568
569/*
570 * Find set by index, reference it once. The reference makes sure the
571 * thing pointed to, does not go away under our feet.
572 *
573 * The nfnl mutex is used in the function.
574 */
575ip_set_id_t
576ip_set_nfnl_get_byindex(ip_set_id_t index)
577{
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000578 struct ip_set *set;
579
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100580 if (index > ip_set_max)
581 return IPSET_INVALID_ID;
582
Pablo Neira Ayusoc14b78e2013-02-05 01:50:26 +0100583 nfnl_lock(NFNL_SUBSYS_IPSET);
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000584 set = nfnl_set(index);
585 if (set)
586 __ip_set_get(set);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100587 else
588 index = IPSET_INVALID_ID;
Pablo Neira Ayusoc14b78e2013-02-05 01:50:26 +0100589 nfnl_unlock(NFNL_SUBSYS_IPSET);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100590
591 return index;
592}
593EXPORT_SYMBOL_GPL(ip_set_nfnl_get_byindex);
594
595/*
596 * If the given set pointer points to a valid set, decrement
597 * reference count by 1. The caller shall not assume the index
598 * to be valid, after calling this function.
599 *
600 * The nfnl mutex is used in the function.
601 */
602void
603ip_set_nfnl_put(ip_set_id_t index)
604{
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000605 struct ip_set *set;
Pablo Neira Ayusoc14b78e2013-02-05 01:50:26 +0100606 nfnl_lock(NFNL_SUBSYS_IPSET);
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000607 set = nfnl_set(index);
608 if (set != NULL)
609 __ip_set_put(set);
Pablo Neira Ayusoc14b78e2013-02-05 01:50:26 +0100610 nfnl_unlock(NFNL_SUBSYS_IPSET);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100611}
612EXPORT_SYMBOL_GPL(ip_set_nfnl_put);
613
614/*
615 * Communication protocol with userspace over netlink.
616 *
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200617 * The commands are serialized by the nfnl mutex.
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100618 */
619
620static inline bool
621protocol_failed(const struct nlattr * const tb[])
622{
623 return !tb[IPSET_ATTR_PROTOCOL] ||
624 nla_get_u8(tb[IPSET_ATTR_PROTOCOL]) != IPSET_PROTOCOL;
625}
626
627static inline u32
628flag_exist(const struct nlmsghdr *nlh)
629{
630 return nlh->nlmsg_flags & NLM_F_EXCL ? 0 : IPSET_FLAG_EXIST;
631}
632
633static struct nlmsghdr *
Eric W. Biederman15e47302012-09-07 20:12:54 +0000634start_msg(struct sk_buff *skb, u32 portid, u32 seq, unsigned int flags,
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100635 enum ipset_cmd cmd)
636{
637 struct nlmsghdr *nlh;
638 struct nfgenmsg *nfmsg;
639
Eric W. Biederman15e47302012-09-07 20:12:54 +0000640 nlh = nlmsg_put(skb, portid, seq, cmd | (NFNL_SUBSYS_IPSET << 8),
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100641 sizeof(*nfmsg), flags);
642 if (nlh == NULL)
643 return NULL;
644
645 nfmsg = nlmsg_data(nlh);
Jan Engelhardtc15f1c82012-02-14 00:24:10 +0100646 nfmsg->nfgen_family = NFPROTO_IPV4;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100647 nfmsg->version = NFNETLINK_V0;
648 nfmsg->res_id = 0;
649
650 return nlh;
651}
652
653/* Create a set */
654
655static const struct nla_policy ip_set_create_policy[IPSET_ATTR_CMD_MAX + 1] = {
656 [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
657 [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING,
658 .len = IPSET_MAXNAMELEN - 1 },
659 [IPSET_ATTR_TYPENAME] = { .type = NLA_NUL_STRING,
660 .len = IPSET_MAXNAMELEN - 1},
661 [IPSET_ATTR_REVISION] = { .type = NLA_U8 },
662 [IPSET_ATTR_FAMILY] = { .type = NLA_U8 },
663 [IPSET_ATTR_DATA] = { .type = NLA_NESTED },
664};
665
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000666static struct ip_set *
667find_set_and_id(const char *name, ip_set_id_t *id)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100668{
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000669 struct ip_set *set = NULL;
670 ip_set_id_t i;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100671
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000672 *id = IPSET_INVALID_ID;
673 for (i = 0; i < ip_set_max; i++) {
674 set = nfnl_set(i);
675 if (set != NULL && STREQ(set->name, name)) {
676 *id = i;
677 break;
678 }
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100679 }
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000680 return (*id == IPSET_INVALID_ID ? NULL : set);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100681}
682
683static inline struct ip_set *
684find_set(const char *name)
685{
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000686 ip_set_id_t id;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100687
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000688 return find_set_and_id(name, &id);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100689}
690
691static int
692find_free_id(const char *name, ip_set_id_t *index, struct ip_set **set)
693{
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000694 struct ip_set *s;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100695 ip_set_id_t i;
696
697 *index = IPSET_INVALID_ID;
698 for (i = 0; i < ip_set_max; i++) {
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000699 s = nfnl_set(i);
700 if (s == NULL) {
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100701 if (*index == IPSET_INVALID_ID)
702 *index = i;
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000703 } else if (STREQ(name, s->name)) {
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100704 /* Name clash */
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000705 *set = s;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100706 return -EEXIST;
707 }
708 }
709 if (*index == IPSET_INVALID_ID)
710 /* No free slot remained */
711 return -IPSET_ERR_MAX_SETS;
712 return 0;
713}
714
715static int
Tomasz Bursztykad31f4d42012-06-28 02:57:48 +0000716ip_set_none(struct sock *ctnl, struct sk_buff *skb,
717 const struct nlmsghdr *nlh,
718 const struct nlattr * const attr[])
719{
720 return -EOPNOTSUPP;
721}
722
723static int
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100724ip_set_create(struct sock *ctnl, struct sk_buff *skb,
725 const struct nlmsghdr *nlh,
726 const struct nlattr * const attr[])
727{
Shan Wei9846ada2011-03-08 15:37:27 +0100728 struct ip_set *set, *clash = NULL;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100729 ip_set_id_t index = IPSET_INVALID_ID;
730 struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1] = {};
731 const char *name, *typename;
732 u8 family, revision;
733 u32 flags = flag_exist(nlh);
734 int ret = 0;
735
736 if (unlikely(protocol_failed(attr) ||
737 attr[IPSET_ATTR_SETNAME] == NULL ||
738 attr[IPSET_ATTR_TYPENAME] == NULL ||
739 attr[IPSET_ATTR_REVISION] == NULL ||
740 attr[IPSET_ATTR_FAMILY] == NULL ||
741 (attr[IPSET_ATTR_DATA] != NULL &&
742 !flag_nested(attr[IPSET_ATTR_DATA]))))
743 return -IPSET_ERR_PROTOCOL;
744
745 name = nla_data(attr[IPSET_ATTR_SETNAME]);
746 typename = nla_data(attr[IPSET_ATTR_TYPENAME]);
747 family = nla_get_u8(attr[IPSET_ATTR_FAMILY]);
748 revision = nla_get_u8(attr[IPSET_ATTR_REVISION]);
749 pr_debug("setname: %s, typename: %s, family: %s, revision: %u\n",
750 name, typename, family_name(family), revision);
751
752 /*
753 * First, and without any locks, allocate and initialize
754 * a normal base set structure.
755 */
756 set = kzalloc(sizeof(struct ip_set), GFP_KERNEL);
757 if (!set)
758 return -ENOMEM;
759 rwlock_init(&set->lock);
760 strlcpy(set->name, name, IPSET_MAXNAMELEN);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100761 set->family = family;
Jozsef Kadlecsikf1e00b32011-06-16 18:51:41 +0200762 set->revision = revision;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100763
764 /*
765 * Next, check that we know the type, and take
766 * a reference on the type, to make sure it stays available
767 * while constructing our new set.
768 *
769 * After referencing the type, we try to create the type
770 * specific part of the set without holding any locks.
771 */
772 ret = find_set_type_get(typename, family, revision, &(set->type));
773 if (ret)
774 goto out;
775
776 /*
777 * Without holding any locks, create private part.
778 */
779 if (attr[IPSET_ATTR_DATA] &&
Patrick McHardy8da560c2011-02-01 16:27:25 +0100780 nla_parse_nested(tb, IPSET_ATTR_CREATE_MAX, attr[IPSET_ATTR_DATA],
781 set->type->create_policy)) {
Jozsef Kadlecsik15b4d932011-06-16 19:01:26 +0200782 ret = -IPSET_ERR_PROTOCOL;
783 goto put_out;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100784 }
785
786 ret = set->type->create(set, tb, flags);
787 if (ret != 0)
788 goto put_out;
789
790 /* BTW, ret==0 here. */
791
792 /*
793 * Here, we have a valid, constructed set and we are protected
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200794 * by the nfnl mutex. Find the first free index in ip_set_list
795 * and check clashing.
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100796 */
Jozsef Kadlecsik3ace95c2012-09-21 22:01:45 +0200797 ret = find_free_id(set->name, &index, &clash);
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000798 if (ret == -EEXIST) {
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100799 /* If this is the same set and requested, ignore error */
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000800 if ((flags & IPSET_FLAG_EXIST) &&
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100801 STREQ(set->type->name, clash->type->name) &&
802 set->type->family == clash->type->family &&
Jozsef Kadlecsikf1e00b32011-06-16 18:51:41 +0200803 set->type->revision_min == clash->type->revision_min &&
804 set->type->revision_max == clash->type->revision_max &&
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100805 set->variant->same_set(set, clash))
806 ret = 0;
807 goto cleanup;
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000808 } else if (ret == -IPSET_ERR_MAX_SETS) {
809 struct ip_set **list, **tmp;
810 ip_set_id_t i = ip_set_max + IP_SET_INC;
811
812 if (i < ip_set_max || i == IPSET_INVALID_ID)
813 /* Wraparound */
814 goto cleanup;
815
816 list = kzalloc(sizeof(struct ip_set *) * i, GFP_KERNEL);
817 if (!list)
818 goto cleanup;
819 /* nfnl mutex is held, both lists are valid */
820 tmp = nfnl_dereference(ip_set_list);
821 memcpy(list, tmp, sizeof(struct ip_set *) * ip_set_max);
822 rcu_assign_pointer(ip_set_list, list);
823 /* Make sure all current packets have passed through */
824 synchronize_net();
825 /* Use new list */
826 index = ip_set_max;
827 ip_set_max = i;
828 kfree(tmp);
829 ret = 0;
830 } else if (ret)
831 goto cleanup;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100832
833 /*
834 * Finally! Add our shiny new set to the list, and be done.
835 */
836 pr_debug("create: '%s' created with index %u!\n", set->name, index);
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000837 nfnl_set(index) = set;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100838
839 return ret;
840
841cleanup:
842 set->variant->destroy(set);
843put_out:
844 module_put(set->type->me);
845out:
846 kfree(set);
847 return ret;
848}
849
850/* Destroy sets */
851
852static const struct nla_policy
853ip_set_setname_policy[IPSET_ATTR_CMD_MAX + 1] = {
854 [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
855 [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING,
856 .len = IPSET_MAXNAMELEN - 1 },
857};
858
859static void
860ip_set_destroy_set(ip_set_id_t index)
861{
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000862 struct ip_set *set = nfnl_set(index);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100863
864 pr_debug("set: %s\n", set->name);
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000865 nfnl_set(index) = NULL;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100866
867 /* Must call it without holding any lock */
868 set->variant->destroy(set);
869 module_put(set->type->me);
870 kfree(set);
871}
872
873static int
874ip_set_destroy(struct sock *ctnl, struct sk_buff *skb,
875 const struct nlmsghdr *nlh,
876 const struct nlattr * const attr[])
877{
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000878 struct ip_set *s;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100879 ip_set_id_t i;
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200880 int ret = 0;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100881
882 if (unlikely(protocol_failed(attr)))
883 return -IPSET_ERR_PROTOCOL;
884
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200885 /* Commands are serialized and references are
886 * protected by the ip_set_ref_lock.
887 * External systems (i.e. xt_set) must call
888 * ip_set_put|get_nfnl_* functions, that way we
889 * can safely check references here.
890 *
891 * list:set timer can only decrement the reference
892 * counter, so if it's already zero, we can proceed
893 * without holding the lock.
894 */
895 read_lock_bh(&ip_set_ref_lock);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100896 if (!attr[IPSET_ATTR_SETNAME]) {
897 for (i = 0; i < ip_set_max; i++) {
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000898 s = nfnl_set(i);
899 if (s != NULL && s->ref) {
Jozsef Kadlecsik9d883232011-06-16 18:57:44 +0200900 ret = -IPSET_ERR_BUSY;
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200901 goto out;
902 }
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100903 }
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200904 read_unlock_bh(&ip_set_ref_lock);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100905 for (i = 0; i < ip_set_max; i++) {
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000906 s = nfnl_set(i);
907 if (s != NULL)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100908 ip_set_destroy_set(i);
909 }
910 } else {
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000911 s = find_set_and_id(nla_data(attr[IPSET_ATTR_SETNAME]), &i);
912 if (s == NULL) {
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200913 ret = -ENOENT;
914 goto out;
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000915 } else if (s->ref) {
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200916 ret = -IPSET_ERR_BUSY;
917 goto out;
918 }
919 read_unlock_bh(&ip_set_ref_lock);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100920
921 ip_set_destroy_set(i);
922 }
923 return 0;
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200924out:
925 read_unlock_bh(&ip_set_ref_lock);
926 return ret;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100927}
928
929/* Flush sets */
930
931static void
932ip_set_flush_set(struct ip_set *set)
933{
934 pr_debug("set: %s\n", set->name);
935
936 write_lock_bh(&set->lock);
937 set->variant->flush(set);
938 write_unlock_bh(&set->lock);
939}
940
941static int
942ip_set_flush(struct sock *ctnl, struct sk_buff *skb,
943 const struct nlmsghdr *nlh,
944 const struct nlattr * const attr[])
945{
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000946 struct ip_set *s;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100947 ip_set_id_t i;
948
949 if (unlikely(protocol_failed(attr)))
Jozsef Kadlecsik9184a9c2011-05-24 10:20:19 +0200950 return -IPSET_ERR_PROTOCOL;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100951
952 if (!attr[IPSET_ATTR_SETNAME]) {
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000953 for (i = 0; i < ip_set_max; i++) {
954 s = nfnl_set(i);
955 if (s != NULL)
956 ip_set_flush_set(s);
957 }
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100958 } else {
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000959 s = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
960 if (s == NULL)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100961 return -ENOENT;
962
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000963 ip_set_flush_set(s);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100964 }
965
966 return 0;
967}
968
969/* Rename a set */
970
971static const struct nla_policy
972ip_set_setname2_policy[IPSET_ATTR_CMD_MAX + 1] = {
973 [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
974 [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING,
975 .len = IPSET_MAXNAMELEN - 1 },
976 [IPSET_ATTR_SETNAME2] = { .type = NLA_NUL_STRING,
977 .len = IPSET_MAXNAMELEN - 1 },
978};
979
980static int
981ip_set_rename(struct sock *ctnl, struct sk_buff *skb,
982 const struct nlmsghdr *nlh,
983 const struct nlattr * const attr[])
984{
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +0000985 struct ip_set *set, *s;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100986 const char *name2;
987 ip_set_id_t i;
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200988 int ret = 0;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100989
990 if (unlikely(protocol_failed(attr) ||
991 attr[IPSET_ATTR_SETNAME] == NULL ||
992 attr[IPSET_ATTR_SETNAME2] == NULL))
993 return -IPSET_ERR_PROTOCOL;
994
995 set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
996 if (set == NULL)
997 return -ENOENT;
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200998
999 read_lock_bh(&ip_set_ref_lock);
1000 if (set->ref != 0) {
1001 ret = -IPSET_ERR_REFERENCED;
1002 goto out;
1003 }
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001004
1005 name2 = nla_data(attr[IPSET_ATTR_SETNAME2]);
1006 for (i = 0; i < ip_set_max; i++) {
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001007 s = nfnl_set(i);
1008 if (s != NULL && STREQ(s->name, name2)) {
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +02001009 ret = -IPSET_ERR_EXIST_SETNAME2;
1010 goto out;
1011 }
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001012 }
1013 strncpy(set->name, name2, IPSET_MAXNAMELEN);
1014
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +02001015out:
1016 read_unlock_bh(&ip_set_ref_lock);
1017 return ret;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001018}
1019
1020/* Swap two sets so that name/index points to the other.
1021 * References and set names are also swapped.
1022 *
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +02001023 * The commands are serialized by the nfnl mutex and references are
1024 * protected by the ip_set_ref_lock. The kernel interfaces
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001025 * do not hold the mutex but the pointer settings are atomic
1026 * so the ip_set_list always contains valid pointers to the sets.
1027 */
1028
1029static int
1030ip_set_swap(struct sock *ctnl, struct sk_buff *skb,
1031 const struct nlmsghdr *nlh,
1032 const struct nlattr * const attr[])
1033{
1034 struct ip_set *from, *to;
1035 ip_set_id_t from_id, to_id;
1036 char from_name[IPSET_MAXNAMELEN];
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001037
1038 if (unlikely(protocol_failed(attr) ||
1039 attr[IPSET_ATTR_SETNAME] == NULL ||
1040 attr[IPSET_ATTR_SETNAME2] == NULL))
1041 return -IPSET_ERR_PROTOCOL;
1042
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001043 from = find_set_and_id(nla_data(attr[IPSET_ATTR_SETNAME]), &from_id);
1044 if (from == NULL)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001045 return -ENOENT;
1046
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001047 to = find_set_and_id(nla_data(attr[IPSET_ATTR_SETNAME2]), &to_id);
1048 if (to == NULL)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001049 return -IPSET_ERR_EXIST_SETNAME2;
1050
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001051 /* Features must not change.
Lucas De Marchi25985ed2011-03-30 22:57:33 -03001052 * Not an artificial restriction anymore, as we must prevent
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001053 * possible loops created by swapping in setlist type of sets. */
1054 if (!(from->type->features == to->type->features &&
1055 from->type->family == to->type->family))
1056 return -IPSET_ERR_TYPE_MISMATCH;
1057
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001058 strncpy(from_name, from->name, IPSET_MAXNAMELEN);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001059 strncpy(from->name, to->name, IPSET_MAXNAMELEN);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001060 strncpy(to->name, from_name, IPSET_MAXNAMELEN);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001061
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +02001062 write_lock_bh(&ip_set_ref_lock);
1063 swap(from->ref, to->ref);
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001064 nfnl_set(from_id) = to;
1065 nfnl_set(to_id) = from;
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +02001066 write_unlock_bh(&ip_set_ref_lock);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001067
1068 return 0;
1069}
1070
1071/* List/save set data */
1072
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001073#define DUMP_INIT 0
1074#define DUMP_ALL 1
1075#define DUMP_ONE 2
1076#define DUMP_LAST 3
1077
1078#define DUMP_TYPE(arg) (((u32)(arg)) & 0x0000FFFF)
1079#define DUMP_FLAGS(arg) (((u32)(arg)) >> 16)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001080
1081static int
1082ip_set_dump_done(struct netlink_callback *cb)
1083{
1084 if (cb->args[2]) {
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001085 pr_debug("release set %s\n", nfnl_set(cb->args[1])->name);
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +02001086 ip_set_put_byindex((ip_set_id_t) cb->args[1]);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001087 }
1088 return 0;
1089}
1090
1091static inline void
1092dump_attrs(struct nlmsghdr *nlh)
1093{
1094 const struct nlattr *attr;
1095 int rem;
1096
1097 pr_debug("dump nlmsg\n");
1098 nlmsg_for_each_attr(attr, nlh, sizeof(struct nfgenmsg), rem) {
1099 pr_debug("type: %u, len %u\n", nla_type(attr), attr->nla_len);
1100 }
1101}
1102
1103static int
1104dump_init(struct netlink_callback *cb)
1105{
1106 struct nlmsghdr *nlh = nlmsg_hdr(cb->skb);
Hong zhi guo573ce262013-03-27 06:47:04 +00001107 int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001108 struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
1109 struct nlattr *attr = (void *)nlh + min_len;
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001110 u32 dump_type;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001111 ip_set_id_t index;
1112
1113 /* Second pass, so parser can't fail */
1114 nla_parse(cda, IPSET_ATTR_CMD_MAX,
1115 attr, nlh->nlmsg_len - min_len, ip_set_setname_policy);
1116
1117 /* cb->args[0] : dump single set/all sets
1118 * [1] : set index
1119 * [..]: type specific
1120 */
1121
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001122 if (cda[IPSET_ATTR_SETNAME]) {
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001123 struct ip_set *set;
1124
1125 set = find_set_and_id(nla_data(cda[IPSET_ATTR_SETNAME]),
1126 &index);
1127 if (set == NULL)
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001128 return -ENOENT;
1129
1130 dump_type = DUMP_ONE;
1131 cb->args[1] = index;
1132 } else
1133 dump_type = DUMP_ALL;
1134
1135 if (cda[IPSET_ATTR_FLAGS]) {
1136 u32 f = ip_set_get_h32(cda[IPSET_ATTR_FLAGS]);
1137 dump_type |= (f << 16);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001138 }
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001139 cb->args[0] = dump_type;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001140
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001141 return 0;
1142}
1143
1144static int
1145ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
1146{
1147 ip_set_id_t index = IPSET_INVALID_ID, max;
1148 struct ip_set *set = NULL;
1149 struct nlmsghdr *nlh = NULL;
Eric W. Biederman15e47302012-09-07 20:12:54 +00001150 unsigned int flags = NETLINK_CB(cb->skb).portid ? NLM_F_MULTI : 0;
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001151 u32 dump_type, dump_flags;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001152 int ret = 0;
1153
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001154 if (!cb->args[0]) {
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001155 ret = dump_init(cb);
1156 if (ret < 0) {
1157 nlh = nlmsg_hdr(cb->skb);
1158 /* We have to create and send the error message
1159 * manually :-( */
1160 if (nlh->nlmsg_flags & NLM_F_ACK)
1161 netlink_ack(cb->skb, nlh, ret);
1162 return ret;
1163 }
1164 }
1165
1166 if (cb->args[1] >= ip_set_max)
1167 goto out;
1168
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001169 dump_type = DUMP_TYPE(cb->args[0]);
1170 dump_flags = DUMP_FLAGS(cb->args[0]);
1171 max = dump_type == DUMP_ONE ? cb->args[1] + 1 : ip_set_max;
Jozsef Kadlecsika8a8a092011-04-19 15:59:15 +02001172dump_last:
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001173 pr_debug("args[0]: %u %u args[1]: %ld\n",
1174 dump_type, dump_flags, cb->args[1]);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001175 for (; cb->args[1] < max; cb->args[1]++) {
1176 index = (ip_set_id_t) cb->args[1];
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001177 set = nfnl_set(index);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001178 if (set == NULL) {
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001179 if (dump_type == DUMP_ONE) {
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001180 ret = -ENOENT;
1181 goto out;
1182 }
1183 continue;
1184 }
1185 /* When dumping all sets, we must dump "sorted"
1186 * so that lists (unions of sets) are dumped last.
1187 */
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001188 if (dump_type != DUMP_ONE &&
1189 ((dump_type == DUMP_ALL) ==
Jozsef Kadlecsika8a8a092011-04-19 15:59:15 +02001190 !!(set->type->features & IPSET_DUMP_LAST)))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001191 continue;
1192 pr_debug("List set: %s\n", set->name);
1193 if (!cb->args[2]) {
1194 /* Start listing: make sure set won't be destroyed */
1195 pr_debug("reference set\n");
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001196 __ip_set_get(set);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001197 }
Eric W. Biederman15e47302012-09-07 20:12:54 +00001198 nlh = start_msg(skb, NETLINK_CB(cb->skb).portid,
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001199 cb->nlh->nlmsg_seq, flags,
1200 IPSET_CMD_LIST);
1201 if (!nlh) {
1202 ret = -EMSGSIZE;
1203 goto release_refcount;
1204 }
David S. Miller7cf78992012-04-01 19:54:46 -04001205 if (nla_put_u8(skb, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL) ||
1206 nla_put_string(skb, IPSET_ATTR_SETNAME, set->name))
1207 goto nla_put_failure;
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001208 if (dump_flags & IPSET_FLAG_LIST_SETNAME)
1209 goto next_set;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001210 switch (cb->args[2]) {
1211 case 0:
1212 /* Core header data */
David S. Miller7cf78992012-04-01 19:54:46 -04001213 if (nla_put_string(skb, IPSET_ATTR_TYPENAME,
1214 set->type->name) ||
1215 nla_put_u8(skb, IPSET_ATTR_FAMILY,
1216 set->family) ||
1217 nla_put_u8(skb, IPSET_ATTR_REVISION,
1218 set->revision))
1219 goto nla_put_failure;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001220 ret = set->variant->head(set, skb);
1221 if (ret < 0)
1222 goto release_refcount;
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001223 if (dump_flags & IPSET_FLAG_LIST_HEADER)
1224 goto next_set;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001225 /* Fall through and add elements */
1226 default:
1227 read_lock_bh(&set->lock);
1228 ret = set->variant->list(set, skb, cb);
1229 read_unlock_bh(&set->lock);
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001230 if (!cb->args[2])
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001231 /* Set is done, proceed with next one */
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001232 goto next_set;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001233 goto release_refcount;
1234 }
1235 }
Jozsef Kadlecsika8a8a092011-04-19 15:59:15 +02001236 /* If we dump all sets, continue with dumping last ones */
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001237 if (dump_type == DUMP_ALL) {
1238 dump_type = DUMP_LAST;
1239 cb->args[0] = dump_type | (dump_flags << 16);
Jozsef Kadlecsika8a8a092011-04-19 15:59:15 +02001240 cb->args[1] = 0;
1241 goto dump_last;
1242 }
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001243 goto out;
1244
1245nla_put_failure:
1246 ret = -EFAULT;
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001247next_set:
1248 if (dump_type == DUMP_ONE)
1249 cb->args[1] = IPSET_INVALID_ID;
1250 else
1251 cb->args[1]++;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001252release_refcount:
1253 /* If there was an error or set is done, release set */
1254 if (ret || !cb->args[2]) {
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001255 pr_debug("release set %s\n", nfnl_set(index)->name);
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +02001256 ip_set_put_byindex(index);
Jozsef Kadlecsikbe94db92012-01-14 16:42:13 +01001257 cb->args[2] = 0;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001258 }
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001259out:
1260 if (nlh) {
1261 nlmsg_end(skb, nlh);
1262 pr_debug("nlmsg_len: %u\n", nlh->nlmsg_len);
1263 dump_attrs(nlh);
1264 }
1265
1266 return ret < 0 ? ret : skb->len;
1267}
1268
1269static int
1270ip_set_dump(struct sock *ctnl, struct sk_buff *skb,
1271 const struct nlmsghdr *nlh,
1272 const struct nlattr * const attr[])
1273{
1274 if (unlikely(protocol_failed(attr)))
1275 return -IPSET_ERR_PROTOCOL;
1276
Pablo Neira Ayuso80d326f2012-02-24 14:30:15 +00001277 {
1278 struct netlink_dump_control c = {
1279 .dump = ip_set_dump_start,
1280 .done = ip_set_dump_done,
1281 };
1282 return netlink_dump_start(ctnl, skb, nlh, &c);
1283 }
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001284}
1285
1286/* Add, del and test */
1287
1288static const struct nla_policy ip_set_adt_policy[IPSET_ATTR_CMD_MAX + 1] = {
1289 [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
1290 [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING,
1291 .len = IPSET_MAXNAMELEN - 1 },
1292 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
1293 [IPSET_ATTR_DATA] = { .type = NLA_NESTED },
1294 [IPSET_ATTR_ADT] = { .type = NLA_NESTED },
1295};
1296
1297static int
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001298call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001299 struct nlattr *tb[], enum ipset_adt adt,
1300 u32 flags, bool use_lineno)
1301{
Jozsef Kadlecsik3d14b172011-06-16 18:49:17 +02001302 int ret;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001303 u32 lineno = 0;
Jozsef Kadlecsik3d14b172011-06-16 18:49:17 +02001304 bool eexist = flags & IPSET_FLAG_EXIST, retried = false;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001305
1306 do {
1307 write_lock_bh(&set->lock);
Jozsef Kadlecsik3d14b172011-06-16 18:49:17 +02001308 ret = set->variant->uadt(set, tb, adt, &lineno, flags, retried);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001309 write_unlock_bh(&set->lock);
Jozsef Kadlecsik3d14b172011-06-16 18:49:17 +02001310 retried = true;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001311 } while (ret == -EAGAIN &&
1312 set->variant->resize &&
Jozsef Kadlecsik3d14b172011-06-16 18:49:17 +02001313 (ret = set->variant->resize(set, retried)) == 0);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001314
1315 if (!ret || (ret == -IPSET_ERR_EXIST && eexist))
1316 return 0;
1317 if (lineno && use_lineno) {
1318 /* Error in restore/batch mode: send back lineno */
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001319 struct nlmsghdr *rep, *nlh = nlmsg_hdr(skb);
1320 struct sk_buff *skb2;
1321 struct nlmsgerr *errmsg;
1322 size_t payload = sizeof(*errmsg) + nlmsg_len(nlh);
Hong zhi guo573ce262013-03-27 06:47:04 +00001323 int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001324 struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001325 struct nlattr *cmdattr;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001326 u32 *errline;
1327
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001328 skb2 = nlmsg_new(payload, GFP_KERNEL);
1329 if (skb2 == NULL)
1330 return -ENOMEM;
Eric W. Biederman15e47302012-09-07 20:12:54 +00001331 rep = __nlmsg_put(skb2, NETLINK_CB(skb).portid,
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001332 nlh->nlmsg_seq, NLMSG_ERROR, payload, 0);
1333 errmsg = nlmsg_data(rep);
1334 errmsg->error = ret;
1335 memcpy(&errmsg->msg, nlh, nlh->nlmsg_len);
1336 cmdattr = (void *)&errmsg->msg + min_len;
1337
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001338 nla_parse(cda, IPSET_ATTR_CMD_MAX,
1339 cmdattr, nlh->nlmsg_len - min_len,
1340 ip_set_adt_policy);
1341
1342 errline = nla_data(cda[IPSET_ATTR_LINENO]);
1343
1344 *errline = lineno;
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001345
Eric W. Biederman15e47302012-09-07 20:12:54 +00001346 netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001347 /* Signal netlink not to send its ACK/errmsg. */
1348 return -EINTR;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001349 }
1350
1351 return ret;
1352}
1353
1354static int
1355ip_set_uadd(struct sock *ctnl, struct sk_buff *skb,
1356 const struct nlmsghdr *nlh,
1357 const struct nlattr * const attr[])
1358{
1359 struct ip_set *set;
1360 struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
1361 const struct nlattr *nla;
1362 u32 flags = flag_exist(nlh);
1363 bool use_lineno;
1364 int ret = 0;
1365
1366 if (unlikely(protocol_failed(attr) ||
1367 attr[IPSET_ATTR_SETNAME] == NULL ||
1368 !((attr[IPSET_ATTR_DATA] != NULL) ^
1369 (attr[IPSET_ATTR_ADT] != NULL)) ||
1370 (attr[IPSET_ATTR_DATA] != NULL &&
1371 !flag_nested(attr[IPSET_ATTR_DATA])) ||
1372 (attr[IPSET_ATTR_ADT] != NULL &&
1373 (!flag_nested(attr[IPSET_ATTR_ADT]) ||
1374 attr[IPSET_ATTR_LINENO] == NULL))))
1375 return -IPSET_ERR_PROTOCOL;
1376
1377 set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
1378 if (set == NULL)
1379 return -ENOENT;
1380
1381 use_lineno = !!attr[IPSET_ATTR_LINENO];
1382 if (attr[IPSET_ATTR_DATA]) {
Patrick McHardy8da560c2011-02-01 16:27:25 +01001383 if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX,
1384 attr[IPSET_ATTR_DATA],
1385 set->type->adt_policy))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001386 return -IPSET_ERR_PROTOCOL;
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001387 ret = call_ad(ctnl, skb, set, tb, IPSET_ADD, flags,
1388 use_lineno);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001389 } else {
1390 int nla_rem;
1391
1392 nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) {
1393 memset(tb, 0, sizeof(tb));
1394 if (nla_type(nla) != IPSET_ATTR_DATA ||
1395 !flag_nested(nla) ||
Patrick McHardy8da560c2011-02-01 16:27:25 +01001396 nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla,
1397 set->type->adt_policy))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001398 return -IPSET_ERR_PROTOCOL;
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001399 ret = call_ad(ctnl, skb, set, tb, IPSET_ADD,
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001400 flags, use_lineno);
1401 if (ret < 0)
1402 return ret;
1403 }
1404 }
1405 return ret;
1406}
1407
1408static int
1409ip_set_udel(struct sock *ctnl, struct sk_buff *skb,
1410 const struct nlmsghdr *nlh,
1411 const struct nlattr * const attr[])
1412{
1413 struct ip_set *set;
1414 struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
1415 const struct nlattr *nla;
1416 u32 flags = flag_exist(nlh);
1417 bool use_lineno;
1418 int ret = 0;
1419
1420 if (unlikely(protocol_failed(attr) ||
1421 attr[IPSET_ATTR_SETNAME] == NULL ||
1422 !((attr[IPSET_ATTR_DATA] != NULL) ^
1423 (attr[IPSET_ATTR_ADT] != NULL)) ||
1424 (attr[IPSET_ATTR_DATA] != NULL &&
1425 !flag_nested(attr[IPSET_ATTR_DATA])) ||
1426 (attr[IPSET_ATTR_ADT] != NULL &&
1427 (!flag_nested(attr[IPSET_ATTR_ADT]) ||
1428 attr[IPSET_ATTR_LINENO] == NULL))))
1429 return -IPSET_ERR_PROTOCOL;
1430
1431 set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
1432 if (set == NULL)
1433 return -ENOENT;
1434
1435 use_lineno = !!attr[IPSET_ATTR_LINENO];
1436 if (attr[IPSET_ATTR_DATA]) {
Patrick McHardy8da560c2011-02-01 16:27:25 +01001437 if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX,
1438 attr[IPSET_ATTR_DATA],
1439 set->type->adt_policy))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001440 return -IPSET_ERR_PROTOCOL;
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001441 ret = call_ad(ctnl, skb, set, tb, IPSET_DEL, flags,
1442 use_lineno);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001443 } else {
1444 int nla_rem;
1445
1446 nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) {
1447 memset(tb, 0, sizeof(*tb));
1448 if (nla_type(nla) != IPSET_ATTR_DATA ||
1449 !flag_nested(nla) ||
Patrick McHardy8da560c2011-02-01 16:27:25 +01001450 nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla,
1451 set->type->adt_policy))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001452 return -IPSET_ERR_PROTOCOL;
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001453 ret = call_ad(ctnl, skb, set, tb, IPSET_DEL,
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001454 flags, use_lineno);
1455 if (ret < 0)
1456 return ret;
1457 }
1458 }
1459 return ret;
1460}
1461
1462static int
1463ip_set_utest(struct sock *ctnl, struct sk_buff *skb,
1464 const struct nlmsghdr *nlh,
1465 const struct nlattr * const attr[])
1466{
1467 struct ip_set *set;
1468 struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
1469 int ret = 0;
1470
1471 if (unlikely(protocol_failed(attr) ||
1472 attr[IPSET_ATTR_SETNAME] == NULL ||
1473 attr[IPSET_ATTR_DATA] == NULL ||
1474 !flag_nested(attr[IPSET_ATTR_DATA])))
1475 return -IPSET_ERR_PROTOCOL;
1476
1477 set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
1478 if (set == NULL)
1479 return -ENOENT;
1480
Patrick McHardy8da560c2011-02-01 16:27:25 +01001481 if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, attr[IPSET_ATTR_DATA],
1482 set->type->adt_policy))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001483 return -IPSET_ERR_PROTOCOL;
1484
1485 read_lock_bh(&set->lock);
Jozsef Kadlecsik3d14b172011-06-16 18:49:17 +02001486 ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0, 0);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001487 read_unlock_bh(&set->lock);
1488 /* Userspace can't trigger element to be re-added */
1489 if (ret == -EAGAIN)
1490 ret = 1;
1491
Jozsef Kadlecsik0f1799b2013-09-16 20:04:53 +02001492 return ret > 0 ? 0 : -IPSET_ERR_EXIST;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001493}
1494
1495/* Get headed data of a set */
1496
1497static int
1498ip_set_header(struct sock *ctnl, struct sk_buff *skb,
1499 const struct nlmsghdr *nlh,
1500 const struct nlattr * const attr[])
1501{
1502 const struct ip_set *set;
1503 struct sk_buff *skb2;
1504 struct nlmsghdr *nlh2;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001505 int ret = 0;
1506
1507 if (unlikely(protocol_failed(attr) ||
1508 attr[IPSET_ATTR_SETNAME] == NULL))
1509 return -IPSET_ERR_PROTOCOL;
1510
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001511 set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
1512 if (set == NULL)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001513 return -ENOENT;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001514
1515 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1516 if (skb2 == NULL)
1517 return -ENOMEM;
1518
Eric W. Biederman15e47302012-09-07 20:12:54 +00001519 nlh2 = start_msg(skb2, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001520 IPSET_CMD_HEADER);
1521 if (!nlh2)
1522 goto nlmsg_failure;
David S. Miller7cf78992012-04-01 19:54:46 -04001523 if (nla_put_u8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL) ||
1524 nla_put_string(skb2, IPSET_ATTR_SETNAME, set->name) ||
1525 nla_put_string(skb2, IPSET_ATTR_TYPENAME, set->type->name) ||
1526 nla_put_u8(skb2, IPSET_ATTR_FAMILY, set->family) ||
1527 nla_put_u8(skb2, IPSET_ATTR_REVISION, set->revision))
1528 goto nla_put_failure;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001529 nlmsg_end(skb2, nlh2);
1530
Eric W. Biederman15e47302012-09-07 20:12:54 +00001531 ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001532 if (ret < 0)
1533 return ret;
1534
1535 return 0;
1536
1537nla_put_failure:
1538 nlmsg_cancel(skb2, nlh2);
1539nlmsg_failure:
1540 kfree_skb(skb2);
1541 return -EMSGSIZE;
1542}
1543
1544/* Get type data */
1545
1546static const struct nla_policy ip_set_type_policy[IPSET_ATTR_CMD_MAX + 1] = {
1547 [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
1548 [IPSET_ATTR_TYPENAME] = { .type = NLA_NUL_STRING,
1549 .len = IPSET_MAXNAMELEN - 1 },
1550 [IPSET_ATTR_FAMILY] = { .type = NLA_U8 },
1551};
1552
1553static int
1554ip_set_type(struct sock *ctnl, struct sk_buff *skb,
1555 const struct nlmsghdr *nlh,
1556 const struct nlattr * const attr[])
1557{
1558 struct sk_buff *skb2;
1559 struct nlmsghdr *nlh2;
1560 u8 family, min, max;
1561 const char *typename;
1562 int ret = 0;
1563
1564 if (unlikely(protocol_failed(attr) ||
1565 attr[IPSET_ATTR_TYPENAME] == NULL ||
1566 attr[IPSET_ATTR_FAMILY] == NULL))
1567 return -IPSET_ERR_PROTOCOL;
1568
1569 family = nla_get_u8(attr[IPSET_ATTR_FAMILY]);
1570 typename = nla_data(attr[IPSET_ATTR_TYPENAME]);
1571 ret = find_set_type_minmax(typename, family, &min, &max);
1572 if (ret)
1573 return ret;
1574
1575 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1576 if (skb2 == NULL)
1577 return -ENOMEM;
1578
Eric W. Biederman15e47302012-09-07 20:12:54 +00001579 nlh2 = start_msg(skb2, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001580 IPSET_CMD_TYPE);
1581 if (!nlh2)
1582 goto nlmsg_failure;
David S. Miller7cf78992012-04-01 19:54:46 -04001583 if (nla_put_u8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL) ||
1584 nla_put_string(skb2, IPSET_ATTR_TYPENAME, typename) ||
1585 nla_put_u8(skb2, IPSET_ATTR_FAMILY, family) ||
1586 nla_put_u8(skb2, IPSET_ATTR_REVISION, max) ||
1587 nla_put_u8(skb2, IPSET_ATTR_REVISION_MIN, min))
1588 goto nla_put_failure;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001589 nlmsg_end(skb2, nlh2);
1590
1591 pr_debug("Send TYPE, nlmsg_len: %u\n", nlh2->nlmsg_len);
Eric W. Biederman15e47302012-09-07 20:12:54 +00001592 ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001593 if (ret < 0)
1594 return ret;
1595
1596 return 0;
1597
1598nla_put_failure:
1599 nlmsg_cancel(skb2, nlh2);
1600nlmsg_failure:
1601 kfree_skb(skb2);
1602 return -EMSGSIZE;
1603}
1604
1605/* Get protocol version */
1606
1607static const struct nla_policy
1608ip_set_protocol_policy[IPSET_ATTR_CMD_MAX + 1] = {
1609 [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
1610};
1611
1612static int
1613ip_set_protocol(struct sock *ctnl, struct sk_buff *skb,
1614 const struct nlmsghdr *nlh,
1615 const struct nlattr * const attr[])
1616{
1617 struct sk_buff *skb2;
1618 struct nlmsghdr *nlh2;
1619 int ret = 0;
1620
1621 if (unlikely(attr[IPSET_ATTR_PROTOCOL] == NULL))
1622 return -IPSET_ERR_PROTOCOL;
1623
1624 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1625 if (skb2 == NULL)
1626 return -ENOMEM;
1627
Eric W. Biederman15e47302012-09-07 20:12:54 +00001628 nlh2 = start_msg(skb2, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001629 IPSET_CMD_PROTOCOL);
1630 if (!nlh2)
1631 goto nlmsg_failure;
David S. Miller7cf78992012-04-01 19:54:46 -04001632 if (nla_put_u8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL))
1633 goto nla_put_failure;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001634 nlmsg_end(skb2, nlh2);
1635
Eric W. Biederman15e47302012-09-07 20:12:54 +00001636 ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).portid, MSG_DONTWAIT);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001637 if (ret < 0)
1638 return ret;
1639
1640 return 0;
1641
1642nla_put_failure:
1643 nlmsg_cancel(skb2, nlh2);
1644nlmsg_failure:
1645 kfree_skb(skb2);
1646 return -EMSGSIZE;
1647}
1648
1649static const struct nfnl_callback ip_set_netlink_subsys_cb[IPSET_MSG_MAX] = {
Tomasz Bursztykad31f4d42012-06-28 02:57:48 +00001650 [IPSET_CMD_NONE] = {
1651 .call = ip_set_none,
1652 .attr_count = IPSET_ATTR_CMD_MAX,
1653 },
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001654 [IPSET_CMD_CREATE] = {
1655 .call = ip_set_create,
1656 .attr_count = IPSET_ATTR_CMD_MAX,
1657 .policy = ip_set_create_policy,
1658 },
1659 [IPSET_CMD_DESTROY] = {
1660 .call = ip_set_destroy,
1661 .attr_count = IPSET_ATTR_CMD_MAX,
1662 .policy = ip_set_setname_policy,
1663 },
1664 [IPSET_CMD_FLUSH] = {
1665 .call = ip_set_flush,
1666 .attr_count = IPSET_ATTR_CMD_MAX,
1667 .policy = ip_set_setname_policy,
1668 },
1669 [IPSET_CMD_RENAME] = {
1670 .call = ip_set_rename,
1671 .attr_count = IPSET_ATTR_CMD_MAX,
1672 .policy = ip_set_setname2_policy,
1673 },
1674 [IPSET_CMD_SWAP] = {
1675 .call = ip_set_swap,
1676 .attr_count = IPSET_ATTR_CMD_MAX,
1677 .policy = ip_set_setname2_policy,
1678 },
1679 [IPSET_CMD_LIST] = {
1680 .call = ip_set_dump,
1681 .attr_count = IPSET_ATTR_CMD_MAX,
1682 .policy = ip_set_setname_policy,
1683 },
1684 [IPSET_CMD_SAVE] = {
1685 .call = ip_set_dump,
1686 .attr_count = IPSET_ATTR_CMD_MAX,
1687 .policy = ip_set_setname_policy,
1688 },
1689 [IPSET_CMD_ADD] = {
1690 .call = ip_set_uadd,
1691 .attr_count = IPSET_ATTR_CMD_MAX,
1692 .policy = ip_set_adt_policy,
1693 },
1694 [IPSET_CMD_DEL] = {
1695 .call = ip_set_udel,
1696 .attr_count = IPSET_ATTR_CMD_MAX,
1697 .policy = ip_set_adt_policy,
1698 },
1699 [IPSET_CMD_TEST] = {
1700 .call = ip_set_utest,
1701 .attr_count = IPSET_ATTR_CMD_MAX,
1702 .policy = ip_set_adt_policy,
1703 },
1704 [IPSET_CMD_HEADER] = {
1705 .call = ip_set_header,
1706 .attr_count = IPSET_ATTR_CMD_MAX,
1707 .policy = ip_set_setname_policy,
1708 },
1709 [IPSET_CMD_TYPE] = {
1710 .call = ip_set_type,
1711 .attr_count = IPSET_ATTR_CMD_MAX,
1712 .policy = ip_set_type_policy,
1713 },
1714 [IPSET_CMD_PROTOCOL] = {
1715 .call = ip_set_protocol,
1716 .attr_count = IPSET_ATTR_CMD_MAX,
1717 .policy = ip_set_protocol_policy,
1718 },
1719};
1720
1721static struct nfnetlink_subsystem ip_set_netlink_subsys __read_mostly = {
1722 .name = "ip_set",
1723 .subsys_id = NFNL_SUBSYS_IPSET,
1724 .cb_count = IPSET_MSG_MAX,
1725 .cb = ip_set_netlink_subsys_cb,
1726};
1727
1728/* Interface to iptables/ip6tables */
1729
1730static int
1731ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
1732{
Eric Dumazet95c96172012-04-15 05:58:06 +00001733 unsigned int *op;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001734 void *data;
1735 int copylen = *len, ret = 0;
1736
Eric W. Biedermandf008c92012-11-16 03:03:07 +00001737 if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001738 return -EPERM;
1739 if (optval != SO_IP_SET)
1740 return -EBADF;
Eric Dumazet95c96172012-04-15 05:58:06 +00001741 if (*len < sizeof(unsigned int))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001742 return -EINVAL;
1743
1744 data = vmalloc(*len);
1745 if (!data)
1746 return -ENOMEM;
1747 if (copy_from_user(data, user, *len) != 0) {
1748 ret = -EFAULT;
1749 goto done;
1750 }
Eric Dumazet95c96172012-04-15 05:58:06 +00001751 op = (unsigned int *) data;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001752
1753 if (*op < IP_SET_OP_VERSION) {
1754 /* Check the version at the beginning of operations */
1755 struct ip_set_req_version *req_version = data;
1756 if (req_version->version != IPSET_PROTOCOL) {
1757 ret = -EPROTO;
1758 goto done;
1759 }
1760 }
1761
1762 switch (*op) {
1763 case IP_SET_OP_VERSION: {
1764 struct ip_set_req_version *req_version = data;
1765
1766 if (*len != sizeof(struct ip_set_req_version)) {
1767 ret = -EINVAL;
1768 goto done;
1769 }
1770
1771 req_version->version = IPSET_PROTOCOL;
1772 ret = copy_to_user(user, req_version,
1773 sizeof(struct ip_set_req_version));
1774 goto done;
1775 }
1776 case IP_SET_OP_GET_BYNAME: {
1777 struct ip_set_req_get_set *req_get = data;
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001778 ip_set_id_t id;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001779
1780 if (*len != sizeof(struct ip_set_req_get_set)) {
1781 ret = -EINVAL;
1782 goto done;
1783 }
1784 req_get->set.name[IPSET_MAXNAMELEN - 1] = '\0';
Pablo Neira Ayusoc14b78e2013-02-05 01:50:26 +01001785 nfnl_lock(NFNL_SUBSYS_IPSET);
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001786 find_set_and_id(req_get->set.name, &id);
1787 req_get->set.index = id;
Pablo Neira Ayusoc14b78e2013-02-05 01:50:26 +01001788 nfnl_unlock(NFNL_SUBSYS_IPSET);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001789 goto copy;
1790 }
1791 case IP_SET_OP_GET_BYINDEX: {
1792 struct ip_set_req_get_set *req_get = data;
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001793 struct ip_set *set;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001794
1795 if (*len != sizeof(struct ip_set_req_get_set) ||
1796 req_get->set.index >= ip_set_max) {
1797 ret = -EINVAL;
1798 goto done;
1799 }
Pablo Neira Ayusoc14b78e2013-02-05 01:50:26 +01001800 nfnl_lock(NFNL_SUBSYS_IPSET);
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001801 set = nfnl_set(req_get->set.index);
1802 strncpy(req_get->set.name, set ? set->name : "",
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001803 IPSET_MAXNAMELEN);
Pablo Neira Ayusoc14b78e2013-02-05 01:50:26 +01001804 nfnl_unlock(NFNL_SUBSYS_IPSET);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001805 goto copy;
1806 }
1807 default:
1808 ret = -EBADMSG;
1809 goto done;
1810 } /* end of switch(op) */
1811
1812copy:
1813 ret = copy_to_user(user, data, copylen);
1814
1815done:
1816 vfree(data);
1817 if (ret > 0)
1818 ret = 0;
1819 return ret;
1820}
1821
1822static struct nf_sockopt_ops so_set __read_mostly = {
1823 .pf = PF_INET,
1824 .get_optmin = SO_IP_SET,
1825 .get_optmax = SO_IP_SET + 1,
1826 .get = &ip_set_sockfn_get,
1827 .owner = THIS_MODULE,
1828};
1829
1830static int __init
1831ip_set_init(void)
1832{
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001833 struct ip_set **list;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001834 int ret;
1835
1836 if (max_sets)
1837 ip_set_max = max_sets;
1838 if (ip_set_max >= IPSET_INVALID_ID)
1839 ip_set_max = IPSET_INVALID_ID - 1;
1840
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001841 list = kzalloc(sizeof(struct ip_set *) * ip_set_max, GFP_KERNEL);
1842 if (!list)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001843 return -ENOMEM;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001844
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001845 rcu_assign_pointer(ip_set_list, list);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001846 ret = nfnetlink_subsys_register(&ip_set_netlink_subsys);
1847 if (ret != 0) {
1848 pr_err("ip_set: cannot register with nfnetlink.\n");
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001849 kfree(list);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001850 return ret;
1851 }
1852 ret = nf_register_sockopt(&so_set);
1853 if (ret != 0) {
1854 pr_err("SO_SET registry failed: %d\n", ret);
1855 nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001856 kfree(list);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001857 return ret;
1858 }
1859
1860 pr_notice("ip_set: protocol %u\n", IPSET_PROTOCOL);
1861 return 0;
1862}
1863
1864static void __exit
1865ip_set_fini(void)
1866{
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001867 struct ip_set **list = rcu_dereference_protected(ip_set_list, 1);
1868
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001869 /* There can't be any existing set */
1870 nf_unregister_sockopt(&so_set);
1871 nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
Jozsef Kadlecsik9076aea2012-11-27 09:58:09 +00001872 kfree(list);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001873 pr_debug("these are the famous last words\n");
1874}
1875
1876module_init(ip_set_init);
1877module_exit(ip_set_fini);