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