Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * (C) 2012-2013 by Pablo Neira Ayuso <pablo@netfilter.org>
0004  *
0005  * This software has been sponsored by Sophos Astaro <http://www.sophos.com>
0006  */
0007 
0008 #include <linux/kernel.h>
0009 #include <linux/init.h>
0010 #include <linux/module.h>
0011 #include <linux/netlink.h>
0012 #include <linux/netfilter.h>
0013 #include <linux/netfilter/nfnetlink.h>
0014 #include <linux/netfilter/nf_tables.h>
0015 #include <linux/netfilter/nf_tables_compat.h>
0016 #include <linux/netfilter/x_tables.h>
0017 #include <linux/netfilter_ipv4/ip_tables.h>
0018 #include <linux/netfilter_ipv6/ip6_tables.h>
0019 #include <linux/netfilter_bridge/ebtables.h>
0020 #include <linux/netfilter_arp/arp_tables.h>
0021 #include <net/netfilter/nf_tables.h>
0022 #include <net/netfilter/nf_log.h>
0023 
0024 /* Used for matches where *info is larger than X byte */
0025 #define NFT_MATCH_LARGE_THRESH  192
0026 
0027 struct nft_xt_match_priv {
0028     void *info;
0029 };
0030 
0031 static int nft_compat_chain_validate_dependency(const struct nft_ctx *ctx,
0032                         const char *tablename)
0033 {
0034     enum nft_chain_types type = NFT_CHAIN_T_DEFAULT;
0035     const struct nft_chain *chain = ctx->chain;
0036     const struct nft_base_chain *basechain;
0037 
0038     if (!tablename ||
0039         !nft_is_base_chain(chain))
0040         return 0;
0041 
0042     basechain = nft_base_chain(chain);
0043     if (strcmp(tablename, "nat") == 0) {
0044         if (ctx->family != NFPROTO_BRIDGE)
0045             type = NFT_CHAIN_T_NAT;
0046         if (basechain->type->type != type)
0047             return -EINVAL;
0048     }
0049 
0050     return 0;
0051 }
0052 
0053 union nft_entry {
0054     struct ipt_entry e4;
0055     struct ip6t_entry e6;
0056     struct ebt_entry ebt;
0057     struct arpt_entry arp;
0058 };
0059 
0060 static inline void
0061 nft_compat_set_par(struct xt_action_param *par,
0062            const struct nft_pktinfo *pkt,
0063            const void *xt, const void *xt_info)
0064 {
0065     par->state  = pkt->state;
0066     par->thoff  = nft_thoff(pkt);
0067     par->fragoff    = pkt->fragoff;
0068     par->target = xt;
0069     par->targinfo   = xt_info;
0070     par->hotdrop    = false;
0071 }
0072 
0073 static void nft_target_eval_xt(const struct nft_expr *expr,
0074                    struct nft_regs *regs,
0075                    const struct nft_pktinfo *pkt)
0076 {
0077     void *info = nft_expr_priv(expr);
0078     struct xt_target *target = expr->ops->data;
0079     struct sk_buff *skb = pkt->skb;
0080     struct xt_action_param xt;
0081     int ret;
0082 
0083     nft_compat_set_par(&xt, pkt, target, info);
0084 
0085     ret = target->target(skb, &xt);
0086 
0087     if (xt.hotdrop)
0088         ret = NF_DROP;
0089 
0090     switch (ret) {
0091     case XT_CONTINUE:
0092         regs->verdict.code = NFT_CONTINUE;
0093         break;
0094     default:
0095         regs->verdict.code = ret;
0096         break;
0097     }
0098 }
0099 
0100 static void nft_target_eval_bridge(const struct nft_expr *expr,
0101                    struct nft_regs *regs,
0102                    const struct nft_pktinfo *pkt)
0103 {
0104     void *info = nft_expr_priv(expr);
0105     struct xt_target *target = expr->ops->data;
0106     struct sk_buff *skb = pkt->skb;
0107     struct xt_action_param xt;
0108     int ret;
0109 
0110     nft_compat_set_par(&xt, pkt, target, info);
0111 
0112     ret = target->target(skb, &xt);
0113 
0114     if (xt.hotdrop)
0115         ret = NF_DROP;
0116 
0117     switch (ret) {
0118     case EBT_ACCEPT:
0119         regs->verdict.code = NF_ACCEPT;
0120         break;
0121     case EBT_DROP:
0122         regs->verdict.code = NF_DROP;
0123         break;
0124     case EBT_CONTINUE:
0125         regs->verdict.code = NFT_CONTINUE;
0126         break;
0127     case EBT_RETURN:
0128         regs->verdict.code = NFT_RETURN;
0129         break;
0130     default:
0131         regs->verdict.code = ret;
0132         break;
0133     }
0134 }
0135 
0136 static const struct nla_policy nft_target_policy[NFTA_TARGET_MAX + 1] = {
0137     [NFTA_TARGET_NAME]  = { .type = NLA_NUL_STRING },
0138     [NFTA_TARGET_REV]   = { .type = NLA_U32 },
0139     [NFTA_TARGET_INFO]  = { .type = NLA_BINARY },
0140 };
0141 
0142 static void
0143 nft_target_set_tgchk_param(struct xt_tgchk_param *par,
0144                const struct nft_ctx *ctx,
0145                struct xt_target *target, void *info,
0146                union nft_entry *entry, u16 proto, bool inv)
0147 {
0148     par->net    = ctx->net;
0149     par->table  = ctx->table->name;
0150     switch (ctx->family) {
0151     case AF_INET:
0152         entry->e4.ip.proto = proto;
0153         entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0;
0154         break;
0155     case AF_INET6:
0156         if (proto)
0157             entry->e6.ipv6.flags |= IP6T_F_PROTO;
0158 
0159         entry->e6.ipv6.proto = proto;
0160         entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0;
0161         break;
0162     case NFPROTO_BRIDGE:
0163         entry->ebt.ethproto = (__force __be16)proto;
0164         entry->ebt.invflags = inv ? EBT_IPROTO : 0;
0165         break;
0166     case NFPROTO_ARP:
0167         break;
0168     }
0169     par->entryinfo  = entry;
0170     par->target = target;
0171     par->targinfo   = info;
0172     if (nft_is_base_chain(ctx->chain)) {
0173         const struct nft_base_chain *basechain =
0174                         nft_base_chain(ctx->chain);
0175         const struct nf_hook_ops *ops = &basechain->ops;
0176 
0177         par->hook_mask = 1 << ops->hooknum;
0178     } else {
0179         par->hook_mask = 0;
0180     }
0181     par->family = ctx->family;
0182     par->nft_compat = true;
0183 }
0184 
0185 static void target_compat_from_user(struct xt_target *t, void *in, void *out)
0186 {
0187     int pad;
0188 
0189     memcpy(out, in, t->targetsize);
0190     pad = XT_ALIGN(t->targetsize) - t->targetsize;
0191     if (pad > 0)
0192         memset(out + t->targetsize, 0, pad);
0193 }
0194 
0195 static const struct nla_policy nft_rule_compat_policy[NFTA_RULE_COMPAT_MAX + 1] = {
0196     [NFTA_RULE_COMPAT_PROTO]    = { .type = NLA_U32 },
0197     [NFTA_RULE_COMPAT_FLAGS]    = { .type = NLA_U32 },
0198 };
0199 
0200 static int nft_parse_compat(const struct nlattr *attr, u16 *proto, bool *inv)
0201 {
0202     struct nlattr *tb[NFTA_RULE_COMPAT_MAX+1];
0203     u32 flags;
0204     int err;
0205 
0206     err = nla_parse_nested_deprecated(tb, NFTA_RULE_COMPAT_MAX, attr,
0207                       nft_rule_compat_policy, NULL);
0208     if (err < 0)
0209         return err;
0210 
0211     if (!tb[NFTA_RULE_COMPAT_PROTO] || !tb[NFTA_RULE_COMPAT_FLAGS])
0212         return -EINVAL;
0213 
0214     flags = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_FLAGS]));
0215     if (flags & ~NFT_RULE_COMPAT_F_MASK)
0216         return -EINVAL;
0217     if (flags & NFT_RULE_COMPAT_F_INV)
0218         *inv = true;
0219 
0220     *proto = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_PROTO]));
0221     return 0;
0222 }
0223 
0224 static void nft_compat_wait_for_destructors(void)
0225 {
0226     /* xtables matches or targets can have side effects, e.g.
0227      * creation/destruction of /proc files.
0228      * The xt ->destroy functions are run asynchronously from
0229      * work queue.  If we have pending invocations we thus
0230      * need to wait for those to finish.
0231      */
0232     nf_tables_trans_destroy_flush_work();
0233 }
0234 
0235 static int
0236 nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
0237         const struct nlattr * const tb[])
0238 {
0239     void *info = nft_expr_priv(expr);
0240     struct xt_target *target = expr->ops->data;
0241     struct xt_tgchk_param par;
0242     size_t size = XT_ALIGN(nla_len(tb[NFTA_TARGET_INFO]));
0243     u16 proto = 0;
0244     bool inv = false;
0245     union nft_entry e = {};
0246     int ret;
0247 
0248     target_compat_from_user(target, nla_data(tb[NFTA_TARGET_INFO]), info);
0249 
0250     if (ctx->nla[NFTA_RULE_COMPAT]) {
0251         ret = nft_parse_compat(ctx->nla[NFTA_RULE_COMPAT], &proto, &inv);
0252         if (ret < 0)
0253             return ret;
0254     }
0255 
0256     nft_target_set_tgchk_param(&par, ctx, target, info, &e, proto, inv);
0257 
0258     nft_compat_wait_for_destructors();
0259 
0260     ret = xt_check_target(&par, size, proto, inv);
0261     if (ret < 0) {
0262         if (ret == -ENOENT) {
0263             const char *modname = NULL;
0264 
0265             if (strcmp(target->name, "LOG") == 0)
0266                 modname = "nf_log_syslog";
0267             else if (strcmp(target->name, "NFLOG") == 0)
0268                 modname = "nfnetlink_log";
0269 
0270             if (modname &&
0271                 nft_request_module(ctx->net, "%s", modname) == -EAGAIN)
0272                 return -EAGAIN;
0273         }
0274 
0275         return ret;
0276     }
0277 
0278     /* The standard target cannot be used */
0279     if (!target->target)
0280         return -EINVAL;
0281 
0282     return 0;
0283 }
0284 
0285 static void __nft_mt_tg_destroy(struct module *me, const struct nft_expr *expr)
0286 {
0287     module_put(me);
0288     kfree(expr->ops);
0289 }
0290 
0291 static void
0292 nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
0293 {
0294     struct xt_target *target = expr->ops->data;
0295     void *info = nft_expr_priv(expr);
0296     struct module *me = target->me;
0297     struct xt_tgdtor_param par;
0298 
0299     par.net = ctx->net;
0300     par.target = target;
0301     par.targinfo = info;
0302     par.family = ctx->family;
0303     if (par.target->destroy != NULL)
0304         par.target->destroy(&par);
0305 
0306     __nft_mt_tg_destroy(me, expr);
0307 }
0308 
0309 static int nft_extension_dump_info(struct sk_buff *skb, int attr,
0310                    const void *info,
0311                    unsigned int size, unsigned int user_size)
0312 {
0313     unsigned int info_size, aligned_size = XT_ALIGN(size);
0314     struct nlattr *nla;
0315 
0316     nla = nla_reserve(skb, attr, aligned_size);
0317     if (!nla)
0318         return -1;
0319 
0320     info_size = user_size ? : size;
0321     memcpy(nla_data(nla), info, info_size);
0322     memset(nla_data(nla) + info_size, 0, aligned_size - info_size);
0323 
0324     return 0;
0325 }
0326 
0327 static int nft_target_dump(struct sk_buff *skb, const struct nft_expr *expr)
0328 {
0329     const struct xt_target *target = expr->ops->data;
0330     void *info = nft_expr_priv(expr);
0331 
0332     if (nla_put_string(skb, NFTA_TARGET_NAME, target->name) ||
0333         nla_put_be32(skb, NFTA_TARGET_REV, htonl(target->revision)) ||
0334         nft_extension_dump_info(skb, NFTA_TARGET_INFO, info,
0335                     target->targetsize, target->usersize))
0336         goto nla_put_failure;
0337 
0338     return 0;
0339 
0340 nla_put_failure:
0341     return -1;
0342 }
0343 
0344 static int nft_target_validate(const struct nft_ctx *ctx,
0345                    const struct nft_expr *expr,
0346                    const struct nft_data **data)
0347 {
0348     struct xt_target *target = expr->ops->data;
0349     unsigned int hook_mask = 0;
0350     int ret;
0351 
0352     if (nft_is_base_chain(ctx->chain)) {
0353         const struct nft_base_chain *basechain =
0354                         nft_base_chain(ctx->chain);
0355         const struct nf_hook_ops *ops = &basechain->ops;
0356 
0357         hook_mask = 1 << ops->hooknum;
0358         if (target->hooks && !(hook_mask & target->hooks))
0359             return -EINVAL;
0360 
0361         ret = nft_compat_chain_validate_dependency(ctx, target->table);
0362         if (ret < 0)
0363             return ret;
0364     }
0365     return 0;
0366 }
0367 
0368 static void __nft_match_eval(const struct nft_expr *expr,
0369                  struct nft_regs *regs,
0370                  const struct nft_pktinfo *pkt,
0371                  void *info)
0372 {
0373     struct xt_match *match = expr->ops->data;
0374     struct sk_buff *skb = pkt->skb;
0375     struct xt_action_param xt;
0376     bool ret;
0377 
0378     nft_compat_set_par(&xt, pkt, match, info);
0379 
0380     ret = match->match(skb, &xt);
0381 
0382     if (xt.hotdrop) {
0383         regs->verdict.code = NF_DROP;
0384         return;
0385     }
0386 
0387     switch (ret ? 1 : 0) {
0388     case 1:
0389         regs->verdict.code = NFT_CONTINUE;
0390         break;
0391     case 0:
0392         regs->verdict.code = NFT_BREAK;
0393         break;
0394     }
0395 }
0396 
0397 static void nft_match_large_eval(const struct nft_expr *expr,
0398                  struct nft_regs *regs,
0399                  const struct nft_pktinfo *pkt)
0400 {
0401     struct nft_xt_match_priv *priv = nft_expr_priv(expr);
0402 
0403     __nft_match_eval(expr, regs, pkt, priv->info);
0404 }
0405 
0406 static void nft_match_eval(const struct nft_expr *expr,
0407                struct nft_regs *regs,
0408                const struct nft_pktinfo *pkt)
0409 {
0410     __nft_match_eval(expr, regs, pkt, nft_expr_priv(expr));
0411 }
0412 
0413 static const struct nla_policy nft_match_policy[NFTA_MATCH_MAX + 1] = {
0414     [NFTA_MATCH_NAME]   = { .type = NLA_NUL_STRING },
0415     [NFTA_MATCH_REV]    = { .type = NLA_U32 },
0416     [NFTA_MATCH_INFO]   = { .type = NLA_BINARY },
0417 };
0418 
0419 /* struct xt_mtchk_param and xt_tgchk_param look very similar */
0420 static void
0421 nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
0422               struct xt_match *match, void *info,
0423               union nft_entry *entry, u16 proto, bool inv)
0424 {
0425     par->net    = ctx->net;
0426     par->table  = ctx->table->name;
0427     switch (ctx->family) {
0428     case AF_INET:
0429         entry->e4.ip.proto = proto;
0430         entry->e4.ip.invflags = inv ? IPT_INV_PROTO : 0;
0431         break;
0432     case AF_INET6:
0433         if (proto)
0434             entry->e6.ipv6.flags |= IP6T_F_PROTO;
0435 
0436         entry->e6.ipv6.proto = proto;
0437         entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0;
0438         break;
0439     case NFPROTO_BRIDGE:
0440         entry->ebt.ethproto = (__force __be16)proto;
0441         entry->ebt.invflags = inv ? EBT_IPROTO : 0;
0442         break;
0443     case NFPROTO_ARP:
0444         break;
0445     }
0446     par->entryinfo  = entry;
0447     par->match  = match;
0448     par->matchinfo  = info;
0449     if (nft_is_base_chain(ctx->chain)) {
0450         const struct nft_base_chain *basechain =
0451                         nft_base_chain(ctx->chain);
0452         const struct nf_hook_ops *ops = &basechain->ops;
0453 
0454         par->hook_mask = 1 << ops->hooknum;
0455     } else {
0456         par->hook_mask = 0;
0457     }
0458     par->family = ctx->family;
0459     par->nft_compat = true;
0460 }
0461 
0462 static void match_compat_from_user(struct xt_match *m, void *in, void *out)
0463 {
0464     int pad;
0465 
0466     memcpy(out, in, m->matchsize);
0467     pad = XT_ALIGN(m->matchsize) - m->matchsize;
0468     if (pad > 0)
0469         memset(out + m->matchsize, 0, pad);
0470 }
0471 
0472 static int
0473 __nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
0474          const struct nlattr * const tb[],
0475          void *info)
0476 {
0477     struct xt_match *match = expr->ops->data;
0478     struct xt_mtchk_param par;
0479     size_t size = XT_ALIGN(nla_len(tb[NFTA_MATCH_INFO]));
0480     u16 proto = 0;
0481     bool inv = false;
0482     union nft_entry e = {};
0483     int ret;
0484 
0485     match_compat_from_user(match, nla_data(tb[NFTA_MATCH_INFO]), info);
0486 
0487     if (ctx->nla[NFTA_RULE_COMPAT]) {
0488         ret = nft_parse_compat(ctx->nla[NFTA_RULE_COMPAT], &proto, &inv);
0489         if (ret < 0)
0490             return ret;
0491     }
0492 
0493     nft_match_set_mtchk_param(&par, ctx, match, info, &e, proto, inv);
0494 
0495     nft_compat_wait_for_destructors();
0496 
0497     return xt_check_match(&par, size, proto, inv);
0498 }
0499 
0500 static int
0501 nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
0502            const struct nlattr * const tb[])
0503 {
0504     return __nft_match_init(ctx, expr, tb, nft_expr_priv(expr));
0505 }
0506 
0507 static int
0508 nft_match_large_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
0509              const struct nlattr * const tb[])
0510 {
0511     struct nft_xt_match_priv *priv = nft_expr_priv(expr);
0512     struct xt_match *m = expr->ops->data;
0513     int ret;
0514 
0515     priv->info = kmalloc(XT_ALIGN(m->matchsize), GFP_KERNEL);
0516     if (!priv->info)
0517         return -ENOMEM;
0518 
0519     ret = __nft_match_init(ctx, expr, tb, priv->info);
0520     if (ret)
0521         kfree(priv->info);
0522     return ret;
0523 }
0524 
0525 static void
0526 __nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr,
0527             void *info)
0528 {
0529     struct xt_match *match = expr->ops->data;
0530     struct module *me = match->me;
0531     struct xt_mtdtor_param par;
0532 
0533     par.net = ctx->net;
0534     par.match = match;
0535     par.matchinfo = info;
0536     par.family = ctx->family;
0537     if (par.match->destroy != NULL)
0538         par.match->destroy(&par);
0539 
0540     __nft_mt_tg_destroy(me, expr);
0541 }
0542 
0543 static void
0544 nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
0545 {
0546     __nft_match_destroy(ctx, expr, nft_expr_priv(expr));
0547 }
0548 
0549 static void
0550 nft_match_large_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
0551 {
0552     struct nft_xt_match_priv *priv = nft_expr_priv(expr);
0553 
0554     __nft_match_destroy(ctx, expr, priv->info);
0555     kfree(priv->info);
0556 }
0557 
0558 static int __nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr,
0559                 void *info)
0560 {
0561     struct xt_match *match = expr->ops->data;
0562 
0563     if (nla_put_string(skb, NFTA_MATCH_NAME, match->name) ||
0564         nla_put_be32(skb, NFTA_MATCH_REV, htonl(match->revision)) ||
0565         nft_extension_dump_info(skb, NFTA_MATCH_INFO, info,
0566                     match->matchsize, match->usersize))
0567         goto nla_put_failure;
0568 
0569     return 0;
0570 
0571 nla_put_failure:
0572     return -1;
0573 }
0574 
0575 static int nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr)
0576 {
0577     return __nft_match_dump(skb, expr, nft_expr_priv(expr));
0578 }
0579 
0580 static int nft_match_large_dump(struct sk_buff *skb, const struct nft_expr *e)
0581 {
0582     struct nft_xt_match_priv *priv = nft_expr_priv(e);
0583 
0584     return __nft_match_dump(skb, e, priv->info);
0585 }
0586 
0587 static int nft_match_validate(const struct nft_ctx *ctx,
0588                   const struct nft_expr *expr,
0589                   const struct nft_data **data)
0590 {
0591     struct xt_match *match = expr->ops->data;
0592     unsigned int hook_mask = 0;
0593     int ret;
0594 
0595     if (nft_is_base_chain(ctx->chain)) {
0596         const struct nft_base_chain *basechain =
0597                         nft_base_chain(ctx->chain);
0598         const struct nf_hook_ops *ops = &basechain->ops;
0599 
0600         hook_mask = 1 << ops->hooknum;
0601         if (match->hooks && !(hook_mask & match->hooks))
0602             return -EINVAL;
0603 
0604         ret = nft_compat_chain_validate_dependency(ctx, match->table);
0605         if (ret < 0)
0606             return ret;
0607     }
0608     return 0;
0609 }
0610 
0611 static int
0612 nfnl_compat_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
0613               int event, u16 family, const char *name,
0614               int rev, int target)
0615 {
0616     struct nlmsghdr *nlh;
0617     unsigned int flags = portid ? NLM_F_MULTI : 0;
0618 
0619     event = nfnl_msg_type(NFNL_SUBSYS_NFT_COMPAT, event);
0620     nlh = nfnl_msg_put(skb, portid, seq, event, flags, family,
0621                NFNETLINK_V0, 0);
0622     if (!nlh)
0623         goto nlmsg_failure;
0624 
0625     if (nla_put_string(skb, NFTA_COMPAT_NAME, name) ||
0626         nla_put_be32(skb, NFTA_COMPAT_REV, htonl(rev)) ||
0627         nla_put_be32(skb, NFTA_COMPAT_TYPE, htonl(target)))
0628         goto nla_put_failure;
0629 
0630     nlmsg_end(skb, nlh);
0631     return skb->len;
0632 
0633 nlmsg_failure:
0634 nla_put_failure:
0635     nlmsg_cancel(skb, nlh);
0636     return -1;
0637 }
0638 
0639 static int nfnl_compat_get_rcu(struct sk_buff *skb,
0640                    const struct nfnl_info *info,
0641                    const struct nlattr * const tb[])
0642 {
0643     u8 family = info->nfmsg->nfgen_family;
0644     const char *name, *fmt;
0645     struct sk_buff *skb2;
0646     int ret = 0, target;
0647     u32 rev;
0648 
0649     if (tb[NFTA_COMPAT_NAME] == NULL ||
0650         tb[NFTA_COMPAT_REV] == NULL ||
0651         tb[NFTA_COMPAT_TYPE] == NULL)
0652         return -EINVAL;
0653 
0654     name = nla_data(tb[NFTA_COMPAT_NAME]);
0655     rev = ntohl(nla_get_be32(tb[NFTA_COMPAT_REV]));
0656     target = ntohl(nla_get_be32(tb[NFTA_COMPAT_TYPE]));
0657 
0658     switch(family) {
0659     case AF_INET:
0660         fmt = "ipt_%s";
0661         break;
0662     case AF_INET6:
0663         fmt = "ip6t_%s";
0664         break;
0665     case NFPROTO_BRIDGE:
0666         fmt = "ebt_%s";
0667         break;
0668     case NFPROTO_ARP:
0669         fmt = "arpt_%s";
0670         break;
0671     default:
0672         pr_err("nft_compat: unsupported protocol %d\n", family);
0673         return -EINVAL;
0674     }
0675 
0676     if (!try_module_get(THIS_MODULE))
0677         return -EINVAL;
0678 
0679     rcu_read_unlock();
0680     try_then_request_module(xt_find_revision(family, name, rev, target, &ret),
0681                 fmt, name);
0682     if (ret < 0)
0683         goto out_put;
0684 
0685     skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
0686     if (skb2 == NULL) {
0687         ret = -ENOMEM;
0688         goto out_put;
0689     }
0690 
0691     /* include the best revision for this extension in the message */
0692     if (nfnl_compat_fill_info(skb2, NETLINK_CB(skb).portid,
0693                   info->nlh->nlmsg_seq,
0694                   NFNL_MSG_TYPE(info->nlh->nlmsg_type),
0695                   NFNL_MSG_COMPAT_GET,
0696                   family, name, ret, target) <= 0) {
0697         kfree_skb(skb2);
0698         goto out_put;
0699     }
0700 
0701     ret = nfnetlink_unicast(skb2, info->net, NETLINK_CB(skb).portid);
0702 out_put:
0703     rcu_read_lock();
0704     module_put(THIS_MODULE);
0705 
0706     return ret;
0707 }
0708 
0709 static const struct nla_policy nfnl_compat_policy_get[NFTA_COMPAT_MAX+1] = {
0710     [NFTA_COMPAT_NAME]  = { .type = NLA_NUL_STRING,
0711                     .len = NFT_COMPAT_NAME_MAX-1 },
0712     [NFTA_COMPAT_REV]   = { .type = NLA_U32 },
0713     [NFTA_COMPAT_TYPE]  = { .type = NLA_U32 },
0714 };
0715 
0716 static const struct nfnl_callback nfnl_nft_compat_cb[NFNL_MSG_COMPAT_MAX] = {
0717     [NFNL_MSG_COMPAT_GET]   = {
0718         .call       = nfnl_compat_get_rcu,
0719         .type       = NFNL_CB_RCU,
0720         .attr_count = NFTA_COMPAT_MAX,
0721         .policy     = nfnl_compat_policy_get
0722     },
0723 };
0724 
0725 static const struct nfnetlink_subsystem nfnl_compat_subsys = {
0726     .name       = "nft-compat",
0727     .subsys_id  = NFNL_SUBSYS_NFT_COMPAT,
0728     .cb_count   = NFNL_MSG_COMPAT_MAX,
0729     .cb     = nfnl_nft_compat_cb,
0730 };
0731 
0732 static struct nft_expr_type nft_match_type;
0733 
0734 static bool nft_match_reduce(struct nft_regs_track *track,
0735                  const struct nft_expr *expr)
0736 {
0737     const struct xt_match *match = expr->ops->data;
0738 
0739     return strcmp(match->name, "comment") == 0;
0740 }
0741 
0742 static const struct nft_expr_ops *
0743 nft_match_select_ops(const struct nft_ctx *ctx,
0744              const struct nlattr * const tb[])
0745 {
0746     struct nft_expr_ops *ops;
0747     struct xt_match *match;
0748     unsigned int matchsize;
0749     char *mt_name;
0750     u32 rev, family;
0751     int err;
0752 
0753     if (tb[NFTA_MATCH_NAME] == NULL ||
0754         tb[NFTA_MATCH_REV] == NULL ||
0755         tb[NFTA_MATCH_INFO] == NULL)
0756         return ERR_PTR(-EINVAL);
0757 
0758     mt_name = nla_data(tb[NFTA_MATCH_NAME]);
0759     rev = ntohl(nla_get_be32(tb[NFTA_MATCH_REV]));
0760     family = ctx->family;
0761 
0762     match = xt_request_find_match(family, mt_name, rev);
0763     if (IS_ERR(match))
0764         return ERR_PTR(-ENOENT);
0765 
0766     if (match->matchsize > nla_len(tb[NFTA_MATCH_INFO])) {
0767         err = -EINVAL;
0768         goto err;
0769     }
0770 
0771     ops = kzalloc(sizeof(struct nft_expr_ops), GFP_KERNEL);
0772     if (!ops) {
0773         err = -ENOMEM;
0774         goto err;
0775     }
0776 
0777     ops->type = &nft_match_type;
0778     ops->eval = nft_match_eval;
0779     ops->init = nft_match_init;
0780     ops->destroy = nft_match_destroy;
0781     ops->dump = nft_match_dump;
0782     ops->validate = nft_match_validate;
0783     ops->data = match;
0784     ops->reduce = nft_match_reduce;
0785 
0786     matchsize = NFT_EXPR_SIZE(XT_ALIGN(match->matchsize));
0787     if (matchsize > NFT_MATCH_LARGE_THRESH) {
0788         matchsize = NFT_EXPR_SIZE(sizeof(struct nft_xt_match_priv));
0789 
0790         ops->eval = nft_match_large_eval;
0791         ops->init = nft_match_large_init;
0792         ops->destroy = nft_match_large_destroy;
0793         ops->dump = nft_match_large_dump;
0794     }
0795 
0796     ops->size = matchsize;
0797 
0798     return ops;
0799 err:
0800     module_put(match->me);
0801     return ERR_PTR(err);
0802 }
0803 
0804 static void nft_match_release_ops(const struct nft_expr_ops *ops)
0805 {
0806     struct xt_match *match = ops->data;
0807 
0808     module_put(match->me);
0809     kfree(ops);
0810 }
0811 
0812 static struct nft_expr_type nft_match_type __read_mostly = {
0813     .name       = "match",
0814     .select_ops = nft_match_select_ops,
0815     .release_ops    = nft_match_release_ops,
0816     .policy     = nft_match_policy,
0817     .maxattr    = NFTA_MATCH_MAX,
0818     .owner      = THIS_MODULE,
0819 };
0820 
0821 static struct nft_expr_type nft_target_type;
0822 
0823 static const struct nft_expr_ops *
0824 nft_target_select_ops(const struct nft_ctx *ctx,
0825               const struct nlattr * const tb[])
0826 {
0827     struct nft_expr_ops *ops;
0828     struct xt_target *target;
0829     char *tg_name;
0830     u32 rev, family;
0831     int err;
0832 
0833     if (tb[NFTA_TARGET_NAME] == NULL ||
0834         tb[NFTA_TARGET_REV] == NULL ||
0835         tb[NFTA_TARGET_INFO] == NULL)
0836         return ERR_PTR(-EINVAL);
0837 
0838     tg_name = nla_data(tb[NFTA_TARGET_NAME]);
0839     rev = ntohl(nla_get_be32(tb[NFTA_TARGET_REV]));
0840     family = ctx->family;
0841 
0842     if (strcmp(tg_name, XT_ERROR_TARGET) == 0 ||
0843         strcmp(tg_name, XT_STANDARD_TARGET) == 0 ||
0844         strcmp(tg_name, "standard") == 0)
0845         return ERR_PTR(-EINVAL);
0846 
0847     target = xt_request_find_target(family, tg_name, rev);
0848     if (IS_ERR(target))
0849         return ERR_PTR(-ENOENT);
0850 
0851     if (!target->target) {
0852         err = -EINVAL;
0853         goto err;
0854     }
0855 
0856     if (target->targetsize > nla_len(tb[NFTA_TARGET_INFO])) {
0857         err = -EINVAL;
0858         goto err;
0859     }
0860 
0861     ops = kzalloc(sizeof(struct nft_expr_ops), GFP_KERNEL);
0862     if (!ops) {
0863         err = -ENOMEM;
0864         goto err;
0865     }
0866 
0867     ops->type = &nft_target_type;
0868     ops->size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize));
0869     ops->init = nft_target_init;
0870     ops->destroy = nft_target_destroy;
0871     ops->dump = nft_target_dump;
0872     ops->validate = nft_target_validate;
0873     ops->data = target;
0874     ops->reduce = NFT_REDUCE_READONLY;
0875 
0876     if (family == NFPROTO_BRIDGE)
0877         ops->eval = nft_target_eval_bridge;
0878     else
0879         ops->eval = nft_target_eval_xt;
0880 
0881     return ops;
0882 err:
0883     module_put(target->me);
0884     return ERR_PTR(err);
0885 }
0886 
0887 static void nft_target_release_ops(const struct nft_expr_ops *ops)
0888 {
0889     struct xt_target *target = ops->data;
0890 
0891     module_put(target->me);
0892     kfree(ops);
0893 }
0894 
0895 static struct nft_expr_type nft_target_type __read_mostly = {
0896     .name       = "target",
0897     .select_ops = nft_target_select_ops,
0898     .release_ops    = nft_target_release_ops,
0899     .policy     = nft_target_policy,
0900     .maxattr    = NFTA_TARGET_MAX,
0901     .owner      = THIS_MODULE,
0902 };
0903 
0904 static int __init nft_compat_module_init(void)
0905 {
0906     int ret;
0907 
0908     ret = nft_register_expr(&nft_match_type);
0909     if (ret < 0)
0910         return ret;
0911 
0912     ret = nft_register_expr(&nft_target_type);
0913     if (ret < 0)
0914         goto err_match;
0915 
0916     ret = nfnetlink_subsys_register(&nfnl_compat_subsys);
0917     if (ret < 0) {
0918         pr_err("nft_compat: cannot register with nfnetlink.\n");
0919         goto err_target;
0920     }
0921 
0922     return ret;
0923 err_target:
0924     nft_unregister_expr(&nft_target_type);
0925 err_match:
0926     nft_unregister_expr(&nft_match_type);
0927     return ret;
0928 }
0929 
0930 static void __exit nft_compat_module_exit(void)
0931 {
0932     nfnetlink_subsys_unregister(&nfnl_compat_subsys);
0933     nft_unregister_expr(&nft_target_type);
0934     nft_unregister_expr(&nft_match_type);
0935 }
0936 
0937 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_NFT_COMPAT);
0938 
0939 module_init(nft_compat_module_init);
0940 module_exit(nft_compat_module_exit);
0941 
0942 MODULE_LICENSE("GPL");
0943 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
0944 MODULE_ALIAS_NFT_EXPR("match");
0945 MODULE_ALIAS_NFT_EXPR("target");
0946 MODULE_DESCRIPTION("x_tables over nftables support");