netfilter: ipset: add xt_action_param to the variant level kadt functions, ipset...
[linux-flexiantxendom0-3.2.10.git] / net / netfilter / ipset / ip_set_hash_ipportip.c
1 /* Copyright (C) 2003-2011 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,port,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_timeout.h>
25 #include <linux/netfilter/ipset/ip_set_getport.h>
26 #include <linux/netfilter/ipset/ip_set_hash.h>
27
28 MODULE_LICENSE("GPL");
29 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
30 MODULE_DESCRIPTION("hash:ip,port,ip type of IP sets");
31 MODULE_ALIAS("ip_set_hash:ip,port,ip");
32
33 /* Type specific function prefix */
34 #define TYPE            hash_ipportip
35
36 static bool
37 hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b);
38
39 #define hash_ipportip4_same_set hash_ipportip_same_set
40 #define hash_ipportip6_same_set hash_ipportip_same_set
41
42 /* The type variant functions: IPv4 */
43
44 /* Member elements without timeout */
45 struct hash_ipportip4_elem {
46         __be32 ip;
47         __be32 ip2;
48         __be16 port;
49         u8 proto;
50         u8 padding;
51 };
52
53 /* Member elements with timeout support */
54 struct hash_ipportip4_telem {
55         __be32 ip;
56         __be32 ip2;
57         __be16 port;
58         u8 proto;
59         u8 padding;
60         unsigned long timeout;
61 };
62
63 static inline bool
64 hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1,
65                           const struct hash_ipportip4_elem *ip2)
66 {
67         return ip1->ip == ip2->ip &&
68                ip1->ip2 == ip2->ip2 &&
69                ip1->port == ip2->port &&
70                ip1->proto == ip2->proto;
71 }
72
73 static inline bool
74 hash_ipportip4_data_isnull(const struct hash_ipportip4_elem *elem)
75 {
76         return elem->proto == 0;
77 }
78
79 static inline void
80 hash_ipportip4_data_copy(struct hash_ipportip4_elem *dst,
81                          const struct hash_ipportip4_elem *src)
82 {
83         memcpy(dst, src, sizeof(*dst));
84 }
85
86 static inline void
87 hash_ipportip4_data_zero_out(struct hash_ipportip4_elem *elem)
88 {
89         elem->proto = 0;
90 }
91
92 static bool
93 hash_ipportip4_data_list(struct sk_buff *skb,
94                        const struct hash_ipportip4_elem *data)
95 {
96         NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
97         NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, data->ip2);
98         NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
99         NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
100         return 0;
101
102 nla_put_failure:
103         return 1;
104 }
105
106 static bool
107 hash_ipportip4_data_tlist(struct sk_buff *skb,
108                         const struct hash_ipportip4_elem *data)
109 {
110         const struct hash_ipportip4_telem *tdata =
111                 (const struct hash_ipportip4_telem *)data;
112
113         NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
114         NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, tdata->ip2);
115         NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
116         NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
117         NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
118                       htonl(ip_set_timeout_get(tdata->timeout)));
119
120         return 0;
121
122 nla_put_failure:
123         return 1;
124 }
125
126 #define PF              4
127 #define HOST_MASK       32
128 #include <linux/netfilter/ipset/ip_set_ahash.h>
129
130 static inline void
131 hash_ipportip4_data_next(struct ip_set_hash *h,
132                          const struct hash_ipportip4_elem *d)
133 {
134         h->next.ip = ntohl(d->ip);
135         h->next.port = ntohs(d->port);
136 }
137
138 static int
139 hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
140                     const struct xt_action_param *par,
141                     enum ipset_adt adt, const struct ip_set_adt_opt *opt)
142 {
143         const struct ip_set_hash *h = set->data;
144         ipset_adtfn adtfn = set->variant->adt[adt];
145         struct hash_ipportip4_elem data = { };
146
147         if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
148                                  &data.port, &data.proto))
149                 return -EINVAL;
150
151         ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
152         ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2);
153
154         return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
155 }
156
157 static int
158 hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
159                     enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
160 {
161         const struct ip_set_hash *h = set->data;
162         ipset_adtfn adtfn = set->variant->adt[adt];
163         struct hash_ipportip4_elem data = { };
164         u32 ip, ip_to, p = 0, port, port_to;
165         u32 timeout = h->timeout;
166         bool with_ports = false;
167         int ret;
168
169         if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
170                      !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
171                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
172                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
173                 return -IPSET_ERR_PROTOCOL;
174
175         if (tb[IPSET_ATTR_LINENO])
176                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
177
178         ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
179         if (ret)
180                 return ret;
181
182         ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2);
183         if (ret)
184                 return ret;
185
186         if (tb[IPSET_ATTR_PORT])
187                 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
188         else
189                 return -IPSET_ERR_PROTOCOL;
190
191         if (tb[IPSET_ATTR_PROTO]) {
192                 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
193                 with_ports = ip_set_proto_with_ports(data.proto);
194
195                 if (data.proto == 0)
196                         return -IPSET_ERR_INVALID_PROTO;
197         } else
198                 return -IPSET_ERR_MISSING_PROTO;
199
200         if (!(with_ports || data.proto == IPPROTO_ICMP))
201                 data.port = 0;
202
203         if (tb[IPSET_ATTR_TIMEOUT]) {
204                 if (!with_timeout(h->timeout))
205                         return -IPSET_ERR_TIMEOUT;
206                 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
207         }
208
209         if (adt == IPSET_TEST ||
210             !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
211               tb[IPSET_ATTR_PORT_TO])) {
212                 ret = adtfn(set, &data, timeout, flags);
213                 return ip_set_eexist(ret, flags) ? 0 : ret;
214         }
215
216         ip = ntohl(data.ip);
217         if (tb[IPSET_ATTR_IP_TO]) {
218                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
219                 if (ret)
220                         return ret;
221                 if (ip > ip_to)
222                         swap(ip, ip_to);
223         } else if (tb[IPSET_ATTR_CIDR]) {
224                 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
225
226                 if (cidr > 32)
227                         return -IPSET_ERR_INVALID_CIDR;
228                 ip_set_mask_from_to(ip, ip_to, cidr);
229         } else
230                 ip_to = ip;
231
232         port_to = port = ntohs(data.port);
233         if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
234                 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
235                 if (port > port_to)
236                         swap(port, port_to);
237         }
238
239         if (retried)
240                 ip = h->next.ip;
241         for (; !before(ip_to, ip); ip++) {
242                 p = retried && ip == h->next.ip ? h->next.port : port;
243                 for (; p <= port_to; p++) {
244                         data.ip = htonl(ip);
245                         data.port = htons(p);
246                         ret = adtfn(set, &data, timeout, flags);
247
248                         if (ret && !ip_set_eexist(ret, flags))
249                                 return ret;
250                         else
251                                 ret = 0;
252                 }
253         }
254         return ret;
255 }
256
257 static bool
258 hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b)
259 {
260         const struct ip_set_hash *x = a->data;
261         const struct ip_set_hash *y = b->data;
262
263         /* Resizing changes htable_bits, so we ignore it */
264         return x->maxelem == y->maxelem &&
265                x->timeout == y->timeout;
266 }
267
268 /* The type variant functions: IPv6 */
269
270 struct hash_ipportip6_elem {
271         union nf_inet_addr ip;
272         union nf_inet_addr ip2;
273         __be16 port;
274         u8 proto;
275         u8 padding;
276 };
277
278 struct hash_ipportip6_telem {
279         union nf_inet_addr ip;
280         union nf_inet_addr ip2;
281         __be16 port;
282         u8 proto;
283         u8 padding;
284         unsigned long timeout;
285 };
286
287 static inline bool
288 hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1,
289                           const struct hash_ipportip6_elem *ip2)
290 {
291         return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
292                ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
293                ip1->port == ip2->port &&
294                ip1->proto == ip2->proto;
295 }
296
297 static inline bool
298 hash_ipportip6_data_isnull(const struct hash_ipportip6_elem *elem)
299 {
300         return elem->proto == 0;
301 }
302
303 static inline void
304 hash_ipportip6_data_copy(struct hash_ipportip6_elem *dst,
305                          const struct hash_ipportip6_elem *src)
306 {
307         memcpy(dst, src, sizeof(*dst));
308 }
309
310 static inline void
311 hash_ipportip6_data_zero_out(struct hash_ipportip6_elem *elem)
312 {
313         elem->proto = 0;
314 }
315
316 static bool
317 hash_ipportip6_data_list(struct sk_buff *skb,
318                          const struct hash_ipportip6_elem *data)
319 {
320         NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
321         NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
322         NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
323         NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
324         return 0;
325
326 nla_put_failure:
327         return 1;
328 }
329
330 static bool
331 hash_ipportip6_data_tlist(struct sk_buff *skb,
332                           const struct hash_ipportip6_elem *data)
333 {
334         const struct hash_ipportip6_telem *e =
335                 (const struct hash_ipportip6_telem *)data;
336
337         NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
338         NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
339         NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
340         NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
341         NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
342                       htonl(ip_set_timeout_get(e->timeout)));
343         return 0;
344
345 nla_put_failure:
346         return 1;
347 }
348
349 #undef PF
350 #undef HOST_MASK
351
352 #define PF              6
353 #define HOST_MASK       128
354 #include <linux/netfilter/ipset/ip_set_ahash.h>
355
356 static inline void
357 hash_ipportip6_data_next(struct ip_set_hash *h,
358                          const struct hash_ipportip6_elem *d)
359 {
360         h->next.port = ntohs(d->port);
361 }
362
363 static int
364 hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
365                     const struct xt_action_param *par,
366                     enum ipset_adt adt, const struct ip_set_adt_opt *opt)
367 {
368         const struct ip_set_hash *h = set->data;
369         ipset_adtfn adtfn = set->variant->adt[adt];
370         struct hash_ipportip6_elem data = { };
371
372         if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
373                                  &data.port, &data.proto))
374                 return -EINVAL;
375
376         ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
377         ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
378
379         return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
380 }
381
382 static int
383 hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
384                     enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
385 {
386         const struct ip_set_hash *h = set->data;
387         ipset_adtfn adtfn = set->variant->adt[adt];
388         struct hash_ipportip6_elem data = { };
389         u32 port, port_to;
390         u32 timeout = h->timeout;
391         bool with_ports = false;
392         int ret;
393
394         if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
395                      !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
396                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
397                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
398                      tb[IPSET_ATTR_IP_TO] ||
399                      tb[IPSET_ATTR_CIDR]))
400                 return -IPSET_ERR_PROTOCOL;
401
402         if (tb[IPSET_ATTR_LINENO])
403                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
404
405         ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
406         if (ret)
407                 return ret;
408
409         ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2);
410         if (ret)
411                 return ret;
412
413         if (tb[IPSET_ATTR_PORT])
414                 data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
415         else
416                 return -IPSET_ERR_PROTOCOL;
417
418         if (tb[IPSET_ATTR_PROTO]) {
419                 data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
420                 with_ports = ip_set_proto_with_ports(data.proto);
421
422                 if (data.proto == 0)
423                         return -IPSET_ERR_INVALID_PROTO;
424         } else
425                 return -IPSET_ERR_MISSING_PROTO;
426
427         if (!(with_ports || data.proto == IPPROTO_ICMPV6))
428                 data.port = 0;
429
430         if (tb[IPSET_ATTR_TIMEOUT]) {
431                 if (!with_timeout(h->timeout))
432                         return -IPSET_ERR_TIMEOUT;
433                 timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
434         }
435
436         if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
437                 ret = adtfn(set, &data, timeout, flags);
438                 return ip_set_eexist(ret, flags) ? 0 : ret;
439         }
440
441         port = ntohs(data.port);
442         port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
443         if (port > port_to)
444                 swap(port, port_to);
445
446         if (retried)
447                 port = h->next.port;
448         for (; port <= port_to; port++) {
449                 data.port = htons(port);
450                 ret = adtfn(set, &data, timeout, flags);
451
452                 if (ret && !ip_set_eexist(ret, flags))
453                         return ret;
454                 else
455                         ret = 0;
456         }
457         return ret;
458 }
459
460 /* Create hash:ip type of sets */
461
462 static int
463 hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
464 {
465         struct ip_set_hash *h;
466         u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
467         u8 hbits;
468
469         if (!(set->family == AF_INET || set->family == AF_INET6))
470                 return -IPSET_ERR_INVALID_FAMILY;
471
472         if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
473                      !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
474                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
475                 return -IPSET_ERR_PROTOCOL;
476
477         if (tb[IPSET_ATTR_HASHSIZE]) {
478                 hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
479                 if (hashsize < IPSET_MIMINAL_HASHSIZE)
480                         hashsize = IPSET_MIMINAL_HASHSIZE;
481         }
482
483         if (tb[IPSET_ATTR_MAXELEM])
484                 maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
485
486         h = kzalloc(sizeof(*h), GFP_KERNEL);
487         if (!h)
488                 return -ENOMEM;
489
490         h->maxelem = maxelem;
491         get_random_bytes(&h->initval, sizeof(h->initval));
492         h->timeout = IPSET_NO_TIMEOUT;
493
494         hbits = htable_bits(hashsize);
495         h->table = ip_set_alloc(
496                         sizeof(struct htable)
497                         + jhash_size(hbits) * sizeof(struct hbucket));
498         if (!h->table) {
499                 kfree(h);
500                 return -ENOMEM;
501         }
502         h->table->htable_bits = hbits;
503
504         set->data = h;
505
506         if (tb[IPSET_ATTR_TIMEOUT]) {
507                 h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
508
509                 set->variant = set->family == AF_INET
510                         ? &hash_ipportip4_tvariant : &hash_ipportip6_tvariant;
511
512                 if (set->family == AF_INET)
513                         hash_ipportip4_gc_init(set);
514                 else
515                         hash_ipportip6_gc_init(set);
516         } else {
517                 set->variant = set->family == AF_INET
518                         ? &hash_ipportip4_variant : &hash_ipportip6_variant;
519         }
520
521         pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
522                  set->name, jhash_size(h->table->htable_bits),
523                  h->table->htable_bits, h->maxelem, set->data, h->table);
524
525         return 0;
526 }
527
528 static struct ip_set_type hash_ipportip_type __read_mostly = {
529         .name           = "hash:ip,port,ip",
530         .protocol       = IPSET_PROTOCOL,
531         .features       = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
532         .dimension      = IPSET_DIM_THREE,
533         .family         = AF_UNSPEC,
534         .revision_min   = 0,
535         .revision_max   = 1,    /* SCTP and UDPLITE support added */
536         .create         = hash_ipportip_create,
537         .create_policy  = {
538                 [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
539                 [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
540                 [IPSET_ATTR_PROBES]     = { .type = NLA_U8 },
541                 [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
542                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
543         },
544         .adt_policy     = {
545                 [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
546                 [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
547                 [IPSET_ATTR_IP2]        = { .type = NLA_NESTED },
548                 [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
549                 [IPSET_ATTR_PORT_TO]    = { .type = NLA_U16 },
550                 [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
551                 [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
552                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
553                 [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
554         },
555         .me             = THIS_MODULE,
556 };
557
558 static int __init
559 hash_ipportip_init(void)
560 {
561         return ip_set_type_register(&hash_ipportip_type);
562 }
563
564 static void __exit
565 hash_ipportip_fini(void)
566 {
567         ip_set_type_unregister(&hash_ipportip_type);
568 }
569
570 module_init(hash_ipportip_init);
571 module_exit(hash_ipportip_fini);