1
2
3
4
5
6
7
8
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
27MODULE_LICENSE("GPL");
28MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
29MODULE_DESCRIPTION("hash:net,port type of IP sets");
30MODULE_ALIAS("ip_set_hash:net,port");
31
32
33#define TYPE hash_netport
34
35static bool
36hash_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
42
43
44struct hash_netport4_elem {
45 __be32 ip;
46 __be16 port;
47 u8 proto;
48 u8 cidr;
49};
50
51
52struct hash_netport4_telem {
53 __be32 ip;
54 __be16 port;
55 u8 proto;
56 u8 cidr;
57 unsigned long timeout;
58};
59
60static inline bool
61hash_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
71static inline bool
72hash_netport4_data_isnull(const struct hash_netport4_elem *elem)
73{
74 return elem->proto == 0;
75}
76
77static inline void
78hash_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
87static inline void
88hash_netport4_data_netmask(struct hash_netport4_elem *elem, u8 cidr)
89{
90 elem->ip &= ip_set_netmask(cidr);
91 elem->cidr = cidr;
92}
93
94static inline void
95hash_netport4_data_zero_out(struct hash_netport4_elem *elem)
96{
97 elem->proto = 0;
98}
99
100static bool
101hash_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
110nla_put_failure:
111 return 1;
112}
113
114static bool
115hash_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
130nla_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
141static inline void
142hash_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
149static int
150hash_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
175static int
176hash_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
274static bool
275hash_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
281 return x->maxelem == y->maxelem &&
282 x->timeout == y->timeout;
283}
284
285
286
287struct hash_netport6_elem {
288 union nf_inet_addr ip;
289 __be16 port;
290 u8 proto;
291 u8 cidr;
292};
293
294struct hash_netport6_telem {
295 union nf_inet_addr ip;
296 __be16 port;
297 u8 proto;
298 u8 cidr;
299 unsigned long timeout;
300};
301
302static inline bool
303hash_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
313static inline bool
314hash_netport6_data_isnull(const struct hash_netport6_elem *elem)
315{
316 return elem->proto == 0;
317}
318
319static inline void
320hash_netport6_data_copy(struct hash_netport6_elem *dst,
321 const struct hash_netport6_elem *src)
322{
323 memcpy(dst, src, sizeof(*dst));
324}
325
326static inline void
327hash_netport6_data_zero_out(struct hash_netport6_elem *elem)
328{
329 elem->proto = 0;
330}
331
332static inline void
333ip6_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
341static inline void
342hash_netport6_data_netmask(struct hash_netport6_elem *elem, u8 cidr)
343{
344 ip6_netmask(&elem->ip, cidr);
345 elem->cidr = cidr;
346}
347
348static bool
349hash_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
358nla_put_failure:
359 return 1;
360}
361
362static bool
363hash_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
377nla_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
388static inline void
389hash_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
395static int
396hash_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
421static int
422hash_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
502
503static int
504hash_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
571static 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
579 .revision_max = 2,
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
602static int __init
603hash_netport_init(void)
604{
605 return ip_set_type_register(&hash_netport_type);
606}
607
608static void __exit
609hash_netport_fini(void)
610{
611 ip_set_type_unregister(&hash_netport_type);
612}
613
614module_init(hash_netport_init);
615module_exit(hash_netport_fini);
616