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