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