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