linux/net/netfilter/nft_compat.c
<<
>>
Prefs
   1/*
   2 * (C) 2012-2013 by Pablo Neira Ayuso <pablo@netfilter.org>
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 *
   8 * This software has been sponsored by Sophos Astaro <http://www.sophos.com>
   9 */
  10
  11#include <linux/kernel.h>
  12#include <linux/init.h>
  13#include <linux/module.h>
  14#include <linux/netlink.h>
  15#include <linux/netfilter.h>
  16#include <linux/netfilter/nfnetlink.h>
  17#include <linux/netfilter/nf_tables.h>
  18#include <linux/netfilter/nf_tables_compat.h>
  19#include <linux/netfilter/x_tables.h>
  20#include <linux/netfilter_ipv4/ip_tables.h>
  21#include <linux/netfilter_ipv6/ip6_tables.h>
  22#include <linux/netfilter_bridge/ebtables.h>
  23#include <net/netfilter/nf_tables.h>
  24
  25static int nft_compat_chain_validate_dependency(const char *tablename,
  26                                                const struct nft_chain *chain)
  27{
  28        const struct nft_base_chain *basechain;
  29
  30        if (!tablename || !(chain->flags & NFT_BASE_CHAIN))
  31                return 0;
  32
  33        basechain = nft_base_chain(chain);
  34        if (strcmp(tablename, "nat") == 0 &&
  35            basechain->type->type != NFT_CHAIN_T_NAT)
  36                return -EINVAL;
  37
  38        return 0;
  39}
  40
  41union nft_entry {
  42        struct ipt_entry e4;
  43        struct ip6t_entry e6;
  44        struct ebt_entry ebt;
  45};
  46
  47static inline void
  48nft_compat_set_par(struct xt_action_param *par, void *xt, const void *xt_info)
  49{
  50        par->target     = xt;
  51        par->targinfo   = xt_info;
  52        par->hotdrop    = false;
  53}
  54
  55static void nft_target_eval_xt(const struct nft_expr *expr,
  56                               struct nft_data data[NFT_REG_MAX + 1],
  57                               const struct nft_pktinfo *pkt)
  58{
  59        void *info = nft_expr_priv(expr);
  60        struct xt_target *target = expr->ops->data;
  61        struct sk_buff *skb = pkt->skb;
  62        int ret;
  63
  64        nft_compat_set_par((struct xt_action_param *)&pkt->xt, target, info);
  65
  66        ret = target->target(skb, &pkt->xt);
  67
  68        if (pkt->xt.hotdrop)
  69                ret = NF_DROP;
  70
  71        switch (ret) {
  72        case XT_CONTINUE:
  73                data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
  74                break;
  75        default:
  76                data[NFT_REG_VERDICT].verdict = ret;
  77                break;
  78        }
  79}
  80
  81static void nft_target_eval_bridge(const struct nft_expr *expr,
  82                                   struct nft_data data[NFT_REG_MAX + 1],
  83                                   const struct nft_pktinfo *pkt)
  84{
  85        void *info = nft_expr_priv(expr);
  86        struct xt_target *target = expr->ops->data;
  87        struct sk_buff *skb = pkt->skb;
  88        int ret;
  89
  90        nft_compat_set_par((struct xt_action_param *)&pkt->xt, target, info);
  91
  92        ret = target->target(skb, &pkt->xt);
  93
  94        if (pkt->xt.hotdrop)
  95                ret = NF_DROP;
  96
  97        switch (ret) {
  98        case EBT_ACCEPT:
  99                data[NFT_REG_VERDICT].verdict = NF_ACCEPT;
 100                break;
 101        case EBT_DROP:
 102                data[NFT_REG_VERDICT].verdict = NF_DROP;
 103                break;
 104        case EBT_CONTINUE:
 105                data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
 106                break;
 107        case EBT_RETURN:
 108                data[NFT_REG_VERDICT].verdict = NFT_RETURN;
 109                break;
 110        default:
 111                data[NFT_REG_VERDICT].verdict = ret;
 112                break;
 113        }
 114}
 115
 116static const struct nla_policy nft_target_policy[NFTA_TARGET_MAX + 1] = {
 117        [NFTA_TARGET_NAME]      = { .type = NLA_NUL_STRING },
 118        [NFTA_TARGET_REV]       = { .type = NLA_U32 },
 119        [NFTA_TARGET_INFO]      = { .type = NLA_BINARY },
 120};
 121
 122static void
 123nft_target_set_tgchk_param(struct xt_tgchk_param *par,
 124                           const struct nft_ctx *ctx,
 125                           struct xt_target *target, void *info,
 126                           union nft_entry *entry, u16 proto, bool inv)
 127{
 128        par->net        = ctx->net;
 129        par->table      = ctx->table->name;
 130        switch (ctx->afi->family) {
 131        case AF_INET:
 132                entry->e4.ip.proto = proto;
 133                entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0;
 134                break;
 135        case AF_INET6:
 136                if (proto)
 137                        entry->e6.ipv6.flags |= IP6T_F_PROTO;
 138
 139                entry->e6.ipv6.proto = proto;
 140                entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0;
 141                break;
 142        case NFPROTO_BRIDGE:
 143                entry->ebt.ethproto = (__force __be16)proto;
 144                entry->ebt.invflags = inv ? EBT_IPROTO : 0;
 145                break;
 146        }
 147        par->entryinfo  = entry;
 148        par->target     = target;
 149        par->targinfo   = info;
 150        if (ctx->chain->flags & NFT_BASE_CHAIN) {
 151                const struct nft_base_chain *basechain =
 152                                                nft_base_chain(ctx->chain);
 153                const struct nf_hook_ops *ops = &basechain->ops[0];
 154
 155                par->hook_mask = 1 << ops->hooknum;
 156        } else {
 157                par->hook_mask = 0;
 158        }
 159        par->family     = ctx->afi->family;
 160}
 161
 162static void target_compat_from_user(struct xt_target *t, void *in, void *out)
 163{
 164        int pad;
 165
 166        memcpy(out, in, t->targetsize);
 167        pad = XT_ALIGN(t->targetsize) - t->targetsize;
 168        if (pad > 0)
 169                memset(out + t->targetsize, 0, pad);
 170}
 171
 172static const struct nla_policy nft_rule_compat_policy[NFTA_RULE_COMPAT_MAX + 1] = {
 173        [NFTA_RULE_COMPAT_PROTO]        = { .type = NLA_U32 },
 174        [NFTA_RULE_COMPAT_FLAGS]        = { .type = NLA_U32 },
 175};
 176
 177static int nft_parse_compat(const struct nlattr *attr, u16 *proto, bool *inv)
 178{
 179        struct nlattr *tb[NFTA_RULE_COMPAT_MAX+1];
 180        u32 flags;
 181        int err;
 182
 183        err = nla_parse_nested(tb, NFTA_RULE_COMPAT_MAX, attr,
 184                               nft_rule_compat_policy);
 185        if (err < 0)
 186                return err;
 187
 188        if (!tb[NFTA_RULE_COMPAT_PROTO] || !tb[NFTA_RULE_COMPAT_FLAGS])
 189                return -EINVAL;
 190
 191        flags = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_FLAGS]));
 192        if (flags & ~NFT_RULE_COMPAT_F_MASK)
 193                return -EINVAL;
 194        if (flags & NFT_RULE_COMPAT_F_INV)
 195                *inv = true;
 196
 197        *proto = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_PROTO]));
 198        return 0;
 199}
 200
 201static int
 202nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 203                const struct nlattr * const tb[])
 204{
 205        void *info = nft_expr_priv(expr);
 206        struct xt_target *target = expr->ops->data;
 207        struct xt_tgchk_param par;
 208        size_t size = XT_ALIGN(nla_len(tb[NFTA_TARGET_INFO]));
 209        u16 proto = 0;
 210        bool inv = false;
 211        union nft_entry e = {};
 212        int ret;
 213
 214        ret = nft_compat_chain_validate_dependency(target->table, ctx->chain);
 215        if (ret < 0)
 216                goto err;
 217
 218        target_compat_from_user(target, nla_data(tb[NFTA_TARGET_INFO]), info);
 219
 220        if (ctx->nla[NFTA_RULE_COMPAT]) {
 221                ret = nft_parse_compat(ctx->nla[NFTA_RULE_COMPAT], &proto, &inv);
 222                if (ret < 0)
 223                        goto err;
 224        }
 225
 226        nft_target_set_tgchk_param(&par, ctx, target, info, &e, proto, inv);
 227
 228        ret = xt_check_target(&par, size, proto, inv);
 229        if (ret < 0)
 230                goto err;
 231
 232        /* The standard target cannot be used */
 233        if (target->target == NULL) {
 234                ret = -EINVAL;
 235                goto err;
 236        }
 237
 238        return 0;
 239err:
 240        module_put(target->me);
 241        return ret;
 242}
 243
 244static void
 245nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
 246{
 247        struct xt_target *target = expr->ops->data;
 248        void *info = nft_expr_priv(expr);
 249        struct xt_tgdtor_param par;
 250
 251        par.net = ctx->net;
 252        par.target = target;
 253        par.targinfo = info;
 254        par.family = ctx->afi->family;
 255        if (par.target->destroy != NULL)
 256                par.target->destroy(&par);
 257
 258        module_put(target->me);
 259}
 260
 261static int nft_target_dump(struct sk_buff *skb, const struct nft_expr *expr)
 262{
 263        const struct xt_target *target = expr->ops->data;
 264        void *info = nft_expr_priv(expr);
 265
 266        if (nla_put_string(skb, NFTA_TARGET_NAME, target->name) ||
 267            nla_put_be32(skb, NFTA_TARGET_REV, htonl(target->revision)) ||
 268            nla_put(skb, NFTA_TARGET_INFO, XT_ALIGN(target->targetsize), info))
 269                goto nla_put_failure;
 270
 271        return 0;
 272
 273nla_put_failure:
 274        return -1;
 275}
 276
 277static int nft_target_validate(const struct nft_ctx *ctx,
 278                               const struct nft_expr *expr,
 279                               const struct nft_data **data)
 280{
 281        struct xt_target *target = expr->ops->data;
 282        unsigned int hook_mask = 0;
 283        int ret;
 284
 285        if (ctx->chain->flags & NFT_BASE_CHAIN) {
 286                const struct nft_base_chain *basechain =
 287                                                nft_base_chain(ctx->chain);
 288                const struct nf_hook_ops *ops = &basechain->ops[0];
 289
 290                hook_mask = 1 << ops->hooknum;
 291                if (!(hook_mask & target->hooks))
 292                        return -EINVAL;
 293
 294                ret = nft_compat_chain_validate_dependency(target->table,
 295                                                           ctx->chain);
 296                if (ret < 0)
 297                        return ret;
 298        }
 299        return 0;
 300}
 301
 302static void nft_match_eval(const struct nft_expr *expr,
 303                           struct nft_data data[NFT_REG_MAX + 1],
 304                           const struct nft_pktinfo *pkt)
 305{
 306        void *info = nft_expr_priv(expr);
 307        struct xt_match *match = expr->ops->data;
 308        struct sk_buff *skb = pkt->skb;
 309        bool ret;
 310
 311        nft_compat_set_par((struct xt_action_param *)&pkt->xt, match, info);
 312
 313        ret = match->match(skb, (struct xt_action_param *)&pkt->xt);
 314
 315        if (pkt->xt.hotdrop) {
 316                data[NFT_REG_VERDICT].verdict = NF_DROP;
 317                return;
 318        }
 319
 320        switch(ret) {
 321        case true:
 322                data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
 323                break;
 324        case false:
 325                data[NFT_REG_VERDICT].verdict = NFT_BREAK;
 326                break;
 327        }
 328}
 329
 330static const struct nla_policy nft_match_policy[NFTA_MATCH_MAX + 1] = {
 331        [NFTA_MATCH_NAME]       = { .type = NLA_NUL_STRING },
 332        [NFTA_MATCH_REV]        = { .type = NLA_U32 },
 333        [NFTA_MATCH_INFO]       = { .type = NLA_BINARY },
 334};
 335
 336/* struct xt_mtchk_param and xt_tgchk_param look very similar */
 337static void
 338nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
 339                          struct xt_match *match, void *info,
 340                          union nft_entry *entry, u16 proto, bool inv)
 341{
 342        par->net        = ctx->net;
 343        par->table      = ctx->table->name;
 344        switch (ctx->afi->family) {
 345        case AF_INET:
 346                entry->e4.ip.proto = proto;
 347                entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0;
 348                break;
 349        case AF_INET6:
 350                if (proto)
 351                        entry->e6.ipv6.flags |= IP6T_F_PROTO;
 352
 353                entry->e6.ipv6.proto = proto;
 354                entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0;
 355                break;
 356        case NFPROTO_BRIDGE:
 357                entry->ebt.ethproto = (__force __be16)proto;
 358                entry->ebt.invflags = inv ? EBT_IPROTO : 0;
 359                break;
 360        }
 361        par->entryinfo  = entry;
 362        par->match      = match;
 363        par->matchinfo  = info;
 364        if (ctx->chain->flags & NFT_BASE_CHAIN) {
 365                const struct nft_base_chain *basechain =
 366                                                nft_base_chain(ctx->chain);
 367                const struct nf_hook_ops *ops = &basechain->ops[0];
 368
 369                par->hook_mask = 1 << ops->hooknum;
 370        } else {
 371                par->hook_mask = 0;
 372        }
 373        par->family     = ctx->afi->family;
 374}
 375
 376static void match_compat_from_user(struct xt_match *m, void *in, void *out)
 377{
 378        int pad;
 379
 380        memcpy(out, in, m->matchsize);
 381        pad = XT_ALIGN(m->matchsize) - m->matchsize;
 382        if (pad > 0)
 383                memset(out + m->matchsize, 0, pad);
 384}
 385
 386static int
 387nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 388                const struct nlattr * const tb[])
 389{
 390        void *info = nft_expr_priv(expr);
 391        struct xt_match *match = expr->ops->data;
 392        struct xt_mtchk_param par;
 393        size_t size = XT_ALIGN(nla_len(tb[NFTA_MATCH_INFO]));
 394        u16 proto = 0;
 395        bool inv = false;
 396        union nft_entry e = {};
 397        int ret;
 398
 399        ret = nft_compat_chain_validate_dependency(match->table, ctx->chain);
 400        if (ret < 0)
 401                goto err;
 402
 403        match_compat_from_user(match, nla_data(tb[NFTA_MATCH_INFO]), info);
 404
 405        if (ctx->nla[NFTA_RULE_COMPAT]) {
 406                ret = nft_parse_compat(ctx->nla[NFTA_RULE_COMPAT], &proto, &inv);
 407                if (ret < 0)
 408                        goto err;
 409        }
 410
 411        nft_match_set_mtchk_param(&par, ctx, match, info, &e, proto, inv);
 412
 413        ret = xt_check_match(&par, size, proto, inv);
 414        if (ret < 0)
 415                goto err;
 416
 417        return 0;
 418err:
 419        module_put(match->me);
 420        return ret;
 421}
 422
 423static void
 424nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
 425{
 426        struct xt_match *match = expr->ops->data;
 427        void *info = nft_expr_priv(expr);
 428        struct xt_mtdtor_param par;
 429
 430        par.net = ctx->net;
 431        par.match = match;
 432        par.matchinfo = info;
 433        par.family = ctx->afi->family;
 434        if (par.match->destroy != NULL)
 435                par.match->destroy(&par);
 436
 437        module_put(match->me);
 438}
 439
 440static int nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr)
 441{
 442        void *info = nft_expr_priv(expr);
 443        struct xt_match *match = expr->ops->data;
 444
 445        if (nla_put_string(skb, NFTA_MATCH_NAME, match->name) ||
 446            nla_put_be32(skb, NFTA_MATCH_REV, htonl(match->revision)) ||
 447            nla_put(skb, NFTA_MATCH_INFO, XT_ALIGN(match->matchsize), info))
 448                goto nla_put_failure;
 449
 450        return 0;
 451
 452nla_put_failure:
 453        return -1;
 454}
 455
 456static int nft_match_validate(const struct nft_ctx *ctx,
 457                              const struct nft_expr *expr,
 458                              const struct nft_data **data)
 459{
 460        struct xt_match *match = expr->ops->data;
 461        unsigned int hook_mask = 0;
 462        int ret;
 463
 464        if (ctx->chain->flags & NFT_BASE_CHAIN) {
 465                const struct nft_base_chain *basechain =
 466                                                nft_base_chain(ctx->chain);
 467                const struct nf_hook_ops *ops = &basechain->ops[0];
 468
 469                hook_mask = 1 << ops->hooknum;
 470                if (!(hook_mask & match->hooks))
 471                        return -EINVAL;
 472
 473                ret = nft_compat_chain_validate_dependency(match->table,
 474                                                           ctx->chain);
 475                if (ret < 0)
 476                        return ret;
 477        }
 478        return 0;
 479}
 480
 481static int
 482nfnl_compat_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
 483                      int event, u16 family, const char *name,
 484                      int rev, int target)
 485{
 486        struct nlmsghdr *nlh;
 487        struct nfgenmsg *nfmsg;
 488        unsigned int flags = portid ? NLM_F_MULTI : 0;
 489
 490        event |= NFNL_SUBSYS_NFT_COMPAT << 8;
 491        nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
 492        if (nlh == NULL)
 493                goto nlmsg_failure;
 494
 495        nfmsg = nlmsg_data(nlh);
 496        nfmsg->nfgen_family = family;
 497        nfmsg->version = NFNETLINK_V0;
 498        nfmsg->res_id = 0;
 499
 500        if (nla_put_string(skb, NFTA_COMPAT_NAME, name) ||
 501            nla_put_be32(skb, NFTA_COMPAT_REV, htonl(rev)) ||
 502            nla_put_be32(skb, NFTA_COMPAT_TYPE, htonl(target)))
 503                goto nla_put_failure;
 504
 505        nlmsg_end(skb, nlh);
 506        return skb->len;
 507
 508nlmsg_failure:
 509nla_put_failure:
 510        nlmsg_cancel(skb, nlh);
 511        return -1;
 512}
 513
 514static int
 515nfnl_compat_get(struct sock *nfnl, struct sk_buff *skb,
 516                const struct nlmsghdr *nlh, const struct nlattr * const tb[])
 517{
 518        int ret = 0, target;
 519        struct nfgenmsg *nfmsg;
 520        const char *fmt;
 521        const char *name;
 522        u32 rev;
 523        struct sk_buff *skb2;
 524
 525        if (tb[NFTA_COMPAT_NAME] == NULL ||
 526            tb[NFTA_COMPAT_REV] == NULL ||
 527            tb[NFTA_COMPAT_TYPE] == NULL)
 528                return -EINVAL;
 529
 530        name = nla_data(tb[NFTA_COMPAT_NAME]);
 531        rev = ntohl(nla_get_be32(tb[NFTA_COMPAT_REV]));
 532        target = ntohl(nla_get_be32(tb[NFTA_COMPAT_TYPE]));
 533
 534        nfmsg = nlmsg_data(nlh);
 535
 536        switch(nfmsg->nfgen_family) {
 537        case AF_INET:
 538                fmt = "ipt_%s";
 539                break;
 540        case AF_INET6:
 541                fmt = "ip6t_%s";
 542                break;
 543        case NFPROTO_BRIDGE:
 544                fmt = "ebt_%s";
 545                break;
 546        default:
 547                pr_err("nft_compat: unsupported protocol %d\n",
 548                        nfmsg->nfgen_family);
 549                return -EINVAL;
 550        }
 551
 552        try_then_request_module(xt_find_revision(nfmsg->nfgen_family, name,
 553                                                 rev, target, &ret),
 554                                                 fmt, name);
 555
 556        if (ret < 0)
 557                return ret;
 558
 559        skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 560        if (skb2 == NULL)
 561                return -ENOMEM;
 562
 563        /* include the best revision for this extension in the message */
 564        if (nfnl_compat_fill_info(skb2, NETLINK_CB(skb).portid,
 565                                  nlh->nlmsg_seq,
 566                                  NFNL_MSG_TYPE(nlh->nlmsg_type),
 567                                  NFNL_MSG_COMPAT_GET,
 568                                  nfmsg->nfgen_family,
 569                                  name, ret, target) <= 0) {
 570                kfree_skb(skb2);
 571                return -ENOSPC;
 572        }
 573
 574        ret = netlink_unicast(nfnl, skb2, NETLINK_CB(skb).portid,
 575                                MSG_DONTWAIT);
 576        if (ret > 0)
 577                ret = 0;
 578
 579        return ret == -EAGAIN ? -ENOBUFS : ret;
 580}
 581
 582static const struct nla_policy nfnl_compat_policy_get[NFTA_COMPAT_MAX+1] = {
 583        [NFTA_COMPAT_NAME]      = { .type = NLA_NUL_STRING,
 584                                    .len = NFT_COMPAT_NAME_MAX-1 },
 585        [NFTA_COMPAT_REV]       = { .type = NLA_U32 },
 586        [NFTA_COMPAT_TYPE]      = { .type = NLA_U32 },
 587};
 588
 589static const struct nfnl_callback nfnl_nft_compat_cb[NFNL_MSG_COMPAT_MAX] = {
 590        [NFNL_MSG_COMPAT_GET]           = { .call = nfnl_compat_get,
 591                                            .attr_count = NFTA_COMPAT_MAX,
 592                                            .policy = nfnl_compat_policy_get },
 593};
 594
 595static const struct nfnetlink_subsystem nfnl_compat_subsys = {
 596        .name           = "nft-compat",
 597        .subsys_id      = NFNL_SUBSYS_NFT_COMPAT,
 598        .cb_count       = NFNL_MSG_COMPAT_MAX,
 599        .cb             = nfnl_nft_compat_cb,
 600};
 601
 602static LIST_HEAD(nft_match_list);
 603
 604struct nft_xt {
 605        struct list_head        head;
 606        struct nft_expr_ops     ops;
 607};
 608
 609static struct nft_expr_type nft_match_type;
 610
 611static const struct nft_expr_ops *
 612nft_match_select_ops(const struct nft_ctx *ctx,
 613                     const struct nlattr * const tb[])
 614{
 615        struct nft_xt *nft_match;
 616        struct xt_match *match;
 617        char *mt_name;
 618        __u32 rev, family;
 619
 620        if (tb[NFTA_MATCH_NAME] == NULL ||
 621            tb[NFTA_MATCH_REV] == NULL ||
 622            tb[NFTA_MATCH_INFO] == NULL)
 623                return ERR_PTR(-EINVAL);
 624
 625        mt_name = nla_data(tb[NFTA_MATCH_NAME]);
 626        rev = ntohl(nla_get_be32(tb[NFTA_MATCH_REV]));
 627        family = ctx->afi->family;
 628
 629        /* Re-use the existing match if it's already loaded. */
 630        list_for_each_entry(nft_match, &nft_match_list, head) {
 631                struct xt_match *match = nft_match->ops.data;
 632
 633                if (strcmp(match->name, mt_name) == 0 &&
 634                    match->revision == rev && match->family == family) {
 635                        if (!try_module_get(match->me))
 636                                return ERR_PTR(-ENOENT);
 637
 638                        return &nft_match->ops;
 639                }
 640        }
 641
 642        match = xt_request_find_match(family, mt_name, rev);
 643        if (IS_ERR(match))
 644                return ERR_PTR(-ENOENT);
 645
 646        /* This is the first time we use this match, allocate operations */
 647        nft_match = kzalloc(sizeof(struct nft_xt), GFP_KERNEL);
 648        if (nft_match == NULL)
 649                return ERR_PTR(-ENOMEM);
 650
 651        nft_match->ops.type = &nft_match_type;
 652        nft_match->ops.size = NFT_EXPR_SIZE(XT_ALIGN(match->matchsize));
 653        nft_match->ops.eval = nft_match_eval;
 654        nft_match->ops.init = nft_match_init;
 655        nft_match->ops.destroy = nft_match_destroy;
 656        nft_match->ops.dump = nft_match_dump;
 657        nft_match->ops.validate = nft_match_validate;
 658        nft_match->ops.data = match;
 659
 660        list_add(&nft_match->head, &nft_match_list);
 661
 662        return &nft_match->ops;
 663}
 664
 665static void nft_match_release(void)
 666{
 667        struct nft_xt *nft_match, *tmp;
 668
 669        list_for_each_entry_safe(nft_match, tmp, &nft_match_list, head)
 670                kfree(nft_match);
 671}
 672
 673static struct nft_expr_type nft_match_type __read_mostly = {
 674        .name           = "match",
 675        .select_ops     = nft_match_select_ops,
 676        .policy         = nft_match_policy,
 677        .maxattr        = NFTA_MATCH_MAX,
 678        .owner          = THIS_MODULE,
 679};
 680
 681static LIST_HEAD(nft_target_list);
 682
 683static struct nft_expr_type nft_target_type;
 684
 685static const struct nft_expr_ops *
 686nft_target_select_ops(const struct nft_ctx *ctx,
 687                      const struct nlattr * const tb[])
 688{
 689        struct nft_xt *nft_target;
 690        struct xt_target *target;
 691        char *tg_name;
 692        __u32 rev, family;
 693
 694        if (tb[NFTA_TARGET_NAME] == NULL ||
 695            tb[NFTA_TARGET_REV] == NULL ||
 696            tb[NFTA_TARGET_INFO] == NULL)
 697                return ERR_PTR(-EINVAL);
 698
 699        tg_name = nla_data(tb[NFTA_TARGET_NAME]);
 700        rev = ntohl(nla_get_be32(tb[NFTA_TARGET_REV]));
 701        family = ctx->afi->family;
 702
 703        /* Re-use the existing target if it's already loaded. */
 704        list_for_each_entry(nft_target, &nft_target_list, head) {
 705                struct xt_target *target = nft_target->ops.data;
 706
 707                if (strcmp(target->name, tg_name) == 0 &&
 708                    target->revision == rev && target->family == family) {
 709                        if (!try_module_get(target->me))
 710                                return ERR_PTR(-ENOENT);
 711
 712                        return &nft_target->ops;
 713                }
 714        }
 715
 716        target = xt_request_find_target(family, tg_name, rev);
 717        if (IS_ERR(target))
 718                return ERR_PTR(-ENOENT);
 719
 720        /* This is the first time we use this target, allocate operations */
 721        nft_target = kzalloc(sizeof(struct nft_xt), GFP_KERNEL);
 722        if (nft_target == NULL)
 723                return ERR_PTR(-ENOMEM);
 724
 725        nft_target->ops.type = &nft_target_type;
 726        nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize));
 727        nft_target->ops.init = nft_target_init;
 728        nft_target->ops.destroy = nft_target_destroy;
 729        nft_target->ops.dump = nft_target_dump;
 730        nft_target->ops.validate = nft_target_validate;
 731        nft_target->ops.data = target;
 732
 733        if (family == NFPROTO_BRIDGE)
 734                nft_target->ops.eval = nft_target_eval_bridge;
 735        else
 736                nft_target->ops.eval = nft_target_eval_xt;
 737
 738        list_add(&nft_target->head, &nft_target_list);
 739
 740        return &nft_target->ops;
 741}
 742
 743static void nft_target_release(void)
 744{
 745        struct nft_xt *nft_target, *tmp;
 746
 747        list_for_each_entry_safe(nft_target, tmp, &nft_target_list, head)
 748                kfree(nft_target);
 749}
 750
 751static struct nft_expr_type nft_target_type __read_mostly = {
 752        .name           = "target",
 753        .select_ops     = nft_target_select_ops,
 754        .policy         = nft_target_policy,
 755        .maxattr        = NFTA_TARGET_MAX,
 756        .owner          = THIS_MODULE,
 757};
 758
 759static int __init nft_compat_module_init(void)
 760{
 761        int ret;
 762
 763        ret = nft_register_expr(&nft_match_type);
 764        if (ret < 0)
 765                return ret;
 766
 767        ret = nft_register_expr(&nft_target_type);
 768        if (ret < 0)
 769                goto err_match;
 770
 771        ret = nfnetlink_subsys_register(&nfnl_compat_subsys);
 772        if (ret < 0) {
 773                pr_err("nft_compat: cannot register with nfnetlink.\n");
 774                goto err_target;
 775        }
 776
 777        pr_info("nf_tables_compat: (c) 2012 Pablo Neira Ayuso <pablo@netfilter.org>\n");
 778
 779        return ret;
 780
 781err_target:
 782        nft_unregister_expr(&nft_target_type);
 783err_match:
 784        nft_unregister_expr(&nft_match_type);
 785        return ret;
 786}
 787
 788static void __exit nft_compat_module_exit(void)
 789{
 790        nfnetlink_subsys_unregister(&nfnl_compat_subsys);
 791        nft_unregister_expr(&nft_target_type);
 792        nft_unregister_expr(&nft_match_type);
 793        nft_match_release();
 794        nft_target_release();
 795}
 796
 797MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_NFT_COMPAT);
 798
 799module_init(nft_compat_module_init);
 800module_exit(nft_compat_module_exit);
 801
 802MODULE_LICENSE("GPL");
 803MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
 804MODULE_ALIAS_NFT_EXPR("match");
 805MODULE_ALIAS_NFT_EXPR("target");
 806