linux/net/netfilter/nft_ct.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
   4 * Copyright (c) 2016 Pablo Neira Ayuso <pablo@netfilter.org>
   5 *
   6 * Development of this code funded by Astaro AG (http://www.astaro.com/)
   7 */
   8
   9#include <linux/kernel.h>
  10#include <linux/init.h>
  11#include <linux/module.h>
  12#include <linux/netlink.h>
  13#include <linux/netfilter.h>
  14#include <linux/netfilter/nf_tables.h>
  15#include <net/netfilter/nf_tables.h>
  16#include <net/netfilter/nf_conntrack.h>
  17#include <net/netfilter/nf_conntrack_acct.h>
  18#include <net/netfilter/nf_conntrack_tuple.h>
  19#include <net/netfilter/nf_conntrack_helper.h>
  20#include <net/netfilter/nf_conntrack_ecache.h>
  21#include <net/netfilter/nf_conntrack_labels.h>
  22#include <net/netfilter/nf_conntrack_timeout.h>
  23#include <net/netfilter/nf_conntrack_l4proto.h>
  24#include <net/netfilter/nf_conntrack_expect.h>
  25
  26struct nft_ct {
  27        enum nft_ct_keys        key:8;
  28        enum ip_conntrack_dir   dir:8;
  29        union {
  30                u8              dreg;
  31                u8              sreg;
  32        };
  33};
  34
  35struct nft_ct_helper_obj  {
  36        struct nf_conntrack_helper *helper4;
  37        struct nf_conntrack_helper *helper6;
  38        u8 l4proto;
  39};
  40
  41#ifdef CONFIG_NF_CONNTRACK_ZONES
  42static DEFINE_PER_CPU(struct nf_conn *, nft_ct_pcpu_template);
  43static unsigned int nft_ct_pcpu_template_refcnt __read_mostly;
  44#endif
  45
  46static u64 nft_ct_get_eval_counter(const struct nf_conn_counter *c,
  47                                   enum nft_ct_keys k,
  48                                   enum ip_conntrack_dir d)
  49{
  50        if (d < IP_CT_DIR_MAX)
  51                return k == NFT_CT_BYTES ? atomic64_read(&c[d].bytes) :
  52                                           atomic64_read(&c[d].packets);
  53
  54        return nft_ct_get_eval_counter(c, k, IP_CT_DIR_ORIGINAL) +
  55               nft_ct_get_eval_counter(c, k, IP_CT_DIR_REPLY);
  56}
  57
  58static void nft_ct_get_eval(const struct nft_expr *expr,
  59                            struct nft_regs *regs,
  60                            const struct nft_pktinfo *pkt)
  61{
  62        const struct nft_ct *priv = nft_expr_priv(expr);
  63        u32 *dest = &regs->data[priv->dreg];
  64        enum ip_conntrack_info ctinfo;
  65        const struct nf_conn *ct;
  66        const struct nf_conn_help *help;
  67        const struct nf_conntrack_tuple *tuple;
  68        const struct nf_conntrack_helper *helper;
  69        unsigned int state;
  70
  71        ct = nf_ct_get(pkt->skb, &ctinfo);
  72
  73        switch (priv->key) {
  74        case NFT_CT_STATE:
  75                if (ct)
  76                        state = NF_CT_STATE_BIT(ctinfo);
  77                else if (ctinfo == IP_CT_UNTRACKED)
  78                        state = NF_CT_STATE_UNTRACKED_BIT;
  79                else
  80                        state = NF_CT_STATE_INVALID_BIT;
  81                *dest = state;
  82                return;
  83        default:
  84                break;
  85        }
  86
  87        if (ct == NULL)
  88                goto err;
  89
  90        switch (priv->key) {
  91        case NFT_CT_DIRECTION:
  92                nft_reg_store8(dest, CTINFO2DIR(ctinfo));
  93                return;
  94        case NFT_CT_STATUS:
  95                *dest = ct->status;
  96                return;
  97#ifdef CONFIG_NF_CONNTRACK_MARK
  98        case NFT_CT_MARK:
  99                *dest = ct->mark;
 100                return;
 101#endif
 102#ifdef CONFIG_NF_CONNTRACK_SECMARK
 103        case NFT_CT_SECMARK:
 104                *dest = ct->secmark;
 105                return;
 106#endif
 107        case NFT_CT_EXPIRATION:
 108                *dest = jiffies_to_msecs(nf_ct_expires(ct));
 109                return;
 110        case NFT_CT_HELPER:
 111                if (ct->master == NULL)
 112                        goto err;
 113                help = nfct_help(ct->master);
 114                if (help == NULL)
 115                        goto err;
 116                helper = rcu_dereference(help->helper);
 117                if (helper == NULL)
 118                        goto err;
 119                strncpy((char *)dest, helper->name, NF_CT_HELPER_NAME_LEN);
 120                return;
 121#ifdef CONFIG_NF_CONNTRACK_LABELS
 122        case NFT_CT_LABELS: {
 123                struct nf_conn_labels *labels = nf_ct_labels_find(ct);
 124
 125                if (labels)
 126                        memcpy(dest, labels->bits, NF_CT_LABELS_MAX_SIZE);
 127                else
 128                        memset(dest, 0, NF_CT_LABELS_MAX_SIZE);
 129                return;
 130        }
 131#endif
 132        case NFT_CT_BYTES:
 133        case NFT_CT_PKTS: {
 134                const struct nf_conn_acct *acct = nf_conn_acct_find(ct);
 135                u64 count = 0;
 136
 137                if (acct)
 138                        count = nft_ct_get_eval_counter(acct->counter,
 139                                                        priv->key, priv->dir);
 140                memcpy(dest, &count, sizeof(count));
 141                return;
 142        }
 143        case NFT_CT_AVGPKT: {
 144                const struct nf_conn_acct *acct = nf_conn_acct_find(ct);
 145                u64 avgcnt = 0, bcnt = 0, pcnt = 0;
 146
 147                if (acct) {
 148                        pcnt = nft_ct_get_eval_counter(acct->counter,
 149                                                       NFT_CT_PKTS, priv->dir);
 150                        bcnt = nft_ct_get_eval_counter(acct->counter,
 151                                                       NFT_CT_BYTES, priv->dir);
 152                        if (pcnt != 0)
 153                                avgcnt = div64_u64(bcnt, pcnt);
 154                }
 155
 156                memcpy(dest, &avgcnt, sizeof(avgcnt));
 157                return;
 158        }
 159        case NFT_CT_L3PROTOCOL:
 160                nft_reg_store8(dest, nf_ct_l3num(ct));
 161                return;
 162        case NFT_CT_PROTOCOL:
 163                nft_reg_store8(dest, nf_ct_protonum(ct));
 164                return;
 165#ifdef CONFIG_NF_CONNTRACK_ZONES
 166        case NFT_CT_ZONE: {
 167                const struct nf_conntrack_zone *zone = nf_ct_zone(ct);
 168                u16 zoneid;
 169
 170                if (priv->dir < IP_CT_DIR_MAX)
 171                        zoneid = nf_ct_zone_id(zone, priv->dir);
 172                else
 173                        zoneid = zone->id;
 174
 175                nft_reg_store16(dest, zoneid);
 176                return;
 177        }
 178#endif
 179        case NFT_CT_ID:
 180                *dest = nf_ct_get_id(ct);
 181                return;
 182        default:
 183                break;
 184        }
 185
 186        tuple = &ct->tuplehash[priv->dir].tuple;
 187        switch (priv->key) {
 188        case NFT_CT_SRC:
 189                memcpy(dest, tuple->src.u3.all,
 190                       nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16);
 191                return;
 192        case NFT_CT_DST:
 193                memcpy(dest, tuple->dst.u3.all,
 194                       nf_ct_l3num(ct) == NFPROTO_IPV4 ? 4 : 16);
 195                return;
 196        case NFT_CT_PROTO_SRC:
 197                nft_reg_store16(dest, (__force u16)tuple->src.u.all);
 198                return;
 199        case NFT_CT_PROTO_DST:
 200                nft_reg_store16(dest, (__force u16)tuple->dst.u.all);
 201                return;
 202        case NFT_CT_SRC_IP:
 203                if (nf_ct_l3num(ct) != NFPROTO_IPV4)
 204                        goto err;
 205                *dest = tuple->src.u3.ip;
 206                return;
 207        case NFT_CT_DST_IP:
 208                if (nf_ct_l3num(ct) != NFPROTO_IPV4)
 209                        goto err;
 210                *dest = tuple->dst.u3.ip;
 211                return;
 212        case NFT_CT_SRC_IP6:
 213                if (nf_ct_l3num(ct) != NFPROTO_IPV6)
 214                        goto err;
 215                memcpy(dest, tuple->src.u3.ip6, sizeof(struct in6_addr));
 216                return;
 217        case NFT_CT_DST_IP6:
 218                if (nf_ct_l3num(ct) != NFPROTO_IPV6)
 219                        goto err;
 220                memcpy(dest, tuple->dst.u3.ip6, sizeof(struct in6_addr));
 221                return;
 222        default:
 223                break;
 224        }
 225        return;
 226err:
 227        regs->verdict.code = NFT_BREAK;
 228}
 229
 230#ifdef CONFIG_NF_CONNTRACK_ZONES
 231static void nft_ct_set_zone_eval(const struct nft_expr *expr,
 232                                 struct nft_regs *regs,
 233                                 const struct nft_pktinfo *pkt)
 234{
 235        struct nf_conntrack_zone zone = { .dir = NF_CT_DEFAULT_ZONE_DIR };
 236        const struct nft_ct *priv = nft_expr_priv(expr);
 237        struct sk_buff *skb = pkt->skb;
 238        enum ip_conntrack_info ctinfo;
 239        u16 value = nft_reg_load16(&regs->data[priv->sreg]);
 240        struct nf_conn *ct;
 241
 242        ct = nf_ct_get(skb, &ctinfo);
 243        if (ct) /* already tracked */
 244                return;
 245
 246        zone.id = value;
 247
 248        switch (priv->dir) {
 249        case IP_CT_DIR_ORIGINAL:
 250                zone.dir = NF_CT_ZONE_DIR_ORIG;
 251                break;
 252        case IP_CT_DIR_REPLY:
 253                zone.dir = NF_CT_ZONE_DIR_REPL;
 254                break;
 255        default:
 256                break;
 257        }
 258
 259        ct = this_cpu_read(nft_ct_pcpu_template);
 260
 261        if (likely(atomic_read(&ct->ct_general.use) == 1)) {
 262                nf_ct_zone_add(ct, &zone);
 263        } else {
 264                /* previous skb got queued to userspace */
 265                ct = nf_ct_tmpl_alloc(nft_net(pkt), &zone, GFP_ATOMIC);
 266                if (!ct) {
 267                        regs->verdict.code = NF_DROP;
 268                        return;
 269                }
 270        }
 271
 272        atomic_inc(&ct->ct_general.use);
 273        nf_ct_set(skb, ct, IP_CT_NEW);
 274}
 275#endif
 276
 277static void nft_ct_set_eval(const struct nft_expr *expr,
 278                            struct nft_regs *regs,
 279                            const struct nft_pktinfo *pkt)
 280{
 281        const struct nft_ct *priv = nft_expr_priv(expr);
 282        struct sk_buff *skb = pkt->skb;
 283#if defined(CONFIG_NF_CONNTRACK_MARK) || defined(CONFIG_NF_CONNTRACK_SECMARK)
 284        u32 value = regs->data[priv->sreg];
 285#endif
 286        enum ip_conntrack_info ctinfo;
 287        struct nf_conn *ct;
 288
 289        ct = nf_ct_get(skb, &ctinfo);
 290        if (ct == NULL || nf_ct_is_template(ct))
 291                return;
 292
 293        switch (priv->key) {
 294#ifdef CONFIG_NF_CONNTRACK_MARK
 295        case NFT_CT_MARK:
 296                if (ct->mark != value) {
 297                        ct->mark = value;
 298                        nf_conntrack_event_cache(IPCT_MARK, ct);
 299                }
 300                break;
 301#endif
 302#ifdef CONFIG_NF_CONNTRACK_SECMARK
 303        case NFT_CT_SECMARK:
 304                if (ct->secmark != value) {
 305                        ct->secmark = value;
 306                        nf_conntrack_event_cache(IPCT_SECMARK, ct);
 307                }
 308                break;
 309#endif
 310#ifdef CONFIG_NF_CONNTRACK_LABELS
 311        case NFT_CT_LABELS:
 312                nf_connlabels_replace(ct,
 313                                      &regs->data[priv->sreg],
 314                                      &regs->data[priv->sreg],
 315                                      NF_CT_LABELS_MAX_SIZE / sizeof(u32));
 316                break;
 317#endif
 318#ifdef CONFIG_NF_CONNTRACK_EVENTS
 319        case NFT_CT_EVENTMASK: {
 320                struct nf_conntrack_ecache *e = nf_ct_ecache_find(ct);
 321                u32 ctmask = regs->data[priv->sreg];
 322
 323                if (e) {
 324                        if (e->ctmask != ctmask)
 325                                e->ctmask = ctmask;
 326                        break;
 327                }
 328
 329                if (ctmask && !nf_ct_is_confirmed(ct))
 330                        nf_ct_ecache_ext_add(ct, ctmask, 0, GFP_ATOMIC);
 331                break;
 332        }
 333#endif
 334        default:
 335                break;
 336        }
 337}
 338
 339static const struct nla_policy nft_ct_policy[NFTA_CT_MAX + 1] = {
 340        [NFTA_CT_DREG]          = { .type = NLA_U32 },
 341        [NFTA_CT_KEY]           = { .type = NLA_U32 },
 342        [NFTA_CT_DIRECTION]     = { .type = NLA_U8 },
 343        [NFTA_CT_SREG]          = { .type = NLA_U32 },
 344};
 345
 346#ifdef CONFIG_NF_CONNTRACK_ZONES
 347static void nft_ct_tmpl_put_pcpu(void)
 348{
 349        struct nf_conn *ct;
 350        int cpu;
 351
 352        for_each_possible_cpu(cpu) {
 353                ct = per_cpu(nft_ct_pcpu_template, cpu);
 354                if (!ct)
 355                        break;
 356                nf_ct_put(ct);
 357                per_cpu(nft_ct_pcpu_template, cpu) = NULL;
 358        }
 359}
 360
 361static bool nft_ct_tmpl_alloc_pcpu(void)
 362{
 363        struct nf_conntrack_zone zone = { .id = 0 };
 364        struct nf_conn *tmp;
 365        int cpu;
 366
 367        if (nft_ct_pcpu_template_refcnt)
 368                return true;
 369
 370        for_each_possible_cpu(cpu) {
 371                tmp = nf_ct_tmpl_alloc(&init_net, &zone, GFP_KERNEL);
 372                if (!tmp) {
 373                        nft_ct_tmpl_put_pcpu();
 374                        return false;
 375                }
 376
 377                atomic_set(&tmp->ct_general.use, 1);
 378                per_cpu(nft_ct_pcpu_template, cpu) = tmp;
 379        }
 380
 381        return true;
 382}
 383#endif
 384
 385static int nft_ct_get_init(const struct nft_ctx *ctx,
 386                           const struct nft_expr *expr,
 387                           const struct nlattr * const tb[])
 388{
 389        struct nft_ct *priv = nft_expr_priv(expr);
 390        unsigned int len;
 391        int err;
 392
 393        priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY]));
 394        priv->dir = IP_CT_DIR_MAX;
 395        switch (priv->key) {
 396        case NFT_CT_DIRECTION:
 397                if (tb[NFTA_CT_DIRECTION] != NULL)
 398                        return -EINVAL;
 399                len = sizeof(u8);
 400                break;
 401        case NFT_CT_STATE:
 402        case NFT_CT_STATUS:
 403#ifdef CONFIG_NF_CONNTRACK_MARK
 404        case NFT_CT_MARK:
 405#endif
 406#ifdef CONFIG_NF_CONNTRACK_SECMARK
 407        case NFT_CT_SECMARK:
 408#endif
 409        case NFT_CT_EXPIRATION:
 410                if (tb[NFTA_CT_DIRECTION] != NULL)
 411                        return -EINVAL;
 412                len = sizeof(u32);
 413                break;
 414#ifdef CONFIG_NF_CONNTRACK_LABELS
 415        case NFT_CT_LABELS:
 416                if (tb[NFTA_CT_DIRECTION] != NULL)
 417                        return -EINVAL;
 418                len = NF_CT_LABELS_MAX_SIZE;
 419                break;
 420#endif
 421        case NFT_CT_HELPER:
 422                if (tb[NFTA_CT_DIRECTION] != NULL)
 423                        return -EINVAL;
 424                len = NF_CT_HELPER_NAME_LEN;
 425                break;
 426
 427        case NFT_CT_L3PROTOCOL:
 428        case NFT_CT_PROTOCOL:
 429                /* For compatibility, do not report error if NFTA_CT_DIRECTION
 430                 * attribute is specified.
 431                 */
 432                len = sizeof(u8);
 433                break;
 434        case NFT_CT_SRC:
 435        case NFT_CT_DST:
 436                if (tb[NFTA_CT_DIRECTION] == NULL)
 437                        return -EINVAL;
 438
 439                switch (ctx->family) {
 440                case NFPROTO_IPV4:
 441                        len = sizeof_field(struct nf_conntrack_tuple,
 442                                           src.u3.ip);
 443                        break;
 444                case NFPROTO_IPV6:
 445                case NFPROTO_INET:
 446                        len = sizeof_field(struct nf_conntrack_tuple,
 447                                           src.u3.ip6);
 448                        break;
 449                default:
 450                        return -EAFNOSUPPORT;
 451                }
 452                break;
 453        case NFT_CT_SRC_IP:
 454        case NFT_CT_DST_IP:
 455                if (tb[NFTA_CT_DIRECTION] == NULL)
 456                        return -EINVAL;
 457
 458                len = sizeof_field(struct nf_conntrack_tuple, src.u3.ip);
 459                break;
 460        case NFT_CT_SRC_IP6:
 461        case NFT_CT_DST_IP6:
 462                if (tb[NFTA_CT_DIRECTION] == NULL)
 463                        return -EINVAL;
 464
 465                len = sizeof_field(struct nf_conntrack_tuple, src.u3.ip6);
 466                break;
 467        case NFT_CT_PROTO_SRC:
 468        case NFT_CT_PROTO_DST:
 469                if (tb[NFTA_CT_DIRECTION] == NULL)
 470                        return -EINVAL;
 471                len = sizeof_field(struct nf_conntrack_tuple, src.u.all);
 472                break;
 473        case NFT_CT_BYTES:
 474        case NFT_CT_PKTS:
 475        case NFT_CT_AVGPKT:
 476                len = sizeof(u64);
 477                break;
 478#ifdef CONFIG_NF_CONNTRACK_ZONES
 479        case NFT_CT_ZONE:
 480                len = sizeof(u16);
 481                break;
 482#endif
 483        case NFT_CT_ID:
 484                len = sizeof(u32);
 485                break;
 486        default:
 487                return -EOPNOTSUPP;
 488        }
 489
 490        if (tb[NFTA_CT_DIRECTION] != NULL) {
 491                priv->dir = nla_get_u8(tb[NFTA_CT_DIRECTION]);
 492                switch (priv->dir) {
 493                case IP_CT_DIR_ORIGINAL:
 494                case IP_CT_DIR_REPLY:
 495                        break;
 496                default:
 497                        return -EINVAL;
 498                }
 499        }
 500
 501        err = nft_parse_register_store(ctx, tb[NFTA_CT_DREG], &priv->dreg, NULL,
 502                                       NFT_DATA_VALUE, len);
 503        if (err < 0)
 504                return err;
 505
 506        err = nf_ct_netns_get(ctx->net, ctx->family);
 507        if (err < 0)
 508                return err;
 509
 510        if (priv->key == NFT_CT_BYTES ||
 511            priv->key == NFT_CT_PKTS  ||
 512            priv->key == NFT_CT_AVGPKT)
 513                nf_ct_set_acct(ctx->net, true);
 514
 515        return 0;
 516}
 517
 518static void __nft_ct_set_destroy(const struct nft_ctx *ctx, struct nft_ct *priv)
 519{
 520        switch (priv->key) {
 521#ifdef CONFIG_NF_CONNTRACK_LABELS
 522        case NFT_CT_LABELS:
 523                nf_connlabels_put(ctx->net);
 524                break;
 525#endif
 526#ifdef CONFIG_NF_CONNTRACK_ZONES
 527        case NFT_CT_ZONE:
 528                if (--nft_ct_pcpu_template_refcnt == 0)
 529                        nft_ct_tmpl_put_pcpu();
 530                break;
 531#endif
 532        default:
 533                break;
 534        }
 535}
 536
 537static int nft_ct_set_init(const struct nft_ctx *ctx,
 538                           const struct nft_expr *expr,
 539                           const struct nlattr * const tb[])
 540{
 541        struct nft_ct *priv = nft_expr_priv(expr);
 542        unsigned int len;
 543        int err;
 544
 545        priv->dir = IP_CT_DIR_MAX;
 546        priv->key = ntohl(nla_get_be32(tb[NFTA_CT_KEY]));
 547        switch (priv->key) {
 548#ifdef CONFIG_NF_CONNTRACK_MARK
 549        case NFT_CT_MARK:
 550                if (tb[NFTA_CT_DIRECTION])
 551                        return -EINVAL;
 552                len = sizeof_field(struct nf_conn, mark);
 553                break;
 554#endif
 555#ifdef CONFIG_NF_CONNTRACK_LABELS
 556        case NFT_CT_LABELS:
 557                if (tb[NFTA_CT_DIRECTION])
 558                        return -EINVAL;
 559                len = NF_CT_LABELS_MAX_SIZE;
 560                err = nf_connlabels_get(ctx->net, (len * BITS_PER_BYTE) - 1);
 561                if (err)
 562                        return err;
 563                break;
 564#endif
 565#ifdef CONFIG_NF_CONNTRACK_ZONES
 566        case NFT_CT_ZONE:
 567                if (!nft_ct_tmpl_alloc_pcpu())
 568                        return -ENOMEM;
 569                nft_ct_pcpu_template_refcnt++;
 570                len = sizeof(u16);
 571                break;
 572#endif
 573#ifdef CONFIG_NF_CONNTRACK_EVENTS
 574        case NFT_CT_EVENTMASK:
 575                if (tb[NFTA_CT_DIRECTION])
 576                        return -EINVAL;
 577                len = sizeof(u32);
 578                break;
 579#endif
 580#ifdef CONFIG_NF_CONNTRACK_SECMARK
 581        case NFT_CT_SECMARK:
 582                if (tb[NFTA_CT_DIRECTION])
 583                        return -EINVAL;
 584                len = sizeof(u32);
 585                break;
 586#endif
 587        default:
 588                return -EOPNOTSUPP;
 589        }
 590
 591        if (tb[NFTA_CT_DIRECTION]) {
 592                priv->dir = nla_get_u8(tb[NFTA_CT_DIRECTION]);
 593                switch (priv->dir) {
 594                case IP_CT_DIR_ORIGINAL:
 595                case IP_CT_DIR_REPLY:
 596                        break;
 597                default:
 598                        err = -EINVAL;
 599                        goto err1;
 600                }
 601        }
 602
 603        err = nft_parse_register_load(tb[NFTA_CT_SREG], &priv->sreg, len);
 604        if (err < 0)
 605                goto err1;
 606
 607        err = nf_ct_netns_get(ctx->net, ctx->family);
 608        if (err < 0)
 609                goto err1;
 610
 611        return 0;
 612
 613err1:
 614        __nft_ct_set_destroy(ctx, priv);
 615        return err;
 616}
 617
 618static void nft_ct_get_destroy(const struct nft_ctx *ctx,
 619                               const struct nft_expr *expr)
 620{
 621        nf_ct_netns_put(ctx->net, ctx->family);
 622}
 623
 624static void nft_ct_set_destroy(const struct nft_ctx *ctx,
 625                               const struct nft_expr *expr)
 626{
 627        struct nft_ct *priv = nft_expr_priv(expr);
 628
 629        __nft_ct_set_destroy(ctx, priv);
 630        nf_ct_netns_put(ctx->net, ctx->family);
 631}
 632
 633static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr)
 634{
 635        const struct nft_ct *priv = nft_expr_priv(expr);
 636
 637        if (nft_dump_register(skb, NFTA_CT_DREG, priv->dreg))
 638                goto nla_put_failure;
 639        if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key)))
 640                goto nla_put_failure;
 641
 642        switch (priv->key) {
 643        case NFT_CT_SRC:
 644        case NFT_CT_DST:
 645        case NFT_CT_SRC_IP:
 646        case NFT_CT_DST_IP:
 647        case NFT_CT_SRC_IP6:
 648        case NFT_CT_DST_IP6:
 649        case NFT_CT_PROTO_SRC:
 650        case NFT_CT_PROTO_DST:
 651                if (nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
 652                        goto nla_put_failure;
 653                break;
 654        case NFT_CT_BYTES:
 655        case NFT_CT_PKTS:
 656        case NFT_CT_AVGPKT:
 657        case NFT_CT_ZONE:
 658                if (priv->dir < IP_CT_DIR_MAX &&
 659                    nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
 660                        goto nla_put_failure;
 661                break;
 662        default:
 663                break;
 664        }
 665
 666        return 0;
 667
 668nla_put_failure:
 669        return -1;
 670}
 671
 672static int nft_ct_set_dump(struct sk_buff *skb, const struct nft_expr *expr)
 673{
 674        const struct nft_ct *priv = nft_expr_priv(expr);
 675
 676        if (nft_dump_register(skb, NFTA_CT_SREG, priv->sreg))
 677                goto nla_put_failure;
 678        if (nla_put_be32(skb, NFTA_CT_KEY, htonl(priv->key)))
 679                goto nla_put_failure;
 680
 681        switch (priv->key) {
 682        case NFT_CT_ZONE:
 683                if (priv->dir < IP_CT_DIR_MAX &&
 684                    nla_put_u8(skb, NFTA_CT_DIRECTION, priv->dir))
 685                        goto nla_put_failure;
 686                break;
 687        default:
 688                break;
 689        }
 690
 691        return 0;
 692
 693nla_put_failure:
 694        return -1;
 695}
 696
 697static struct nft_expr_type nft_ct_type;
 698static const struct nft_expr_ops nft_ct_get_ops = {
 699        .type           = &nft_ct_type,
 700        .size           = NFT_EXPR_SIZE(sizeof(struct nft_ct)),
 701        .eval           = nft_ct_get_eval,
 702        .init           = nft_ct_get_init,
 703        .destroy        = nft_ct_get_destroy,
 704        .dump           = nft_ct_get_dump,
 705};
 706
 707static const struct nft_expr_ops nft_ct_set_ops = {
 708        .type           = &nft_ct_type,
 709        .size           = NFT_EXPR_SIZE(sizeof(struct nft_ct)),
 710        .eval           = nft_ct_set_eval,
 711        .init           = nft_ct_set_init,
 712        .destroy        = nft_ct_set_destroy,
 713        .dump           = nft_ct_set_dump,
 714};
 715
 716#ifdef CONFIG_NF_CONNTRACK_ZONES
 717static const struct nft_expr_ops nft_ct_set_zone_ops = {
 718        .type           = &nft_ct_type,
 719        .size           = NFT_EXPR_SIZE(sizeof(struct nft_ct)),
 720        .eval           = nft_ct_set_zone_eval,
 721        .init           = nft_ct_set_init,
 722        .destroy        = nft_ct_set_destroy,
 723        .dump           = nft_ct_set_dump,
 724};
 725#endif
 726
 727static const struct nft_expr_ops *
 728nft_ct_select_ops(const struct nft_ctx *ctx,
 729                    const struct nlattr * const tb[])
 730{
 731        if (tb[NFTA_CT_KEY] == NULL)
 732                return ERR_PTR(-EINVAL);
 733
 734        if (tb[NFTA_CT_DREG] && tb[NFTA_CT_SREG])
 735                return ERR_PTR(-EINVAL);
 736
 737        if (tb[NFTA_CT_DREG])
 738                return &nft_ct_get_ops;
 739
 740        if (tb[NFTA_CT_SREG]) {
 741#ifdef CONFIG_NF_CONNTRACK_ZONES
 742                if (nla_get_be32(tb[NFTA_CT_KEY]) == htonl(NFT_CT_ZONE))
 743                        return &nft_ct_set_zone_ops;
 744#endif
 745                return &nft_ct_set_ops;
 746        }
 747
 748        return ERR_PTR(-EINVAL);
 749}
 750
 751static struct nft_expr_type nft_ct_type __read_mostly = {
 752        .name           = "ct",
 753        .select_ops     = nft_ct_select_ops,
 754        .policy         = nft_ct_policy,
 755        .maxattr        = NFTA_CT_MAX,
 756        .owner          = THIS_MODULE,
 757};
 758
 759static void nft_notrack_eval(const struct nft_expr *expr,
 760                             struct nft_regs *regs,
 761                             const struct nft_pktinfo *pkt)
 762{
 763        struct sk_buff *skb = pkt->skb;
 764        enum ip_conntrack_info ctinfo;
 765        struct nf_conn *ct;
 766
 767        ct = nf_ct_get(pkt->skb, &ctinfo);
 768        /* Previously seen (loopback or untracked)?  Ignore. */
 769        if (ct || ctinfo == IP_CT_UNTRACKED)
 770                return;
 771
 772        nf_ct_set(skb, ct, IP_CT_UNTRACKED);
 773}
 774
 775static struct nft_expr_type nft_notrack_type;
 776static const struct nft_expr_ops nft_notrack_ops = {
 777        .type           = &nft_notrack_type,
 778        .size           = NFT_EXPR_SIZE(0),
 779        .eval           = nft_notrack_eval,
 780};
 781
 782static struct nft_expr_type nft_notrack_type __read_mostly = {
 783        .name           = "notrack",
 784        .ops            = &nft_notrack_ops,
 785        .owner          = THIS_MODULE,
 786};
 787
 788#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
 789static int
 790nft_ct_timeout_parse_policy(void *timeouts,
 791                            const struct nf_conntrack_l4proto *l4proto,
 792                            struct net *net, const struct nlattr *attr)
 793{
 794        struct nlattr **tb;
 795        int ret = 0;
 796
 797        tb = kcalloc(l4proto->ctnl_timeout.nlattr_max + 1, sizeof(*tb),
 798                     GFP_KERNEL);
 799
 800        if (!tb)
 801                return -ENOMEM;
 802
 803        ret = nla_parse_nested_deprecated(tb,
 804                                          l4proto->ctnl_timeout.nlattr_max,
 805                                          attr,
 806                                          l4proto->ctnl_timeout.nla_policy,
 807                                          NULL);
 808        if (ret < 0)
 809                goto err;
 810
 811        ret = l4proto->ctnl_timeout.nlattr_to_obj(tb, net, timeouts);
 812
 813err:
 814        kfree(tb);
 815        return ret;
 816}
 817
 818struct nft_ct_timeout_obj {
 819        struct nf_ct_timeout    *timeout;
 820        u8                      l4proto;
 821};
 822
 823static void nft_ct_timeout_obj_eval(struct nft_object *obj,
 824                                    struct nft_regs *regs,
 825                                    const struct nft_pktinfo *pkt)
 826{
 827        const struct nft_ct_timeout_obj *priv = nft_obj_data(obj);
 828        struct nf_conn *ct = (struct nf_conn *)skb_nfct(pkt->skb);
 829        struct nf_conn_timeout *timeout;
 830        const unsigned int *values;
 831
 832        if (priv->l4proto != pkt->tprot)
 833                return;
 834
 835        if (!ct || nf_ct_is_template(ct) || nf_ct_is_confirmed(ct))
 836                return;
 837
 838        timeout = nf_ct_timeout_find(ct);
 839        if (!timeout) {
 840                timeout = nf_ct_timeout_ext_add(ct, priv->timeout, GFP_ATOMIC);
 841                if (!timeout) {
 842                        regs->verdict.code = NF_DROP;
 843                        return;
 844                }
 845        }
 846
 847        rcu_assign_pointer(timeout->timeout, priv->timeout);
 848
 849        /* adjust the timeout as per 'new' state. ct is unconfirmed,
 850         * so the current timestamp must not be added.
 851         */
 852        values = nf_ct_timeout_data(timeout);
 853        if (values)
 854                nf_ct_refresh(ct, pkt->skb, values[0]);
 855}
 856
 857static int nft_ct_timeout_obj_init(const struct nft_ctx *ctx,
 858                                   const struct nlattr * const tb[],
 859                                   struct nft_object *obj)
 860{
 861        struct nft_ct_timeout_obj *priv = nft_obj_data(obj);
 862        const struct nf_conntrack_l4proto *l4proto;
 863        struct nf_ct_timeout *timeout;
 864        int l3num = ctx->family;
 865        __u8 l4num;
 866        int ret;
 867
 868        if (!tb[NFTA_CT_TIMEOUT_L4PROTO] ||
 869            !tb[NFTA_CT_TIMEOUT_DATA])
 870                return -EINVAL;
 871
 872        if (tb[NFTA_CT_TIMEOUT_L3PROTO])
 873                l3num = ntohs(nla_get_be16(tb[NFTA_CT_TIMEOUT_L3PROTO]));
 874
 875        l4num = nla_get_u8(tb[NFTA_CT_TIMEOUT_L4PROTO]);
 876        priv->l4proto = l4num;
 877
 878        l4proto = nf_ct_l4proto_find(l4num);
 879
 880        if (l4proto->l4proto != l4num) {
 881                ret = -EOPNOTSUPP;
 882                goto err_proto_put;
 883        }
 884
 885        timeout = kzalloc(sizeof(struct nf_ct_timeout) +
 886                          l4proto->ctnl_timeout.obj_size, GFP_KERNEL);
 887        if (timeout == NULL) {
 888                ret = -ENOMEM;
 889                goto err_proto_put;
 890        }
 891
 892        ret = nft_ct_timeout_parse_policy(&timeout->data, l4proto, ctx->net,
 893                                          tb[NFTA_CT_TIMEOUT_DATA]);
 894        if (ret < 0)
 895                goto err_free_timeout;
 896
 897        timeout->l3num = l3num;
 898        timeout->l4proto = l4proto;
 899
 900        ret = nf_ct_netns_get(ctx->net, ctx->family);
 901        if (ret < 0)
 902                goto err_free_timeout;
 903
 904        priv->timeout = timeout;
 905        return 0;
 906
 907err_free_timeout:
 908        kfree(timeout);
 909err_proto_put:
 910        return ret;
 911}
 912
 913static void nft_ct_timeout_obj_destroy(const struct nft_ctx *ctx,
 914                                       struct nft_object *obj)
 915{
 916        struct nft_ct_timeout_obj *priv = nft_obj_data(obj);
 917        struct nf_ct_timeout *timeout = priv->timeout;
 918
 919        nf_ct_untimeout(ctx->net, timeout);
 920        nf_ct_netns_put(ctx->net, ctx->family);
 921        kfree(priv->timeout);
 922}
 923
 924static int nft_ct_timeout_obj_dump(struct sk_buff *skb,
 925                                   struct nft_object *obj, bool reset)
 926{
 927        const struct nft_ct_timeout_obj *priv = nft_obj_data(obj);
 928        const struct nf_ct_timeout *timeout = priv->timeout;
 929        struct nlattr *nest_params;
 930        int ret;
 931
 932        if (nla_put_u8(skb, NFTA_CT_TIMEOUT_L4PROTO, timeout->l4proto->l4proto) ||
 933            nla_put_be16(skb, NFTA_CT_TIMEOUT_L3PROTO, htons(timeout->l3num)))
 934                return -1;
 935
 936        nest_params = nla_nest_start(skb, NFTA_CT_TIMEOUT_DATA);
 937        if (!nest_params)
 938                return -1;
 939
 940        ret = timeout->l4proto->ctnl_timeout.obj_to_nlattr(skb, &timeout->data);
 941        if (ret < 0)
 942                return -1;
 943        nla_nest_end(skb, nest_params);
 944        return 0;
 945}
 946
 947static const struct nla_policy nft_ct_timeout_policy[NFTA_CT_TIMEOUT_MAX + 1] = {
 948        [NFTA_CT_TIMEOUT_L3PROTO] = {.type = NLA_U16 },
 949        [NFTA_CT_TIMEOUT_L4PROTO] = {.type = NLA_U8 },
 950        [NFTA_CT_TIMEOUT_DATA]    = {.type = NLA_NESTED },
 951};
 952
 953static struct nft_object_type nft_ct_timeout_obj_type;
 954
 955static const struct nft_object_ops nft_ct_timeout_obj_ops = {
 956        .type           = &nft_ct_timeout_obj_type,
 957        .size           = sizeof(struct nft_ct_timeout_obj),
 958        .eval           = nft_ct_timeout_obj_eval,
 959        .init           = nft_ct_timeout_obj_init,
 960        .destroy        = nft_ct_timeout_obj_destroy,
 961        .dump           = nft_ct_timeout_obj_dump,
 962};
 963
 964static struct nft_object_type nft_ct_timeout_obj_type __read_mostly = {
 965        .type           = NFT_OBJECT_CT_TIMEOUT,
 966        .ops            = &nft_ct_timeout_obj_ops,
 967        .maxattr        = NFTA_CT_TIMEOUT_MAX,
 968        .policy         = nft_ct_timeout_policy,
 969        .owner          = THIS_MODULE,
 970};
 971#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
 972
 973static int nft_ct_helper_obj_init(const struct nft_ctx *ctx,
 974                                  const struct nlattr * const tb[],
 975                                  struct nft_object *obj)
 976{
 977        struct nft_ct_helper_obj *priv = nft_obj_data(obj);
 978        struct nf_conntrack_helper *help4, *help6;
 979        char name[NF_CT_HELPER_NAME_LEN];
 980        int family = ctx->family;
 981        int err;
 982
 983        if (!tb[NFTA_CT_HELPER_NAME] || !tb[NFTA_CT_HELPER_L4PROTO])
 984                return -EINVAL;
 985
 986        priv->l4proto = nla_get_u8(tb[NFTA_CT_HELPER_L4PROTO]);
 987        if (!priv->l4proto)
 988                return -ENOENT;
 989
 990        nla_strscpy(name, tb[NFTA_CT_HELPER_NAME], sizeof(name));
 991
 992        if (tb[NFTA_CT_HELPER_L3PROTO])
 993                family = ntohs(nla_get_be16(tb[NFTA_CT_HELPER_L3PROTO]));
 994
 995        help4 = NULL;
 996        help6 = NULL;
 997
 998        switch (family) {
 999        case NFPROTO_IPV4:
1000                if (ctx->family == NFPROTO_IPV6)
1001                        return -EINVAL;
1002
1003                help4 = nf_conntrack_helper_try_module_get(name, family,
1004                                                           priv->l4proto);
1005                break;
1006        case NFPROTO_IPV6:
1007                if (ctx->family == NFPROTO_IPV4)
1008                        return -EINVAL;
1009
1010                help6 = nf_conntrack_helper_try_module_get(name, family,
1011                                                           priv->l4proto);
1012                break;
1013        case NFPROTO_NETDEV:
1014        case NFPROTO_BRIDGE:
1015        case NFPROTO_INET:
1016                help4 = nf_conntrack_helper_try_module_get(name, NFPROTO_IPV4,
1017                                                           priv->l4proto);
1018                help6 = nf_conntrack_helper_try_module_get(name, NFPROTO_IPV6,
1019                                                           priv->l4proto);
1020                break;
1021        default:
1022                return -EAFNOSUPPORT;
1023        }
1024
1025        /* && is intentional; only error if INET found neither ipv4 or ipv6 */
1026        if (!help4 && !help6)
1027                return -ENOENT;
1028
1029        priv->helper4 = help4;
1030        priv->helper6 = help6;
1031
1032        err = nf_ct_netns_get(ctx->net, ctx->family);
1033        if (err < 0)
1034                goto err_put_helper;
1035
1036        return 0;
1037
1038err_put_helper:
1039        if (priv->helper4)
1040                nf_conntrack_helper_put(priv->helper4);
1041        if (priv->helper6)
1042                nf_conntrack_helper_put(priv->helper6);
1043        return err;
1044}
1045
1046static void nft_ct_helper_obj_destroy(const struct nft_ctx *ctx,
1047                                      struct nft_object *obj)
1048{
1049        struct nft_ct_helper_obj *priv = nft_obj_data(obj);
1050
1051        if (priv->helper4)
1052                nf_conntrack_helper_put(priv->helper4);
1053        if (priv->helper6)
1054                nf_conntrack_helper_put(priv->helper6);
1055
1056        nf_ct_netns_put(ctx->net, ctx->family);
1057}
1058
1059static void nft_ct_helper_obj_eval(struct nft_object *obj,
1060                                   struct nft_regs *regs,
1061                                   const struct nft_pktinfo *pkt)
1062{
1063        const struct nft_ct_helper_obj *priv = nft_obj_data(obj);
1064        struct nf_conn *ct = (struct nf_conn *)skb_nfct(pkt->skb);
1065        struct nf_conntrack_helper *to_assign = NULL;
1066        struct nf_conn_help *help;
1067
1068        if (!ct ||
1069            nf_ct_is_confirmed(ct) ||
1070            nf_ct_is_template(ct) ||
1071            priv->l4proto != nf_ct_protonum(ct))
1072                return;
1073
1074        switch (nf_ct_l3num(ct)) {
1075        case NFPROTO_IPV4:
1076                to_assign = priv->helper4;
1077                break;
1078        case NFPROTO_IPV6:
1079                to_assign = priv->helper6;
1080                break;
1081        default:
1082                WARN_ON_ONCE(1);
1083                return;
1084        }
1085
1086        if (!to_assign)
1087                return;
1088
1089        if (test_bit(IPS_HELPER_BIT, &ct->status))
1090                return;
1091
1092        help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
1093        if (help) {
1094                rcu_assign_pointer(help->helper, to_assign);
1095                set_bit(IPS_HELPER_BIT, &ct->status);
1096        }
1097}
1098
1099static int nft_ct_helper_obj_dump(struct sk_buff *skb,
1100                                  struct nft_object *obj, bool reset)
1101{
1102        const struct nft_ct_helper_obj *priv = nft_obj_data(obj);
1103        const struct nf_conntrack_helper *helper;
1104        u16 family;
1105
1106        if (priv->helper4 && priv->helper6) {
1107                family = NFPROTO_INET;
1108                helper = priv->helper4;
1109        } else if (priv->helper6) {
1110                family = NFPROTO_IPV6;
1111                helper = priv->helper6;
1112        } else {
1113                family = NFPROTO_IPV4;
1114                helper = priv->helper4;
1115        }
1116
1117        if (nla_put_string(skb, NFTA_CT_HELPER_NAME, helper->name))
1118                return -1;
1119
1120        if (nla_put_u8(skb, NFTA_CT_HELPER_L4PROTO, priv->l4proto))
1121                return -1;
1122
1123        if (nla_put_be16(skb, NFTA_CT_HELPER_L3PROTO, htons(family)))
1124                return -1;
1125
1126        return 0;
1127}
1128
1129static const struct nla_policy nft_ct_helper_policy[NFTA_CT_HELPER_MAX + 1] = {
1130        [NFTA_CT_HELPER_NAME] = { .type = NLA_STRING,
1131                                  .len = NF_CT_HELPER_NAME_LEN - 1 },
1132        [NFTA_CT_HELPER_L3PROTO] = { .type = NLA_U16 },
1133        [NFTA_CT_HELPER_L4PROTO] = { .type = NLA_U8 },
1134};
1135
1136static struct nft_object_type nft_ct_helper_obj_type;
1137static const struct nft_object_ops nft_ct_helper_obj_ops = {
1138        .type           = &nft_ct_helper_obj_type,
1139        .size           = sizeof(struct nft_ct_helper_obj),
1140        .eval           = nft_ct_helper_obj_eval,
1141        .init           = nft_ct_helper_obj_init,
1142        .destroy        = nft_ct_helper_obj_destroy,
1143        .dump           = nft_ct_helper_obj_dump,
1144};
1145
1146static struct nft_object_type nft_ct_helper_obj_type __read_mostly = {
1147        .type           = NFT_OBJECT_CT_HELPER,
1148        .ops            = &nft_ct_helper_obj_ops,
1149        .maxattr        = NFTA_CT_HELPER_MAX,
1150        .policy         = nft_ct_helper_policy,
1151        .owner          = THIS_MODULE,
1152};
1153
1154struct nft_ct_expect_obj {
1155        u16             l3num;
1156        __be16          dport;
1157        u8              l4proto;
1158        u8              size;
1159        u32             timeout;
1160};
1161
1162static int nft_ct_expect_obj_init(const struct nft_ctx *ctx,
1163                                  const struct nlattr * const tb[],
1164                                  struct nft_object *obj)
1165{
1166        struct nft_ct_expect_obj *priv = nft_obj_data(obj);
1167
1168        if (!tb[NFTA_CT_EXPECT_L4PROTO] ||
1169            !tb[NFTA_CT_EXPECT_DPORT] ||
1170            !tb[NFTA_CT_EXPECT_TIMEOUT] ||
1171            !tb[NFTA_CT_EXPECT_SIZE])
1172                return -EINVAL;
1173
1174        priv->l3num = ctx->family;
1175        if (tb[NFTA_CT_EXPECT_L3PROTO])
1176                priv->l3num = ntohs(nla_get_be16(tb[NFTA_CT_EXPECT_L3PROTO]));
1177
1178        priv->l4proto = nla_get_u8(tb[NFTA_CT_EXPECT_L4PROTO]);
1179        priv->dport = nla_get_be16(tb[NFTA_CT_EXPECT_DPORT]);
1180        priv->timeout = nla_get_u32(tb[NFTA_CT_EXPECT_TIMEOUT]);
1181        priv->size = nla_get_u8(tb[NFTA_CT_EXPECT_SIZE]);
1182
1183        return nf_ct_netns_get(ctx->net, ctx->family);
1184}
1185
1186static void nft_ct_expect_obj_destroy(const struct nft_ctx *ctx,
1187                                       struct nft_object *obj)
1188{
1189        nf_ct_netns_put(ctx->net, ctx->family);
1190}
1191
1192static int nft_ct_expect_obj_dump(struct sk_buff *skb,
1193                                  struct nft_object *obj, bool reset)
1194{
1195        const struct nft_ct_expect_obj *priv = nft_obj_data(obj);
1196
1197        if (nla_put_be16(skb, NFTA_CT_EXPECT_L3PROTO, htons(priv->l3num)) ||
1198            nla_put_u8(skb, NFTA_CT_EXPECT_L4PROTO, priv->l4proto) ||
1199            nla_put_be16(skb, NFTA_CT_EXPECT_DPORT, priv->dport) ||
1200            nla_put_u32(skb, NFTA_CT_EXPECT_TIMEOUT, priv->timeout) ||
1201            nla_put_u8(skb, NFTA_CT_EXPECT_SIZE, priv->size))
1202                return -1;
1203
1204        return 0;
1205}
1206
1207static void nft_ct_expect_obj_eval(struct nft_object *obj,
1208                                   struct nft_regs *regs,
1209                                   const struct nft_pktinfo *pkt)
1210{
1211        const struct nft_ct_expect_obj *priv = nft_obj_data(obj);
1212        struct nf_conntrack_expect *exp;
1213        enum ip_conntrack_info ctinfo;
1214        struct nf_conn_help *help;
1215        enum ip_conntrack_dir dir;
1216        u16 l3num = priv->l3num;
1217        struct nf_conn *ct;
1218
1219        ct = nf_ct_get(pkt->skb, &ctinfo);
1220        if (!ct || nf_ct_is_confirmed(ct) || nf_ct_is_template(ct)) {
1221                regs->verdict.code = NFT_BREAK;
1222                return;
1223        }
1224        dir = CTINFO2DIR(ctinfo);
1225
1226        help = nfct_help(ct);
1227        if (!help)
1228                help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
1229        if (!help) {
1230                regs->verdict.code = NF_DROP;
1231                return;
1232        }
1233
1234        if (help->expecting[NF_CT_EXPECT_CLASS_DEFAULT] >= priv->size) {
1235                regs->verdict.code = NFT_BREAK;
1236                return;
1237        }
1238        if (l3num == NFPROTO_INET)
1239                l3num = nf_ct_l3num(ct);
1240
1241        exp = nf_ct_expect_alloc(ct);
1242        if (exp == NULL) {
1243                regs->verdict.code = NF_DROP;
1244                return;
1245        }
1246        nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, l3num,
1247                          &ct->tuplehash[!dir].tuple.src.u3,
1248                          &ct->tuplehash[!dir].tuple.dst.u3,
1249                          priv->l4proto, NULL, &priv->dport);
1250        exp->timeout.expires = jiffies + priv->timeout * HZ;
1251
1252        if (nf_ct_expect_related(exp, 0) != 0)
1253                regs->verdict.code = NF_DROP;
1254}
1255
1256static const struct nla_policy nft_ct_expect_policy[NFTA_CT_EXPECT_MAX + 1] = {
1257        [NFTA_CT_EXPECT_L3PROTO]        = { .type = NLA_U16 },
1258        [NFTA_CT_EXPECT_L4PROTO]        = { .type = NLA_U8 },
1259        [NFTA_CT_EXPECT_DPORT]          = { .type = NLA_U16 },
1260        [NFTA_CT_EXPECT_TIMEOUT]        = { .type = NLA_U32 },
1261        [NFTA_CT_EXPECT_SIZE]           = { .type = NLA_U8 },
1262};
1263
1264static struct nft_object_type nft_ct_expect_obj_type;
1265
1266static const struct nft_object_ops nft_ct_expect_obj_ops = {
1267        .type           = &nft_ct_expect_obj_type,
1268        .size           = sizeof(struct nft_ct_expect_obj),
1269        .eval           = nft_ct_expect_obj_eval,
1270        .init           = nft_ct_expect_obj_init,
1271        .destroy        = nft_ct_expect_obj_destroy,
1272        .dump           = nft_ct_expect_obj_dump,
1273};
1274
1275static struct nft_object_type nft_ct_expect_obj_type __read_mostly = {
1276        .type           = NFT_OBJECT_CT_EXPECT,
1277        .ops            = &nft_ct_expect_obj_ops,
1278        .maxattr        = NFTA_CT_EXPECT_MAX,
1279        .policy         = nft_ct_expect_policy,
1280        .owner          = THIS_MODULE,
1281};
1282
1283static int __init nft_ct_module_init(void)
1284{
1285        int err;
1286
1287        BUILD_BUG_ON(NF_CT_LABELS_MAX_SIZE > NFT_REG_SIZE);
1288
1289        err = nft_register_expr(&nft_ct_type);
1290        if (err < 0)
1291                return err;
1292
1293        err = nft_register_expr(&nft_notrack_type);
1294        if (err < 0)
1295                goto err1;
1296
1297        err = nft_register_obj(&nft_ct_helper_obj_type);
1298        if (err < 0)
1299                goto err2;
1300
1301        err = nft_register_obj(&nft_ct_expect_obj_type);
1302        if (err < 0)
1303                goto err3;
1304#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
1305        err = nft_register_obj(&nft_ct_timeout_obj_type);
1306        if (err < 0)
1307                goto err4;
1308#endif
1309        return 0;
1310
1311#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
1312err4:
1313        nft_unregister_obj(&nft_ct_expect_obj_type);
1314#endif
1315err3:
1316        nft_unregister_obj(&nft_ct_helper_obj_type);
1317err2:
1318        nft_unregister_expr(&nft_notrack_type);
1319err1:
1320        nft_unregister_expr(&nft_ct_type);
1321        return err;
1322}
1323
1324static void __exit nft_ct_module_exit(void)
1325{
1326#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
1327        nft_unregister_obj(&nft_ct_timeout_obj_type);
1328#endif
1329        nft_unregister_obj(&nft_ct_expect_obj_type);
1330        nft_unregister_obj(&nft_ct_helper_obj_type);
1331        nft_unregister_expr(&nft_notrack_type);
1332        nft_unregister_expr(&nft_ct_type);
1333}
1334
1335module_init(nft_ct_module_init);
1336module_exit(nft_ct_module_exit);
1337
1338MODULE_LICENSE("GPL");
1339MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
1340MODULE_ALIAS_NFT_EXPR("ct");
1341MODULE_ALIAS_NFT_EXPR("notrack");
1342MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_CT_HELPER);
1343MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_CT_TIMEOUT);
1344MODULE_ALIAS_NFT_OBJ(NFT_OBJECT_CT_EXPECT);
1345MODULE_DESCRIPTION("Netfilter nf_tables conntrack module");
1346
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.