summaryrefslogtreecommitdiffstats
path: root/kernel/ip_set.c
diff options
context:
space:
mode:
author/C=EU/ST=EU/CN=Jozsef Kadlecsik/emailAddress=kadlec@blackhole.kfki.hu </C=EU/ST=EU/CN=Jozsef Kadlecsik/emailAddress=kadlec@blackhole.kfki.hu>2008-10-20 10:00:26 +0000
committer/C=EU/ST=EU/CN=Jozsef Kadlecsik/emailAddress=kadlec@blackhole.kfki.hu </C=EU/ST=EU/CN=Jozsef Kadlecsik/emailAddress=kadlec@blackhole.kfki.hu>2008-10-20 10:00:26 +0000
commita96e4fca10506462df4ee4035f0f86f09bd9dc34 (patch)
tree103bed0a7ae3608675f371d2ac91f3fa7f3a58cc /kernel/ip_set.c
parentbc2ddd2d8da1252e78a1f25bd91c1e3cd8016ead (diff)
ipset 2.4 release
userspace changes: - Added KBUILD_OUTPUT support (Sven Wegener) - Fix memory leak in ipset_iptreemap (Sven Wegener) - Fix multiple compiler warnings (Sven Wegener) - ipportiphash, ipportnethash and setlist types added - binding marked as deprecated functionality - element separator token changed to ',' in anticipating IPv6 addresses, old separator tokens are still supported - unnecessary includes removed - ipset does not try to resolve IP addresses when listing the content of sets (default changed) - manpage updated - ChangeLog forked for kernel part kernel part changes: - ipportiphash, ipportnethash and setlist types added - set type modules reworked to avoid code duplication as much as possible, code unification macros - expand_macros Makefile target added to help debugging code unification macros - ip_set_addip_kernel and ip_set_delip_kernel changed from void to int, __ip_set_get_byname and __ip_set_put_byid added for the sake of setlist type - unnecessary includes removed - compatibility fix for kernels >= 2.6.27: semaphore.h was moved from asm/ to linux/ (James King) - ChangeLog forked for kernel part
Diffstat (limited to 'kernel/ip_set.c')
-rw-r--r--kernel/ip_set.c76
1 files changed, 70 insertions, 6 deletions
diff --git a/kernel/ip_set.c b/kernel/ip_set.c
index a525518..c4fcc69 100644
--- a/kernel/ip_set.c
+++ b/kernel/ip_set.c
@@ -20,7 +20,6 @@
#include <linux/skbuff.h>
#include <linux/random.h>
#include <linux/jhash.h>
-#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <asm/bitops.h>
@@ -30,10 +29,10 @@
#include <linux/semaphore.h>
#endif
#include <linux/spinlock.h>
-#include <linux/vmalloc.h>
#define ASSERT_READ_LOCK(x)
#define ASSERT_WRITE_LOCK(x)
+#include <linux/netfilter.h>
#include <linux/netfilter_ipv4/ip_set.h>
static struct list_head set_type_list; /* all registered sets */
@@ -235,10 +234,10 @@ ip_set_testip_kernel(ip_set_id_t index,
&& follow_bindings(index, set, ip));
read_unlock_bh(&ip_set_lock);
- return res;
+ return (res < 0 ? 0 : res);
}
-void
+int
ip_set_addip_kernel(ip_set_id_t index,
const struct sk_buff *skb,
const u_int32_t *flags)
@@ -268,9 +267,11 @@ ip_set_addip_kernel(ip_set_id_t index,
&& set->type->retry
&& (res = set->type->retry(set)) == 0)
goto retry;
+
+ return res;
}
-void
+int
ip_set_delip_kernel(ip_set_id_t index,
const struct sk_buff *skb,
const u_int32_t *flags)
@@ -294,6 +295,8 @@ ip_set_delip_kernel(ip_set_id_t index,
&& flags[i]
&& follow_bindings(index, set, ip));
read_unlock_bh(&ip_set_lock);
+
+ return res;
}
/* Register and deregister settype */
@@ -358,6 +361,29 @@ ip_set_unregister_set_type(struct ip_set_type *set_type)
}
+ip_set_id_t
+__ip_set_get_byname(const char *name, struct ip_set **set)
+{
+ ip_set_id_t i, index = IP_SET_INVALID_ID;
+
+ for (i = 0; i < ip_set_max; i++) {
+ if (ip_set_list[i] != NULL
+ && SETNAME_EQ(ip_set_list[i]->name, name)) {
+ __ip_set_get(i);
+ index = i;
+ *set = ip_set_list[i];
+ break;
+ }
+ }
+ return index;
+}
+
+void __ip_set_put_byid(ip_set_id_t index)
+{
+ if (ip_set_list[index])
+ __ip_set_put(index);
+}
+
/*
* Userspace routines
*/
@@ -490,7 +516,16 @@ ip_set_addip(ip_set_id_t index,
const void *data,
size_t size)
{
+ struct ip_set *set = ip_set_list[index];
+
+ IP_SET_ASSERT(set);
+ if (size - sizeof(struct ip_set_req_adt) != set->type->reqsize) {
+ ip_set_printk("data length wrong (want %zu, have %zu)",
+ set->type->reqsize,
+ size - sizeof(struct ip_set_req_adt));
+ return -EINVAL;
+ }
return __ip_set_addip(index,
data + sizeof(struct ip_set_req_adt),
size - sizeof(struct ip_set_req_adt));
@@ -506,6 +541,13 @@ ip_set_delip(ip_set_id_t index,
int res;
IP_SET_ASSERT(set);
+
+ if (size - sizeof(struct ip_set_req_adt) != set->type->reqsize) {
+ ip_set_printk("data length wrong (want %zu, have %zu)",
+ set->type->reqsize,
+ size - sizeof(struct ip_set_req_adt));
+ return -EINVAL;
+ }
write_lock_bh(&set->lock);
res = set->type->delip(set,
data + sizeof(struct ip_set_req_adt),
@@ -526,6 +568,13 @@ ip_set_testip(ip_set_id_t index,
int res;
IP_SET_ASSERT(set);
+
+ if (size - sizeof(struct ip_set_req_adt) != set->type->reqsize) {
+ ip_set_printk("data length wrong (want %zu, have %zu)",
+ set->type->reqsize,
+ size - sizeof(struct ip_set_req_adt));
+ return -EINVAL;
+ }
res = __ip_set_testip(set,
data + sizeof(struct ip_set_req_adt),
size - sizeof(struct ip_set_req_adt),
@@ -805,6 +854,7 @@ ip_set_create(const char *name,
int res = 0;
DP("setname: %s, typename: %s, id: %u", name, typename, restore);
+
/*
* First, and without any locks, allocate and initialize
* a normal base set structure.
@@ -848,6 +898,14 @@ ip_set_create(const char *name,
}
read_unlock_bh(&ip_set_lock);
+ /* Check request size */
+ if (size != set->type->header_size) {
+ ip_set_printk("data length wrong (want %zu, have %zu)",
+ set->type->header_size,
+ size);
+ goto put_out;
+ }
+
/*
* Without holding any locks, create private part.
*/
@@ -1007,7 +1065,9 @@ ip_set_swap(ip_set_id_t from_index, ip_set_id_t to_index)
u_int32_t from_ref;
DP("set: %s to %s", from->name, to->name);
- /* Features must not change. Artifical restriction. */
+ /* Features must not change.
+ * Not an artifical restriction anymore, as we must prevent
+ * possible loops created by swapping in setlist type of sets. */
if (from->type->features != to->type->features)
return -ENOEXEC;
@@ -1916,6 +1976,7 @@ static struct nf_sockopt_ops so_set = {
};
static int max_sets, hash_size;
+
module_param(max_sets, int, 0600);
MODULE_PARM_DESC(max_sets, "maximal number of sets");
module_param(hash_size, int, 0600);
@@ -1958,6 +2019,7 @@ static int __init ip_set_init(void)
vfree(ip_set_hash);
return res;
}
+
return 0;
}
@@ -1976,6 +2038,8 @@ EXPORT_SYMBOL(ip_set_unregister_set_type);
EXPORT_SYMBOL(ip_set_get_byname);
EXPORT_SYMBOL(ip_set_get_byindex);
EXPORT_SYMBOL(ip_set_put);
+EXPORT_SYMBOL(__ip_set_get_byname);
+EXPORT_SYMBOL(__ip_set_put_byid);
EXPORT_SYMBOL(ip_set_addip_kernel);
EXPORT_SYMBOL(ip_set_delip_kernel);