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