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