RT-AC66 3.0.0.4.374.130 core
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / net / ipv4 / netfilter / ip_set.c
blob7ecdc831aeb6132bc93eed81415ad06aeb9fbba2
1 /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
2 * Patrick Schaaf <bof@bof.de>
3 * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
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 */
10 /* Kernel module for IP set management */
12 #include <linux/version.h>
13 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
14 #include <linux/config.h>
15 #endif
16 #include <linux/module.h>
17 #include <linux/moduleparam.h>
18 #include <linux/kmod.h>
19 #include <linux/ip.h>
20 #include <linux/skbuff.h>
21 #include <linux/random.h>
22 #include <linux/netfilter_ipv4/ip_set_jhash.h>
23 #include <linux/errno.h>
24 #include <linux/capability.h>
25 #include <asm/uaccess.h>
26 #include <asm/bitops.h>
27 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
28 #include <asm/semaphore.h>
29 #else
30 #include <linux/semaphore.h>
31 #endif
32 #include <linux/spinlock.h>
34 #define ASSERT_READ_LOCK(x)
35 #define ASSERT_WRITE_LOCK(x)
36 #include <linux/netfilter.h>
37 #include <linux/netfilter_ipv4/ip_set.h>
39 static struct list_head set_type_list; /* all registered sets */
40 static struct ip_set **ip_set_list; /* all individual sets */
41 static DEFINE_RWLOCK(ip_set_lock); /* protects the lists and the hash */
42 static struct semaphore ip_set_app_mutex; /* serializes user access */
43 static ip_set_id_t ip_set_max = CONFIG_IP_NF_SET_MAX;
44 static int protocol_version = IP_SET_PROTOCOL_VERSION;
46 #define STREQ(a,b) (strncmp(a,b,IP_SET_MAXNAMELEN) == 0)
47 #define DONT_ALIGN (protocol_version == IP_SET_PROTOCOL_UNALIGNED)
48 #define ALIGNED(len) IPSET_VALIGN(len, DONT_ALIGN)
51 * Sets are identified either by the index in ip_set_list or by id.
52 * The id never changes. The index may change by swapping and used
53 * by external references (set/SET netfilter modules, etc.)
55 * Userspace requests are serialized by ip_set_mutex and sets can
56 * be deleted only from userspace. Therefore ip_set_list locking
57 * must obey the following rules:
59 * - kernel requests: read and write locking mandatory
60 * - user requests: read locking optional, write locking mandatory
63 static inline void
64 __ip_set_get(ip_set_id_t index)
66 atomic_inc(&ip_set_list[index]->ref);
69 static inline void
70 __ip_set_put(ip_set_id_t index)
72 atomic_dec(&ip_set_list[index]->ref);
75 /* Add, del and test set entries from kernel */
77 int
78 ip_set_testip_kernel(ip_set_id_t index,
79 const struct sk_buff *skb,
80 const u_int32_t *flags)
82 struct ip_set *set;
83 int res;
85 read_lock_bh(&ip_set_lock);
86 set = ip_set_list[index];
87 IP_SET_ASSERT(set);
88 DP("set %s, index %u", set->name, index);
90 read_lock_bh(&set->lock);
91 res = set->type->testip_kernel(set, skb, flags);
92 read_unlock_bh(&set->lock);
94 read_unlock_bh(&ip_set_lock);
96 return (res < 0 ? 0 : res);
99 int
100 ip_set_addip_kernel(ip_set_id_t index,
101 const struct sk_buff *skb,
102 const u_int32_t *flags)
104 struct ip_set *set;
105 int res;
107 retry:
108 read_lock_bh(&ip_set_lock);
109 set = ip_set_list[index];
110 IP_SET_ASSERT(set);
111 DP("set %s, index %u", set->name, index);
113 write_lock_bh(&set->lock);
114 res = set->type->addip_kernel(set, skb, flags);
115 write_unlock_bh(&set->lock);
117 read_unlock_bh(&ip_set_lock);
118 /* Retry function called without holding any lock */
119 if (res == -EAGAIN
120 && set->type->retry
121 && (res = set->type->retry(set)) == 0)
122 goto retry;
124 return res;
128 ip_set_delip_kernel(ip_set_id_t index,
129 const struct sk_buff *skb,
130 const u_int32_t *flags)
132 struct ip_set *set;
133 int res;
135 read_lock_bh(&ip_set_lock);
136 set = ip_set_list[index];
137 IP_SET_ASSERT(set);
138 DP("set %s, index %u", set->name, index);
140 write_lock_bh(&set->lock);
141 res = set->type->delip_kernel(set, skb, flags);
142 write_unlock_bh(&set->lock);
144 read_unlock_bh(&ip_set_lock);
146 return res;
149 /* Register and deregister settype */
151 static inline struct ip_set_type *
152 find_set_type(const char *name)
154 struct ip_set_type *set_type;
156 list_for_each_entry(set_type, &set_type_list, list)
157 if (STREQ(set_type->typename, name))
158 return set_type;
159 return NULL;
163 ip_set_register_set_type(struct ip_set_type *set_type)
165 int ret = 0;
167 if (set_type->protocol_version != IP_SET_PROTOCOL_VERSION) {
168 ip_set_printk("'%s' uses wrong protocol version %u (want %u)",
169 set_type->typename,
170 set_type->protocol_version,
171 IP_SET_PROTOCOL_VERSION);
172 return -EINVAL;
175 write_lock_bh(&ip_set_lock);
176 if (find_set_type(set_type->typename)) {
177 /* Duplicate! */
178 ip_set_printk("'%s' already registered!",
179 set_type->typename);
180 ret = -EINVAL;
181 goto unlock;
183 if (!try_module_get(THIS_MODULE)) {
184 ret = -EFAULT;
185 goto unlock;
187 list_add(&set_type->list, &set_type_list);
188 DP("'%s' registered.", set_type->typename);
189 unlock:
190 write_unlock_bh(&ip_set_lock);
191 return ret;
194 void
195 ip_set_unregister_set_type(struct ip_set_type *set_type)
197 write_lock_bh(&ip_set_lock);
198 if (!find_set_type(set_type->typename)) {
199 ip_set_printk("'%s' not registered?",
200 set_type->typename);
201 goto unlock;
203 list_del(&set_type->list);
204 module_put(THIS_MODULE);
205 DP("'%s' unregistered.", set_type->typename);
206 unlock:
207 write_unlock_bh(&ip_set_lock);
211 ip_set_id_t
212 __ip_set_get_byname(const char *name, struct ip_set **set)
214 ip_set_id_t i, index = IP_SET_INVALID_ID;
216 for (i = 0; i < ip_set_max; i++) {
217 if (ip_set_list[i] != NULL
218 && STREQ(ip_set_list[i]->name, name)) {
219 __ip_set_get(i);
220 index = i;
221 *set = ip_set_list[i];
222 break;
225 return index;
228 void
229 __ip_set_put_byindex(ip_set_id_t index)
231 if (ip_set_list[index])
232 __ip_set_put(index);
236 * Userspace routines
240 * Find set by name, reference it once. The reference makes sure the
241 * thing pointed to, does not go away under our feet. Drop the reference
242 * later, using ip_set_put().
244 ip_set_id_t
245 ip_set_get_byname(const char *name)
247 ip_set_id_t i, index = IP_SET_INVALID_ID;
249 down(&ip_set_app_mutex);
250 for (i = 0; i < ip_set_max; i++) {
251 if (ip_set_list[i] != NULL
252 && STREQ(ip_set_list[i]->name, name)) {
253 __ip_set_get(i);
254 index = i;
255 break;
258 up(&ip_set_app_mutex);
259 return index;
263 * Find set by index, reference it once. The reference makes sure the
264 * thing pointed to, does not go away under our feet. Drop the reference
265 * later, using ip_set_put().
267 ip_set_id_t
268 ip_set_get_byindex(ip_set_id_t index)
270 down(&ip_set_app_mutex);
272 if (index >= ip_set_max)
273 return IP_SET_INVALID_ID;
275 if (ip_set_list[index])
276 __ip_set_get(index);
277 else
278 index = IP_SET_INVALID_ID;
280 up(&ip_set_app_mutex);
281 return index;
285 * Find the set id belonging to the index.
286 * We are protected by the mutex, so we do not need to use
287 * ip_set_lock. There is no need to reference the sets either.
289 ip_set_id_t
290 ip_set_id(ip_set_id_t index)
292 if (index >= ip_set_max || !ip_set_list[index])
293 return IP_SET_INVALID_ID;
295 return ip_set_list[index]->id;
299 * If the given set pointer points to a valid set, decrement
300 * reference count by 1. The caller shall not assume the index
301 * to be valid, after calling this function.
303 void
304 ip_set_put_byindex(ip_set_id_t index)
306 down(&ip_set_app_mutex);
307 if (ip_set_list[index])
308 __ip_set_put(index);
309 up(&ip_set_app_mutex);
312 /* Find a set by name or index */
313 static ip_set_id_t
314 ip_set_find_byname(const char *name)
316 ip_set_id_t i, index = IP_SET_INVALID_ID;
318 for (i = 0; i < ip_set_max; i++) {
319 if (ip_set_list[i] != NULL
320 && STREQ(ip_set_list[i]->name, name)) {
321 index = i;
322 break;
325 return index;
328 static ip_set_id_t
329 ip_set_find_byindex(ip_set_id_t index)
331 if (index >= ip_set_max || ip_set_list[index] == NULL)
332 index = IP_SET_INVALID_ID;
334 return index;
338 * Add, del and test
341 static int
342 ip_set_addip(struct ip_set *set, const void *data, u_int32_t size)
344 int res;
346 IP_SET_ASSERT(set);
347 do {
348 write_lock_bh(&set->lock);
349 res = set->type->addip(set, data, size);
350 write_unlock_bh(&set->lock);
351 } while (res == -EAGAIN
352 && set->type->retry
353 && (res = set->type->retry(set)) == 0);
355 return res;
358 static int
359 ip_set_delip(struct ip_set *set, const void *data, u_int32_t size)
361 int res;
363 IP_SET_ASSERT(set);
365 write_lock_bh(&set->lock);
366 res = set->type->delip(set, data, size);
367 write_unlock_bh(&set->lock);
369 return res;
372 static int
373 ip_set_testip(struct ip_set *set, const void *data, u_int32_t size)
375 int res;
377 IP_SET_ASSERT(set);
379 read_lock_bh(&set->lock);
380 res = set->type->testip(set, data, size);
381 read_unlock_bh(&set->lock);
383 return (res > 0 ? -EEXIST : res);
386 static struct ip_set_type *
387 find_set_type_rlock(const char *typename)
389 struct ip_set_type *type;
391 read_lock_bh(&ip_set_lock);
392 type = find_set_type(typename);
393 if (type == NULL)
394 read_unlock_bh(&ip_set_lock);
396 return type;
399 static int
400 find_free_id(const char *name,
401 ip_set_id_t *index,
402 ip_set_id_t *id)
404 ip_set_id_t i;
406 *id = IP_SET_INVALID_ID;
407 for (i = 0; i < ip_set_max; i++) {
408 if (ip_set_list[i] == NULL) {
409 if (*id == IP_SET_INVALID_ID)
410 *id = *index = i;
411 } else if (STREQ(name, ip_set_list[i]->name))
412 /* Name clash */
413 return -EEXIST;
415 if (*id == IP_SET_INVALID_ID)
416 /* No free slot remained */
417 return -ERANGE;
418 /* Check that index is usable as id (swapping) */
419 check:
420 for (i = 0; i < ip_set_max; i++) {
421 if (ip_set_list[i] != NULL
422 && ip_set_list[i]->id == *id) {
423 *id = i;
424 goto check;
427 return 0;
431 * Create a set
433 static int
434 ip_set_create(const char *name,
435 const char *typename,
436 ip_set_id_t restore,
437 const void *data,
438 u_int32_t size)
440 struct ip_set *set;
441 ip_set_id_t index = 0, id;
442 int res = 0;
444 DP("setname: %s, typename: %s, id: %u", name, typename, restore);
447 * First, and without any locks, allocate and initialize
448 * a normal base set structure.
450 set = kmalloc(sizeof(struct ip_set), GFP_KERNEL);
451 if (!set)
452 return -ENOMEM;
453 rwlock_init(&set->lock);
454 strncpy(set->name, name, IP_SET_MAXNAMELEN);
455 atomic_set(&set->ref, 0);
458 * Next, take the &ip_set_lock, check that we know the type,
459 * and take a reference on the type, to make sure it
460 * stays available while constructing our new set.
462 * After referencing the type, we drop the &ip_set_lock,
463 * and let the new set construction run without locks.
465 set->type = find_set_type_rlock(typename);
466 if (set->type == NULL) {
467 /* Try loading the module */
468 char modulename[IP_SET_MAXNAMELEN + strlen("ip_set_") + 1];
469 strcpy(modulename, "ip_set_");
470 strcat(modulename, typename);
471 DP("try to load %s", modulename);
472 request_module(modulename);
473 set->type = find_set_type_rlock(typename);
475 if (set->type == NULL) {
476 ip_set_printk("no set type '%s', set '%s' not created",
477 typename, name);
478 res = -ENOENT;
479 goto out;
481 if (!try_module_get(set->type->me)) {
482 read_unlock_bh(&ip_set_lock);
483 res = -EFAULT;
484 goto out;
486 read_unlock_bh(&ip_set_lock);
488 /* Check request size */
489 if (size != set->type->header_size) {
490 ip_set_printk("data length wrong (want %lu, have %lu)",
491 (long unsigned)set->type->header_size,
492 (long unsigned)size);
493 goto put_out;
497 * Without holding any locks, create private part.
499 res = set->type->create(set, data, size);
500 if (res != 0)
501 goto put_out;
503 /* BTW, res==0 here. */
506 * Here, we have a valid, constructed set. &ip_set_lock again,
507 * find free id/index and check that it is not already in
508 * ip_set_list.
510 write_lock_bh(&ip_set_lock);
511 if ((res = find_free_id(set->name, &index, &id)) != 0) {
512 DP("no free id!");
513 goto cleanup;
516 /* Make sure restore gets the same index */
517 if (restore != IP_SET_INVALID_ID && index != restore) {
518 DP("Can't restore, sets are screwed up");
519 res = -ERANGE;
520 goto cleanup;
524 * Finally! Add our shiny new set to the list, and be done.
526 DP("create: '%s' created with index %u, id %u!", set->name, index, id);
527 set->id = id;
528 ip_set_list[index] = set;
529 write_unlock_bh(&ip_set_lock);
530 return res;
532 cleanup:
533 write_unlock_bh(&ip_set_lock);
534 set->type->destroy(set);
535 put_out:
536 module_put(set->type->me);
537 out:
538 kfree(set);
539 return res;
543 * Destroy a given existing set
545 static void
546 ip_set_destroy_set(ip_set_id_t index)
548 struct ip_set *set = ip_set_list[index];
550 IP_SET_ASSERT(set);
551 DP("set: %s", set->name);
552 write_lock_bh(&ip_set_lock);
553 ip_set_list[index] = NULL;
554 write_unlock_bh(&ip_set_lock);
556 /* Must call it without holding any lock */
557 set->type->destroy(set);
558 module_put(set->type->me);
559 kfree(set);
563 * Destroy a set - or all sets
564 * Sets must not be referenced/used.
566 static int
567 ip_set_destroy(ip_set_id_t index)
569 ip_set_id_t i;
571 /* ref modification always protected by the mutex */
572 if (index != IP_SET_INVALID_ID) {
573 if (atomic_read(&ip_set_list[index]->ref))
574 return -EBUSY;
575 ip_set_destroy_set(index);
576 } else {
577 for (i = 0; i < ip_set_max; i++) {
578 if (ip_set_list[i] != NULL
579 && (atomic_read(&ip_set_list[i]->ref)))
580 return -EBUSY;
583 for (i = 0; i < ip_set_max; i++) {
584 if (ip_set_list[i] != NULL)
585 ip_set_destroy_set(i);
588 return 0;
591 static void
592 ip_set_flush_set(struct ip_set *set)
594 DP("set: %s %u", set->name, set->id);
596 write_lock_bh(&set->lock);
597 set->type->flush(set);
598 write_unlock_bh(&set->lock);
602 * Flush data in a set - or in all sets
604 static int
605 ip_set_flush(ip_set_id_t index)
607 if (index != IP_SET_INVALID_ID) {
608 IP_SET_ASSERT(ip_set_list[index]);
609 ip_set_flush_set(ip_set_list[index]);
610 } else {
611 ip_set_id_t i;
613 for (i = 0; i < ip_set_max; i++)
614 if (ip_set_list[i] != NULL)
615 ip_set_flush_set(ip_set_list[i]);
618 return 0;
621 /* Rename a set */
622 static int
623 ip_set_rename(ip_set_id_t index, const char *name)
625 struct ip_set *set = ip_set_list[index];
626 ip_set_id_t i;
627 int res = 0;
629 DP("set: %s to %s", set->name, name);
630 write_lock_bh(&ip_set_lock);
631 for (i = 0; i < ip_set_max; i++) {
632 if (ip_set_list[i] != NULL
633 && STREQ(ip_set_list[i]->name, name)) {
634 res = -EEXIST;
635 goto unlock;
638 strncpy(set->name, name, IP_SET_MAXNAMELEN);
639 unlock:
640 write_unlock_bh(&ip_set_lock);
641 return res;
645 * Swap two sets so that name/index points to the other.
646 * References are also swapped.
648 static int
649 ip_set_swap(ip_set_id_t from_index, ip_set_id_t to_index)
651 struct ip_set *from = ip_set_list[from_index];
652 struct ip_set *to = ip_set_list[to_index];
653 char from_name[IP_SET_MAXNAMELEN];
654 u_int32_t from_ref;
656 DP("set: %s to %s", from->name, to->name);
657 /* Features must not change.
658 * Not an artifical restriction anymore, as we must prevent
659 * possible loops created by swapping in setlist type of sets. */
660 if (from->type->features != to->type->features)
661 return -ENOEXEC;
663 /* No magic here: ref munging protected by the mutex */
664 write_lock_bh(&ip_set_lock);
665 strncpy(from_name, from->name, IP_SET_MAXNAMELEN);
666 from_ref = atomic_read(&from->ref);
668 strncpy(from->name, to->name, IP_SET_MAXNAMELEN);
669 atomic_set(&from->ref, atomic_read(&to->ref));
670 strncpy(to->name, from_name, IP_SET_MAXNAMELEN);
671 atomic_set(&to->ref, from_ref);
673 ip_set_list[from_index] = to;
674 ip_set_list[to_index] = from;
676 write_unlock_bh(&ip_set_lock);
677 return 0;
681 * List set data
684 static int
685 ip_set_list_set(ip_set_id_t index, void *data, int *used, int len)
687 struct ip_set *set = ip_set_list[index];
688 struct ip_set_list *set_list;
690 /* Pointer to our header */
691 set_list = data + *used;
693 DP("set: %s, used: %d len %u %p %p", set->name, *used, len, data, data + *used);
695 /* Get and ensure header size */
696 if (*used + ALIGNED(sizeof(struct ip_set_list)) > len)
697 goto not_enough_mem;
698 *used += ALIGNED(sizeof(struct ip_set_list));
700 read_lock_bh(&set->lock);
701 /* Get and ensure set specific header size */
702 set_list->header_size = ALIGNED(set->type->header_size);
703 if (*used + set_list->header_size > len)
704 goto unlock_set;
706 /* Fill in the header */
707 set_list->index = index;
708 set_list->binding = IP_SET_INVALID_ID;
709 set_list->ref = atomic_read(&set->ref);
711 /* Fill in set spefific header data */
712 set->type->list_header(set, data + *used);
713 *used += set_list->header_size;
715 /* Get and ensure set specific members size */
716 set_list->members_size = set->type->list_members_size(set, DONT_ALIGN);
717 if (*used + set_list->members_size > len)
718 goto unlock_set;
720 /* Fill in set spefific members data */
721 set->type->list_members(set, data + *used, DONT_ALIGN);
722 *used += set_list->members_size;
723 read_unlock_bh(&set->lock);
725 /* Bindings */
726 set_list->bindings_size = 0;
728 return 0;
730 unlock_set:
731 read_unlock_bh(&set->lock);
732 not_enough_mem:
733 DP("not enough mem, try again");
734 return -EAGAIN;
738 * Save sets
740 static inline int
741 ip_set_save_marker(void *data, int *used, int len)
743 struct ip_set_save *set_save;
745 DP("used %u, len %u", *used, len);
746 /* Get and ensure header size */
747 if (*used + ALIGNED(sizeof(struct ip_set_save)) > len)
748 return -ENOMEM;
750 /* Marker: just for backward compatibility */
751 set_save = data + *used;
752 set_save->index = IP_SET_INVALID_ID;
753 set_save->header_size = 0;
754 set_save->members_size = 0;
755 *used += ALIGNED(sizeof(struct ip_set_save));
757 return 0;
760 static int
761 ip_set_save_set(ip_set_id_t index, void *data, int *used, int len)
763 struct ip_set *set;
764 struct ip_set_save *set_save;
766 /* Pointer to our header */
767 set_save = data + *used;
769 /* Get and ensure header size */
770 if (*used + ALIGNED(sizeof(struct ip_set_save)) > len)
771 goto not_enough_mem;
772 *used += ALIGNED(sizeof(struct ip_set_save));
774 set = ip_set_list[index];
775 DP("set: %s, used: %d(%d) %p %p", set->name, *used, len,
776 data, data + *used);
778 read_lock_bh(&set->lock);
779 /* Get and ensure set specific header size */
780 set_save->header_size = ALIGNED(set->type->header_size);
781 if (*used + set_save->header_size > len)
782 goto unlock_set;
784 /* Fill in the header */
785 set_save->index = index;
786 set_save->binding = IP_SET_INVALID_ID;
788 /* Fill in set spefific header data */
789 set->type->list_header(set, data + *used);
790 *used += set_save->header_size;
792 DP("set header filled: %s, used: %d(%lu) %p %p", set->name, *used,
793 (unsigned long)set_save->header_size, data, data + *used);
794 /* Get and ensure set specific members size */
795 set_save->members_size = set->type->list_members_size(set, DONT_ALIGN);
796 if (*used + set_save->members_size > len)
797 goto unlock_set;
799 /* Fill in set spefific members data */
800 set->type->list_members(set, data + *used, DONT_ALIGN);
801 *used += set_save->members_size;
802 read_unlock_bh(&set->lock);
803 DP("set members filled: %s, used: %d(%lu) %p %p", set->name, *used,
804 (unsigned long)set_save->members_size, data, data + *used);
805 return 0;
807 unlock_set:
808 read_unlock_bh(&set->lock);
809 not_enough_mem:
810 DP("not enough mem, try again");
811 return -EAGAIN;
815 * Restore sets
817 static int
818 ip_set_restore(void *data, int len)
820 int res = 0;
821 int line = 0, used = 0, members_size;
822 struct ip_set *set;
823 struct ip_set_restore *set_restore;
824 ip_set_id_t index;
826 /* Loop to restore sets */
827 while (1) {
828 line++;
830 DP("%d %zu %d", used, ALIGNED(sizeof(struct ip_set_restore)), len);
831 /* Get and ensure header size */
832 if (used + ALIGNED(sizeof(struct ip_set_restore)) > len)
833 return line;
834 set_restore = data + used;
835 used += ALIGNED(sizeof(struct ip_set_restore));
837 /* Ensure data size */
838 if (used
839 + set_restore->header_size
840 + set_restore->members_size > len)
841 return line;
843 /* Check marker */
844 if (set_restore->index == IP_SET_INVALID_ID) {
845 line--;
846 goto finish;
849 /* Try to create the set */
850 DP("restore %s %s", set_restore->name, set_restore->typename);
851 res = ip_set_create(set_restore->name,
852 set_restore->typename,
853 set_restore->index,
854 data + used,
855 set_restore->header_size);
857 if (res != 0)
858 return line;
859 used += ALIGNED(set_restore->header_size);
861 index = ip_set_find_byindex(set_restore->index);
862 DP("index %u, restore_index %u", index, set_restore->index);
863 if (index != set_restore->index)
864 return line;
865 /* Try to restore members data */
866 set = ip_set_list[index];
867 members_size = 0;
868 DP("members_size %lu reqsize %lu",
869 (unsigned long)set_restore->members_size,
870 (unsigned long)set->type->reqsize);
871 while (members_size + ALIGNED(set->type->reqsize) <=
872 set_restore->members_size) {
873 line++;
874 DP("members: %d, line %d", members_size, line);
875 res = ip_set_addip(set,
876 data + used + members_size,
877 set->type->reqsize);
878 if (!(res == 0 || res == -EEXIST))
879 return line;
880 members_size += ALIGNED(set->type->reqsize);
883 DP("members_size %lu %d",
884 (unsigned long)set_restore->members_size, members_size);
885 if (members_size != set_restore->members_size)
886 return line++;
887 used += set_restore->members_size;
890 finish:
891 if (used != len)
892 return line;
894 return 0;
897 static int
898 ip_set_sockfn_set(struct sock *sk, int optval, void *user, unsigned int len)
900 void *data;
901 int res = 0; /* Assume OK */
902 size_t offset;
903 unsigned *op;
904 struct ip_set_req_adt *req_adt;
905 ip_set_id_t index = IP_SET_INVALID_ID;
906 int (*adtfn)(struct ip_set *set,
907 const void *data, u_int32_t size);
908 struct fn_table {
909 int (*fn)(struct ip_set *set,
910 const void *data, u_int32_t size);
911 } adtfn_table[] =
912 { { ip_set_addip }, { ip_set_delip }, { ip_set_testip},
915 DP("optval=%d, user=%p, len=%d", optval, user, len);
916 if (!capable(CAP_NET_ADMIN))
917 return -EPERM;
918 if (optval != SO_IP_SET)
919 return -EBADF;
920 if (len <= sizeof(unsigned)) {
921 ip_set_printk("short userdata (want >%zu, got %u)",
922 sizeof(unsigned), len);
923 return -EINVAL;
925 data = vmalloc(len);
926 if (!data) {
927 DP("out of mem for %u bytes", len);
928 return -ENOMEM;
930 if (copy_from_user(data, user, len) != 0) {
931 res = -EFAULT;
932 goto cleanup;
934 if (down_interruptible(&ip_set_app_mutex)) {
935 res = -EINTR;
936 goto cleanup;
939 op = (unsigned *)data;
940 DP("op=%x", *op);
942 if (*op < IP_SET_OP_VERSION) {
943 /* Check the version at the beginning of operations */
944 struct ip_set_req_version *req_version = data;
945 if (!(req_version->version == IP_SET_PROTOCOL_UNALIGNED
946 || req_version->version == IP_SET_PROTOCOL_VERSION)) {
947 res = -EPROTO;
948 goto done;
950 protocol_version = req_version->version;
953 switch (*op) {
954 case IP_SET_OP_CREATE:{
955 struct ip_set_req_create *req_create = data;
956 offset = ALIGNED(sizeof(struct ip_set_req_create));
958 if (len < offset) {
959 ip_set_printk("short CREATE data (want >=%zu, got %u)",
960 offset, len);
961 res = -EINVAL;
962 goto done;
964 req_create->name[IP_SET_MAXNAMELEN - 1] = '\0';
965 req_create->typename[IP_SET_MAXNAMELEN - 1] = '\0';
966 res = ip_set_create(req_create->name,
967 req_create->typename,
968 IP_SET_INVALID_ID,
969 data + offset,
970 len - offset);
971 goto done;
973 case IP_SET_OP_DESTROY:{
974 struct ip_set_req_std *req_destroy = data;
976 if (len != sizeof(struct ip_set_req_std)) {
977 ip_set_printk("invalid DESTROY data (want %zu, got %u)",
978 sizeof(struct ip_set_req_std), len);
979 res = -EINVAL;
980 goto done;
982 if (STREQ(req_destroy->name, IPSET_TOKEN_ALL)) {
983 /* Destroy all sets */
984 index = IP_SET_INVALID_ID;
985 } else {
986 req_destroy->name[IP_SET_MAXNAMELEN - 1] = '\0';
987 index = ip_set_find_byname(req_destroy->name);
989 if (index == IP_SET_INVALID_ID) {
990 res = -ENOENT;
991 goto done;
995 res = ip_set_destroy(index);
996 goto done;
998 case IP_SET_OP_FLUSH:{
999 struct ip_set_req_std *req_flush = data;
1001 if (len != sizeof(struct ip_set_req_std)) {
1002 ip_set_printk("invalid FLUSH data (want %zu, got %u)",
1003 sizeof(struct ip_set_req_std), len);
1004 res = -EINVAL;
1005 goto done;
1007 if (STREQ(req_flush->name, IPSET_TOKEN_ALL)) {
1008 /* Flush all sets */
1009 index = IP_SET_INVALID_ID;
1010 } else {
1011 req_flush->name[IP_SET_MAXNAMELEN - 1] = '\0';
1012 index = ip_set_find_byname(req_flush->name);
1014 if (index == IP_SET_INVALID_ID) {
1015 res = -ENOENT;
1016 goto done;
1019 res = ip_set_flush(index);
1020 goto done;
1022 case IP_SET_OP_RENAME:{
1023 struct ip_set_req_create *req_rename = data;
1025 if (len != sizeof(struct ip_set_req_create)) {
1026 ip_set_printk("invalid RENAME data (want %zu, got %u)",
1027 sizeof(struct ip_set_req_create), len);
1028 res = -EINVAL;
1029 goto done;
1032 req_rename->name[IP_SET_MAXNAMELEN - 1] = '\0';
1033 req_rename->typename[IP_SET_MAXNAMELEN - 1] = '\0';
1035 index = ip_set_find_byname(req_rename->name);
1036 if (index == IP_SET_INVALID_ID) {
1037 res = -ENOENT;
1038 goto done;
1040 res = ip_set_rename(index, req_rename->typename);
1041 goto done;
1043 case IP_SET_OP_SWAP:{
1044 struct ip_set_req_create *req_swap = data;
1045 ip_set_id_t to_index;
1047 if (len != sizeof(struct ip_set_req_create)) {
1048 ip_set_printk("invalid SWAP data (want %zu, got %u)",
1049 sizeof(struct ip_set_req_create), len);
1050 res = -EINVAL;
1051 goto done;
1054 req_swap->name[IP_SET_MAXNAMELEN - 1] = '\0';
1055 req_swap->typename[IP_SET_MAXNAMELEN - 1] = '\0';
1057 index = ip_set_find_byname(req_swap->name);
1058 if (index == IP_SET_INVALID_ID) {
1059 res = -ENOENT;
1060 goto done;
1062 to_index = ip_set_find_byname(req_swap->typename);
1063 if (to_index == IP_SET_INVALID_ID) {
1064 res = -ENOENT;
1065 goto done;
1067 res = ip_set_swap(index, to_index);
1068 goto done;
1070 default:
1071 break; /* Set identified by id */
1074 /* There we may have add/del/test/bind/unbind/test_bind operations */
1075 if (*op < IP_SET_OP_ADD_IP || *op > IP_SET_OP_TEST_IP) {
1076 res = -EBADMSG;
1077 goto done;
1079 adtfn = adtfn_table[*op - IP_SET_OP_ADD_IP].fn;
1081 if (len < ALIGNED(sizeof(struct ip_set_req_adt))) {
1082 ip_set_printk("short data in adt request (want >=%zu, got %u)",
1083 ALIGNED(sizeof(struct ip_set_req_adt)), len);
1084 res = -EINVAL;
1085 goto done;
1087 req_adt = data;
1089 index = ip_set_find_byindex(req_adt->index);
1090 if (index == IP_SET_INVALID_ID) {
1091 res = -ENOENT;
1092 goto done;
1094 do {
1095 struct ip_set *set = ip_set_list[index];
1096 size_t offset = ALIGNED(sizeof(struct ip_set_req_adt));
1098 IP_SET_ASSERT(set);
1100 if (len - offset != set->type->reqsize) {
1101 ip_set_printk("data length wrong (want %lu, have %zu)",
1102 (long unsigned)set->type->reqsize,
1103 len - offset);
1104 res = -EINVAL;
1105 goto done;
1107 res = adtfn(set, data + offset, len - offset);
1108 } while (0);
1110 done:
1111 up(&ip_set_app_mutex);
1112 cleanup:
1113 vfree(data);
1114 if (res > 0)
1115 res = 0;
1116 DP("final result %d", res);
1117 return res;
1120 static int
1121 ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len)
1123 int res = 0;
1124 unsigned *op;
1125 ip_set_id_t index = IP_SET_INVALID_ID;
1126 void *data;
1127 int copylen = *len;
1129 DP("optval=%d, user=%p, len=%d", optval, user, *len);
1130 if (!capable(CAP_NET_ADMIN))
1131 return -EPERM;
1132 if (optval != SO_IP_SET)
1133 return -EBADF;
1134 if (*len < sizeof(unsigned)) {
1135 ip_set_printk("short userdata (want >=%zu, got %d)",
1136 sizeof(unsigned), *len);
1137 return -EINVAL;
1139 data = vmalloc(*len);
1140 if (!data) {
1141 DP("out of mem for %d bytes", *len);
1142 return -ENOMEM;
1144 if (copy_from_user(data, user, *len) != 0) {
1145 res = -EFAULT;
1146 goto cleanup;
1148 if (down_interruptible(&ip_set_app_mutex)) {
1149 res = -EINTR;
1150 goto cleanup;
1153 op = (unsigned *) data;
1154 DP("op=%x", *op);
1156 if (*op < IP_SET_OP_VERSION) {
1157 /* Check the version at the beginning of operations */
1158 struct ip_set_req_version *req_version = data;
1159 if (!(req_version->version == IP_SET_PROTOCOL_UNALIGNED
1160 || req_version->version == IP_SET_PROTOCOL_VERSION)) {
1161 res = -EPROTO;
1162 goto done;
1164 protocol_version = req_version->version;
1167 switch (*op) {
1168 case IP_SET_OP_VERSION: {
1169 struct ip_set_req_version *req_version = data;
1171 if (*len != sizeof(struct ip_set_req_version)) {
1172 ip_set_printk("invalid VERSION (want %zu, got %d)",
1173 sizeof(struct ip_set_req_version),
1174 *len);
1175 res = -EINVAL;
1176 goto done;
1179 req_version->version = IP_SET_PROTOCOL_VERSION;
1180 res = copy_to_user(user, req_version,
1181 sizeof(struct ip_set_req_version));
1182 goto done;
1184 case IP_SET_OP_GET_BYNAME: {
1185 struct ip_set_req_get_set *req_get = data;
1187 if (*len != sizeof(struct ip_set_req_get_set)) {
1188 ip_set_printk("invalid GET_BYNAME (want %zu, got %d)",
1189 sizeof(struct ip_set_req_get_set), *len);
1190 res = -EINVAL;
1191 goto done;
1193 req_get->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
1194 index = ip_set_find_byname(req_get->set.name);
1195 req_get->set.index = index;
1196 goto copy;
1198 case IP_SET_OP_GET_BYINDEX: {
1199 struct ip_set_req_get_set *req_get = data;
1201 if (*len != sizeof(struct ip_set_req_get_set)) {
1202 ip_set_printk("invalid GET_BYINDEX (want %zu, got %d)",
1203 sizeof(struct ip_set_req_get_set), *len);
1204 res = -EINVAL;
1205 goto done;
1207 req_get->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
1208 index = ip_set_find_byindex(req_get->set.index);
1209 strncpy(req_get->set.name,
1210 index == IP_SET_INVALID_ID ? ""
1211 : ip_set_list[index]->name, IP_SET_MAXNAMELEN);
1212 goto copy;
1214 case IP_SET_OP_ADT_GET: {
1215 struct ip_set_req_adt_get *req_get = data;
1217 if (*len != sizeof(struct ip_set_req_adt_get)) {
1218 ip_set_printk("invalid ADT_GET (want %zu, got %d)",
1219 sizeof(struct ip_set_req_adt_get), *len);
1220 res = -EINVAL;
1221 goto done;
1223 req_get->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
1224 index = ip_set_find_byname(req_get->set.name);
1225 if (index != IP_SET_INVALID_ID) {
1226 req_get->set.index = index;
1227 strncpy(req_get->typename,
1228 ip_set_list[index]->type->typename,
1229 IP_SET_MAXNAMELEN - 1);
1230 } else {
1231 res = -ENOENT;
1232 goto done;
1234 goto copy;
1236 case IP_SET_OP_MAX_SETS: {
1237 struct ip_set_req_max_sets *req_max_sets = data;
1238 ip_set_id_t i;
1240 if (*len != sizeof(struct ip_set_req_max_sets)) {
1241 ip_set_printk("invalid MAX_SETS (want %zu, got %d)",
1242 sizeof(struct ip_set_req_max_sets), *len);
1243 res = -EINVAL;
1244 goto done;
1247 if (STREQ(req_max_sets->set.name, IPSET_TOKEN_ALL)) {
1248 req_max_sets->set.index = IP_SET_INVALID_ID;
1249 } else {
1250 req_max_sets->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
1251 req_max_sets->set.index =
1252 ip_set_find_byname(req_max_sets->set.name);
1253 if (req_max_sets->set.index == IP_SET_INVALID_ID) {
1254 res = -ENOENT;
1255 goto done;
1258 req_max_sets->max_sets = ip_set_max;
1259 req_max_sets->sets = 0;
1260 for (i = 0; i < ip_set_max; i++) {
1261 if (ip_set_list[i] != NULL)
1262 req_max_sets->sets++;
1264 goto copy;
1266 case IP_SET_OP_LIST_SIZE:
1267 case IP_SET_OP_SAVE_SIZE: {
1268 struct ip_set_req_setnames *req_setnames = data;
1269 struct ip_set_name_list *name_list;
1270 struct ip_set *set;
1271 ip_set_id_t i;
1272 int used;
1274 if (*len < ALIGNED(sizeof(struct ip_set_req_setnames))) {
1275 ip_set_printk("short LIST_SIZE (want >=%zu, got %d)",
1276 ALIGNED(sizeof(struct ip_set_req_setnames)),
1277 *len);
1278 res = -EINVAL;
1279 goto done;
1282 req_setnames->size = 0;
1283 used = ALIGNED(sizeof(struct ip_set_req_setnames));
1284 for (i = 0; i < ip_set_max; i++) {
1285 if (ip_set_list[i] == NULL)
1286 continue;
1287 name_list = data + used;
1288 used += ALIGNED(sizeof(struct ip_set_name_list));
1289 if (used > copylen) {
1290 res = -EAGAIN;
1291 goto done;
1293 set = ip_set_list[i];
1294 /* Fill in index, name, etc. */
1295 name_list->index = i;
1296 name_list->id = set->id;
1297 strncpy(name_list->name,
1298 set->name,
1299 IP_SET_MAXNAMELEN - 1);
1300 strncpy(name_list->typename,
1301 set->type->typename,
1302 IP_SET_MAXNAMELEN - 1);
1303 DP("filled %s of type %s, index %u\n",
1304 name_list->name, name_list->typename,
1305 name_list->index);
1306 if (!(req_setnames->index == IP_SET_INVALID_ID
1307 || req_setnames->index == i))
1308 continue;
1309 /* Update size */
1310 req_setnames->size +=
1311 (*op == IP_SET_OP_LIST_SIZE ?
1312 ALIGNED(sizeof(struct ip_set_list)) :
1313 ALIGNED(sizeof(struct ip_set_save)))
1314 + ALIGNED(set->type->header_size)
1315 + set->type->list_members_size(set, DONT_ALIGN);
1317 if (copylen != used) {
1318 res = -EAGAIN;
1319 goto done;
1321 goto copy;
1323 case IP_SET_OP_LIST: {
1324 struct ip_set_req_list *req_list = data;
1325 ip_set_id_t i;
1326 int used;
1328 if (*len < sizeof(struct ip_set_req_list)) {
1329 ip_set_printk("short LIST (want >=%zu, got %d)",
1330 sizeof(struct ip_set_req_list), *len);
1331 res = -EINVAL;
1332 goto done;
1334 index = req_list->index;
1335 if (index != IP_SET_INVALID_ID
1336 && ip_set_find_byindex(index) != index) {
1337 res = -ENOENT;
1338 goto done;
1340 used = 0;
1341 if (index == IP_SET_INVALID_ID) {
1342 /* List all sets */
1343 for (i = 0; i < ip_set_max && res == 0; i++) {
1344 if (ip_set_list[i] != NULL)
1345 res = ip_set_list_set(i, data, &used, *len);
1347 } else {
1348 /* List an individual set */
1349 res = ip_set_list_set(index, data, &used, *len);
1351 if (res != 0)
1352 goto done;
1353 else if (copylen != used) {
1354 res = -EAGAIN;
1355 goto done;
1357 goto copy;
1359 case IP_SET_OP_SAVE: {
1360 struct ip_set_req_list *req_save = data;
1361 ip_set_id_t i;
1362 int used;
1364 if (*len < sizeof(struct ip_set_req_list)) {
1365 ip_set_printk("short SAVE (want >=%zu, got %d)",
1366 sizeof(struct ip_set_req_list), *len);
1367 res = -EINVAL;
1368 goto done;
1370 index = req_save->index;
1371 if (index != IP_SET_INVALID_ID
1372 && ip_set_find_byindex(index) != index) {
1373 res = -ENOENT;
1374 goto done;
1377 #define SETLIST(set) (strcmp(set->type->typename, "setlist") == 0)
1379 used = 0;
1380 if (index == IP_SET_INVALID_ID) {
1381 /* Save all sets: ugly setlist type dependency */
1382 int setlist = 0;
1383 setlists:
1384 for (i = 0; i < ip_set_max && res == 0; i++) {
1385 if (ip_set_list[i] != NULL
1386 && !(setlist ^ SETLIST(ip_set_list[i])))
1387 res = ip_set_save_set(i, data, &used, *len);
1389 if (!setlist) {
1390 setlist = 1;
1391 goto setlists;
1393 } else {
1394 /* Save an individual set */
1395 res = ip_set_save_set(index, data, &used, *len);
1397 if (res == 0)
1398 res = ip_set_save_marker(data, &used, *len);
1400 if (res != 0)
1401 goto done;
1402 else if (copylen != used) {
1403 res = -EAGAIN;
1404 goto done;
1406 goto copy;
1408 case IP_SET_OP_RESTORE: {
1409 struct ip_set_req_setnames *req_restore = data;
1410 size_t offset = ALIGNED(sizeof(struct ip_set_req_setnames));
1411 int line;
1413 if (*len < offset || *len != req_restore->size) {
1414 ip_set_printk("invalid RESTORE (want =%lu, got %d)",
1415 (long unsigned)req_restore->size, *len);
1416 res = -EINVAL;
1417 goto done;
1419 line = ip_set_restore(data + offset, req_restore->size - offset);
1420 DP("ip_set_restore: %d", line);
1421 if (line != 0) {
1422 res = -EAGAIN;
1423 req_restore->size = line;
1424 copylen = sizeof(struct ip_set_req_setnames);
1425 goto copy;
1427 goto done;
1429 default:
1430 res = -EBADMSG;
1431 goto done;
1432 } /* end of switch(op) */
1434 copy:
1435 DP("set %s, copylen %d", index != IP_SET_INVALID_ID
1436 && ip_set_list[index]
1437 ? ip_set_list[index]->name
1438 : ":all:", copylen);
1439 res = copy_to_user(user, data, copylen);
1441 done:
1442 up(&ip_set_app_mutex);
1443 cleanup:
1444 vfree(data);
1445 if (res > 0)
1446 res = 0;
1447 DP("final result %d", res);
1448 return res;
1451 static struct nf_sockopt_ops so_set = {
1452 .pf = PF_INET,
1453 .set_optmin = SO_IP_SET,
1454 .set_optmax = SO_IP_SET + 1,
1455 .set = &ip_set_sockfn_set,
1456 .get_optmin = SO_IP_SET,
1457 .get_optmax = SO_IP_SET + 1,
1458 .get = &ip_set_sockfn_get,
1459 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
1460 .use = 0,
1461 #else
1462 .owner = THIS_MODULE,
1463 #endif
1466 static int max_sets;
1468 module_param(max_sets, int, 0600);
1469 MODULE_PARM_DESC(max_sets, "maximal number of sets");
1470 MODULE_LICENSE("GPL");
1471 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
1472 MODULE_DESCRIPTION("module implementing core IP set support");
1474 static int __init
1475 ip_set_init(void)
1477 int res;
1479 /* For the -rt branch, DECLARE_MUTEX/init_MUTEX avoided */
1480 sema_init(&ip_set_app_mutex, 1);
1482 if (max_sets)
1483 ip_set_max = max_sets;
1484 if (ip_set_max >= IP_SET_INVALID_ID)
1485 ip_set_max = IP_SET_INVALID_ID - 1;
1487 ip_set_list = vmalloc(sizeof(struct ip_set *) * ip_set_max);
1488 if (!ip_set_list) {
1489 printk(KERN_ERR "Unable to create ip_set_list\n");
1490 return -ENOMEM;
1492 memset(ip_set_list, 0, sizeof(struct ip_set *) * ip_set_max);
1494 INIT_LIST_HEAD(&set_type_list);
1496 res = nf_register_sockopt(&so_set);
1497 if (res != 0) {
1498 ip_set_printk("SO_SET registry failed: %d", res);
1499 vfree(ip_set_list);
1500 return res;
1503 printk("ip_set version %u loaded\n", IP_SET_PROTOCOL_VERSION);
1504 return 0;
1507 static void __exit
1508 ip_set_fini(void)
1510 /* There can't be any existing set or binding */
1511 nf_unregister_sockopt(&so_set);
1512 vfree(ip_set_list);
1513 DP("these are the famous last words");
1516 EXPORT_SYMBOL(ip_set_register_set_type);
1517 EXPORT_SYMBOL(ip_set_unregister_set_type);
1519 EXPORT_SYMBOL(ip_set_get_byname);
1520 EXPORT_SYMBOL(ip_set_get_byindex);
1521 EXPORT_SYMBOL(ip_set_put_byindex);
1522 EXPORT_SYMBOL(ip_set_id);
1523 EXPORT_SYMBOL(__ip_set_get_byname);
1524 EXPORT_SYMBOL(__ip_set_put_byindex);
1526 EXPORT_SYMBOL(ip_set_addip_kernel);
1527 EXPORT_SYMBOL(ip_set_delip_kernel);
1528 EXPORT_SYMBOL(ip_set_testip_kernel);
1530 module_init(ip_set_init);
1531 module_exit(ip_set_fini);