Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ip_set_hash_ipportnet.c
Go to the documentation of this file.
1 /* Copyright (C) 2003-2011 Jozsef Kadlecsik <[email protected]>
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,net 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>
23 #include <linux/netfilter/ipset/ip_set.h>
26 #include <linux/netfilter/ipset/ip_set_hash.h>
27 
28 #define REVISION_MIN 0
29 /* 1 SCTP and UDPLITE support added */
30 /* 2 Range as input support for IPv4 added */
31 #define REVISION_MAX 3 /* nomatch flag support added */
32 
33 MODULE_LICENSE("GPL");
34 MODULE_AUTHOR("Jozsef Kadlecsik <[email protected]>");
35 IP_SET_MODULE_DESC("hash:ip,port,net", REVISION_MIN, REVISION_MAX);
36 MODULE_ALIAS("ip_set_hash:ip,port,net");
37 
38 /* Type specific function prefix */
39 #define TYPE hash_ipportnet
40 
41 static bool
42 hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b);
43 
44 #define hash_ipportnet4_same_set hash_ipportnet_same_set
45 #define hash_ipportnet6_same_set hash_ipportnet_same_set
46 
47 /* The type variant functions: IPv4 */
48 
49 /* We squeeze the "nomatch" flag into cidr: we don't support cidr == 0
50  * However this way we have to store internally cidr - 1,
51  * dancing back and forth.
52  */
53 #define IP_SET_HASH_WITH_NETS_PACKED
54 
55 /* Member elements without timeout */
60  u8 cidr:7;
63 };
64 
65 /* Member elements with timeout support */
70  u8 cidr:7;
73  unsigned long timeout;
74 };
75 
76 static inline bool
77 hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1,
78  const struct hash_ipportnet4_elem *ip2,
79  u32 *multi)
80 {
81  return ip1->ip == ip2->ip &&
82  ip1->ip2 == ip2->ip2 &&
83  ip1->cidr == ip2->cidr &&
84  ip1->port == ip2->port &&
85  ip1->proto == ip2->proto;
86 }
87 
88 static inline bool
89 hash_ipportnet4_data_isnull(const struct hash_ipportnet4_elem *elem)
90 {
91  return elem->proto == 0;
92 }
93 
94 static inline void
95 hash_ipportnet4_data_copy(struct hash_ipportnet4_elem *dst,
96  const struct hash_ipportnet4_elem *src)
97 {
98  memcpy(dst, src, sizeof(*dst));
99 }
100 
101 static inline void
102 hash_ipportnet4_data_flags(struct hash_ipportnet4_elem *dst, u32 flags)
103 {
104  dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
105 }
106 
107 static inline int
108 hash_ipportnet4_data_match(const struct hash_ipportnet4_elem *elem)
109 {
110  return elem->nomatch ? -ENOTEMPTY : 1;
111 }
112 
113 static inline void
114 hash_ipportnet4_data_netmask(struct hash_ipportnet4_elem *elem, u8 cidr)
115 {
116  elem->ip2 &= ip_set_netmask(cidr);
117  elem->cidr = cidr - 1;
118 }
119 
120 static inline void
121 hash_ipportnet4_data_zero_out(struct hash_ipportnet4_elem *elem)
122 {
123  elem->proto = 0;
124 }
125 
126 static bool
127 hash_ipportnet4_data_list(struct sk_buff *skb,
128  const struct hash_ipportnet4_elem *data)
129 {
130  u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
131 
132  if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) ||
133  nla_put_ipaddr4(skb, IPSET_ATTR_IP2, data->ip2) ||
134  nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
135  nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr + 1) ||
136  nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
137  (flags &&
138  nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
139  goto nla_put_failure;
140  return 0;
141 
142 nla_put_failure:
143  return 1;
144 }
145 
146 static bool
147 hash_ipportnet4_data_tlist(struct sk_buff *skb,
148  const struct hash_ipportnet4_elem *data)
149 {
150  const struct hash_ipportnet4_telem *tdata =
151  (const struct hash_ipportnet4_telem *)data;
152  u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
153 
154  if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, tdata->ip) ||
155  nla_put_ipaddr4(skb, IPSET_ATTR_IP2, tdata->ip2) ||
156  nla_put_net16(skb, IPSET_ATTR_PORT, tdata->port) ||
157  nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr + 1) ||
158  nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
159  nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
160  htonl(ip_set_timeout_get(tdata->timeout))) ||
161  (flags &&
162  nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
163  goto nla_put_failure;
164  return 0;
165 
166 nla_put_failure:
167  return 1;
168 }
169 
170 #define IP_SET_HASH_WITH_PROTO
171 #define IP_SET_HASH_WITH_NETS
172 
173 #define PF 4
174 #define HOST_MASK 32
176 
177 static inline void
178 hash_ipportnet4_data_next(struct ip_set_hash *h,
179  const struct hash_ipportnet4_elem *d)
180 {
181  h->next.ip = d->ip;
182  h->next.port = d->port;
183  h->next.ip2 = d->ip2;
184 }
185 
186 static int
187 hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
188  const struct xt_action_param *par,
189  enum ipset_adt adt, const struct ip_set_adt_opt *opt)
190 {
191  const struct ip_set_hash *h = set->data;
192  ipset_adtfn adtfn = set->variant->adt[adt];
193  struct hash_ipportnet4_elem data = {
194  .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1
195  };
196 
197  if (adt == IPSET_TEST)
198  data.cidr = HOST_MASK - 1;
199 
201  &data.port, &data.proto))
202  return -EINVAL;
203 
204  ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
205  ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2);
206  data.ip2 &= ip_set_netmask(data.cidr + 1);
207 
208  return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
209 }
210 
211 static int
212 hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
213  enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
214 {
215  const struct ip_set_hash *h = set->data;
216  ipset_adtfn adtfn = set->variant->adt[adt];
217  struct hash_ipportnet4_elem data = { .cidr = HOST_MASK - 1 };
218  u32 ip, ip_to, p = 0, port, port_to;
219  u32 ip2_from, ip2_to, ip2_last, ip2;
220  u32 timeout = h->timeout;
221  bool with_ports = false;
222  u8 cidr;
223  int ret;
224 
225  if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
226  !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
227  !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
228  !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
229  !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
230  return -IPSET_ERR_PROTOCOL;
231 
232  if (tb[IPSET_ATTR_LINENO])
233  *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
234 
235  ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
236  if (ret)
237  return ret;
238 
239  ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2], &ip2_from);
240  if (ret)
241  return ret;
242 
243  if (tb[IPSET_ATTR_CIDR2]) {
244  cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
245  if (!cidr || cidr > HOST_MASK)
246  return -IPSET_ERR_INVALID_CIDR;
247  data.cidr = cidr - 1;
248  }
249 
250  if (tb[IPSET_ATTR_PORT])
251  data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
252  else
253  return -IPSET_ERR_PROTOCOL;
254 
255  if (tb[IPSET_ATTR_PROTO]) {
256  data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
257  with_ports = ip_set_proto_with_ports(data.proto);
258 
259  if (data.proto == 0)
260  return -IPSET_ERR_INVALID_PROTO;
261  } else
262  return -IPSET_ERR_MISSING_PROTO;
263 
264  if (!(with_ports || data.proto == IPPROTO_ICMP))
265  data.port = 0;
266 
267  if (tb[IPSET_ATTR_TIMEOUT]) {
268  if (!with_timeout(h->timeout))
269  return -IPSET_ERR_TIMEOUT;
270  timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
271  }
272 
273  if (tb[IPSET_ATTR_CADT_FLAGS] && adt == IPSET_ADD) {
274  u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
275  if (cadt_flags & IPSET_FLAG_NOMATCH)
276  flags |= (cadt_flags << 16);
277  }
278 
279  with_ports = with_ports && tb[IPSET_ATTR_PORT_TO];
280  if (adt == IPSET_TEST ||
281  !(tb[IPSET_ATTR_CIDR] || tb[IPSET_ATTR_IP_TO] || with_ports ||
282  tb[IPSET_ATTR_IP2_TO])) {
283  data.ip = htonl(ip);
284  data.ip2 = htonl(ip2_from & ip_set_hostmask(data.cidr + 1));
285  ret = adtfn(set, &data, timeout, flags);
286  return ip_set_eexist(ret, flags) ? 0 : ret;
287  }
288 
289  ip_to = ip;
290  if (tb[IPSET_ATTR_IP_TO]) {
291  ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
292  if (ret)
293  return ret;
294  if (ip > ip_to)
295  swap(ip, ip_to);
296  } else if (tb[IPSET_ATTR_CIDR]) {
297  u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
298 
299  if (!cidr || cidr > 32)
300  return -IPSET_ERR_INVALID_CIDR;
301  ip_set_mask_from_to(ip, ip_to, cidr);
302  }
303 
304  port_to = port = ntohs(data.port);
305  if (tb[IPSET_ATTR_PORT_TO]) {
306  port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
307  if (port > port_to)
308  swap(port, port_to);
309  }
310 
311  ip2_to = ip2_from;
312  if (tb[IPSET_ATTR_IP2_TO]) {
313  ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
314  if (ret)
315  return ret;
316  if (ip2_from > ip2_to)
317  swap(ip2_from, ip2_to);
318  if (ip2_from + UINT_MAX == ip2_to)
319  return -IPSET_ERR_HASH_RANGE;
320  } else {
321  ip_set_mask_from_to(ip2_from, ip2_to, data.cidr + 1);
322  }
323 
324  if (retried)
325  ip = ntohl(h->next.ip);
326  for (; !before(ip_to, ip); ip++) {
327  data.ip = htonl(ip);
328  p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
329  : port;
330  for (; p <= port_to; p++) {
331  data.port = htons(p);
332  ip2 = retried
333  && ip == ntohl(h->next.ip)
334  && p == ntohs(h->next.port)
335  ? ntohl(h->next.ip2) : ip2_from;
336  while (!after(ip2, ip2_to)) {
337  data.ip2 = htonl(ip2);
338  ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
339  &cidr);
340  data.cidr = cidr - 1;
341  ret = adtfn(set, &data, timeout, flags);
342 
343  if (ret && !ip_set_eexist(ret, flags))
344  return ret;
345  else
346  ret = 0;
347  ip2 = ip2_last + 1;
348  }
349  }
350  }
351  return ret;
352 }
353 
354 static bool
355 hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b)
356 {
357  const struct ip_set_hash *x = a->data;
358  const struct ip_set_hash *y = b->data;
359 
360  /* Resizing changes htable_bits, so we ignore it */
361  return x->maxelem == y->maxelem &&
362  x->timeout == y->timeout;
363 }
364 
365 /* The type variant functions: IPv6 */
366 
368  union nf_inet_addr ip;
369  union nf_inet_addr ip2;
371  u8 cidr:7;
374 };
375 
377  union nf_inet_addr ip;
378  union nf_inet_addr ip2;
380  u8 cidr:7;
383  unsigned long timeout;
384 };
385 
386 static inline bool
387 hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
388  const struct hash_ipportnet6_elem *ip2,
389  u32 *multi)
390 {
391  return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
392  ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
393  ip1->cidr == ip2->cidr &&
394  ip1->port == ip2->port &&
395  ip1->proto == ip2->proto;
396 }
397 
398 static inline bool
399 hash_ipportnet6_data_isnull(const struct hash_ipportnet6_elem *elem)
400 {
401  return elem->proto == 0;
402 }
403 
404 static inline void
405 hash_ipportnet6_data_copy(struct hash_ipportnet6_elem *dst,
406  const struct hash_ipportnet6_elem *src)
407 {
408  memcpy(dst, src, sizeof(*dst));
409 }
410 
411 static inline void
412 hash_ipportnet6_data_flags(struct hash_ipportnet6_elem *dst, u32 flags)
413 {
414  dst->nomatch = !!(flags & IPSET_FLAG_NOMATCH);
415 }
416 
417 static inline int
418 hash_ipportnet6_data_match(const struct hash_ipportnet6_elem *elem)
419 {
420  return elem->nomatch ? -ENOTEMPTY : 1;
421 }
422 
423 static inline void
424 hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem *elem)
425 {
426  elem->proto = 0;
427 }
428 
429 static inline void
430 ip6_netmask(union nf_inet_addr *ip, u8 prefix)
431 {
432  ip->ip6[0] &= ip_set_netmask6(prefix)[0];
433  ip->ip6[1] &= ip_set_netmask6(prefix)[1];
434  ip->ip6[2] &= ip_set_netmask6(prefix)[2];
435  ip->ip6[3] &= ip_set_netmask6(prefix)[3];
436 }
437 
438 static inline void
439 hash_ipportnet6_data_netmask(struct hash_ipportnet6_elem *elem, u8 cidr)
440 {
441  ip6_netmask(&elem->ip2, cidr);
442  elem->cidr = cidr - 1;
443 }
444 
445 static bool
446 hash_ipportnet6_data_list(struct sk_buff *skb,
447  const struct hash_ipportnet6_elem *data)
448 {
449  u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
450 
451  if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) ||
452  nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip2.in6) ||
453  nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
454  nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr + 1) ||
455  nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
456  (flags &&
457  nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
458  goto nla_put_failure;
459  return 0;
460 
461 nla_put_failure:
462  return 1;
463 }
464 
465 static bool
466 hash_ipportnet6_data_tlist(struct sk_buff *skb,
467  const struct hash_ipportnet6_elem *data)
468 {
469  const struct hash_ipportnet6_telem *e =
470  (const struct hash_ipportnet6_telem *)data;
471  u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
472 
473  if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6) ||
474  nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip2.in6) ||
475  nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
476  nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr + 1) ||
477  nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
478  nla_put_net32(skb, IPSET_ATTR_TIMEOUT,
479  htonl(ip_set_timeout_get(e->timeout))) ||
480  (flags &&
481  nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
482  goto nla_put_failure;
483  return 0;
484 
485 nla_put_failure:
486  return 1;
487 }
488 
489 #undef PF
490 #undef HOST_MASK
491 
492 #define PF 6
493 #define HOST_MASK 128
495 
496 static inline void
497 hash_ipportnet6_data_next(struct ip_set_hash *h,
498  const struct hash_ipportnet6_elem *d)
499 {
500  h->next.port = d->port;
501 }
502 
503 static int
504 hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
505  const struct xt_action_param *par,
506  enum ipset_adt adt, const struct ip_set_adt_opt *opt)
507 {
508  const struct ip_set_hash *h = set->data;
509  ipset_adtfn adtfn = set->variant->adt[adt];
510  struct hash_ipportnet6_elem data = {
511  .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1
512  };
513 
514  if (adt == IPSET_TEST)
515  data.cidr = HOST_MASK - 1;
516 
517  if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
518  &data.port, &data.proto))
519  return -EINVAL;
520 
521  ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
522  ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
523  ip6_netmask(&data.ip2, data.cidr + 1);
524 
525  return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
526 }
527 
528 static int
529 hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
530  enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
531 {
532  const struct ip_set_hash *h = set->data;
533  ipset_adtfn adtfn = set->variant->adt[adt];
534  struct hash_ipportnet6_elem data = { .cidr = HOST_MASK - 1 };
535  u32 port, port_to;
536  u32 timeout = h->timeout;
537  bool with_ports = false;
538  u8 cidr;
539  int ret;
540 
541  if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
542  !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
543  !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
544  !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
545  !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
546  tb[IPSET_ATTR_IP_TO] ||
547  tb[IPSET_ATTR_CIDR]))
548  return -IPSET_ERR_PROTOCOL;
549  if (unlikely(tb[IPSET_ATTR_IP_TO]))
551 
552  if (tb[IPSET_ATTR_LINENO])
553  *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
554 
555  ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
556  if (ret)
557  return ret;
558 
559  ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2);
560  if (ret)
561  return ret;
562 
563  if (tb[IPSET_ATTR_CIDR2]) {
564  cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
565  if (!cidr || cidr > HOST_MASK)
566  return -IPSET_ERR_INVALID_CIDR;
567  data.cidr = cidr - 1;
568  }
569 
570  ip6_netmask(&data.ip2, data.cidr + 1);
571 
572  if (tb[IPSET_ATTR_PORT])
573  data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
574  else
575  return -IPSET_ERR_PROTOCOL;
576 
577  if (tb[IPSET_ATTR_PROTO]) {
578  data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
579  with_ports = ip_set_proto_with_ports(data.proto);
580 
581  if (data.proto == 0)
582  return -IPSET_ERR_INVALID_PROTO;
583  } else
584  return -IPSET_ERR_MISSING_PROTO;
585 
586  if (!(with_ports || data.proto == IPPROTO_ICMPV6))
587  data.port = 0;
588 
589  if (tb[IPSET_ATTR_TIMEOUT]) {
590  if (!with_timeout(h->timeout))
591  return -IPSET_ERR_TIMEOUT;
592  timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
593  }
594 
595  if (tb[IPSET_ATTR_CADT_FLAGS] && adt == IPSET_ADD) {
596  u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
597  if (cadt_flags & IPSET_FLAG_NOMATCH)
598  flags |= (cadt_flags << 16);
599  }
600 
601  if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
602  ret = adtfn(set, &data, timeout, flags);
603  return ip_set_eexist(ret, flags) ? 0 : ret;
604  }
605 
606  port = ntohs(data.port);
607  port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
608  if (port > port_to)
609  swap(port, port_to);
610 
611  if (retried)
612  port = ntohs(h->next.port);
613  for (; port <= port_to; port++) {
614  data.port = htons(port);
615  ret = adtfn(set, &data, timeout, flags);
616 
617  if (ret && !ip_set_eexist(ret, flags))
618  return ret;
619  else
620  ret = 0;
621  }
622  return ret;
623 }
624 
625 /* Create hash:ip type of sets */
626 
627 static int
628 hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
629 {
630  struct ip_set_hash *h;
632  u8 hbits;
633  size_t hsize;
634 
635  if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
636  return -IPSET_ERR_INVALID_FAMILY;
637 
638  if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
639  !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
640  !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
641  return -IPSET_ERR_PROTOCOL;
642 
643  if (tb[IPSET_ATTR_HASHSIZE]) {
644  hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
645  if (hashsize < IPSET_MIMINAL_HASHSIZE)
646  hashsize = IPSET_MIMINAL_HASHSIZE;
647  }
648 
649  if (tb[IPSET_ATTR_MAXELEM])
650  maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
651 
652  h = kzalloc(sizeof(*h)
653  + sizeof(struct ip_set_hash_nets)
654  * (set->family == NFPROTO_IPV4 ? 32 : 128), GFP_KERNEL);
655  if (!h)
656  return -ENOMEM;
657 
658  h->maxelem = maxelem;
659  get_random_bytes(&h->initval, sizeof(h->initval));
660  h->timeout = IPSET_NO_TIMEOUT;
661 
662  hbits = htable_bits(hashsize);
663  hsize = htable_size(hbits);
664  if (hsize == 0) {
665  kfree(h);
666  return -ENOMEM;
667  }
668  h->table = ip_set_alloc(hsize);
669  if (!h->table) {
670  kfree(h);
671  return -ENOMEM;
672  }
673  h->table->htable_bits = hbits;
674 
675  set->data = h;
676 
677  if (tb[IPSET_ATTR_TIMEOUT]) {
678  h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
679 
680  set->variant = set->family == NFPROTO_IPV4
681  ? &hash_ipportnet4_tvariant
682  : &hash_ipportnet6_tvariant;
683 
684  if (set->family == NFPROTO_IPV4)
685  hash_ipportnet4_gc_init(set);
686  else
687  hash_ipportnet6_gc_init(set);
688  } else {
689  set->variant = set->family == NFPROTO_IPV4
690  ? &hash_ipportnet4_variant : &hash_ipportnet6_variant;
691  }
692 
693  pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
694  set->name, jhash_size(h->table->htable_bits),
695  h->table->htable_bits, h->maxelem, set->data, h->table);
696 
697  return 0;
698 }
699 
700 static struct ip_set_type hash_ipportnet_type __read_mostly = {
701  .name = "hash:ip,port,net",
702  .protocol = IPSET_PROTOCOL,
705  .dimension = IPSET_DIM_THREE,
706  .family = NFPROTO_UNSPEC,
707  .revision_min = REVISION_MIN,
708  .revision_max = REVISION_MAX,
709  .create = hash_ipportnet_create,
710  .create_policy = {
711  [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
712  [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
713  [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
714  [IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
715  [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
716  },
717  .adt_policy = {
718  [IPSET_ATTR_IP] = { .type = NLA_NESTED },
719  [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
720  [IPSET_ATTR_IP2] = { .type = NLA_NESTED },
721  [IPSET_ATTR_IP2_TO] = { .type = NLA_NESTED },
722  [IPSET_ATTR_PORT] = { .type = NLA_U16 },
723  [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
724  [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
725  [IPSET_ATTR_CIDR2] = { .type = NLA_U8 },
726  [IPSET_ATTR_PROTO] = { .type = NLA_U8 },
727  [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
728  [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
729  [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
730  },
731  .me = THIS_MODULE,
732 };
733 
734 static int __init
735 hash_ipportnet_init(void)
736 {
737  return ip_set_type_register(&hash_ipportnet_type);
738 }
739 
740 static void __exit
741 hash_ipportnet_fini(void)
742 {
743  ip_set_type_unregister(&hash_ipportnet_type);
744 }
745 
746 module_init(hash_ipportnet_init);
747 module_exit(hash_ipportnet_fini);