From a96e4fca10506462df4ee4035f0f86f09bd9dc34 Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Jozsef Kadlecsik/emailAddress=kadlec@blackhole.kfki.hu" Date: Mon, 20 Oct 2008 10:00:26 +0000 Subject: 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 --- kernel/ip_set.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 6 deletions(-) (limited to 'kernel/ip_set.c') 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 #include #include -#include #include #include #include @@ -30,10 +29,10 @@ #include #endif #include -#include #define ASSERT_READ_LOCK(x) #define ASSERT_WRITE_LOCK(x) +#include #include 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); -- cgit v1.2.3