1 /* Copyright (C) 2003-2008 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
8 /* Kernel module implementing a cidr nethash set */
10 #include <linux/module.h>
11 #include <linux/moduleparam.h>
13 #include <linux/skbuff.h>
14 #include <linux/netfilter_ipv4/ip_set_jhash.h>
15 #include <linux/errno.h>
16 #include <asm/uaccess.h>
17 #include <asm/bitops.h>
18 #include <linux/spinlock.h>
19 #include <linux/random.h>
23 #include <linux/netfilter_ipv4/ip_set_nethash.h>
25 static int limit
= MAX_RANGE
;
28 nethash_id_cidr(const struct ip_set_nethash
*map
,
36 ip
= pack_ip_cidr(ip
, cidr
);
40 for (i
= 0; i
< map
->probes
; i
++) {
41 id
= jhash_ip(map
, i
, ip
) % map
->hashsize
;
42 DP("hash key: %u", id
);
43 elem
= HARRAY_ELEM(map
->members
, ip_set_ip_t
*, id
);
46 /* No shortcut - there can be deleted entries. */
52 nethash_id(struct ip_set
*set
, ip_set_ip_t ip
)
54 const struct ip_set_nethash
*map
= set
->data
;
58 for (i
= 0; i
< 30 && map
->cidr
[i
]; i
++) {
59 id
= nethash_id_cidr(map
, ip
, map
->cidr
[i
]);
67 nethash_test_cidr(struct ip_set
*set
, ip_set_ip_t ip
, uint8_t cidr
)
69 const struct ip_set_nethash
*map
= set
->data
;
71 return (nethash_id_cidr(map
, ip
, cidr
) != UINT_MAX
);
75 nethash_test(struct ip_set
*set
, ip_set_ip_t ip
)
77 return (nethash_id(set
, ip
) != UINT_MAX
);
81 nethash_utest(struct ip_set
*set
, const void *data
, u_int32_t size
)
83 const struct ip_set_req_nethash
*req
= data
;
85 if (req
->cidr
<= 0 || req
->cidr
> 32)
87 return (req
->cidr
== 32 ? nethash_test(set
, req
->ip
)
88 : nethash_test_cidr(set
, req
->ip
, req
->cidr
));
91 #define KADT_CONDITION
93 KADT(nethash
, test
, ipaddr
)
96 __nethash_add(struct ip_set_nethash
*map
, ip_set_ip_t
*ip
)
100 ip_set_ip_t
*elem
, *slot
= NULL
;
102 for (i
= 0; i
< map
->probes
; i
++) {
103 probe
= jhash_ip(map
, i
, *ip
) % map
->hashsize
;
104 elem
= HARRAY_ELEM(map
->members
, ip_set_ip_t
*, probe
);
107 if (!(slot
|| *elem
))
109 /* There can be deleted entries, must check all slots */
116 /* Trigger rehashing */
121 nethash_add(struct ip_set
*set
, ip_set_ip_t ip
, uint8_t cidr
)
123 struct ip_set_nethash
*map
= set
->data
;
126 if (map
->elements
>= limit
|| map
->nets
[cidr
-1] == UINT16_MAX
)
128 if (cidr
<= 0 || cidr
>= 32)
131 ip
= pack_ip_cidr(ip
, cidr
);
135 ret
= __nethash_add(map
, &ip
);
137 if (!map
->nets
[cidr
-1]++)
138 add_cidr_size(map
->cidr
, cidr
);
144 #undef KADT_CONDITION
145 #define KADT_CONDITION \
146 struct ip_set_nethash *map = set->data; \
147 uint8_t cidr = map->cidr[0] ? map->cidr[0] : 31;
149 UADT(nethash
, add
, req
->cidr
)
150 KADT(nethash
, add
, ipaddr
, cidr
)
153 __nethash_retry(struct ip_set_nethash
*tmp
, struct ip_set_nethash
*map
)
155 memcpy(tmp
->cidr
, map
->cidr
, sizeof(tmp
->cidr
));
156 memcpy(tmp
->nets
, map
->nets
, sizeof(tmp
->nets
));
159 HASH_RETRY(nethash
, ip_set_ip_t
)
162 nethash_del(struct ip_set
*set
, ip_set_ip_t ip
, uint8_t cidr
)
164 struct ip_set_nethash
*map
= set
->data
;
165 ip_set_ip_t id
, *elem
;
167 if (cidr
<= 0 || cidr
>= 32)
170 id
= nethash_id_cidr(map
, ip
, cidr
);
174 elem
= HARRAY_ELEM(map
->members
, ip_set_ip_t
*, id
);
177 if (!map
->nets
[cidr
-1]--)
178 del_cidr_size(map
->cidr
, cidr
);
182 UADT(nethash
, del
, req
->cidr
)
183 KADT(nethash
, del
, ipaddr
, cidr
)
186 __nethash_create(const struct ip_set_req_nethash_create
*req
,
187 struct ip_set_nethash
*map
)
189 memset(map
->cidr
, 0, sizeof(map
->cidr
));
190 memset(map
->nets
, 0, sizeof(map
->nets
));
195 HASH_CREATE(nethash
, ip_set_ip_t
)
196 HASH_DESTROY(nethash
)
198 HASH_FLUSH_CIDR(nethash
, ip_set_ip_t
)
201 __nethash_list_header(const struct ip_set_nethash
*map
,
202 struct ip_set_req_nethash_create
*header
)
206 HASH_LIST_HEADER(nethash
)
207 HASH_LIST_MEMBERS_SIZE(nethash
, ip_set_ip_t
)
208 HASH_LIST_MEMBERS(nethash
, ip_set_ip_t
)
210 IP_SET_RTYPE(nethash
, IPSET_TYPE_IP
| IPSET_DATA_SINGLE
)
212 MODULE_LICENSE("GPL");
213 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
214 MODULE_DESCRIPTION("nethash type of IP sets");
215 module_param(limit
, int, 0600);
216 MODULE_PARM_DESC(limit
, "maximal number of elements stored in the sets");
218 REGISTER_MODULE(nethash
)