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