#include <linux/random.h>
#include <linux/jhash.h>
#include <linux/errno.h>
+#include <linux/capability.h>
#include <asm/uaccess.h>
#include <asm/bitops.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
#include <linux/semaphore.h>
#endif
#include <linux/spinlock.h>
-#include <linux/capability.h>
#define ASSERT_READ_LOCK(x)
#define ASSERT_WRITE_LOCK(x)
return index;
}
-void __ip_set_put_byid(ip_set_id_t index)
+void __ip_set_put_byindex(ip_set_id_t index)
{
if (ip_set_list[index])
__ip_set_put(index);
return index;
}
+/*
+ * Find the set id belonging to the index.
+ * We are protected by the mutex, so we do not need to use
+ * ip_set_lock. There is no need to reference the sets either.
+ */
+ip_set_id_t
+ip_set_id(ip_set_id_t index)
+{
+ if (index >= ip_set_max || !ip_set_list[index])
+ return IP_SET_INVALID_ID;
+
+ return ip_set_list[index]->id;
+}
+
/*
* If the given set pointer points to a valid set, decrement
* reference count by 1. The caller shall not assume the index
* to be valid, after calling this function.
*/
-void ip_set_put(ip_set_id_t index)
+void ip_set_put_byindex(ip_set_id_t index)
{
down(&ip_set_app_mutex);
if (ip_set_list[index])
EXPORT_SYMBOL(ip_set_get_byname);
EXPORT_SYMBOL(ip_set_get_byindex);
-EXPORT_SYMBOL(ip_set_put);
+EXPORT_SYMBOL(ip_set_put_byindex);
+EXPORT_SYMBOL(ip_set_id);
EXPORT_SYMBOL(__ip_set_get_byname);
-EXPORT_SYMBOL(__ip_set_put_byid);
+EXPORT_SYMBOL(__ip_set_put_byindex);
EXPORT_SYMBOL(ip_set_addip_kernel);
EXPORT_SYMBOL(ip_set_delip_kernel);
#include "ip_set_setlist.h"
/*
- * before ==> id, ref
- * after ==> ref, id
+ * before ==> index, ref
+ * after ==> ref, index
*/
static inline bool
-next_id_eq(const struct ip_set_setlist *map, int i, ip_set_id_t id)
+next_index_eq(const struct ip_set_setlist *map, int i, ip_set_id_t index)
{
- return i < map->size && map->id[i] == id;
+ return i < map->size && map->index[i] == index;
}
static int
{
const struct ip_set_setlist *map = set->data;
const struct ip_set_req_setlist *req = data;
- ip_set_id_t id, ref = IP_SET_INVALID_ID;
+ ip_set_id_t index, ref = IP_SET_INVALID_ID;
int i, res = 0;
struct ip_set *s;
if (req->before && req->ref[0] == '\0')
return -EINVAL;
- id = __ip_set_get_byname(req->name, &s);
- if (id == IP_SET_INVALID_ID)
+ index = __ip_set_get_byname(req->name, &s);
+ if (index == IP_SET_INVALID_ID)
return -EEXIST;
if (req->ref[0] != '\0') {
ref = __ip_set_get_byname(req->ref, &s);
}
}
for (i = 0; i < map->size
- && map->id[i] != IP_SET_INVALID_ID; i++) {
- if (req->before && map->id[i] == id) {
- res = next_id_eq(map, i + 1, ref);
+ && map->index[i] != IP_SET_INVALID_ID; i++) {
+ if (req->before && map->index[i] == index) {
+ res = next_index_eq(map, i + 1, ref);
break;
} else if (!req->before) {
if ((ref == IP_SET_INVALID_ID
- && map->id[i] == id)
- || (map->id[i] == ref
- && next_id_eq(map, i + 1, id))) {
+ && map->index[i] == index)
+ || (map->index[i] == ref
+ && next_index_eq(map, i + 1, index))) {
res = 1;
break;
}
}
}
if (ref != IP_SET_INVALID_ID)
- __ip_set_put_byid(ref);
+ __ip_set_put_byindex(ref);
finish:
- __ip_set_put_byid(id);
+ __ip_set_put_byindex(index);
return res;
}
int i, res = 0;
for (i = 0; i < map->size
- && map->id[i] != IP_SET_INVALID_ID
+ && map->index[i] != IP_SET_INVALID_ID
&& res == 0; i++)
- res = ip_set_testip_kernel(map->id[i], skb, flags);
+ res = ip_set_testip_kernel(map->index[i], skb, flags);
return res;
}
static inline int
-insert_setlist(struct ip_set_setlist *map, int i, ip_set_id_t id)
+insert_setlist(struct ip_set_setlist *map, int i, ip_set_id_t index)
{
ip_set_id_t tmp;
int j;
- printk("i: %u, last %u\n", i, map->id[map->size - 1]);
- if (i >= map->size || map->id[map->size - 1] != IP_SET_INVALID_ID)
+ DP("i: %u, last %u\n", i, map->index[map->size - 1]);
+ if (i >= map->size || map->index[map->size - 1] != IP_SET_INVALID_ID)
return -ERANGE;
for (j = i; j < map->size
- && id != IP_SET_INVALID_ID; j++) {
- tmp = map->id[j];
- map->id[j] = id;
- id = tmp;
+ && index != IP_SET_INVALID_ID; j++) {
+ tmp = map->index[j];
+ map->index[j] = index;
+ index = tmp;
}
return 0;
}
{
struct ip_set_setlist *map = set->data;
const struct ip_set_req_setlist *req = data;
- ip_set_id_t id, ref = IP_SET_INVALID_ID;
+ ip_set_id_t index, ref = IP_SET_INVALID_ID;
int i, res = -ERANGE;
struct ip_set *s;
if (req->before && req->ref[0] == '\0')
return -EINVAL;
- id = __ip_set_get_byname(req->name, &s);
- if (id == IP_SET_INVALID_ID)
+ index = __ip_set_get_byname(req->name, &s);
+ if (index == IP_SET_INVALID_ID)
return -EEXIST;
/* "Loop detection" */
if (strcmp(s->type->typename, "setlist") == 0)
}
}
for (i = 0; i < map->size; i++) {
- if (map->id[i] != ref)
+ if (map->index[i] != ref)
continue;
if (req->before)
- res = insert_setlist(map, i, id);
+ res = insert_setlist(map, i, index);
else
res = insert_setlist(map,
ref == IP_SET_INVALID_ID ? i : i + 1,
- id);
+ index);
break;
}
if (ref != IP_SET_INVALID_ID)
- __ip_set_put_byid(ref);
- /* In case of success, we keep the reference to the id */
+ __ip_set_put_byindex(ref);
+ /* In case of success, we keep the reference to the set */
finish:
if (res != 0)
- __ip_set_put_byid(id);
+ __ip_set_put_byindex(index);
return res;
}
int i, res = -EINVAL;
for (i = 0; i < map->size
- && map->id[i] != IP_SET_INVALID_ID
+ && map->index[i] != IP_SET_INVALID_ID
&& res != 0; i++)
- res = ip_set_addip_kernel(map->id[i], skb, flags);
+ res = ip_set_addip_kernel(map->index[i], skb, flags);
return res;
}
int j;
for (j = i; j < map->size - 1; j++)
- map->id[j] = map->id[j+1];
- map->id[map->size-1] = IP_SET_INVALID_ID;
+ map->index[j] = map->index[j+1];
+ map->index[map->size-1] = IP_SET_INVALID_ID;
return 0;
}
{
struct ip_set_setlist *map = set->data;
const struct ip_set_req_setlist *req = data;
- ip_set_id_t id, ref = IP_SET_INVALID_ID;
+ ip_set_id_t index, ref = IP_SET_INVALID_ID;
int i, res = -EEXIST;
struct ip_set *s;
if (req->before && req->ref[0] == '\0')
return -EINVAL;
- id = __ip_set_get_byname(req->name, &s);
- if (id == IP_SET_INVALID_ID)
+ index = __ip_set_get_byname(req->name, &s);
+ if (index == IP_SET_INVALID_ID)
return -EEXIST;
if (req->ref[0] != '\0') {
ref = __ip_set_get_byname(req->ref, &s);
goto finish;
}
for (i = 0; i < map->size
- && map->id[i] != IP_SET_INVALID_ID; i++) {
+ && map->index[i] != IP_SET_INVALID_ID; i++) {
if (req->before) {
- if (map->id[i] == id
- && next_id_eq(map, i + 1, ref)) {
+ if (map->index[i] == index
+ && next_index_eq(map, i + 1, ref)) {
res = unshift_setlist(map, i);
break;
}
} else if (ref == IP_SET_INVALID_ID) {
- if (map->id[i] == id) {
+ if (map->index[i] == index) {
res = unshift_setlist(map, i);
break;
}
- } else if (map->id[i] == ref
- && next_id_eq(map, i + 1, id)) {
+ } else if (map->index[i] == ref
+ && next_index_eq(map, i + 1, index)) {
res = unshift_setlist(map, i + 1);
break;
}
}
if (ref != IP_SET_INVALID_ID)
- __ip_set_put_byid(ref);
+ __ip_set_put_byindex(ref);
finish:
- __ip_set_put_byid(id);
- /* In case of success, release the reference to the id */
+ __ip_set_put_byindex(index);
+ /* In case of success, release the reference to the set */
if (res == 0)
- __ip_set_put_byid(id);
+ __ip_set_put_byindex(index);
return res;
}
int i, res = -EINVAL;
for (i = 0; i < map->size
- && map->id[i] != IP_SET_INVALID_ID
+ && map->index[i] != IP_SET_INVALID_ID
&& res != 0; i++)
- res = ip_set_delip_kernel(map->id[i], skb, flags);
+ res = ip_set_delip_kernel(map->index[i], skb, flags);
return res;
}
return -ENOMEM;
map->size = req->size;
for (i = 0; i < map->size; i++)
- map->id[i] = IP_SET_INVALID_ID;
+ map->index[i] = IP_SET_INVALID_ID;
set->data = map;
return 0;
int i;
for (i = 0; i < map->size
- && map->id[i] != IP_SET_INVALID_ID; i++)
- __ip_set_put_byid(map->id[i]);
+ && map->index[i] != IP_SET_INVALID_ID; i++)
+ __ip_set_put_byindex(map->index[i]);
kfree(map);
set->data = NULL;
int i;
for (i = 0; i < map->size
- && map->id[i] != IP_SET_INVALID_ID; i++) {
- __ip_set_put_byid(map->id[i]);
- map->id[i] = IP_SET_INVALID_ID;
+ && map->index[i] != IP_SET_INVALID_ID; i++) {
+ __ip_set_put_byindex(map->index[i]);
+ map->index[i] = IP_SET_INVALID_ID;
}
}
int i;
for (i = 0; i < map->size; i++)
- *((ip_set_id_t *)data + i) = map->id[i];
+ *((ip_set_id_t *)data + i) = ip_set_id(map->index[i]);
}
IP_SET_TYPE(setlist, IPSET_TYPE_SETNAME | IPSET_DATA_SINGLE)