Commit d152159b authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso

netfilter: nf_tables: prepare nft_object for lookups via hashtable

Add a 'key' structure for object, so we can look them up by name + table
combination (the name can be the same in each table).
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 435f3f26
...@@ -1011,12 +1011,22 @@ void nft_unregister_expr(struct nft_expr_type *); ...@@ -1011,12 +1011,22 @@ void nft_unregister_expr(struct nft_expr_type *);
int nft_verdict_dump(struct sk_buff *skb, int type, int nft_verdict_dump(struct sk_buff *skb, int type,
const struct nft_verdict *v); const struct nft_verdict *v);
/**
* struct nft_object_hash_key - key to lookup nft_object
*
* @name: name of the stateful object to look up
* @table: table the object belongs to
*/
struct nft_object_hash_key {
const char *name;
const struct nft_table *table;
};
/** /**
* struct nft_object - nf_tables stateful object * struct nft_object - nf_tables stateful object
* *
* @list: table stateful object list node * @list: table stateful object list node
* @table: table this object belongs to * @key: keys that identify this object
* @name: name of this stateful object
* @genmask: generation mask * @genmask: generation mask
* @use: number of references to this stateful object * @use: number of references to this stateful object
* @handle: unique object handle * @handle: unique object handle
...@@ -1025,8 +1035,7 @@ int nft_verdict_dump(struct sk_buff *skb, int type, ...@@ -1025,8 +1035,7 @@ int nft_verdict_dump(struct sk_buff *skb, int type,
*/ */
struct nft_object { struct nft_object {
struct list_head list; struct list_head list;
char *name; struct nft_object_hash_key key;
struct nft_table *table;
u32 genmask:2, u32 genmask:2,
use:30; use:30;
u64 handle; u64 handle;
...@@ -1047,7 +1056,7 @@ struct nft_object *nft_obj_lookup(const struct nft_table *table, ...@@ -1047,7 +1056,7 @@ struct nft_object *nft_obj_lookup(const struct nft_table *table,
const struct nlattr *nla, u32 objtype, const struct nlattr *nla, u32 objtype,
u8 genmask); u8 genmask);
void nft_obj_notify(struct net *net, struct nft_table *table, void nft_obj_notify(struct net *net, const struct nft_table *table,
struct nft_object *obj, u32 portid, u32 seq, struct nft_object *obj, u32 portid, u32 seq,
int event, int family, int report, gfp_t gfp); int event, int family, int report, gfp_t gfp);
......
...@@ -3853,7 +3853,7 @@ static int nf_tables_fill_setelem(struct sk_buff *skb, ...@@ -3853,7 +3853,7 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) && if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF) &&
nla_put_string(skb, NFTA_SET_ELEM_OBJREF, nla_put_string(skb, NFTA_SET_ELEM_OBJREF,
(*nft_set_ext_obj(ext))->name) < 0) (*nft_set_ext_obj(ext))->key.name) < 0)
goto nla_put_failure; goto nla_put_failure;
if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) && if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) &&
...@@ -4826,7 +4826,7 @@ struct nft_object *nft_obj_lookup(const struct nft_table *table, ...@@ -4826,7 +4826,7 @@ struct nft_object *nft_obj_lookup(const struct nft_table *table,
struct nft_object *obj; struct nft_object *obj;
list_for_each_entry_rcu(obj, &table->objects, list) { list_for_each_entry_rcu(obj, &table->objects, list) {
if (!nla_strcmp(nla, obj->name) && if (!nla_strcmp(nla, obj->key.name) &&
objtype == obj->ops->type->type && objtype == obj->ops->type->type &&
nft_active_genmask(obj, genmask)) nft_active_genmask(obj, genmask))
return obj; return obj;
...@@ -5014,11 +5014,11 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk, ...@@ -5014,11 +5014,11 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
err = PTR_ERR(obj); err = PTR_ERR(obj);
goto err1; goto err1;
} }
obj->table = table; obj->key.table = table;
obj->handle = nf_tables_alloc_handle(table); obj->handle = nf_tables_alloc_handle(table);
obj->name = nla_strdup(nla[NFTA_OBJ_NAME], GFP_KERNEL); obj->key.name = nla_strdup(nla[NFTA_OBJ_NAME], GFP_KERNEL);
if (!obj->name) { if (!obj->key.name) {
err = -ENOMEM; err = -ENOMEM;
goto err2; goto err2;
} }
...@@ -5031,7 +5031,7 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk, ...@@ -5031,7 +5031,7 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
table->use++; table->use++;
return 0; return 0;
err3: err3:
kfree(obj->name); kfree(obj->key.name);
err2: err2:
if (obj->ops->destroy) if (obj->ops->destroy)
obj->ops->destroy(&ctx, obj); obj->ops->destroy(&ctx, obj);
...@@ -5060,7 +5060,7 @@ static int nf_tables_fill_obj_info(struct sk_buff *skb, struct net *net, ...@@ -5060,7 +5060,7 @@ static int nf_tables_fill_obj_info(struct sk_buff *skb, struct net *net,
nfmsg->res_id = htons(net->nft.base_seq & 0xffff); nfmsg->res_id = htons(net->nft.base_seq & 0xffff);
if (nla_put_string(skb, NFTA_OBJ_TABLE, table->name) || if (nla_put_string(skb, NFTA_OBJ_TABLE, table->name) ||
nla_put_string(skb, NFTA_OBJ_NAME, obj->name) || nla_put_string(skb, NFTA_OBJ_NAME, obj->key.name) ||
nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) || nla_put_be32(skb, NFTA_OBJ_TYPE, htonl(obj->ops->type->type)) ||
nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) || nla_put_be32(skb, NFTA_OBJ_USE, htonl(obj->use)) ||
nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset) || nft_object_dump(skb, NFTA_OBJ_DATA, obj, reset) ||
...@@ -5246,7 +5246,7 @@ static void nft_obj_destroy(const struct nft_ctx *ctx, struct nft_object *obj) ...@@ -5246,7 +5246,7 @@ static void nft_obj_destroy(const struct nft_ctx *ctx, struct nft_object *obj)
obj->ops->destroy(ctx, obj); obj->ops->destroy(ctx, obj);
module_put(obj->ops->type->owner); module_put(obj->ops->type->owner);
kfree(obj->name); kfree(obj->key.name);
kfree(obj); kfree(obj);
} }
...@@ -5297,7 +5297,7 @@ static int nf_tables_delobj(struct net *net, struct sock *nlsk, ...@@ -5297,7 +5297,7 @@ static int nf_tables_delobj(struct net *net, struct sock *nlsk,
return nft_delobj(&ctx, obj); return nft_delobj(&ctx, obj);
} }
void nft_obj_notify(struct net *net, struct nft_table *table, void nft_obj_notify(struct net *net, const struct nft_table *table,
struct nft_object *obj, u32 portid, u32 seq, int event, struct nft_object *obj, u32 portid, u32 seq, int event,
int family, int report, gfp_t gfp) int family, int report, gfp_t gfp)
{ {
...@@ -6404,6 +6404,11 @@ static void nf_tables_commit_chain(struct net *net, struct nft_chain *chain) ...@@ -6404,6 +6404,11 @@ static void nf_tables_commit_chain(struct net *net, struct nft_chain *chain)
nf_tables_commit_chain_free_rules_old(g0); nf_tables_commit_chain_free_rules_old(g0);
} }
static void nft_obj_del(struct nft_object *obj)
{
list_del_rcu(&obj->list);
}
static void nft_chain_del(struct nft_chain *chain) static void nft_chain_del(struct nft_chain *chain)
{ {
struct nft_table *table = chain->table; struct nft_table *table = chain->table;
...@@ -6580,7 +6585,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) ...@@ -6580,7 +6585,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
nft_trans_destroy(trans); nft_trans_destroy(trans);
break; break;
case NFT_MSG_DELOBJ: case NFT_MSG_DELOBJ:
list_del_rcu(&nft_trans_obj(trans)->list); nft_obj_del(nft_trans_obj(trans));
nf_tables_obj_notify(&trans->ctx, nft_trans_obj(trans), nf_tables_obj_notify(&trans->ctx, nft_trans_obj(trans),
NFT_MSG_DELOBJ); NFT_MSG_DELOBJ);
break; break;
...@@ -7330,7 +7335,7 @@ static void __nft_release_tables(struct net *net) ...@@ -7330,7 +7335,7 @@ static void __nft_release_tables(struct net *net)
nft_set_destroy(set); nft_set_destroy(set);
} }
list_for_each_entry_safe(obj, ne, &table->objects, list) { list_for_each_entry_safe(obj, ne, &table->objects, list) {
list_del(&obj->list); nft_obj_del(obj);
table->use--; table->use--;
nft_obj_destroy(&ctx, obj); nft_obj_destroy(&ctx, obj);
} }
......
...@@ -53,7 +53,7 @@ static int nft_objref_dump(struct sk_buff *skb, const struct nft_expr *expr) ...@@ -53,7 +53,7 @@ static int nft_objref_dump(struct sk_buff *skb, const struct nft_expr *expr)
{ {
const struct nft_object *obj = nft_objref_priv(expr); const struct nft_object *obj = nft_objref_priv(expr);
if (nla_put_string(skb, NFTA_OBJREF_IMM_NAME, obj->name) || if (nla_put_string(skb, NFTA_OBJREF_IMM_NAME, obj->key.name) ||
nla_put_be32(skb, NFTA_OBJREF_IMM_TYPE, nla_put_be32(skb, NFTA_OBJREF_IMM_TYPE,
htonl(obj->ops->type->type))) htonl(obj->ops->type->type)))
goto nla_put_failure; goto nla_put_failure;
......
...@@ -61,7 +61,7 @@ static void nft_quota_obj_eval(struct nft_object *obj, ...@@ -61,7 +61,7 @@ static void nft_quota_obj_eval(struct nft_object *obj,
if (overquota && if (overquota &&
!test_and_set_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags)) !test_and_set_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags))
nft_obj_notify(nft_net(pkt), obj->table, obj, 0, 0, nft_obj_notify(nft_net(pkt), obj->key.table, obj, 0, 0,
NFT_MSG_NEWOBJ, nft_pf(pkt), 0, GFP_ATOMIC); NFT_MSG_NEWOBJ, nft_pf(pkt), 0, GFP_ATOMIC);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment