]> git.karo-electronics.de Git - karo-tx-linux.git/blob - net/netfilter/ipset/ip_set_hash_ip.c
Input: fix PWM-related undefined reference errors
[karo-tx-linux.git] / net / netfilter / ipset / ip_set_hash_ip.c
1 /* Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2  *
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  */
7
8 /* Kernel module implementing an IP set type: the hash:ip type */
9
10 #include <linux/jhash.h>
11 #include <linux/module.h>
12 #include <linux/ip.h>
13 #include <linux/skbuff.h>
14 #include <linux/errno.h>
15 #include <linux/random.h>
16 #include <net/ip.h>
17 #include <net/ipv6.h>
18 #include <net/netlink.h>
19 #include <net/tcp.h>
20
21 #include <linux/netfilter.h>
22 #include <linux/netfilter/ipset/pfxlen.h>
23 #include <linux/netfilter/ipset/ip_set.h>
24 #include <linux/netfilter/ipset/ip_set_hash.h>
25
26 #define REVISION_MIN    0
27 #define REVISION_MAX    1       /* Counters support */
28
29 MODULE_LICENSE("GPL");
30 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
31 IP_SET_MODULE_DESC("hash:ip", REVISION_MIN, REVISION_MAX);
32 MODULE_ALIAS("ip_set_hash:ip");
33
34 /* Type specific function prefix */
35 #define HTYPE           hash_ip
36 #define IP_SET_HASH_WITH_NETMASK
37
38 /* IPv4 variants */
39
40 /* Member elements */
41 struct hash_ip4_elem {
42         /* Zero valued IP addresses cannot be stored */
43         __be32 ip;
44 };
45
46 struct hash_ip4t_elem {
47         __be32 ip;
48         unsigned long timeout;
49 };
50
51 struct hash_ip4c_elem {
52         __be32 ip;
53         struct ip_set_counter counter;
54 };
55
56 struct hash_ip4ct_elem {
57         __be32 ip;
58         struct ip_set_counter counter;
59         unsigned long timeout;
60 };
61
62 /* Common functions */
63
64 static inline bool
65 hash_ip4_data_equal(const struct hash_ip4_elem *e1,
66                     const struct hash_ip4_elem *e2,
67                     u32 *multi)
68 {
69         return e1->ip == e2->ip;
70 }
71
72 static inline bool
73 hash_ip4_data_list(struct sk_buff *skb, const struct hash_ip4_elem *e)
74 {
75         if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, e->ip))
76                 goto nla_put_failure;
77         return 0;
78
79 nla_put_failure:
80         return 1;
81 }
82
83 static inline void
84 hash_ip4_data_next(struct hash_ip4_elem *next, const struct hash_ip4_elem *e)
85 {
86         next->ip = e->ip;
87 }
88
89 #define MTYPE           hash_ip4
90 #define PF              4
91 #define HOST_MASK       32
92 #include "ip_set_hash_gen.h"
93
94 static int
95 hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
96               const struct xt_action_param *par,
97               enum ipset_adt adt, struct ip_set_adt_opt *opt)
98 {
99         const struct hash_ip *h = set->data;
100         ipset_adtfn adtfn = set->variant->adt[adt];
101         struct hash_ip4_elem e = {};
102         struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
103         __be32 ip;
104
105         ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip);
106         ip &= ip_set_netmask(h->netmask);
107         if (ip == 0)
108                 return -EINVAL;
109
110         e.ip = ip;
111         return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
112 }
113
114 static int
115 hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
116               enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
117 {
118         const struct hash_ip *h = set->data;
119         ipset_adtfn adtfn = set->variant->adt[adt];
120         struct hash_ip4_elem e = {};
121         struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
122         u32 ip, ip_to, hosts;
123         int ret = 0;
124
125         if (unlikely(!tb[IPSET_ATTR_IP] ||
126                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
127                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
128                      !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES)))
129                 return -IPSET_ERR_PROTOCOL;
130
131         if (tb[IPSET_ATTR_LINENO])
132                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
133
134         ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
135               ip_set_get_extensions(set, tb, &ext);
136         if (ret)
137                 return ret;
138
139         ip &= ip_set_hostmask(h->netmask);
140
141         if (adt == IPSET_TEST) {
142                 e.ip = htonl(ip);
143                 if (e.ip == 0)
144                         return -IPSET_ERR_HASH_ELEM;
145                 return adtfn(set, &e, &ext, &ext, flags);
146         }
147
148         ip_to = ip;
149         if (tb[IPSET_ATTR_IP_TO]) {
150                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
151                 if (ret)
152                         return ret;
153                 if (ip > ip_to)
154                         swap(ip, ip_to);
155         } else if (tb[IPSET_ATTR_CIDR]) {
156                 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
157
158                 if (!cidr || cidr > 32)
159                         return -IPSET_ERR_INVALID_CIDR;
160                 ip_set_mask_from_to(ip, ip_to, cidr);
161         }
162
163         hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
164
165         if (retried)
166                 ip = ntohl(h->next.ip);
167         for (; !before(ip_to, ip); ip += hosts) {
168                 e.ip = htonl(ip);
169                 if (e.ip == 0)
170                         return -IPSET_ERR_HASH_ELEM;
171                 ret = adtfn(set, &e, &ext, &ext, flags);
172
173                 if (ret && !ip_set_eexist(ret, flags))
174                         return ret;
175                 else
176                         ret = 0;
177         }
178         return ret;
179 }
180
181 /* IPv6 variants */
182
183 /* Member elements */
184 struct hash_ip6_elem {
185         union nf_inet_addr ip;
186 };
187
188 struct hash_ip6t_elem {
189         union nf_inet_addr ip;
190         unsigned long timeout;
191 };
192
193 struct hash_ip6c_elem {
194         union nf_inet_addr ip;
195         struct ip_set_counter counter;
196 };
197
198 struct hash_ip6ct_elem {
199         union nf_inet_addr ip;
200         struct ip_set_counter counter;
201         unsigned long timeout;
202 };
203
204 /* Common functions */
205
206 static inline bool
207 hash_ip6_data_equal(const struct hash_ip6_elem *ip1,
208                     const struct hash_ip6_elem *ip2,
209                     u32 *multi)
210 {
211         return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6);
212 }
213
214 static inline void
215 hash_ip6_netmask(union nf_inet_addr *ip, u8 prefix)
216 {
217         ip6_netmask(ip, prefix);
218 }
219
220 static bool
221 hash_ip6_data_list(struct sk_buff *skb, const struct hash_ip6_elem *e)
222 {
223         if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6))
224                 goto nla_put_failure;
225         return 0;
226
227 nla_put_failure:
228         return 1;
229 }
230
231 static inline void
232 hash_ip6_data_next(struct hash_ip4_elem *next, const struct hash_ip6_elem *e)
233 {
234 }
235
236 #undef MTYPE
237 #undef PF
238 #undef HOST_MASK
239 #undef HKEY_DATALEN
240
241 #define MTYPE           hash_ip6
242 #define PF              6
243 #define HOST_MASK       128
244
245 #define IP_SET_EMIT_CREATE
246 #include "ip_set_hash_gen.h"
247
248 static int
249 hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb,
250               const struct xt_action_param *par,
251               enum ipset_adt adt, struct ip_set_adt_opt *opt)
252 {
253         const struct hash_ip *h = set->data;
254         ipset_adtfn adtfn = set->variant->adt[adt];
255         struct hash_ip6_elem e = {};
256         struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
257
258         ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
259         hash_ip6_netmask(&e.ip, h->netmask);
260         if (ipv6_addr_any(&e.ip.in6))
261                 return -EINVAL;
262
263         return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
264 }
265
266 static int
267 hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[],
268               enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
269 {
270         const struct hash_ip *h = set->data;
271         ipset_adtfn adtfn = set->variant->adt[adt];
272         struct hash_ip6_elem e = {};
273         struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
274         int ret;
275
276         if (unlikely(!tb[IPSET_ATTR_IP] ||
277                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
278                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
279                      !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
280                      tb[IPSET_ATTR_IP_TO] ||
281                      tb[IPSET_ATTR_CIDR]))
282                 return -IPSET_ERR_PROTOCOL;
283
284         if (tb[IPSET_ATTR_LINENO])
285                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
286
287         ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) ||
288               ip_set_get_extensions(set, tb, &ext);
289         if (ret)
290                 return ret;
291
292         hash_ip6_netmask(&e.ip, h->netmask);
293         if (ipv6_addr_any(&e.ip.in6))
294                 return -IPSET_ERR_HASH_ELEM;
295
296         ret = adtfn(set, &e, &ext, &ext, flags);
297
298         return ip_set_eexist(ret, flags) ? 0 : ret;
299 }
300
301 static struct ip_set_type hash_ip_type __read_mostly = {
302         .name           = "hash:ip",
303         .protocol       = IPSET_PROTOCOL,
304         .features       = IPSET_TYPE_IP,
305         .dimension      = IPSET_DIM_ONE,
306         .family         = NFPROTO_UNSPEC,
307         .revision_min   = REVISION_MIN,
308         .revision_max   = REVISION_MAX,
309         .create         = hash_ip_create,
310         .create_policy  = {
311                 [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
312                 [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
313                 [IPSET_ATTR_PROBES]     = { .type = NLA_U8 },
314                 [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
315                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
316                 [IPSET_ATTR_NETMASK]    = { .type = NLA_U8  },
317                 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
318         },
319         .adt_policy     = {
320                 [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
321                 [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
322                 [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
323                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
324                 [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
325                 [IPSET_ATTR_BYTES]      = { .type = NLA_U64 },
326                 [IPSET_ATTR_PACKETS]    = { .type = NLA_U64 },
327         },
328         .me             = THIS_MODULE,
329 };
330
331 static int __init
332 hash_ip_init(void)
333 {
334         return ip_set_type_register(&hash_ip_type);
335 }
336
337 static void __exit
338 hash_ip_fini(void)
339 {
340         ip_set_type_unregister(&hash_ip_type);
341 }
342
343 module_init(hash_ip_init);
344 module_exit(hash_ip_fini);