linux/net/netfilter/ipset/ip_set_hash_ipportnet.c
<<
>>
Prefs
   1/* Copyright (C) 2003-2013 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,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>
  22#include <linux/netfilter/ipset/pfxlen.h>
  23#include <linux/netfilter/ipset/ip_set.h>
  24#include <linux/netfilter/ipset/ip_set_getport.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/*                      3    nomatch flag support added */
  31#define REVISION_MAX    4 /* Counters support added */
  32
  33MODULE_LICENSE("GPL");
  34MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
  35IP_SET_MODULE_DESC("hash:ip,port,net", REVISION_MIN, REVISION_MAX);
  36MODULE_ALIAS("ip_set_hash:ip,port,net");
  37
  38/* Type specific function prefix */
  39#define HTYPE           hash_ipportnet
  40
  41/* We squeeze the "nomatch" flag into cidr: we don't support cidr == 0
  42 * However this way we have to store internally cidr - 1,
  43 * dancing back and forth.
  44 */
  45#define IP_SET_HASH_WITH_NETS_PACKED
  46#define IP_SET_HASH_WITH_PROTO
  47#define IP_SET_HASH_WITH_NETS
  48
  49/* IPv4 variants */
  50
  51/* Member elements */
  52struct hash_ipportnet4_elem {
  53        __be32 ip;
  54        __be32 ip2;
  55        __be16 port;
  56        u8 cidr:7;
  57        u8 nomatch:1;
  58        u8 proto;
  59};
  60
  61struct hash_ipportnet4t_elem {
  62        __be32 ip;
  63        __be32 ip2;
  64        __be16 port;
  65        u8 cidr:7;
  66        u8 nomatch:1;
  67        u8 proto;
  68        unsigned long timeout;
  69};
  70
  71struct hash_ipportnet4c_elem {
  72        __be32 ip;
  73        __be32 ip2;
  74        __be16 port;
  75        u8 cidr:7;
  76        u8 nomatch:1;
  77        u8 proto;
  78        struct ip_set_counter counter;
  79};
  80
  81struct hash_ipportnet4ct_elem {
  82        __be32 ip;
  83        __be32 ip2;
  84        __be16 port;
  85        u8 cidr:7;
  86        u8 nomatch:1;
  87        u8 proto;
  88        struct ip_set_counter counter;
  89        unsigned long timeout;
  90};
  91
  92/* Common functions */
  93
  94static inline bool
  95hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1,
  96                           const struct hash_ipportnet4_elem *ip2,
  97                           u32 *multi)
  98{
  99        return ip1->ip == ip2->ip &&
 100               ip1->ip2 == ip2->ip2 &&
 101               ip1->cidr == ip2->cidr &&
 102               ip1->port == ip2->port &&
 103               ip1->proto == ip2->proto;
 104}
 105
 106static inline int
 107hash_ipportnet4_do_data_match(const struct hash_ipportnet4_elem *elem)
 108{
 109        return elem->nomatch ? -ENOTEMPTY : 1;
 110}
 111
 112static inline void
 113hash_ipportnet4_data_set_flags(struct hash_ipportnet4_elem *elem, u32 flags)
 114{
 115        elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH);
 116}
 117
 118static inline void
 119hash_ipportnet4_data_reset_flags(struct hash_ipportnet4_elem *elem, u8 *flags)
 120{
 121        swap(*flags, elem->nomatch);
 122}
 123
 124static inline void
 125hash_ipportnet4_data_netmask(struct hash_ipportnet4_elem *elem, u8 cidr)
 126{
 127        elem->ip2 &= ip_set_netmask(cidr);
 128        elem->cidr = cidr - 1;
 129}
 130
 131static bool
 132hash_ipportnet4_data_list(struct sk_buff *skb,
 133                          const struct hash_ipportnet4_elem *data)
 134{
 135        u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
 136
 137        if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) ||
 138            nla_put_ipaddr4(skb, IPSET_ATTR_IP2, data->ip2) ||
 139            nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
 140            nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr + 1) ||
 141            nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
 142            (flags &&
 143             nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
 144                goto nla_put_failure;
 145        return 0;
 146
 147nla_put_failure:
 148        return 1;
 149}
 150
 151static inline void
 152hash_ipportnet4_data_next(struct hash_ipportnet4_elem *next,
 153                          const struct hash_ipportnet4_elem *d)
 154{
 155        next->ip = d->ip;
 156        next->port = d->port;
 157        next->ip2 = d->ip2;
 158}
 159
 160#define MTYPE           hash_ipportnet4
 161#define PF              4
 162#define HOST_MASK       32
 163#include "ip_set_hash_gen.h"
 164
 165static int
 166hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
 167                     const struct xt_action_param *par,
 168                     enum ipset_adt adt, struct ip_set_adt_opt *opt)
 169{
 170        const struct hash_ipportnet *h = set->data;
 171        ipset_adtfn adtfn = set->variant->adt[adt];
 172        struct hash_ipportnet4_elem e = {
 173                .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1
 174        };
 175        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
 176
 177        if (adt == IPSET_TEST)
 178                e.cidr = HOST_MASK - 1;
 179
 180        if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
 181                                 &e.port, &e.proto))
 182                return -EINVAL;
 183
 184        ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
 185        ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &e.ip2);
 186        e.ip2 &= ip_set_netmask(e.cidr + 1);
 187
 188        return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
 189}
 190
 191static int
 192hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
 193                     enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 194{
 195        const struct hash_ipportnet *h = set->data;
 196        ipset_adtfn adtfn = set->variant->adt[adt];
 197        struct hash_ipportnet4_elem e = { .cidr = HOST_MASK - 1 };
 198        struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
 199        u32 ip, ip_to, p = 0, port, port_to;
 200        u32 ip2_from, ip2_to, ip2_last, ip2;
 201        bool with_ports = false;
 202        u8 cidr;
 203        int ret;
 204
 205        if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
 206                     !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
 207                     !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
 208                     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
 209                     !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
 210                     !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
 211                     !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES)))
 212                return -IPSET_ERR_PROTOCOL;
 213
 214        if (tb[IPSET_ATTR_LINENO])
 215                *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
 216
 217        ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) ||
 218              ip_set_get_extensions(set, tb, &ext);
 219        if (ret)
 220                return ret;
 221
 222        ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2], &ip2_from);
 223        if (ret)
 224                return ret;
 225
 226        if (tb[IPSET_ATTR_CIDR2]) {
 227                cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
 228                if (!cidr || cidr > HOST_MASK)
 229                        return -IPSET_ERR_INVALID_CIDR;
 230                e.cidr = cidr - 1;
 231        }
 232
 233        if (tb[IPSET_ATTR_PORT])
 234                e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
 235        else
 236                return -IPSET_ERR_PROTOCOL;
 237
 238        if (tb[IPSET_ATTR_PROTO]) {
 239                e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
 240                with_ports = ip_set_proto_with_ports(e.proto);
 241
 242                if (e.proto == 0)
 243                        return -IPSET_ERR_INVALID_PROTO;
 244        } else
 245                return -IPSET_ERR_MISSING_PROTO;
 246
 247        if (!(with_ports || e.proto == IPPROTO_ICMP))
 248                e.port = 0;
 249
 250        if (tb[IPSET_ATTR_CADT_FLAGS]) {
 251                u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
 252                if (cadt_flags & IPSET_FLAG_NOMATCH)
 253                        flags |= (IPSET_FLAG_NOMATCH << 16);
 254        }
 255
 256        with_ports = with_ports && tb[IPSET_ATTR_PORT_TO];
 257        if (adt == IPSET_TEST ||
 258            !(tb[IPSET_ATTR_CIDR] || tb[IPSET_ATTR_IP_TO] || with_ports ||
 259              tb[IPSET_ATTR_IP2_TO])) {
 260                e.ip = htonl(ip);
 261                e.ip2 = htonl(ip2_from & ip_set_hostmask(e.cidr + 1));
 262                ret = adtfn(set, &e, &ext, &ext, flags);
 263                return ip_set_enomatch(ret, flags, adt) ? 1 :
 264                       ip_set_eexist(ret, flags) ? 0 : ret;
 265        }
 266
 267        ip_to = ip;
 268        if (tb[IPSET_ATTR_IP_TO]) {
 269                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
 270                if (ret)
 271                        return ret;
 272                if (ip > ip_to)
 273                        swap(ip, ip_to);
 274        } else if (tb[IPSET_ATTR_CIDR]) {
 275                u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
 276
 277                if (!cidr || cidr > 32)
 278                        return -IPSET_ERR_INVALID_CIDR;
 279                ip_set_mask_from_to(ip, ip_to, cidr);
 280        }
 281
 282        port_to = port = ntohs(e.port);
 283        if (tb[IPSET_ATTR_PORT_TO]) {
 284                port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
 285                if (port > port_to)
 286                        swap(port, port_to);
 287        }
 288
 289        ip2_to = ip2_from;
 290        if (tb[IPSET_ATTR_IP2_TO]) {
 291                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
 292                if (ret)
 293                        return ret;
 294                if (ip2_from > ip2_to)
 295                        swap(ip2_from, ip2_to);
 296                if (ip2_from + UINT_MAX == ip2_to)
 297                        return -IPSET_ERR_HASH_RANGE;
 298        } else
 299                ip_set_mask_from_to(ip2_from, ip2_to, e.cidr + 1);
 300
 301        if (retried)
 302                ip = ntohl(h->next.ip);
 303        for (; !before(ip_to, ip); ip++) {
 304                e.ip = htonl(ip);
 305                p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
 306                                                       : port;
 307                for (; p <= port_to; p++) {
 308                        e.port = htons(p);
 309                        ip2 = retried
 310                              && ip == ntohl(h->next.ip)
 311                              && p == ntohs(h->next.port)
 312                                ? ntohl(h->next.ip2) : ip2_from;
 313                        while (!after(ip2, ip2_to)) {
 314                                e.ip2 = htonl(ip2);
 315                                ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
 316                                                                &cidr);
 317                                e.cidr = cidr - 1;
 318                                ret = adtfn(set, &e, &ext, &ext, flags);
 319
 320                                if (ret && !ip_set_eexist(ret, flags))
 321                                        return ret;
 322                                else
 323                                        ret = 0;
 324                                ip2 = ip2_last + 1;
 325                        }
 326                }
 327        }
 328        return ret;
 329}
 330
 331/* IPv6 variants */
 332
 333struct hash_ipportnet6_elem {
 334        union nf_inet_addr ip;
 335        union nf_inet_addr ip2;
 336        __be16 port;
 337        u8 cidr:7;
 338        u8 nomatch:1;
 339        u8 proto;
 340};
 341
 342struct hash_ipportnet6t_elem {
 343        union nf_inet_addr ip;
 344        union nf_inet_addr ip2;
 345        __be16 port;
 346        u8 cidr:7;
 347        u8 nomatch:1;
 348        u8 proto;
 349        unsigned long timeout;
 350};
 351
 352struct hash_ipportnet6c_elem {
 353        union nf_inet_addr ip;
 354        union nf_inet_addr ip2;
 355        __be16 port;
 356        u8 cidr:7;
 357        u8 nomatch:1;
 358        u8 proto;
 359        struct ip_set_counter counter;
 360};
 361
 362struct hash_ipportnet6ct_elem {
 363        union nf_inet_addr ip;
 364        union nf_inet_addr ip2;
 365        __be16 port;
 366        u8 cidr:7;
 367        u8 nomatch:1;
 368        u8 proto;
 369        struct ip_set_counter counter;
 370        unsigned long timeout;
 371};
 372
 373/* Common functions */
 374
 375static inline bool
 376hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
 377                           const struct hash_ipportnet6_elem *ip2,
 378                           u32 *multi)
 379{
 380        return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6) &&
 381               ipv6_addr_equal(&ip1->ip2.in6, &ip2->ip2.in6) &&
 382               ip1->cidr == ip2->cidr &&
 383               ip1->port == ip2->port &&
 384               ip1->proto == ip2->proto;
 385}
 386
 387static inline int
 388hash_ipportnet6_do_data_match(const struct hash_ipportnet6_elem *elem)
 389{
 390        return elem->nomatch ? -ENOTEMPTY : 1;
 391}
 392
 393static inline void
 394hash_ipportnet6_data_set_flags(struct hash_ipportnet6_elem *elem, u32 flags)
 395{
 396        elem->nomatch = !!((flags >> 16) & IPSET_FLAG_NOMATCH);
 397}
 398
 399static inline void
 400hash_ipportnet6_data_reset_flags(struct hash_ipportnet6_elem *elem, u8 *flags)
 401{
 402        swap(*flags, elem->nomatch);
 403}
 404
 405static inline void
 406hash_ipportnet6_data_netmask(struct hash_ipportnet6_elem *elem, u8 cidr)
 407{
 408        ip6_netmask(&elem->ip2, cidr);
 409        elem->cidr = cidr - 1;
 410}
 411
 412static bool
 413hash_ipportnet6_data_list(struct sk_buff *skb,
 414                          const struct hash_ipportnet6_elem *data)
 415{
 416        u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0;
 417
 418        if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) ||
 419            nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip2.in6) ||
 420            nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
 421            nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr + 1) ||
 422            nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto) ||
 423            (flags &&
 424             nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags))))
 425                goto nla_put_failure;
 426        return 0;
 427
 428nla_put_failure:
 429        return 1;
 430}
 431
 432static inline void
 433hash_ipportnet6_data_next(struct hash_ipportnet4_elem *next,
 434                          const struct hash_ipportnet6_elem *d)
 435{
 436        next->port = d->port;
 437}
 438
 439#undef MTYPE
 440#undef PF
 441#undef HOST_MASK
 442
 443#define MTYPE           hash_ipportnet6
 444#define PF              6
 445#define HOST_MASK       128
 446#define IP_SET_EMIT_CREATE
 447#include "ip_set_hash_gen.h"
 448
 449static int
 450hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
 451                     const struct xt_action_param *par,
 452                     enum ipset_adt adt, struct ip_set_adt_opt *opt)
 453{
 454        const struct hash_ipportnet *h = set->data;
 455        ipset_adtfn adtfn = set->variant->adt[adt];
 456        struct hash_ipportnet6_elem e = {
 457                .cidr = h->nets[0].cidr ? h->nets[0].cidr - 1 : HOST_MASK - 1
 458        };
 459        struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
 460
 461        if (adt == IPSET_TEST)
 462                e.cidr = HOST_MASK - 1;
 463
 464        if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
 465                                 &e.port, &e.proto))
 466                return -EINVAL;
 467
 468        ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
 469        ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &e.ip2.in6);
 470        ip6_netmask(&e.ip2, e.cidr + 1);
 471
 472        return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
 473}
 474
 475static int
 476hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
 477                     enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
 478{
 479        const struct hash_ipportnet *h = set->data;
 480        ipset_adtfn adtfn = set->variant->adt[adt];
 481        struct hash_ipportnet6_elem e = { .cidr = HOST_MASK - 1 };
 482        struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
 483        u32 port, port_to;
 484        bool with_ports = false;
 485        u8 cidr;
 486        int ret;
 487
 488        if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] ||
 489                     !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
 490                     !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
 491                     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
 492                     !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
 493                     !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
 494                     !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
 495                     tb[IPSET_ATTR_IP_TO] ||
 496                     tb[IPSET_ATTR_CIDR]))
 497                return -IPSET_ERR_PROTOCOL;
 498        if (unlikely(tb[IPSET_ATTR_IP_TO]))
 499                return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
 500
 501        if (tb[IPSET_ATTR_LINENO])
 502                *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
 503
 504        ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) ||
 505              ip_set_get_extensions(set, tb, &ext);
 506        if (ret)
 507                return ret;
 508
 509        ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &e.ip2);
 510        if (ret)
 511                return ret;
 512
 513        if (tb[IPSET_ATTR_CIDR2]) {
 514                cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
 515                if (!cidr || cidr > HOST_MASK)
 516                        return -IPSET_ERR_INVALID_CIDR;
 517                e.cidr = cidr - 1;
 518        }
 519
 520        ip6_netmask(&e.ip2, e.cidr + 1);
 521
 522        if (tb[IPSET_ATTR_PORT])
 523                e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
 524        else
 525                return -IPSET_ERR_PROTOCOL;
 526
 527        if (tb[IPSET_ATTR_PROTO]) {
 528                e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
 529                with_ports = ip_set_proto_with_ports(e.proto);
 530
 531                if (e.proto == 0)
 532                        return -IPSET_ERR_INVALID_PROTO;
 533        } else
 534                return -IPSET_ERR_MISSING_PROTO;
 535
 536        if (!(with_ports || e.proto == IPPROTO_ICMPV6))
 537                e.port = 0;
 538
 539        if (tb[IPSET_ATTR_CADT_FLAGS]) {
 540                u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
 541                if (cadt_flags & IPSET_FLAG_NOMATCH)
 542                        flags |= (IPSET_FLAG_NOMATCH << 16);
 543        }
 544
 545        if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
 546                ret = adtfn(set, &e, &ext, &ext, flags);
 547                return ip_set_enomatch(ret, flags, adt) ? 1 :
 548                       ip_set_eexist(ret, flags) ? 0 : ret;
 549        }
 550
 551        port = ntohs(e.port);
 552        port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
 553        if (port > port_to)
 554                swap(port, port_to);
 555
 556        if (retried)
 557                port = ntohs(h->next.port);
 558        for (; port <= port_to; port++) {
 559                e.port = htons(port);
 560                ret = adtfn(set, &e, &ext, &ext, flags);
 561
 562                if (ret && !ip_set_eexist(ret, flags))
 563                        return ret;
 564                else
 565                        ret = 0;
 566        }
 567        return ret;
 568}
 569
 570static struct ip_set_type hash_ipportnet_type __read_mostly = {
 571        .name           = "hash:ip,port,net",
 572        .protocol       = IPSET_PROTOCOL,
 573        .features       = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2 |
 574                          IPSET_TYPE_NOMATCH,
 575        .dimension      = IPSET_DIM_THREE,
 576        .family         = NFPROTO_UNSPEC,
 577        .revision_min   = REVISION_MIN,
 578        .revision_max   = REVISION_MAX,
 579        .create         = hash_ipportnet_create,
 580        .create_policy  = {
 581                [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
 582                [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
 583                [IPSET_ATTR_PROBES]     = { .type = NLA_U8 },
 584                [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
 585                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 586                [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
 587        },
 588        .adt_policy     = {
 589                [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
 590                [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
 591                [IPSET_ATTR_IP2]        = { .type = NLA_NESTED },
 592                [IPSET_ATTR_IP2_TO]     = { .type = NLA_NESTED },
 593                [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
 594                [IPSET_ATTR_PORT_TO]    = { .type = NLA_U16 },
 595                [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
 596                [IPSET_ATTR_CIDR2]      = { .type = NLA_U8 },
 597                [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
 598                [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
 599                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 600                [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 601                [IPSET_ATTR_BYTES]      = { .type = NLA_U64 },
 602                [IPSET_ATTR_PACKETS]    = { .type = NLA_U64 },
 603        },
 604        .me             = THIS_MODULE,
 605};
 606
 607static int __init
 608hash_ipportnet_init(void)
 609{
 610        return ip_set_type_register(&hash_ipportnet_type);
 611}
 612
 613static void __exit
 614hash_ipportnet_fini(void)
 615{
 616        ip_set_type_unregister(&hash_ipportnet_type);
 617}
 618
 619module_init(hash_ipportnet_init);
 620module_exit(hash_ipportnet_fini);
 621