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