0001
0002
0003
0004
0005
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
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
0227
0228
0229
0230
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
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
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
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");