| @@ -399,6 +399,8 @@ static const struct nla_policy nft_table_policy[NFTA_TABLE_MAX + 1] = { · 398 unmodified lines |
| 399 | [NFTA_TABLE_NAME] = { .type = NLA_STRING, | 399 | [NFTA_TABLE_NAME] = { .type = NLA_STRING, |
| 400 | .len = NFT_TABLE_MAXNAMELEN - 1 }, | 400 | .len = NFT_TABLE_MAXNAMELEN - 1 }, |
| 401 | [NFTA_TABLE_FLAGS] = { .type = NLA_U32 }, | 401 | [NFTA_TABLE_FLAGS] = { .type = NLA_U32 }, |
| | 402 | [NFTA_TABLE_DEV] = { .type = NLA_STRING, |
| | 403 | .len = IFNAMSIZ - 1 }, |
| 402 | }; | 404 | }; |
| 403 | | 405 | |
| 404 | static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net, | 406 | static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net, |
| @@ -423,6 +425,10 @@ static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net, · 18 unmodified lines |
| 423 | nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use))) | 425 | nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use))) |
| 424 | goto nla_put_failure; | 426 | goto nla_put_failure; |
| 425 | | 427 | |
| | 428 | if (table->dev && |
| | 429 | nla_put_string(skb, NFTA_TABLE_DEV, table->dev->name)) |
| | 430 | goto nla_put_failure; |
| | 431 | |
| 426 | nlmsg_end(skb, nlh); | 432 | nlmsg_end(skb, nlh); |
| 427 | return 0; | 433 | return 0; |
| 428 | | 434 | |
| @@ -608,6 +614,11 @@ static int nf_tables_updtable(struct nft_ctx *ctx) · 179 unmodified lines |
| 608 | if (flags == ctx->table->flags) | 614 | if (flags == ctx->table->flags) |
| 609 | return 0; | 615 | return 0; |
| 610 | | 616 | |
| | 617 | if ((ctx->afi->flags & NFT_AF_NEEDS_DEV) && |
| | 618 | ctx->nla[NFTA_TABLE_DEV] && |
| | 619 | nla_strcmp(ctx->nla[NFTA_TABLE_DEV], ctx->table->dev->name)) |
| | 620 | return -EOPNOTSUPP; |
| | 621 | |
| 611 | trans = nft_trans_alloc(ctx, NFT_MSG_NEWTABLE, | 622 | trans = nft_trans_alloc(ctx, NFT_MSG_NEWTABLE, |
| 612 | sizeof(struct nft_trans_table)); | 623 | sizeof(struct nft_trans_table)); |
| 613 | if (trans == NULL) | 624 | if (trans == NULL) |
| @@ -645,6 +656,7 @@ static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb, · 31 unmodified lines |
| 645 | struct nft_table *table; | 656 | struct nft_table *table; |
| 646 | struct net *net = sock_net(skb->sk); | 657 | struct net *net = sock_net(skb->sk); |
| 647 | int family = nfmsg->nfgen_family; | 658 | int family = nfmsg->nfgen_family; |
| | 659 | struct net_device *dev = NULL; |
| 648 | u32 flags = 0; | 660 | u32 flags = 0; |
| 649 | struct nft_ctx ctx; | 661 | struct nft_ctx ctx; |
| 650 | int err; | 662 | int err; |
| @@ -679,30 +691,50 @@ static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb, · 28 unmodified lines |
| 679 | return -EINVAL; | 691 | return -EINVAL; |
| 680 | } | 692 | } |
| 681 | | 693 | |
| | 694 | if (afi->flags & NFT_AF_NEEDS_DEV) { |
| | 695 | char ifname[IFNAMSIZ]; |
| | 696 | |
| | 697 | if (!nla[NFTA_TABLE_DEV]) |
| | 698 | return -EOPNOTSUPP; |
| | 699 | |
| | 700 | nla_strlcpy(ifname, nla[NFTA_TABLE_DEV], IFNAMSIZ); |
| | 701 | dev = dev_get_by_name(net, ifname); |
| | 702 | if (!dev) |
| | 703 | return -ENOENT; |
| | 704 | } else if (nla[NFTA_TABLE_DEV]) { |
| | 705 | return -EOPNOTSUPP; |
| | 706 | } |
| | 707 | |
| | 708 | err = -EAFNOSUPPORT; |
| 682 | if (!try_module_get(afi->owner)) | 709 | if (!try_module_get(afi->owner)) |
| 683 | return -EAFNOSUPPORT; | 710 | goto err1; |
| 684 | | 711 | |
| 685 | err = -ENOMEM; | 712 | err = -ENOMEM; |
| 686 | table = kzalloc(sizeof(*table), GFP_KERNEL); | 713 | table = kzalloc(sizeof(*table), GFP_KERNEL); |
| 687 | if (table == NULL) | 714 | if (table == NULL) |
| 688 | goto err1; | 715 | goto err2; |
| 689 | | 716 | |
| 690 | nla_strlcpy(table->name, name, NFT_TABLE_MAXNAMELEN); | 717 | nla_strlcpy(table->name, name, NFT_TABLE_MAXNAMELEN); |
| 691 | INIT_LIST_HEAD(&table->chains); | 718 | INIT_LIST_HEAD(&table->chains); |
| 692 | INIT_LIST_HEAD(&table->sets); | 719 | INIT_LIST_HEAD(&table->sets); |
| 693 | table->flags = flags; | 720 | table->flags = flags; |
| | 721 | table->dev = dev; |
| 694 | | 722 | |
| 695 | nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla); | 723 | nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla); |
| 696 | err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE); | 724 | err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE); |
| 697 | if (err < 0) | 725 | if (err < 0) |
| 698 | goto err2; | 726 | goto err3; |
| 699 | | 727 | |
| 700 | list_add_tail_rcu(&table->list, &afi->tables); | 728 | list_add_tail_rcu(&table->list, &afi->tables); |
| 701 | return 0; | 729 | return 0; |
| 702 | err2: | 730 | err3: |
| 703 | kfree(table); | 731 | kfree(table); |
| 704 | err1: | 732 | err2: |
| 705 | module_put(afi->owner); | 733 | module_put(afi->owner); |
| | 734 | err1: |
| | 735 | if (dev != NULL) |
| | 736 | dev_put(dev); |
| | 737 | |
| 706 | return err; | 738 | return err; |
| 707 | } | 739 | } |
| 708 | | 740 | |
| @@ -806,6 +838,9 @@ static void nf_tables_table_destroy(struct nft_ctx *ctx) · 97 unmodified lines |
| 806 | { | 838 | { |
| 807 | BUG_ON(ctx->table->use > 0); | 839 | BUG_ON(ctx->table->use > 0); |
| 808 | | 840 | |
| | 841 | if (ctx->table->dev) |
| | 842 | dev_put(ctx->table->dev); |
| | 843 | |
| 809 | kfree(ctx->table); | 844 | kfree(ctx->table); |
| 810 | module_put(ctx->afi->owner); | 845 | module_put(ctx->afi->owner); |
| 811 | } | 846 | } |
| @@ -1361,6 +1396,7 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb, · 549 unmodified lines |
| 1361 | ops->priority = priority; | 1396 | ops->priority = priority; |
| 1362 | ops->priv = chain; | 1397 | ops->priv = chain; |
| 1363 | ops->hook = afi->hooks[ops->hooknum]; | 1398 | ops->hook = afi->hooks[ops->hooknum]; |
| | 1399 | ops->dev = table->dev; |
| 1364 | if (hookfn) | 1400 | if (hookfn) |
| 1365 | ops->hook = hookfn; | 1401 | ops->hook = hookfn; |
| 1366 | if (afi->hook_ops_init) | 1402 | if (afi->hook_ops_init) |