| @@ -26,6 +26,7 @@ · 25 unmodified lines |
| 26 | 26 | static LIST_HEAD(nf_tables_expressions); |
| 27 | 27 | static LIST_HEAD(nf_tables_objects); |
| 28 | 28 | static LIST_HEAD(nf_tables_flowtables); |
| 29 | +static u64 table_handle; |
| 29 | 30 | |
| 30 | 31 | static void nft_ctx_init(struct nft_ctx *ctx, |
| 31 | 32 | struct net *net, |
| @@ -332,6 +333,20 @@ static struct nft_table *nft_table_lookup(const struct net *net, · 300 unmodified lines |
| 332 | 333 | return NULL; |
| 333 | 334 | } |
| 334 | 335 | |
| 336 | +static struct nft_table *nft_table_lookup_byhandle(const struct net *net, |
| 337 | + const struct nlattr *nla, |
| 338 | + u8 genmask) |
| 339 | +{ |
| 340 | + struct nft_table *table; |
| 341 | + |
| 342 | + list_for_each_entry(table, &net->nft.tables, list) { |
| 343 | + if (be64_to_cpu(nla_get_be64(nla)) == table->handle && |
| 344 | + nft_active_genmask(table, genmask)) |
| 345 | + return table; |
| 346 | + } |
| 347 | + return NULL; |
| 348 | +} |
| 349 | + |
| 335 | 350 | static struct nft_table *nf_tables_table_lookup(const struct net *net, |
| 336 | 351 | const struct nlattr *nla, |
| 337 | 352 | u8 family, u8 genmask) |
| @@ -348,6 +363,22 @@ static struct nft_table *nf_tables_table_lookup(const struct net *net, · 10 unmodified lines |
| 348 | 363 | return ERR_PTR(-ENOENT); |
| 349 | 364 | } |
| 350 | 365 | |
| 366 | +static struct nft_table *nf_tables_table_lookup_byhandle(const struct net *net, |
| 367 | + const struct nlattr *nla, |
| 368 | + u8 genmask) |
| 369 | +{ |
| 370 | + struct nft_table *table; |
| 371 | + |
| 372 | + if (nla == NULL) |
| 373 | + return ERR_PTR(-EINVAL); |
| 374 | + |
| 375 | + table = nft_table_lookup_byhandle(net, nla, genmask); |
| 376 | + if (table != NULL) |
| 377 | + return table; |
| 378 | + |
| 379 | + return ERR_PTR(-ENOENT); |
| 380 | +} |
| 381 | + |
| 351 | 382 | static inline u64 nf_tables_alloc_handle(struct nft_table *table) |
| 352 | 383 | { |
| 353 | 384 | return ++table->hgenerator; |
| @@ -394,6 +425,7 @@ static const struct nla_policy nft_table_policy[NFTA_TABLE_MAX + 1] = { · 40 unmodified lines |
| 394 | 425 | [NFTA_TABLE_NAME] = { .type = NLA_STRING, |
| 395 | 426 | .len = NFT_TABLE_MAXNAMELEN - 1 }, |
| 396 | 427 | [NFTA_TABLE_FLAGS] = { .type = NLA_U32 }, |
| 428 | + [NFTA_TABLE_HANDLE] = { .type = NLA_U64 }, |
| 397 | 429 | }; |
| 398 | 430 | |
| 399 | 431 | static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net, |
| @@ -415,7 +447,9 @@ static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net, · 15 unmodified lines |
| 415 | 447 | |
| 416 | 448 | if (nla_put_string(skb, NFTA_TABLE_NAME, table->name) || |
| 417 | 449 | nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags)) || |
| 418 | | − nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use))) |
| 450 | + nla_put_be32(skb, NFTA_TABLE_USE, htonl(table->use)) || |
| 451 | + nla_put_be64(skb, NFTA_TABLE_HANDLE, cpu_to_be64(table->handle), |
| 452 | + NFTA_TABLE_PAD)) |
| 419 | 453 | goto nla_put_failure; |
| 420 | 454 | |
| 421 | 455 | nlmsg_end(skb, nlh); |
| @@ -674,6 +708,7 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk, · 252 unmodified lines |
| 674 | 708 | INIT_LIST_HEAD(&table->flowtables); |
| 675 | 709 | table->family = family; |
| 676 | 710 | table->flags = flags; |
| 711 | + table->handle = ++table_handle; |
| 677 | 712 | |
| 678 | 713 | nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla); |
| 679 | 714 | err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE); |
| @@ -791,11 +826,18 @@ static int nf_tables_deltable(struct net *net, struct sock *nlsk, · 111 unmodified lines |
| 791 | 826 | struct nft_ctx ctx; |
| 792 | 827 | |
| 793 | 828 | nft_ctx_init(&ctx, net, skb, nlh, 0, NULL, NULL, nla); |
| 794 | | − if (family == AF_UNSPEC || nla[NFTA_TABLE_NAME] == NULL) |
| 829 | + if (family == AF_UNSPEC || |
| 830 | + (!nla[NFTA_TABLE_NAME] && !nla[NFTA_TABLE_HANDLE])) |
| 795 | 831 | return nft_flush(&ctx, family); |
| 796 | 832 | |
| 797 | | − table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], family, |
| 798 | | − genmask); |
| 833 | + if (nla[NFTA_TABLE_HANDLE]) |
| 834 | + table = nf_tables_table_lookup_byhandle(net, |
| 835 | + nla[NFTA_TABLE_HANDLE], |
| 836 | + genmask); |
| 837 | + else |
| 838 | + table = nf_tables_table_lookup(net, nla[NFTA_TABLE_NAME], |
| 839 | + family, genmask); |
| 840 | + |
| 799 | 841 | if (IS_ERR(table)) |
| 800 | 842 | return PTR_ERR(table); |
| 801 | 843 | |
| @@ -1539,6 +1581,7 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk, · 737 unmodified lines |
| 1539 | 1581 | struct nft_rule *rule; |
| 1540 | 1582 | int family = nfmsg->nfgen_family; |
| 1541 | 1583 | struct nft_ctx ctx; |
| 1584 | + u64 handle; |
| 1542 | 1585 | u32 use; |
| 1543 | 1586 | int err; |
| 1544 | 1587 | |
| @@ -1547,7 +1590,12 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk, · 2 unmodified lines |
| 1547 | 1590 | if (IS_ERR(table)) |
| 1548 | 1591 | return PTR_ERR(table); |
| 1549 | 1592 | |
| 1550 | | − chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask); |
| 1593 | + if (nla[NFTA_CHAIN_HANDLE]) { |
| 1594 | + handle = be64_to_cpu(nla_get_be64(nla[NFTA_CHAIN_HANDLE])); |
| 1595 | + chain = nf_tables_chain_lookup_byhandle(table, handle, genmask); |
| 1596 | + } else { |
| 1597 | + chain = nf_tables_chain_lookup(table, nla[NFTA_CHAIN_NAME], genmask); |
| 1598 | + } |
| 1551 | 1599 | if (IS_ERR(chain)) |
| 1552 | 1600 | return PTR_ERR(chain); |
| 1553 | 1601 | |
| @@ -2503,6 +2551,7 @@ static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = { · 949 unmodified lines |
| 2503 | 2551 | [NFTA_SET_USERDATA] = { .type = NLA_BINARY, |
| 2504 | 2552 | .len = NFT_USERDATA_MAXLEN }, |
| 2505 | 2553 | [NFTA_SET_OBJ_TYPE] = { .type = NLA_U32 }, |
| 2554 | + [NFTA_SET_HANDLE] = { .type = NLA_U64 }, |
| 2506 | 2555 | }; |
| 2507 | 2556 | |
| 2508 | 2557 | static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = { |
| @@ -2546,6 +2595,22 @@ static struct nft_set *nf_tables_set_lookup(const struct nft_table *table, · 37 unmodified lines |
| 2546 | 2595 | return ERR_PTR(-ENOENT); |
| 2547 | 2596 | } |
| 2548 | 2597 | |
| 2598 | +static struct nft_set *nf_tables_set_lookup_byhandle(const struct nft_table *table, |
| 2599 | + const struct nlattr *nla, u8 genmask) |
| 2600 | +{ |
| 2601 | + struct nft_set *set; |
| 2602 | + |
| 2603 | + if (nla == NULL) |
| 2604 | + return ERR_PTR(-EINVAL); |
| 2605 | + |
| 2606 | + list_for_each_entry(set, &table->sets, list) { |
| 2607 | + if (be64_to_cpu(nla_get_be64(nla)) == set->handle && |
| 2608 | + nft_active_genmask(set, genmask)) |
| 2609 | + return set; |
| 2610 | + } |
| 2611 | + return ERR_PTR(-ENOENT); |
| 2612 | +} |
| 2613 | + |
| 2549 | 2614 | static struct nft_set *nf_tables_set_lookup_byid(const struct net *net, |
| 2550 | 2615 | const struct nlattr *nla, |
| 2551 | 2616 | u8 genmask) |
| @@ -2661,6 +2726,9 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx, · 109 unmodified lines |
| 2661 | 2726 | goto nla_put_failure; |
| 2662 | 2727 | if (nla_put_string(skb, NFTA_SET_NAME, set->name)) |
| 2663 | 2728 | goto nla_put_failure; |
| 2729 | + if (nla_put_be64(skb, NFTA_SET_HANDLE, cpu_to_be64(set->handle), |
| 2730 | + NFTA_SET_PAD)) |
| 2731 | + goto nla_put_failure; |
| 2664 | 2732 | if (set->flags != 0) |
| 2665 | 2733 | if (nla_put_be32(skb, NFTA_SET_FLAGS, htonl(set->flags))) |
| 2666 | 2734 | goto nla_put_failure; |
| @@ -3069,6 +3137,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk, · 402 unmodified lines |
| 3069 | 3137 | set->udata = udata; |
| 3070 | 3138 | set->timeout = timeout; |
| 3071 | 3139 | set->gc_int = gc_int; |
| 3140 | + set->handle = nf_tables_alloc_handle(table); |
| 3072 | 3141 | |
| 3073 | 3142 | err = ops->init(set, &desc, nla); |
| 3074 | 3143 | if (err < 0) |
| @@ -3126,7 +3195,10 @@ static int nf_tables_delset(struct net *net, struct sock *nlsk, · 51 unmodified lines |
| 3126 | 3195 | if (err < 0) |
| 3127 | 3196 | return err; |
| 3128 | 3197 | |
| 3129 | | − set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask); |
| 3198 | + if (nla[NFTA_SET_HANDLE]) |
| 3199 | + set = nf_tables_set_lookup_byhandle(ctx.table, nla[NFTA_SET_HANDLE], genmask); |
| 3200 | + else |
| 3201 | + set = nf_tables_set_lookup(ctx.table, nla[NFTA_SET_NAME], genmask); |
| 3130 | 3202 | if (IS_ERR(set)) |
| 3131 | 3203 | return PTR_ERR(set); |
| 3132 | 3204 | |
| @@ -4256,6 +4328,21 @@ struct nft_object *nf_tables_obj_lookup(const struct nft_table *table, · 1123 unmodified lines |
| 4256 | 4328 | } |
| 4257 | 4329 | EXPORT_SYMBOL_GPL(nf_tables_obj_lookup); |
| 4258 | 4330 | |
| 4331 | +struct nft_object *nf_tables_obj_lookup_byhandle(const struct nft_table *table, |
| 4332 | + const struct nlattr *nla, |
| 4333 | + u32 objtype, u8 genmask) |
| 4334 | +{ |
| 4335 | + struct nft_object *obj; |
| 4336 | + |
| 4337 | + list_for_each_entry(obj, &table->objects, list) { |
| 4338 | + if (be64_to_cpu(nla_get_be64(nla)) == obj->handle && |
| 4339 | + objtype == obj->ops->type->type && |
| 4340 | + nft_active_genmask(obj, genmask)) |
| 4341 | + return obj; |
| 4342 | + } |
| 4343 | + return ERR_PTR(-ENOENT); |
| 4344 | +} |
| 4345 | + |
| 4259 | 4346 | static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = { |
| 4260 | 4347 | [NFTA_OBJ_TABLE] = { .type = NLA_STRING, |
| 4261 | 4348 | .len = NFT_TABLE_MAXNAMELEN - 1 }, |
| @@ -4263,6 +4350,7 @@ static const struct nla_policy nft_obj_policy[NFTA_OBJ_MAX + 1] = { · 1 unmodified line |
| 4263 | 4350 | .len = NFT_OBJ_MAXNAMELEN - 1 }, |
| 4264 | 4351 | [NFTA_OBJ_TYPE] = { .type = NLA_U32 }, |
| 4265 | 4352 | [NFTA_OBJ_DATA] = { .type = NLA_NESTED }, |
| 4353 | + [NFTA_OBJ_HANDLE] = { .type = NLA_U64}, |
| 4266 | 4354 | }; |
| 4267 | 4355 | |
| 4268 | 4356 | static struct nft_object *nft_obj_init(const struct nft_ctx *ctx, |
| @@ -4410,6 +4498,8 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk, · 141 unmodified lines |
| 4410 | 4498 | goto err1; |
| 4411 | 4499 | } |
| 4412 | 4500 | obj->table = table; |
| 4501 | + obj->handle = nf_tables_alloc_handle(table); |
| 4502 | + |
| 4413 | 4503 | obj->name = nla_strdup(nla[NFTA_OBJ_NAME], GFP_KERNEL); |
| 4414 | 4504 | if (!obj->name) { |
| 4415 | 4505 | err = -ENOMEM; |
| @@ -4456,7 +4546,9 @@ static int nf_tables_fill_obj_info(struct sk_buff *skb, struct net *net, · 40 unmodified lines |
| 4456 | 4546 | nla_put_string(skb, NFTA_OBJ_NAME, obj->name) || |
| 4457 | 4547 | nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) || |
| 4458 | 4548 | nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) || |
| 4459 | | − nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset)) |
| 4549 | + nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset) || |
| 4550 | + nla_put_be64(skb, NFTA_OBJ_HANDLE, cpu_to_be64(obj->handle), |
| 4551 | + NFTA_OBJ_PAD)) |
| 4460 | 4552 | goto nla_put_failure; |
| 4461 | 4553 | |
| 4462 | 4554 | nlmsg_end(skb, nlh); |
| @@ -4654,7 +4746,7 @@ static int nf_tables_delobj(struct net *net, struct sock *nlsk, · 191 unmodified lines |
| 4654 | 4746 | u32 objtype; |
| 4655 | 4747 | |
| 4656 | 4748 | if (!nla[NFTA_OBJ_TYPE] || |
| 4657 | | − !nla[NFTA_OBJ_NAME]) |
| 4749 | + (!nla[NFTA_OBJ_NAME] && !nla[NFTA_OBJ_HANDLE])) |
| 4658 | 4750 | return -EINVAL; |
| 4659 | 4751 | |
| 4660 | 4752 | table = nf_tables_table_lookup(net, nla[NFTA_OBJ_TABLE], family, |
| @@ -4663,7 +4755,12 @@ static int nf_tables_delobj(struct net *net, struct sock *nlsk, · 2 unmodified lines |
| 4663 | 4755 | return PTR_ERR(table); |
| 4664 | 4756 | |
| 4665 | 4757 | objtype = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE])); |
| 4666 | | − obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], objtype, genmask); |
| 4758 | + if (nla[NFTA_OBJ_HANDLE]) |
| 4759 | + obj = nf_tables_obj_lookup_byhandle(table, nla[NFTA_OBJ_HANDLE], |
| 4760 | + objtype, genmask); |
| 4761 | + else |
| 4762 | + obj = nf_tables_obj_lookup(table, nla[NFTA_OBJ_NAME], |
| 4763 | + objtype, genmask); |
| 4667 | 4764 | if (IS_ERR(obj)) |
| 4668 | 4765 | return PTR_ERR(obj); |
| 4669 | 4766 | if (obj->use > 0) |
| @@ -4735,6 +4832,7 @@ static const struct nla_policy nft_flowtable_policy[NFTA_FLOWTABLE_MAX + 1] = { · 65 unmodified lines |
| 4735 | 4832 | [NFTA_FLOWTABLE_NAME] = { .type = NLA_STRING, |
| 4736 | 4833 | .len = NFT_NAME_MAXLEN - 1 }, |
| 4737 | 4834 | [NFTA_FLOWTABLE_HOOK] = { .type = NLA_NESTED }, |
| 4835 | + [NFTA_FLOWTABLE_HANDLE] = { .type = NLA_U64 }, |
| 4738 | 4836 | }; |
| 4739 | 4837 | |
| 4740 | 4838 | struct nft_flowtable *nf_tables_flowtable_lookup(const struct nft_table *table, |
| @@ -4752,6 +4850,20 @@ struct nft_flowtable *nf_tables_flowtable_lookup(const struct nft_table *table, · 11 unmodified lines |
| 4752 | 4850 | } |
| 4753 | 4851 | EXPORT_SYMBOL_GPL(nf_tables_flowtable_lookup); |
| 4754 | 4852 | |
| 4853 | +struct nft_flowtable * |
| 4854 | +nf_tables_flowtable_lookup_byhandle(const struct nft_table *table, |
| 4855 | + const struct nlattr *nla, u8 genmask) |
| 4856 | +{ |
| 4857 | + struct nft_flowtable *flowtable; |
| 4858 | + |
| 4859 | + list_for_each_entry(flowtable, &table->flowtables, list) { |
| 4860 | + if (be64_to_cpu(nla_get_be64(nla)) == flowtable->handle && |
| 4861 | + nft_active_genmask(flowtable, genmask)) |
| 4862 | + return flowtable; |
| 4863 | + } |
| 4864 | + return ERR_PTR(-ENOENT); |
| 4865 | +} |
| 4866 | + |
| 4755 | 4867 | #define NFT_FLOWTABLE_DEVICE_MAX 8 |
| 4756 | 4868 | |
| 4757 | 4869 | static int nf_tables_parse_devices(const struct nft_ctx *ctx, |
| @@ -4960,6 +5072,8 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk, · 202 unmodified lines |
| 4960 | 5072 | return -ENOMEM; |
| 4961 | 5073 | |
| 4962 | 5074 | flowtable->table = table; |
| 5075 | + flowtable->handle = nf_tables_alloc_handle(table); |
| 5076 | + |
| 4963 | 5077 | flowtable->name = nla_strdup(nla[NFTA_FLOWTABLE_NAME], GFP_KERNEL); |
| 4964 | 5078 | if (!flowtable->name) { |
| 4965 | 5079 | err = -ENOMEM; |
| @@ -5034,8 +5148,14 @@ static int nf_tables_delflowtable(struct net *net, struct sock *nlsk, · 68 unmodified lines |
| 5034 | 5148 | if (IS_ERR(table)) |
| 5035 | 5149 | return PTR_ERR(table); |
| 5036 | 5150 | |
| 5037 | | − flowtable = nf_tables_flowtable_lookup(table, nla[NFTA_FLOWTABLE_NAME], |
| 5038 | | − genmask); |
| 5151 | + if (nla[NFTA_FLOWTABLE_HANDLE]) |
| 5152 | + flowtable = nf_tables_flowtable_lookup_byhandle(table, |
| 5153 | + nla[NFTA_FLOWTABLE_HANDLE], |
| 5154 | + genmask); |
| 5155 | + else |
| 5156 | + flowtable = nf_tables_flowtable_lookup(table, |
| 5157 | + nla[NFTA_FLOWTABLE_NAME], |
| 5158 | + genmask); |
| 5039 | 5159 | if (IS_ERR(flowtable)) |
| 5040 | 5160 | return PTR_ERR(flowtable); |
| 5041 | 5161 | if (flowtable->use > 0) |
| @@ -5068,7 +5188,9 @@ static int nf_tables_fill_flowtable_info(struct sk_buff *skb, struct net *net, · 26 unmodified lines |
| 5068 | 5188 | |
| 5069 | 5189 | if (nla_put_string(skb, NFTA_FLOWTABLE_TABLE, flowtable->table->name) || |
| 5070 | 5190 | nla_put_string(skb, NFTA_FLOWTABLE_NAME, flowtable->name) || |
| 5071 | | − nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use))) |
| 5191 | + nla_put_be32(skb, NFTA_FLOWTABLE_USE, htonl(flowtable->use)) || |
| 5192 | + nla_put_be64(skb, NFTA_FLOWTABLE_HANDLE, cpu_to_be64(flowtable->handle), |
| 5193 | + NFTA_FLOWTABLE_PAD)) |
| 5072 | 5194 | goto nla_put_failure; |
| 5073 | 5195 | |
| 5074 | 5196 | nest = nla_nest_start(skb, NFTA_FLOWTABLE_HOOK); |