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_iphash.c
blob1accbe306c2acb4ab0e78bf52a7af2960b9e4b17
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.
6 */
8 /* Kernel module implementing an ip hash set */
10 #include <linux/module.h>
11 #include <linux/moduleparam.h>
12 #include <linux/ip.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>
21 #include <net/ip.h>
23 #include <linux/netfilter_ipv4/ip_set_iphash.h>
25 static int limit = MAX_RANGE;
27 static inline __u32
28 iphash_id(struct ip_set *set, ip_set_ip_t ip)
30 struct ip_set_iphash *map = set->data;
31 __u32 id;
32 u_int16_t i;
33 ip_set_ip_t *elem;
36 ip &= map->netmask;
37 DP("set: %s, ip:%u.%u.%u.%u", set->name, HIPQUAD(ip));
38 for (i = 0; i < map->probes; i++) {
39 id = jhash_ip(map, i, ip) % map->hashsize;
40 DP("hash key: %u", id);
41 elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
42 if (*elem == ip)
43 return id;
44 /* No shortcut - there can be deleted entries. */
46 return UINT_MAX;
49 static inline int
50 iphash_test(struct ip_set *set, ip_set_ip_t ip)
52 return (ip && iphash_id(set, ip) != UINT_MAX);
55 #define KADT_CONDITION
57 UADT(iphash, test)
58 KADT(iphash, test, ipaddr)
60 static inline int
61 __iphash_add(struct ip_set_iphash *map, ip_set_ip_t *ip)
63 __u32 probe;
64 u_int16_t i;
65 ip_set_ip_t *elem, *slot = NULL;
67 for (i = 0; i < map->probes; i++) {
68 probe = jhash_ip(map, i, *ip) % map->hashsize;
69 elem = HARRAY_ELEM(map->members, ip_set_ip_t *, probe);
70 if (*elem == *ip)
71 return -EEXIST;
72 if (!(slot || *elem))
73 slot = elem;
74 /* There can be deleted entries, must check all slots */
76 if (slot) {
77 *slot = *ip;
78 map->elements++;
79 return 0;
81 /* Trigger rehashing */
82 return -EAGAIN;
85 static inline int
86 iphash_add(struct ip_set *set, ip_set_ip_t ip)
88 struct ip_set_iphash *map = set->data;
90 if (!ip || map->elements >= limit)
91 return -ERANGE;
93 ip &= map->netmask;
94 return __iphash_add(map, &ip);
97 UADT(iphash, add)
98 KADT(iphash, add, ipaddr)
100 static inline void
101 __iphash_retry(struct ip_set_iphash *tmp, struct ip_set_iphash *map)
103 tmp->netmask = map->netmask;
106 HASH_RETRY(iphash, ip_set_ip_t)
108 static inline int
109 iphash_del(struct ip_set *set, ip_set_ip_t ip)
111 struct ip_set_iphash *map = set->data;
112 ip_set_ip_t id, *elem;
114 if (!ip)
115 return -ERANGE;
117 id = iphash_id(set, ip);
118 if (id == UINT_MAX)
119 return -EEXIST;
121 elem = HARRAY_ELEM(map->members, ip_set_ip_t *, id);
122 *elem = 0;
123 map->elements--;
125 return 0;
128 UADT(iphash, del)
129 KADT(iphash, del, ipaddr)
131 static inline int
132 __iphash_create(const struct ip_set_req_iphash_create *req,
133 struct ip_set_iphash *map)
135 map->netmask = req->netmask;
137 return 0;
140 HASH_CREATE(iphash, ip_set_ip_t)
141 HASH_DESTROY(iphash)
143 HASH_FLUSH(iphash, ip_set_ip_t)
145 static inline void
146 __iphash_list_header(const struct ip_set_iphash *map,
147 struct ip_set_req_iphash_create *header)
149 header->netmask = map->netmask;
152 HASH_LIST_HEADER(iphash)
153 HASH_LIST_MEMBERS_SIZE(iphash, ip_set_ip_t)
154 HASH_LIST_MEMBERS(iphash, ip_set_ip_t)
156 IP_SET_RTYPE(iphash, IPSET_TYPE_IP | IPSET_DATA_SINGLE)
158 MODULE_LICENSE("GPL");
159 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
160 MODULE_DESCRIPTION("iphash type of IP sets");
161 module_param(limit, int, 0600);
162 MODULE_PARM_DESC(limit, "maximal number of elements stored in the sets");
164 REGISTER_MODULE(iphash)