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