blob: 8446c7d81898d7d71a93c3aae59aef34c5f11587 [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>
3 * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
4 *
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>
18#include <linux/netlink.h>
19#include <linux/rculist.h>
20#include <linux/version.h>
21#include <net/netlink.h>
22
23#include <linux/netfilter.h>
24#include <linux/netfilter/nfnetlink.h>
25#include <linux/netfilter/ipset/ip_set.h>
26
27static LIST_HEAD(ip_set_type_list); /* all registered set types */
28static DEFINE_MUTEX(ip_set_type_mutex); /* protects ip_set_type_list */
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +020029static DEFINE_RWLOCK(ip_set_ref_lock); /* protects the set refs */
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +010030
31static struct ip_set **ip_set_list; /* all individual sets */
32static ip_set_id_t ip_set_max = CONFIG_IP_SET_MAX; /* max number of sets */
33
34#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
45/*
46 * The set types are implemented in modules and registered set types
47 * can be found in ip_set_type_list. Adding/deleting types is
48 * serialized by ip_set_type_mutex.
49 */
50
51static inline void
52ip_set_type_lock(void)
53{
54 mutex_lock(&ip_set_type_mutex);
55}
56
57static inline void
58ip_set_type_unlock(void)
59{
60 mutex_unlock(&ip_set_type_mutex);
61}
62
63/* Register and deregister settype */
64
65static struct ip_set_type *
66find_set_type(const char *name, u8 family, u8 revision)
67{
68 struct ip_set_type *type;
69
70 list_for_each_entry_rcu(type, &ip_set_type_list, list)
71 if (STREQ(type->name, name) &&
72 (type->family == family || type->family == AF_UNSPEC) &&
73 type->revision == revision)
74 return type;
75 return NULL;
76}
77
78/* Unlock, try to load a set type module and lock again */
79static int
80try_to_load_type(const char *name)
81{
82 nfnl_unlock();
83 pr_debug("try to load ip_set_%s\n", name);
84 if (request_module("ip_set_%s", name) < 0) {
85 pr_warning("Can't find ip_set type %s\n", name);
86 nfnl_lock();
87 return -IPSET_ERR_FIND_TYPE;
88 }
89 nfnl_lock();
90 return -EAGAIN;
91}
92
93/* Find a set type and reference it */
94static int
95find_set_type_get(const char *name, u8 family, u8 revision,
96 struct ip_set_type **found)
97{
Jozsef Kadlecsik5c1aba42011-03-20 15:35:01 +010098 struct ip_set_type *type;
99 int err;
100
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100101 rcu_read_lock();
102 *found = find_set_type(name, family, revision);
103 if (*found) {
Jozsef Kadlecsik5c1aba42011-03-20 15:35:01 +0100104 err = !try_module_get((*found)->me) ? -EFAULT : 0;
105 goto unlock;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100106 }
Jozsef Kadlecsik5c1aba42011-03-20 15:35:01 +0100107 /* Make sure the type is loaded but we don't support the revision */
108 list_for_each_entry_rcu(type, &ip_set_type_list, list)
109 if (STREQ(type->name, name)) {
110 err = -IPSET_ERR_FIND_TYPE;
111 goto unlock;
112 }
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100113 rcu_read_unlock();
114
115 return try_to_load_type(name);
Jozsef Kadlecsik5c1aba42011-03-20 15:35:01 +0100116
117unlock:
118 rcu_read_unlock();
119 return err;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100120}
121
122/* Find a given set type by name and family.
123 * If we succeeded, the supported minimal and maximum revisions are
124 * filled out.
125 */
126static int
127find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
128{
129 struct ip_set_type *type;
130 bool found = false;
131
Jozsef Kadlecsik5c1aba42011-03-20 15:35:01 +0100132 *min = 255; *max = 0;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100133 rcu_read_lock();
134 list_for_each_entry_rcu(type, &ip_set_type_list, list)
135 if (STREQ(type->name, name) &&
136 (type->family == family || type->family == AF_UNSPEC)) {
137 found = true;
138 if (type->revision < *min)
139 *min = type->revision;
Jozsef Kadlecsik5c1aba42011-03-20 15:35:01 +0100140 if (type->revision > *max)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100141 *max = type->revision;
142 }
143 rcu_read_unlock();
144 if (found)
145 return 0;
146
147 return try_to_load_type(name);
148}
149
150#define family_name(f) ((f) == AF_INET ? "inet" : \
151 (f) == AF_INET6 ? "inet6" : "any")
152
153/* Register a set type structure. The type is identified by
154 * the unique triple of name, family and revision.
155 */
156int
157ip_set_type_register(struct ip_set_type *type)
158{
159 int ret = 0;
160
161 if (type->protocol != IPSET_PROTOCOL) {
162 pr_warning("ip_set type %s, family %s, revision %u uses "
163 "wrong protocol version %u (want %u)\n",
164 type->name, family_name(type->family),
165 type->revision, type->protocol, IPSET_PROTOCOL);
166 return -EINVAL;
167 }
168
169 ip_set_type_lock();
170 if (find_set_type(type->name, type->family, type->revision)) {
171 /* Duplicate! */
172 pr_warning("ip_set type %s, family %s, revision %u "
173 "already registered!\n", type->name,
174 family_name(type->family), type->revision);
175 ret = -EINVAL;
176 goto unlock;
177 }
178 list_add_rcu(&type->list, &ip_set_type_list);
179 pr_debug("type %s, family %s, revision %u registered.\n",
180 type->name, family_name(type->family), type->revision);
181unlock:
182 ip_set_type_unlock();
183 return ret;
184}
185EXPORT_SYMBOL_GPL(ip_set_type_register);
186
187/* Unregister a set type. There's a small race with ip_set_create */
188void
189ip_set_type_unregister(struct ip_set_type *type)
190{
191 ip_set_type_lock();
192 if (!find_set_type(type->name, type->family, type->revision)) {
193 pr_warning("ip_set type %s, family %s, revision %u "
194 "not registered\n", type->name,
195 family_name(type->family), type->revision);
196 goto unlock;
197 }
198 list_del_rcu(&type->list);
199 pr_debug("type %s, family %s, revision %u unregistered.\n",
200 type->name, family_name(type->family), type->revision);
201unlock:
202 ip_set_type_unlock();
203
204 synchronize_rcu();
205}
206EXPORT_SYMBOL_GPL(ip_set_type_unregister);
207
208/* Utility functions */
209void *
210ip_set_alloc(size_t size)
211{
212 void *members = NULL;
213
214 if (size < KMALLOC_MAX_SIZE)
215 members = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
216
217 if (members) {
218 pr_debug("%p: allocated with kmalloc\n", members);
219 return members;
220 }
221
222 members = vzalloc(size);
223 if (!members)
224 return NULL;
225 pr_debug("%p: allocated with vmalloc\n", members);
226
227 return members;
228}
229EXPORT_SYMBOL_GPL(ip_set_alloc);
230
231void
232ip_set_free(void *members)
233{
234 pr_debug("%p: free with %s\n", members,
235 is_vmalloc_addr(members) ? "vfree" : "kfree");
236 if (is_vmalloc_addr(members))
237 vfree(members);
238 else
239 kfree(members);
240}
241EXPORT_SYMBOL_GPL(ip_set_free);
242
243static inline bool
244flag_nested(const struct nlattr *nla)
245{
246 return nla->nla_type & NLA_F_NESTED;
247}
248
249static const struct nla_policy ipaddr_policy[IPSET_ATTR_IPADDR_MAX + 1] = {
250 [IPSET_ATTR_IPADDR_IPV4] = { .type = NLA_U32 },
251 [IPSET_ATTR_IPADDR_IPV6] = { .type = NLA_BINARY,
252 .len = sizeof(struct in6_addr) },
253};
254
255int
256ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr)
257{
258 struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1];
259
260 if (unlikely(!flag_nested(nla)))
261 return -IPSET_ERR_PROTOCOL;
Patrick McHardy8da560c2011-02-01 16:27:25 +0100262 if (nla_parse_nested(tb, IPSET_ATTR_IPADDR_MAX, nla, ipaddr_policy))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100263 return -IPSET_ERR_PROTOCOL;
264 if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV4)))
265 return -IPSET_ERR_PROTOCOL;
266
267 *ipaddr = nla_get_be32(tb[IPSET_ATTR_IPADDR_IPV4]);
268 return 0;
269}
270EXPORT_SYMBOL_GPL(ip_set_get_ipaddr4);
271
272int
273ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr)
274{
275 struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1];
276
277 if (unlikely(!flag_nested(nla)))
278 return -IPSET_ERR_PROTOCOL;
279
Patrick McHardy8da560c2011-02-01 16:27:25 +0100280 if (nla_parse_nested(tb, IPSET_ATTR_IPADDR_MAX, nla, ipaddr_policy))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100281 return -IPSET_ERR_PROTOCOL;
282 if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV6)))
283 return -IPSET_ERR_PROTOCOL;
284
285 memcpy(ipaddr, nla_data(tb[IPSET_ATTR_IPADDR_IPV6]),
286 sizeof(struct in6_addr));
287 return 0;
288}
289EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6);
290
291/*
292 * Creating/destroying/renaming/swapping affect the existence and
293 * the properties of a set. All of these can be executed from userspace
294 * only and serialized by the nfnl mutex indirectly from nfnetlink.
295 *
296 * Sets are identified by their index in ip_set_list and the index
297 * is used by the external references (set/SET netfilter modules).
298 *
299 * The set behind an index may change by swapping only, from userspace.
300 */
301
302static inline void
303__ip_set_get(ip_set_id_t index)
304{
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200305 write_lock_bh(&ip_set_ref_lock);
306 ip_set_list[index]->ref++;
307 write_unlock_bh(&ip_set_ref_lock);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100308}
309
310static inline void
311__ip_set_put(ip_set_id_t index)
312{
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200313 write_lock_bh(&ip_set_ref_lock);
314 BUG_ON(ip_set_list[index]->ref == 0);
315 ip_set_list[index]->ref--;
316 write_unlock_bh(&ip_set_ref_lock);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100317}
318
319/*
320 * Add, del and test set entries from kernel.
321 *
322 * The set behind the index must exist and must be referenced
323 * so it can't be destroyed (or changed) under our foot.
324 */
325
326int
327ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
Jozsef Kadlecsikac8cc922011-06-16 18:42:40 +0200328 const struct ip_set_adt_opt *opt)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100329{
330 struct ip_set *set = ip_set_list[index];
331 int ret = 0;
332
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200333 BUG_ON(set == NULL);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100334 pr_debug("set %s, index %u\n", set->name, index);
335
Jozsef Kadlecsikac8cc922011-06-16 18:42:40 +0200336 if (opt->dim < set->type->dimension ||
337 !(opt->family == set->family || set->family == AF_UNSPEC))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100338 return 0;
339
340 read_lock_bh(&set->lock);
Jozsef Kadlecsikac8cc922011-06-16 18:42:40 +0200341 ret = set->variant->kadt(set, skb, IPSET_TEST, opt);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100342 read_unlock_bh(&set->lock);
343
344 if (ret == -EAGAIN) {
345 /* Type requests element to be completed */
346 pr_debug("element must be competed, ADD is triggered\n");
347 write_lock_bh(&set->lock);
Jozsef Kadlecsikac8cc922011-06-16 18:42:40 +0200348 set->variant->kadt(set, skb, IPSET_ADD, opt);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100349 write_unlock_bh(&set->lock);
350 ret = 1;
351 }
352
353 /* Convert error codes to nomatch */
354 return (ret < 0 ? 0 : ret);
355}
356EXPORT_SYMBOL_GPL(ip_set_test);
357
358int
359ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
Jozsef Kadlecsikac8cc922011-06-16 18:42:40 +0200360 const struct ip_set_adt_opt *opt)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100361{
362 struct ip_set *set = ip_set_list[index];
363 int ret;
364
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200365 BUG_ON(set == NULL);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100366 pr_debug("set %s, index %u\n", set->name, index);
367
Jozsef Kadlecsikac8cc922011-06-16 18:42:40 +0200368 if (opt->dim < set->type->dimension ||
369 !(opt->family == set->family || set->family == AF_UNSPEC))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100370 return 0;
371
372 write_lock_bh(&set->lock);
Jozsef Kadlecsikac8cc922011-06-16 18:42:40 +0200373 ret = set->variant->kadt(set, skb, IPSET_ADD, opt);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100374 write_unlock_bh(&set->lock);
375
376 return ret;
377}
378EXPORT_SYMBOL_GPL(ip_set_add);
379
380int
381ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
Jozsef Kadlecsikac8cc922011-06-16 18:42:40 +0200382 const struct ip_set_adt_opt *opt)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100383{
384 struct ip_set *set = ip_set_list[index];
385 int ret = 0;
386
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200387 BUG_ON(set == NULL);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100388 pr_debug("set %s, index %u\n", set->name, index);
389
Jozsef Kadlecsikac8cc922011-06-16 18:42:40 +0200390 if (opt->dim < set->type->dimension ||
391 !(opt->family == set->family || set->family == AF_UNSPEC))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100392 return 0;
393
394 write_lock_bh(&set->lock);
Jozsef Kadlecsikac8cc922011-06-16 18:42:40 +0200395 ret = set->variant->kadt(set, skb, IPSET_DEL, opt);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100396 write_unlock_bh(&set->lock);
397
398 return ret;
399}
400EXPORT_SYMBOL_GPL(ip_set_del);
401
402/*
403 * Find set by name, reference it once. The reference makes sure the
404 * thing pointed to, does not go away under our feet.
405 *
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100406 */
407ip_set_id_t
408ip_set_get_byname(const char *name, struct ip_set **set)
409{
410 ip_set_id_t i, index = IPSET_INVALID_ID;
411 struct ip_set *s;
412
413 for (i = 0; i < ip_set_max; i++) {
414 s = ip_set_list[i];
415 if (s != NULL && STREQ(s->name, name)) {
416 __ip_set_get(i);
417 index = i;
418 *set = s;
419 }
420 }
421
422 return index;
423}
424EXPORT_SYMBOL_GPL(ip_set_get_byname);
425
426/*
427 * If the given set pointer points to a valid set, decrement
428 * reference count by 1. The caller shall not assume the index
429 * to be valid, after calling this function.
430 *
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100431 */
432void
433ip_set_put_byindex(ip_set_id_t index)
434{
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200435 if (ip_set_list[index] != NULL)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100436 __ip_set_put(index);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100437}
438EXPORT_SYMBOL_GPL(ip_set_put_byindex);
439
440/*
441 * Get the name of a set behind a set index.
442 * We assume the set is referenced, so it does exist and
443 * can't be destroyed. The set cannot be renamed due to
444 * the referencing either.
445 *
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100446 */
447const char *
448ip_set_name_byindex(ip_set_id_t index)
449{
450 const struct ip_set *set = ip_set_list[index];
451
452 BUG_ON(set == NULL);
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200453 BUG_ON(set->ref == 0);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100454
455 /* Referenced, so it's safe */
456 return set->name;
457}
458EXPORT_SYMBOL_GPL(ip_set_name_byindex);
459
460/*
461 * Routines to call by external subsystems, which do not
462 * call nfnl_lock for us.
463 */
464
465/*
466 * Find set by name, reference it once. The reference makes sure the
467 * thing pointed to, does not go away under our feet.
468 *
469 * The nfnl mutex is used in the function.
470 */
471ip_set_id_t
472ip_set_nfnl_get(const char *name)
473{
474 struct ip_set *s;
475 ip_set_id_t index;
476
477 nfnl_lock();
478 index = ip_set_get_byname(name, &s);
479 nfnl_unlock();
480
481 return index;
482}
483EXPORT_SYMBOL_GPL(ip_set_nfnl_get);
484
485/*
486 * Find set by index, reference it once. The reference makes sure the
487 * thing pointed to, does not go away under our feet.
488 *
489 * The nfnl mutex is used in the function.
490 */
491ip_set_id_t
492ip_set_nfnl_get_byindex(ip_set_id_t index)
493{
494 if (index > ip_set_max)
495 return IPSET_INVALID_ID;
496
497 nfnl_lock();
498 if (ip_set_list[index])
499 __ip_set_get(index);
500 else
501 index = IPSET_INVALID_ID;
502 nfnl_unlock();
503
504 return index;
505}
506EXPORT_SYMBOL_GPL(ip_set_nfnl_get_byindex);
507
508/*
509 * If the given set pointer points to a valid set, decrement
510 * reference count by 1. The caller shall not assume the index
511 * to be valid, after calling this function.
512 *
513 * The nfnl mutex is used in the function.
514 */
515void
516ip_set_nfnl_put(ip_set_id_t index)
517{
518 nfnl_lock();
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200519 ip_set_put_byindex(index);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100520 nfnl_unlock();
521}
522EXPORT_SYMBOL_GPL(ip_set_nfnl_put);
523
524/*
525 * Communication protocol with userspace over netlink.
526 *
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200527 * The commands are serialized by the nfnl mutex.
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100528 */
529
530static inline bool
531protocol_failed(const struct nlattr * const tb[])
532{
533 return !tb[IPSET_ATTR_PROTOCOL] ||
534 nla_get_u8(tb[IPSET_ATTR_PROTOCOL]) != IPSET_PROTOCOL;
535}
536
537static inline u32
538flag_exist(const struct nlmsghdr *nlh)
539{
540 return nlh->nlmsg_flags & NLM_F_EXCL ? 0 : IPSET_FLAG_EXIST;
541}
542
543static struct nlmsghdr *
544start_msg(struct sk_buff *skb, u32 pid, u32 seq, unsigned int flags,
545 enum ipset_cmd cmd)
546{
547 struct nlmsghdr *nlh;
548 struct nfgenmsg *nfmsg;
549
550 nlh = nlmsg_put(skb, pid, seq, cmd | (NFNL_SUBSYS_IPSET << 8),
551 sizeof(*nfmsg), flags);
552 if (nlh == NULL)
553 return NULL;
554
555 nfmsg = nlmsg_data(nlh);
556 nfmsg->nfgen_family = AF_INET;
557 nfmsg->version = NFNETLINK_V0;
558 nfmsg->res_id = 0;
559
560 return nlh;
561}
562
563/* Create a set */
564
565static const struct nla_policy ip_set_create_policy[IPSET_ATTR_CMD_MAX + 1] = {
566 [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
567 [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING,
568 .len = IPSET_MAXNAMELEN - 1 },
569 [IPSET_ATTR_TYPENAME] = { .type = NLA_NUL_STRING,
570 .len = IPSET_MAXNAMELEN - 1},
571 [IPSET_ATTR_REVISION] = { .type = NLA_U8 },
572 [IPSET_ATTR_FAMILY] = { .type = NLA_U8 },
573 [IPSET_ATTR_DATA] = { .type = NLA_NESTED },
574};
575
576static ip_set_id_t
577find_set_id(const char *name)
578{
579 ip_set_id_t i, index = IPSET_INVALID_ID;
580 const struct ip_set *set;
581
582 for (i = 0; index == IPSET_INVALID_ID && i < ip_set_max; i++) {
583 set = ip_set_list[i];
584 if (set != NULL && STREQ(set->name, name))
585 index = i;
586 }
587 return index;
588}
589
590static inline struct ip_set *
591find_set(const char *name)
592{
593 ip_set_id_t index = find_set_id(name);
594
595 return index == IPSET_INVALID_ID ? NULL : ip_set_list[index];
596}
597
598static int
599find_free_id(const char *name, ip_set_id_t *index, struct ip_set **set)
600{
601 ip_set_id_t i;
602
603 *index = IPSET_INVALID_ID;
604 for (i = 0; i < ip_set_max; i++) {
605 if (ip_set_list[i] == NULL) {
606 if (*index == IPSET_INVALID_ID)
607 *index = i;
608 } else if (STREQ(name, ip_set_list[i]->name)) {
609 /* Name clash */
610 *set = ip_set_list[i];
611 return -EEXIST;
612 }
613 }
614 if (*index == IPSET_INVALID_ID)
615 /* No free slot remained */
616 return -IPSET_ERR_MAX_SETS;
617 return 0;
618}
619
620static int
621ip_set_create(struct sock *ctnl, struct sk_buff *skb,
622 const struct nlmsghdr *nlh,
623 const struct nlattr * const attr[])
624{
Shan Wei9846ada2011-03-08 15:37:27 +0100625 struct ip_set *set, *clash = NULL;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100626 ip_set_id_t index = IPSET_INVALID_ID;
627 struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1] = {};
628 const char *name, *typename;
629 u8 family, revision;
630 u32 flags = flag_exist(nlh);
631 int ret = 0;
632
633 if (unlikely(protocol_failed(attr) ||
634 attr[IPSET_ATTR_SETNAME] == NULL ||
635 attr[IPSET_ATTR_TYPENAME] == NULL ||
636 attr[IPSET_ATTR_REVISION] == NULL ||
637 attr[IPSET_ATTR_FAMILY] == NULL ||
638 (attr[IPSET_ATTR_DATA] != NULL &&
639 !flag_nested(attr[IPSET_ATTR_DATA]))))
640 return -IPSET_ERR_PROTOCOL;
641
642 name = nla_data(attr[IPSET_ATTR_SETNAME]);
643 typename = nla_data(attr[IPSET_ATTR_TYPENAME]);
644 family = nla_get_u8(attr[IPSET_ATTR_FAMILY]);
645 revision = nla_get_u8(attr[IPSET_ATTR_REVISION]);
646 pr_debug("setname: %s, typename: %s, family: %s, revision: %u\n",
647 name, typename, family_name(family), revision);
648
649 /*
650 * First, and without any locks, allocate and initialize
651 * a normal base set structure.
652 */
653 set = kzalloc(sizeof(struct ip_set), GFP_KERNEL);
654 if (!set)
655 return -ENOMEM;
656 rwlock_init(&set->lock);
657 strlcpy(set->name, name, IPSET_MAXNAMELEN);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100658 set->family = family;
659
660 /*
661 * Next, check that we know the type, and take
662 * a reference on the type, to make sure it stays available
663 * while constructing our new set.
664 *
665 * After referencing the type, we try to create the type
666 * specific part of the set without holding any locks.
667 */
668 ret = find_set_type_get(typename, family, revision, &(set->type));
669 if (ret)
670 goto out;
671
672 /*
673 * Without holding any locks, create private part.
674 */
675 if (attr[IPSET_ATTR_DATA] &&
Patrick McHardy8da560c2011-02-01 16:27:25 +0100676 nla_parse_nested(tb, IPSET_ATTR_CREATE_MAX, attr[IPSET_ATTR_DATA],
677 set->type->create_policy)) {
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100678 ret = -IPSET_ERR_PROTOCOL;
679 goto put_out;
680 }
681
682 ret = set->type->create(set, tb, flags);
683 if (ret != 0)
684 goto put_out;
685
686 /* BTW, ret==0 here. */
687
688 /*
689 * Here, we have a valid, constructed set and we are protected
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200690 * by the nfnl mutex. Find the first free index in ip_set_list
691 * and check clashing.
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100692 */
693 if ((ret = find_free_id(set->name, &index, &clash)) != 0) {
694 /* If this is the same set and requested, ignore error */
695 if (ret == -EEXIST &&
696 (flags & IPSET_FLAG_EXIST) &&
697 STREQ(set->type->name, clash->type->name) &&
698 set->type->family == clash->type->family &&
699 set->type->revision == clash->type->revision &&
700 set->variant->same_set(set, clash))
701 ret = 0;
702 goto cleanup;
703 }
704
705 /*
706 * Finally! Add our shiny new set to the list, and be done.
707 */
708 pr_debug("create: '%s' created with index %u!\n", set->name, index);
709 ip_set_list[index] = set;
710
711 return ret;
712
713cleanup:
714 set->variant->destroy(set);
715put_out:
716 module_put(set->type->me);
717out:
718 kfree(set);
719 return ret;
720}
721
722/* Destroy sets */
723
724static const struct nla_policy
725ip_set_setname_policy[IPSET_ATTR_CMD_MAX + 1] = {
726 [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
727 [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING,
728 .len = IPSET_MAXNAMELEN - 1 },
729};
730
731static void
732ip_set_destroy_set(ip_set_id_t index)
733{
734 struct ip_set *set = ip_set_list[index];
735
736 pr_debug("set: %s\n", set->name);
737 ip_set_list[index] = NULL;
738
739 /* Must call it without holding any lock */
740 set->variant->destroy(set);
741 module_put(set->type->me);
742 kfree(set);
743}
744
745static int
746ip_set_destroy(struct sock *ctnl, struct sk_buff *skb,
747 const struct nlmsghdr *nlh,
748 const struct nlattr * const attr[])
749{
750 ip_set_id_t i;
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200751 int ret = 0;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100752
753 if (unlikely(protocol_failed(attr)))
754 return -IPSET_ERR_PROTOCOL;
755
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200756 /* Commands are serialized and references are
757 * protected by the ip_set_ref_lock.
758 * External systems (i.e. xt_set) must call
759 * ip_set_put|get_nfnl_* functions, that way we
760 * can safely check references here.
761 *
762 * list:set timer can only decrement the reference
763 * counter, so if it's already zero, we can proceed
764 * without holding the lock.
765 */
766 read_lock_bh(&ip_set_ref_lock);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100767 if (!attr[IPSET_ATTR_SETNAME]) {
768 for (i = 0; i < ip_set_max; i++) {
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200769 if (ip_set_list[i] != NULL && ip_set_list[i]->ref) {
770 ret = IPSET_ERR_BUSY;
771 goto out;
772 }
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100773 }
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200774 read_unlock_bh(&ip_set_ref_lock);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100775 for (i = 0; i < ip_set_max; i++) {
776 if (ip_set_list[i] != NULL)
777 ip_set_destroy_set(i);
778 }
779 } else {
780 i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200781 if (i == IPSET_INVALID_ID) {
782 ret = -ENOENT;
783 goto out;
784 } else if (ip_set_list[i]->ref) {
785 ret = -IPSET_ERR_BUSY;
786 goto out;
787 }
788 read_unlock_bh(&ip_set_ref_lock);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100789
790 ip_set_destroy_set(i);
791 }
792 return 0;
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200793out:
794 read_unlock_bh(&ip_set_ref_lock);
795 return ret;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100796}
797
798/* Flush sets */
799
800static void
801ip_set_flush_set(struct ip_set *set)
802{
803 pr_debug("set: %s\n", set->name);
804
805 write_lock_bh(&set->lock);
806 set->variant->flush(set);
807 write_unlock_bh(&set->lock);
808}
809
810static int
811ip_set_flush(struct sock *ctnl, struct sk_buff *skb,
812 const struct nlmsghdr *nlh,
813 const struct nlattr * const attr[])
814{
815 ip_set_id_t i;
816
817 if (unlikely(protocol_failed(attr)))
Jozsef Kadlecsik9184a9c2011-05-24 10:20:19 +0200818 return -IPSET_ERR_PROTOCOL;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100819
820 if (!attr[IPSET_ATTR_SETNAME]) {
821 for (i = 0; i < ip_set_max; i++)
822 if (ip_set_list[i] != NULL)
823 ip_set_flush_set(ip_set_list[i]);
824 } else {
825 i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
826 if (i == IPSET_INVALID_ID)
827 return -ENOENT;
828
829 ip_set_flush_set(ip_set_list[i]);
830 }
831
832 return 0;
833}
834
835/* Rename a set */
836
837static const struct nla_policy
838ip_set_setname2_policy[IPSET_ATTR_CMD_MAX + 1] = {
839 [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
840 [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING,
841 .len = IPSET_MAXNAMELEN - 1 },
842 [IPSET_ATTR_SETNAME2] = { .type = NLA_NUL_STRING,
843 .len = IPSET_MAXNAMELEN - 1 },
844};
845
846static int
847ip_set_rename(struct sock *ctnl, struct sk_buff *skb,
848 const struct nlmsghdr *nlh,
849 const struct nlattr * const attr[])
850{
851 struct ip_set *set;
852 const char *name2;
853 ip_set_id_t i;
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200854 int ret = 0;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100855
856 if (unlikely(protocol_failed(attr) ||
857 attr[IPSET_ATTR_SETNAME] == NULL ||
858 attr[IPSET_ATTR_SETNAME2] == NULL))
859 return -IPSET_ERR_PROTOCOL;
860
861 set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
862 if (set == NULL)
863 return -ENOENT;
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200864
865 read_lock_bh(&ip_set_ref_lock);
866 if (set->ref != 0) {
867 ret = -IPSET_ERR_REFERENCED;
868 goto out;
869 }
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100870
871 name2 = nla_data(attr[IPSET_ATTR_SETNAME2]);
872 for (i = 0; i < ip_set_max; i++) {
873 if (ip_set_list[i] != NULL &&
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200874 STREQ(ip_set_list[i]->name, name2)) {
875 ret = -IPSET_ERR_EXIST_SETNAME2;
876 goto out;
877 }
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100878 }
879 strncpy(set->name, name2, IPSET_MAXNAMELEN);
880
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200881out:
882 read_unlock_bh(&ip_set_ref_lock);
883 return ret;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100884}
885
886/* Swap two sets so that name/index points to the other.
887 * References and set names are also swapped.
888 *
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200889 * The commands are serialized by the nfnl mutex and references are
890 * protected by the ip_set_ref_lock. The kernel interfaces
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100891 * do not hold the mutex but the pointer settings are atomic
892 * so the ip_set_list always contains valid pointers to the sets.
893 */
894
895static int
896ip_set_swap(struct sock *ctnl, struct sk_buff *skb,
897 const struct nlmsghdr *nlh,
898 const struct nlattr * const attr[])
899{
900 struct ip_set *from, *to;
901 ip_set_id_t from_id, to_id;
902 char from_name[IPSET_MAXNAMELEN];
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100903
904 if (unlikely(protocol_failed(attr) ||
905 attr[IPSET_ATTR_SETNAME] == NULL ||
906 attr[IPSET_ATTR_SETNAME2] == NULL))
907 return -IPSET_ERR_PROTOCOL;
908
909 from_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
910 if (from_id == IPSET_INVALID_ID)
911 return -ENOENT;
912
913 to_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME2]));
914 if (to_id == IPSET_INVALID_ID)
915 return -IPSET_ERR_EXIST_SETNAME2;
916
917 from = ip_set_list[from_id];
918 to = ip_set_list[to_id];
919
920 /* Features must not change.
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300921 * Not an artificial restriction anymore, as we must prevent
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100922 * possible loops created by swapping in setlist type of sets. */
923 if (!(from->type->features == to->type->features &&
924 from->type->family == to->type->family))
925 return -IPSET_ERR_TYPE_MISMATCH;
926
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100927 strncpy(from_name, from->name, IPSET_MAXNAMELEN);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100928 strncpy(from->name, to->name, IPSET_MAXNAMELEN);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100929 strncpy(to->name, from_name, IPSET_MAXNAMELEN);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100930
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200931 write_lock_bh(&ip_set_ref_lock);
932 swap(from->ref, to->ref);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100933 ip_set_list[from_id] = to;
934 ip_set_list[to_id] = from;
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200935 write_unlock_bh(&ip_set_ref_lock);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100936
937 return 0;
938}
939
940/* List/save set data */
941
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +0200942#define DUMP_INIT 0
943#define DUMP_ALL 1
944#define DUMP_ONE 2
945#define DUMP_LAST 3
946
947#define DUMP_TYPE(arg) (((u32)(arg)) & 0x0000FFFF)
948#define DUMP_FLAGS(arg) (((u32)(arg)) >> 16)
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100949
950static int
951ip_set_dump_done(struct netlink_callback *cb)
952{
953 if (cb->args[2]) {
954 pr_debug("release set %s\n", ip_set_list[cb->args[1]]->name);
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +0200955 ip_set_put_byindex((ip_set_id_t) cb->args[1]);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100956 }
957 return 0;
958}
959
960static inline void
961dump_attrs(struct nlmsghdr *nlh)
962{
963 const struct nlattr *attr;
964 int rem;
965
966 pr_debug("dump nlmsg\n");
967 nlmsg_for_each_attr(attr, nlh, sizeof(struct nfgenmsg), rem) {
968 pr_debug("type: %u, len %u\n", nla_type(attr), attr->nla_len);
969 }
970}
971
972static int
973dump_init(struct netlink_callback *cb)
974{
975 struct nlmsghdr *nlh = nlmsg_hdr(cb->skb);
976 int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
977 struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
978 struct nlattr *attr = (void *)nlh + min_len;
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +0200979 u32 dump_type;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +0100980 ip_set_id_t index;
981
982 /* Second pass, so parser can't fail */
983 nla_parse(cda, IPSET_ATTR_CMD_MAX,
984 attr, nlh->nlmsg_len - min_len, ip_set_setname_policy);
985
986 /* cb->args[0] : dump single set/all sets
987 * [1] : set index
988 * [..]: type specific
989 */
990
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +0200991 if (cda[IPSET_ATTR_SETNAME]) {
992 index = find_set_id(nla_data(cda[IPSET_ATTR_SETNAME]));
993 if (index == IPSET_INVALID_ID)
994 return -ENOENT;
995
996 dump_type = DUMP_ONE;
997 cb->args[1] = index;
998 } else
999 dump_type = DUMP_ALL;
1000
1001 if (cda[IPSET_ATTR_FLAGS]) {
1002 u32 f = ip_set_get_h32(cda[IPSET_ATTR_FLAGS]);
1003 dump_type |= (f << 16);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001004 }
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001005 cb->args[0] = dump_type;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001006
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001007 return 0;
1008}
1009
1010static int
1011ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
1012{
1013 ip_set_id_t index = IPSET_INVALID_ID, max;
1014 struct ip_set *set = NULL;
1015 struct nlmsghdr *nlh = NULL;
1016 unsigned int flags = NETLINK_CB(cb->skb).pid ? NLM_F_MULTI : 0;
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001017 u32 dump_type, dump_flags;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001018 int ret = 0;
1019
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001020 if (!cb->args[0]) {
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001021 ret = dump_init(cb);
1022 if (ret < 0) {
1023 nlh = nlmsg_hdr(cb->skb);
1024 /* We have to create and send the error message
1025 * manually :-( */
1026 if (nlh->nlmsg_flags & NLM_F_ACK)
1027 netlink_ack(cb->skb, nlh, ret);
1028 return ret;
1029 }
1030 }
1031
1032 if (cb->args[1] >= ip_set_max)
1033 goto out;
1034
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001035 dump_type = DUMP_TYPE(cb->args[0]);
1036 dump_flags = DUMP_FLAGS(cb->args[0]);
1037 max = dump_type == DUMP_ONE ? cb->args[1] + 1 : ip_set_max;
Jozsef Kadlecsika8a8a092011-04-19 15:59:15 +02001038dump_last:
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001039 pr_debug("args[0]: %u %u args[1]: %ld\n",
1040 dump_type, dump_flags, cb->args[1]);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001041 for (; cb->args[1] < max; cb->args[1]++) {
1042 index = (ip_set_id_t) cb->args[1];
1043 set = ip_set_list[index];
1044 if (set == NULL) {
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001045 if (dump_type == DUMP_ONE) {
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001046 ret = -ENOENT;
1047 goto out;
1048 }
1049 continue;
1050 }
1051 /* When dumping all sets, we must dump "sorted"
1052 * so that lists (unions of sets) are dumped last.
1053 */
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001054 if (dump_type != DUMP_ONE &&
1055 ((dump_type == DUMP_ALL) ==
Jozsef Kadlecsika8a8a092011-04-19 15:59:15 +02001056 !!(set->type->features & IPSET_DUMP_LAST)))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001057 continue;
1058 pr_debug("List set: %s\n", set->name);
1059 if (!cb->args[2]) {
1060 /* Start listing: make sure set won't be destroyed */
1061 pr_debug("reference set\n");
1062 __ip_set_get(index);
1063 }
1064 nlh = start_msg(skb, NETLINK_CB(cb->skb).pid,
1065 cb->nlh->nlmsg_seq, flags,
1066 IPSET_CMD_LIST);
1067 if (!nlh) {
1068 ret = -EMSGSIZE;
1069 goto release_refcount;
1070 }
1071 NLA_PUT_U8(skb, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
1072 NLA_PUT_STRING(skb, IPSET_ATTR_SETNAME, set->name);
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001073 if (dump_flags & IPSET_FLAG_LIST_SETNAME)
1074 goto next_set;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001075 switch (cb->args[2]) {
1076 case 0:
1077 /* Core header data */
1078 NLA_PUT_STRING(skb, IPSET_ATTR_TYPENAME,
1079 set->type->name);
1080 NLA_PUT_U8(skb, IPSET_ATTR_FAMILY,
1081 set->family);
1082 NLA_PUT_U8(skb, IPSET_ATTR_REVISION,
1083 set->type->revision);
1084 ret = set->variant->head(set, skb);
1085 if (ret < 0)
1086 goto release_refcount;
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001087 if (dump_flags & IPSET_FLAG_LIST_HEADER)
1088 goto next_set;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001089 /* Fall through and add elements */
1090 default:
1091 read_lock_bh(&set->lock);
1092 ret = set->variant->list(set, skb, cb);
1093 read_unlock_bh(&set->lock);
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001094 if (!cb->args[2])
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001095 /* Set is done, proceed with next one */
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001096 goto next_set;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001097 goto release_refcount;
1098 }
1099 }
Jozsef Kadlecsika8a8a092011-04-19 15:59:15 +02001100 /* If we dump all sets, continue with dumping last ones */
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001101 if (dump_type == DUMP_ALL) {
1102 dump_type = DUMP_LAST;
1103 cb->args[0] = dump_type | (dump_flags << 16);
Jozsef Kadlecsika8a8a092011-04-19 15:59:15 +02001104 cb->args[1] = 0;
1105 goto dump_last;
1106 }
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001107 goto out;
1108
1109nla_put_failure:
1110 ret = -EFAULT;
Jozsef Kadlecsikc1e2e042011-06-16 18:47:07 +02001111next_set:
1112 if (dump_type == DUMP_ONE)
1113 cb->args[1] = IPSET_INVALID_ID;
1114 else
1115 cb->args[1]++;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001116release_refcount:
1117 /* If there was an error or set is done, release set */
1118 if (ret || !cb->args[2]) {
1119 pr_debug("release set %s\n", ip_set_list[index]->name);
Jozsef Kadlecsik2f9f28b2011-04-04 15:19:25 +02001120 ip_set_put_byindex(index);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001121 }
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001122out:
1123 if (nlh) {
1124 nlmsg_end(skb, nlh);
1125 pr_debug("nlmsg_len: %u\n", nlh->nlmsg_len);
1126 dump_attrs(nlh);
1127 }
1128
1129 return ret < 0 ? ret : skb->len;
1130}
1131
1132static int
1133ip_set_dump(struct sock *ctnl, struct sk_buff *skb,
1134 const struct nlmsghdr *nlh,
1135 const struct nlattr * const attr[])
1136{
1137 if (unlikely(protocol_failed(attr)))
1138 return -IPSET_ERR_PROTOCOL;
1139
1140 return netlink_dump_start(ctnl, skb, nlh,
1141 ip_set_dump_start,
Greg Rosec7ac8672011-06-10 01:27:09 +00001142 ip_set_dump_done, 0);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001143}
1144
1145/* Add, del and test */
1146
1147static const struct nla_policy ip_set_adt_policy[IPSET_ATTR_CMD_MAX + 1] = {
1148 [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
1149 [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING,
1150 .len = IPSET_MAXNAMELEN - 1 },
1151 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
1152 [IPSET_ATTR_DATA] = { .type = NLA_NESTED },
1153 [IPSET_ATTR_ADT] = { .type = NLA_NESTED },
1154};
1155
1156static int
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001157call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001158 struct nlattr *tb[], enum ipset_adt adt,
1159 u32 flags, bool use_lineno)
1160{
1161 int ret, retried = 0;
1162 u32 lineno = 0;
1163 bool eexist = flags & IPSET_FLAG_EXIST;
1164
1165 do {
1166 write_lock_bh(&set->lock);
1167 ret = set->variant->uadt(set, tb, adt, &lineno, flags);
1168 write_unlock_bh(&set->lock);
1169 } while (ret == -EAGAIN &&
1170 set->variant->resize &&
1171 (ret = set->variant->resize(set, retried++)) == 0);
1172
1173 if (!ret || (ret == -IPSET_ERR_EXIST && eexist))
1174 return 0;
1175 if (lineno && use_lineno) {
1176 /* Error in restore/batch mode: send back lineno */
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001177 struct nlmsghdr *rep, *nlh = nlmsg_hdr(skb);
1178 struct sk_buff *skb2;
1179 struct nlmsgerr *errmsg;
1180 size_t payload = sizeof(*errmsg) + nlmsg_len(nlh);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001181 int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
1182 struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001183 struct nlattr *cmdattr;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001184 u32 *errline;
1185
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001186 skb2 = nlmsg_new(payload, GFP_KERNEL);
1187 if (skb2 == NULL)
1188 return -ENOMEM;
1189 rep = __nlmsg_put(skb2, NETLINK_CB(skb).pid,
1190 nlh->nlmsg_seq, NLMSG_ERROR, payload, 0);
1191 errmsg = nlmsg_data(rep);
1192 errmsg->error = ret;
1193 memcpy(&errmsg->msg, nlh, nlh->nlmsg_len);
1194 cmdattr = (void *)&errmsg->msg + min_len;
1195
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001196 nla_parse(cda, IPSET_ATTR_CMD_MAX,
1197 cmdattr, nlh->nlmsg_len - min_len,
1198 ip_set_adt_policy);
1199
1200 errline = nla_data(cda[IPSET_ATTR_LINENO]);
1201
1202 *errline = lineno;
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001203
1204 netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
1205 /* Signal netlink not to send its ACK/errmsg. */
1206 return -EINTR;
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001207 }
1208
1209 return ret;
1210}
1211
1212static int
1213ip_set_uadd(struct sock *ctnl, struct sk_buff *skb,
1214 const struct nlmsghdr *nlh,
1215 const struct nlattr * const attr[])
1216{
1217 struct ip_set *set;
1218 struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
1219 const struct nlattr *nla;
1220 u32 flags = flag_exist(nlh);
1221 bool use_lineno;
1222 int ret = 0;
1223
1224 if (unlikely(protocol_failed(attr) ||
1225 attr[IPSET_ATTR_SETNAME] == NULL ||
1226 !((attr[IPSET_ATTR_DATA] != NULL) ^
1227 (attr[IPSET_ATTR_ADT] != NULL)) ||
1228 (attr[IPSET_ATTR_DATA] != NULL &&
1229 !flag_nested(attr[IPSET_ATTR_DATA])) ||
1230 (attr[IPSET_ATTR_ADT] != NULL &&
1231 (!flag_nested(attr[IPSET_ATTR_ADT]) ||
1232 attr[IPSET_ATTR_LINENO] == NULL))))
1233 return -IPSET_ERR_PROTOCOL;
1234
1235 set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
1236 if (set == NULL)
1237 return -ENOENT;
1238
1239 use_lineno = !!attr[IPSET_ATTR_LINENO];
1240 if (attr[IPSET_ATTR_DATA]) {
Patrick McHardy8da560c2011-02-01 16:27:25 +01001241 if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX,
1242 attr[IPSET_ATTR_DATA],
1243 set->type->adt_policy))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001244 return -IPSET_ERR_PROTOCOL;
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001245 ret = call_ad(ctnl, skb, set, tb, IPSET_ADD, flags,
1246 use_lineno);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001247 } else {
1248 int nla_rem;
1249
1250 nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) {
1251 memset(tb, 0, sizeof(tb));
1252 if (nla_type(nla) != IPSET_ATTR_DATA ||
1253 !flag_nested(nla) ||
Patrick McHardy8da560c2011-02-01 16:27:25 +01001254 nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla,
1255 set->type->adt_policy))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001256 return -IPSET_ERR_PROTOCOL;
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001257 ret = call_ad(ctnl, skb, set, tb, IPSET_ADD,
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001258 flags, use_lineno);
1259 if (ret < 0)
1260 return ret;
1261 }
1262 }
1263 return ret;
1264}
1265
1266static int
1267ip_set_udel(struct sock *ctnl, struct sk_buff *skb,
1268 const struct nlmsghdr *nlh,
1269 const struct nlattr * const attr[])
1270{
1271 struct ip_set *set;
1272 struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
1273 const struct nlattr *nla;
1274 u32 flags = flag_exist(nlh);
1275 bool use_lineno;
1276 int ret = 0;
1277
1278 if (unlikely(protocol_failed(attr) ||
1279 attr[IPSET_ATTR_SETNAME] == NULL ||
1280 !((attr[IPSET_ATTR_DATA] != NULL) ^
1281 (attr[IPSET_ATTR_ADT] != NULL)) ||
1282 (attr[IPSET_ATTR_DATA] != NULL &&
1283 !flag_nested(attr[IPSET_ATTR_DATA])) ||
1284 (attr[IPSET_ATTR_ADT] != NULL &&
1285 (!flag_nested(attr[IPSET_ATTR_ADT]) ||
1286 attr[IPSET_ATTR_LINENO] == NULL))))
1287 return -IPSET_ERR_PROTOCOL;
1288
1289 set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
1290 if (set == NULL)
1291 return -ENOENT;
1292
1293 use_lineno = !!attr[IPSET_ATTR_LINENO];
1294 if (attr[IPSET_ATTR_DATA]) {
Patrick McHardy8da560c2011-02-01 16:27:25 +01001295 if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX,
1296 attr[IPSET_ATTR_DATA],
1297 set->type->adt_policy))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001298 return -IPSET_ERR_PROTOCOL;
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001299 ret = call_ad(ctnl, skb, set, tb, IPSET_DEL, flags,
1300 use_lineno);
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001301 } else {
1302 int nla_rem;
1303
1304 nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) {
1305 memset(tb, 0, sizeof(*tb));
1306 if (nla_type(nla) != IPSET_ATTR_DATA ||
1307 !flag_nested(nla) ||
Patrick McHardy8da560c2011-02-01 16:27:25 +01001308 nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla,
1309 set->type->adt_policy))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001310 return -IPSET_ERR_PROTOCOL;
Jozsef Kadlecsik5f52bc32011-02-02 23:56:00 +01001311 ret = call_ad(ctnl, skb, set, tb, IPSET_DEL,
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001312 flags, use_lineno);
1313 if (ret < 0)
1314 return ret;
1315 }
1316 }
1317 return ret;
1318}
1319
1320static int
1321ip_set_utest(struct sock *ctnl, struct sk_buff *skb,
1322 const struct nlmsghdr *nlh,
1323 const struct nlattr * const attr[])
1324{
1325 struct ip_set *set;
1326 struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {};
1327 int ret = 0;
1328
1329 if (unlikely(protocol_failed(attr) ||
1330 attr[IPSET_ATTR_SETNAME] == NULL ||
1331 attr[IPSET_ATTR_DATA] == NULL ||
1332 !flag_nested(attr[IPSET_ATTR_DATA])))
1333 return -IPSET_ERR_PROTOCOL;
1334
1335 set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
1336 if (set == NULL)
1337 return -ENOENT;
1338
Patrick McHardy8da560c2011-02-01 16:27:25 +01001339 if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, attr[IPSET_ATTR_DATA],
1340 set->type->adt_policy))
Jozsef Kadlecsika7b4f982011-02-01 15:28:35 +01001341 return -IPSET_ERR_PROTOCOL;
1342
1343 read_lock_bh(&set->lock);
1344 ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0);
1345 read_unlock_bh(&set->lock);
1346 /* Userspace can't trigger element to be re-added */
1347 if (ret == -EAGAIN)
1348 ret = 1;
1349
1350 return ret < 0 ? ret : ret > 0 ? 0 : -IPSET_ERR_EXIST;
1351}
1352
1353/* Get headed data of a set */
1354
1355static int
1356ip_set_header(struct sock *ctnl, struct sk_buff *skb,
1357 const struct nlmsghdr *nlh,
1358 const struct nlattr * const attr[])
1359{
1360 const struct ip_set *set;
1361 struct sk_buff *skb2;
1362 struct nlmsghdr *nlh2;
1363 ip_set_id_t index;
1364 int ret = 0;
1365
1366 if (unlikely(protocol_failed(attr) ||
1367 attr[IPSET_ATTR_SETNAME] == NULL))
1368 return -IPSET_ERR_PROTOCOL;
1369
1370 index = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
1371 if (index == IPSET_INVALID_ID)
1372 return -ENOENT;
1373 set = ip_set_list[index];
1374
1375 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1376 if (skb2 == NULL)
1377 return -ENOMEM;
1378
1379 nlh2 = start_msg(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0,
1380 IPSET_CMD_HEADER);
1381 if (!nlh2)
1382 goto nlmsg_failure;
1383 NLA_PUT_U8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
1384 NLA_PUT_STRING(skb2, IPSET_ATTR_SETNAME, set->name);
1385 NLA_PUT_STRING(skb2, IPSET_ATTR_TYPENAME, set->type->name);
1386 NLA_PUT_U8(skb2, IPSET_ATTR_FAMILY, set->family);
1387 NLA_PUT_U8(skb2, IPSET_ATTR_REVISION, set->type->revision);
1388 nlmsg_end(skb2, nlh2);
1389
1390 ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
1391 if (ret < 0)
1392 return ret;
1393
1394 return 0;
1395
1396nla_put_failure:
1397 nlmsg_cancel(skb2, nlh2);
1398nlmsg_failure:
1399 kfree_skb(skb2);
1400 return -EMSGSIZE;
1401}
1402
1403/* Get type data */
1404
1405static const struct nla_policy ip_set_type_policy[IPSET_ATTR_CMD_MAX + 1] = {
1406 [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
1407 [IPSET_ATTR_TYPENAME] = { .type = NLA_NUL_STRING,
1408 .len = IPSET_MAXNAMELEN - 1 },
1409 [IPSET_ATTR_FAMILY] = { .type = NLA_U8 },
1410};
1411
1412static int
1413ip_set_type(struct sock *ctnl, struct sk_buff *skb,
1414 const struct nlmsghdr *nlh,
1415 const struct nlattr * const attr[])
1416{
1417 struct sk_buff *skb2;
1418 struct nlmsghdr *nlh2;
1419 u8 family, min, max;
1420 const char *typename;
1421 int ret = 0;
1422
1423 if (unlikely(protocol_failed(attr) ||
1424 attr[IPSET_ATTR_TYPENAME] == NULL ||
1425 attr[IPSET_ATTR_FAMILY] == NULL))
1426 return -IPSET_ERR_PROTOCOL;
1427
1428 family = nla_get_u8(attr[IPSET_ATTR_FAMILY]);
1429 typename = nla_data(attr[IPSET_ATTR_TYPENAME]);
1430 ret = find_set_type_minmax(typename, family, &min, &max);
1431 if (ret)
1432 return ret;
1433
1434 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1435 if (skb2 == NULL)
1436 return -ENOMEM;
1437
1438 nlh2 = start_msg(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0,
1439 IPSET_CMD_TYPE);
1440 if (!nlh2)
1441 goto nlmsg_failure;
1442 NLA_PUT_U8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
1443 NLA_PUT_STRING(skb2, IPSET_ATTR_TYPENAME, typename);
1444 NLA_PUT_U8(skb2, IPSET_ATTR_FAMILY, family);
1445 NLA_PUT_U8(skb2, IPSET_ATTR_REVISION, max);
1446 NLA_PUT_U8(skb2, IPSET_ATTR_REVISION_MIN, min);
1447 nlmsg_end(skb2, nlh2);
1448
1449 pr_debug("Send TYPE, nlmsg_len: %u\n", nlh2->nlmsg_len);
1450 ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
1451 if (ret < 0)
1452 return ret;
1453
1454 return 0;
1455
1456nla_put_failure:
1457 nlmsg_cancel(skb2, nlh2);
1458nlmsg_failure:
1459 kfree_skb(skb2);
1460 return -EMSGSIZE;
1461}
1462
1463/* Get protocol version */
1464
1465static const struct nla_policy
1466ip_set_protocol_policy[IPSET_ATTR_CMD_MAX + 1] = {
1467 [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
1468};
1469
1470static int
1471ip_set_protocol(struct sock *ctnl, struct sk_buff *skb,
1472 const struct nlmsghdr *nlh,
1473 const struct nlattr * const attr[])
1474{
1475 struct sk_buff *skb2;
1476 struct nlmsghdr *nlh2;
1477 int ret = 0;
1478
1479 if (unlikely(attr[IPSET_ATTR_PROTOCOL] == NULL))
1480 return -IPSET_ERR_PROTOCOL;
1481
1482 skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1483 if (skb2 == NULL)
1484 return -ENOMEM;
1485
1486 nlh2 = start_msg(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0,
1487 IPSET_CMD_PROTOCOL);
1488 if (!nlh2)
1489 goto nlmsg_failure;
1490 NLA_PUT_U8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
1491 nlmsg_end(skb2, nlh2);
1492
1493 ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
1494 if (ret < 0)
1495 return ret;
1496
1497 return 0;
1498
1499nla_put_failure:
1500 nlmsg_cancel(skb2, nlh2);
1501nlmsg_failure:
1502 kfree_skb(skb2);
1503 return -EMSGSIZE;
1504}
1505
1506static const struct nfnl_callback ip_set_netlink_subsys_cb[IPSET_MSG_MAX] = {
1507 [IPSET_CMD_CREATE] = {
1508 .call = ip_set_create,
1509 .attr_count = IPSET_ATTR_CMD_MAX,
1510 .policy = ip_set_create_policy,
1511 },
1512 [IPSET_CMD_DESTROY] = {
1513 .call = ip_set_destroy,
1514 .attr_count = IPSET_ATTR_CMD_MAX,
1515 .policy = ip_set_setname_policy,
1516 },
1517 [IPSET_CMD_FLUSH] = {
1518 .call = ip_set_flush,
1519 .attr_count = IPSET_ATTR_CMD_MAX,
1520 .policy = ip_set_setname_policy,
1521 },
1522 [IPSET_CMD_RENAME] = {
1523 .call = ip_set_rename,
1524 .attr_count = IPSET_ATTR_CMD_MAX,
1525 .policy = ip_set_setname2_policy,
1526 },
1527 [IPSET_CMD_SWAP] = {
1528 .call = ip_set_swap,
1529 .attr_count = IPSET_ATTR_CMD_MAX,
1530 .policy = ip_set_setname2_policy,
1531 },
1532 [IPSET_CMD_LIST] = {
1533 .call = ip_set_dump,
1534 .attr_count = IPSET_ATTR_CMD_MAX,
1535 .policy = ip_set_setname_policy,
1536 },
1537 [IPSET_CMD_SAVE] = {
1538 .call = ip_set_dump,
1539 .attr_count = IPSET_ATTR_CMD_MAX,
1540 .policy = ip_set_setname_policy,
1541 },
1542 [IPSET_CMD_ADD] = {
1543 .call = ip_set_uadd,
1544 .attr_count = IPSET_ATTR_CMD_MAX,
1545 .policy = ip_set_adt_policy,
1546 },
1547 [IPSET_CMD_DEL] = {
1548 .call = ip_set_udel,
1549 .attr_count = IPSET_ATTR_CMD_MAX,
1550 .policy = ip_set_adt_policy,
1551 },
1552 [IPSET_CMD_TEST] = {
1553 .call = ip_set_utest,
1554 .attr_count = IPSET_ATTR_CMD_MAX,
1555 .policy = ip_set_adt_policy,
1556 },
1557 [IPSET_CMD_HEADER] = {
1558 .call = ip_set_header,
1559 .attr_count = IPSET_ATTR_CMD_MAX,
1560 .policy = ip_set_setname_policy,
1561 },
1562 [IPSET_CMD_TYPE] = {
1563 .call = ip_set_type,
1564 .attr_count = IPSET_ATTR_CMD_MAX,
1565 .policy = ip_set_type_policy,
1566 },
1567 [IPSET_CMD_PROTOCOL] = {
1568 .call = ip_set_protocol,
1569 .attr_count = IPSET_ATTR_CMD_MAX,
1570 .policy = ip_set_protocol_policy,
1571 },
1572};
1573
1574static struct nfnetlink_subsystem ip_set_netlink_subsys __read_mostly = {
1575 .name = "ip_set",
1576 .subsys_id = NFNL_SUBSYS_IPSET,
1577 .cb_count = IPSET_MSG_MAX,
1578 .cb = ip_set_netlink_subsys_cb,
1579};
1580
1581/* Interface to iptables/ip6tables */
1582
1583static int
1584ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
1585{
1586 unsigned *op;
1587 void *data;
1588 int copylen = *len, ret = 0;
1589
1590 if (!capable(CAP_NET_ADMIN))
1591 return -EPERM;
1592 if (optval != SO_IP_SET)
1593 return -EBADF;
1594 if (*len < sizeof(unsigned))
1595 return -EINVAL;
1596
1597 data = vmalloc(*len);
1598 if (!data)
1599 return -ENOMEM;
1600 if (copy_from_user(data, user, *len) != 0) {
1601 ret = -EFAULT;
1602 goto done;
1603 }
1604 op = (unsigned *) data;
1605
1606 if (*op < IP_SET_OP_VERSION) {
1607 /* Check the version at the beginning of operations */
1608 struct ip_set_req_version *req_version = data;
1609 if (req_version->version != IPSET_PROTOCOL) {
1610 ret = -EPROTO;
1611 goto done;
1612 }
1613 }
1614
1615 switch (*op) {
1616 case IP_SET_OP_VERSION: {
1617 struct ip_set_req_version *req_version = data;
1618
1619 if (*len != sizeof(struct ip_set_req_version)) {
1620 ret = -EINVAL;
1621 goto done;
1622 }
1623
1624 req_version->version = IPSET_PROTOCOL;
1625 ret = copy_to_user(user, req_version,
1626 sizeof(struct ip_set_req_version));
1627 goto done;
1628 }
1629 case IP_SET_OP_GET_BYNAME: {
1630 struct ip_set_req_get_set *req_get = data;
1631
1632 if (*len != sizeof(struct ip_set_req_get_set)) {
1633 ret = -EINVAL;
1634 goto done;
1635 }
1636 req_get->set.name[IPSET_MAXNAMELEN - 1] = '\0';
1637 nfnl_lock();
1638 req_get->set.index = find_set_id(req_get->set.name);
1639 nfnl_unlock();
1640 goto copy;
1641 }
1642 case IP_SET_OP_GET_BYINDEX: {
1643 struct ip_set_req_get_set *req_get = data;
1644
1645 if (*len != sizeof(struct ip_set_req_get_set) ||
1646 req_get->set.index >= ip_set_max) {
1647 ret = -EINVAL;
1648 goto done;
1649 }
1650 nfnl_lock();
1651 strncpy(req_get->set.name,
1652 ip_set_list[req_get->set.index]
1653 ? ip_set_list[req_get->set.index]->name : "",
1654 IPSET_MAXNAMELEN);
1655 nfnl_unlock();
1656 goto copy;
1657 }
1658 default:
1659 ret = -EBADMSG;
1660 goto done;
1661 } /* end of switch(op) */
1662
1663copy:
1664 ret = copy_to_user(user, data, copylen);
1665
1666done:
1667 vfree(data);
1668 if (ret > 0)
1669 ret = 0;
1670 return ret;
1671}
1672
1673static struct nf_sockopt_ops so_set __read_mostly = {
1674 .pf = PF_INET,
1675 .get_optmin = SO_IP_SET,
1676 .get_optmax = SO_IP_SET + 1,
1677 .get = &ip_set_sockfn_get,
1678 .owner = THIS_MODULE,
1679};
1680
1681static int __init
1682ip_set_init(void)
1683{
1684 int ret;
1685
1686 if (max_sets)
1687 ip_set_max = max_sets;
1688 if (ip_set_max >= IPSET_INVALID_ID)
1689 ip_set_max = IPSET_INVALID_ID - 1;
1690
1691 ip_set_list = kzalloc(sizeof(struct ip_set *) * ip_set_max,
1692 GFP_KERNEL);
1693 if (!ip_set_list) {
1694 pr_err("ip_set: Unable to create ip_set_list\n");
1695 return -ENOMEM;
1696 }
1697
1698 ret = nfnetlink_subsys_register(&ip_set_netlink_subsys);
1699 if (ret != 0) {
1700 pr_err("ip_set: cannot register with nfnetlink.\n");
1701 kfree(ip_set_list);
1702 return ret;
1703 }
1704 ret = nf_register_sockopt(&so_set);
1705 if (ret != 0) {
1706 pr_err("SO_SET registry failed: %d\n", ret);
1707 nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
1708 kfree(ip_set_list);
1709 return ret;
1710 }
1711
1712 pr_notice("ip_set: protocol %u\n", IPSET_PROTOCOL);
1713 return 0;
1714}
1715
1716static void __exit
1717ip_set_fini(void)
1718{
1719 /* There can't be any existing set */
1720 nf_unregister_sockopt(&so_set);
1721 nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
1722 kfree(ip_set_list);
1723 pr_debug("these are the famous last words\n");
1724}
1725
1726module_init(ip_set_init);
1727module_exit(ip_set_fini);