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