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 static 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 42 union nft_entry { 43 struct ipt_entry e4; 44 struct ip6t_entry e6; 45 struct ebt_entry ebt; 46 struct arpt_entry arp; 47 }; 48 49 static inline void 50 nft_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 57 static 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 83 static 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 118 static 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 124 static void 125 nft_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 167 static 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 177 static 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 182 static 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 206 static int 207 nft_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; 244 err: 245 module_put(target->me); 246 return ret; 247 } 248 249 static void 250 nft_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 266 static 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 278 nla_put_failure: 279 return -1; 280 } 281 282 static 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 307 static 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 335 static 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 */ 342 static void 343 nft_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 384 static 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 394 static int 395 nft_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; 426 err: 427 module_put(match->me); 428 return ret; 429 } 430 431 static void 432 nft_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 448 static 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 460 nla_put_failure: 461 return -1; 462 } 463 464 static 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 489 static int 490 nfnl_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 516 nlmsg_failure: 517 nla_put_failure: 518 nlmsg_cancel(skb, nlh); 519 return -1; 520 } 521 522 static int 523 nfnl_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 593 static 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 600 static 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 606 static 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 613 static LIST_HEAD(nft_match_list); 614 615 struct nft_xt { 616 struct list_head head; 617 struct nft_expr_ops ops; 618 }; 619 620 static struct nft_expr_type nft_match_type; 621 622 static 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 629 static const struct nft_expr_ops * 630 nft_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 /* This is the first time we use this match, allocate operations */ 664 nft_match = kzalloc(sizeof(struct nft_xt), GFP_KERNEL); 665 if (nft_match == NULL) 666 return ERR_PTR(-ENOMEM); 667 668 nft_match->ops.type = &nft_match_type; 669 nft_match->ops.size = NFT_EXPR_SIZE(XT_ALIGN(match->matchsize)); 670 nft_match->ops.eval = nft_match_eval; 671 nft_match->ops.init = nft_match_init; 672 nft_match->ops.destroy = nft_match_destroy; 673 nft_match->ops.dump = nft_match_dump; 674 nft_match->ops.validate = nft_match_validate; 675 nft_match->ops.data = match; 676 677 list_add(&nft_match->head, &nft_match_list); 678 679 return &nft_match->ops; 680 } 681 682 static void nft_match_release(void) 683 { 684 struct nft_xt *nft_match, *tmp; 685 686 list_for_each_entry_safe(nft_match, tmp, &nft_match_list, head) 687 kfree(nft_match); 688 } 689 690 static struct nft_expr_type nft_match_type __read_mostly = { 691 .name = "match", 692 .select_ops = nft_match_select_ops, 693 .policy = nft_match_policy, 694 .maxattr = NFTA_MATCH_MAX, 695 .owner = THIS_MODULE, 696 }; 697 698 static LIST_HEAD(nft_target_list); 699 700 static struct nft_expr_type nft_target_type; 701 702 static bool nft_target_cmp(const struct xt_target *tg, 703 const char *name, u32 rev, u32 family) 704 { 705 return strcmp(tg->name, name) == 0 && tg->revision == rev && 706 (tg->family == NFPROTO_UNSPEC || tg->family == family); 707 } 708 709 static const struct nft_expr_ops * 710 nft_target_select_ops(const struct nft_ctx *ctx, 711 const struct nlattr * const tb[]) 712 { 713 struct nft_xt *nft_target; 714 struct xt_target *target; 715 char *tg_name; 716 u32 rev, family; 717 718 if (tb[NFTA_TARGET_NAME] == NULL || 719 tb[NFTA_TARGET_REV] == NULL || 720 tb[NFTA_TARGET_INFO] == NULL) 721 return ERR_PTR(-EINVAL); 722 723 tg_name = nla_data(tb[NFTA_TARGET_NAME]); 724 rev = ntohl(nla_get_be32(tb[NFTA_TARGET_REV])); 725 family = ctx->afi->family; 726 727 /* Re-use the existing target if it's already loaded. */ 728 list_for_each_entry(nft_target, &nft_target_list, head) { 729 struct xt_target *target = nft_target->ops.data; 730 731 if (nft_target_cmp(target, tg_name, rev, family)) { 732 if (!try_module_get(target->me)) 733 return ERR_PTR(-ENOENT); 734 735 return &nft_target->ops; 736 } 737 } 738 739 target = xt_request_find_target(family, tg_name, rev); 740 if (IS_ERR(target)) 741 return ERR_PTR(-ENOENT); 742 743 /* This is the first time we use this target, allocate operations */ 744 nft_target = kzalloc(sizeof(struct nft_xt), GFP_KERNEL); 745 if (nft_target == NULL) 746 return ERR_PTR(-ENOMEM); 747 748 nft_target->ops.type = &nft_target_type; 749 nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize)); 750 nft_target->ops.init = nft_target_init; 751 nft_target->ops.destroy = nft_target_destroy; 752 nft_target->ops.dump = nft_target_dump; 753 nft_target->ops.validate = nft_target_validate; 754 nft_target->ops.data = target; 755 756 if (family == NFPROTO_BRIDGE) 757 nft_target->ops.eval = nft_target_eval_bridge; 758 else 759 nft_target->ops.eval = nft_target_eval_xt; 760 761 list_add(&nft_target->head, &nft_target_list); 762 763 return &nft_target->ops; 764 } 765 766 static void nft_target_release(void) 767 { 768 struct nft_xt *nft_target, *tmp; 769 770 list_for_each_entry_safe(nft_target, tmp, &nft_target_list, head) 771 kfree(nft_target); 772 } 773 774 static struct nft_expr_type nft_target_type __read_mostly = { 775 .name = "target", 776 .select_ops = nft_target_select_ops, 777 .policy = nft_target_policy, 778 .maxattr = NFTA_TARGET_MAX, 779 .owner = THIS_MODULE, 780 }; 781 782 static int __init nft_compat_module_init(void) 783 { 784 int ret; 785 786 ret = nft_register_expr(&nft_match_type); 787 if (ret < 0) 788 return ret; 789 790 ret = nft_register_expr(&nft_target_type); 791 if (ret < 0) 792 goto err_match; 793 794 ret = nfnetlink_subsys_register(&nfnl_compat_subsys); 795 if (ret < 0) { 796 pr_err("nft_compat: cannot register with nfnetlink.\n"); 797 goto err_target; 798 } 799 800 pr_info("nf_tables_compat: (c) 2012 Pablo Neira Ayuso <pablo@netfilter.org>\n"); 801 802 return ret; 803 804 err_target: 805 nft_unregister_expr(&nft_target_type); 806 err_match: 807 nft_unregister_expr(&nft_match_type); 808 return ret; 809 } 810 811 static void __exit nft_compat_module_exit(void) 812 { 813 nfnetlink_subsys_unregister(&nfnl_compat_subsys); 814 nft_unregister_expr(&nft_target_type); 815 nft_unregister_expr(&nft_match_type); 816 nft_match_release(); 817 nft_target_release(); 818 } 819 820 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_NFT_COMPAT); 821 822 module_init(nft_compat_module_init); 823 module_exit(nft_compat_module_exit); 824 825 MODULE_LICENSE("GPL"); 826 MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); 827 MODULE_ALIAS_NFT_EXPR("match"); 828 MODULE_ALIAS_NFT_EXPR("target"); 829