Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 78d9f48

Browse files
committed
netfilter: nf_tables: add devices to existing flowtable
This patch allows users to add devices to an existing flowtable. Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent c42d8bd commit 78d9f48

File tree

2 files changed

+92
-11
lines changed

2 files changed

+92
-11
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,10 +1481,16 @@ struct nft_trans_obj {
14811481

14821482
struct nft_trans_flowtable {
14831483
struct nft_flowtable *flowtable;
1484+
bool update;
1485+
struct list_head hook_list;
14841486
};
14851487

14861488
#define nft_trans_flowtable(trans) \
14871489
(((struct nft_trans_flowtable *)trans->data)->flowtable)
1490+
#define nft_trans_flowtable_update(trans) \
1491+
(((struct nft_trans_flowtable *)trans->data)->update)
1492+
#define nft_trans_flowtable_hooks(trans) \
1493+
(((struct nft_trans_flowtable *)trans->data)->hook_list)
14881494

14891495
int __init nft_chain_filter_init(void);
14901496
void nft_chain_filter_fini(void);

net/netfilter/nf_tables_api.c

Lines changed: 86 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6349,6 +6349,62 @@ static void nft_flowtable_hooks_destroy(struct list_head *hook_list)
63496349
}
63506350
}
63516351

6352+
static int nft_flowtable_update(struct nft_ctx *ctx, const struct nlmsghdr *nlh,
6353+
struct nft_flowtable *flowtable)
6354+
{
6355+
const struct nlattr * const *nla = ctx->nla;
6356+
struct nft_flowtable_hook flowtable_hook;
6357+
struct nft_hook *hook, *next;
6358+
struct nft_trans *trans;
6359+
bool unregister = false;
6360+
int err;
6361+
6362+
err = nft_flowtable_parse_hook(ctx, nla[NFTA_FLOWTABLE_HOOK],
6363+
&flowtable_hook, &flowtable->data);
6364+
if (err < 0)
6365+
return err;
6366+
6367+
list_for_each_entry_safe(hook, next, &flowtable_hook.list, list) {
6368+
if (nft_hook_list_find(&flowtable->hook_list, hook)) {
6369+
list_del(&hook->list);
6370+
kfree(hook);
6371+
}
6372+
}
6373+
6374+
err = nft_register_flowtable_net_hooks(ctx->net, ctx->table,
6375+
&flowtable_hook.list, flowtable);
6376+
if (err < 0)
6377+
goto err_flowtable_update_hook;
6378+
6379+
trans = nft_trans_alloc(ctx, NFT_MSG_NEWFLOWTABLE,
6380+
sizeof(struct nft_trans_flowtable));
6381+
if (!trans) {
6382+
unregister = true;
6383+
err = -ENOMEM;
6384+
goto err_flowtable_update_hook;
6385+
}
6386+
6387+
nft_trans_flowtable(trans) = flowtable;
6388+
nft_trans_flowtable_update(trans) = true;
6389+
INIT_LIST_HEAD(&nft_trans_flowtable_hooks(trans));
6390+
list_splice(&flowtable_hook.list, &nft_trans_flowtable_hooks(trans));
6391+
6392+
list_add_tail(&trans->list, &ctx->net->nft.commit_list);
6393+
6394+
return 0;
6395+
6396+
err_flowtable_update_hook:
6397+
list_for_each_entry_safe(hook, next, &flowtable_hook.list, list) {
6398+
if (unregister)
6399+
nft_unregister_flowtable_hook(ctx->net, flowtable, hook);
6400+
list_del_rcu(&hook->list);
6401+
kfree_rcu(hook, rcu);
6402+
}
6403+
6404+
return err;
6405+
6406+
}
6407+
63526408
static int nf_tables_newflowtable(struct net *net, struct sock *nlsk,
63536409
struct sk_buff *skb,
63546410
const struct nlmsghdr *nlh,
@@ -6392,7 +6448,9 @@ static int nf_tables_newflowtable(struct net *net, struct sock *nlsk,
63926448
return -EEXIST;
63936449
}
63946450

6395-
return 0;
6451+
nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
6452+
6453+
return nft_flowtable_update(&ctx, nlh, flowtable);
63966454
}
63976455

63986456
nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
@@ -7495,11 +7553,20 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
74957553
NFT_MSG_DELOBJ);
74967554
break;
74977555
case NFT_MSG_NEWFLOWTABLE:
7498-
nft_clear(net, nft_trans_flowtable(trans));
7499-
nf_tables_flowtable_notify(&trans->ctx,
7500-
nft_trans_flowtable(trans),
7501-
&nft_trans_flowtable(trans)->hook_list,
7502-
NFT_MSG_NEWFLOWTABLE);
7556+
if (nft_trans_flowtable_update(trans)) {
7557+
nf_tables_flowtable_notify(&trans->ctx,
7558+
nft_trans_flowtable(trans),
7559+
&nft_trans_flowtable_hooks(trans),
7560+
NFT_MSG_NEWFLOWTABLE);
7561+
list_splice(&nft_trans_flowtable_hooks(trans),
7562+
&nft_trans_flowtable(trans)->hook_list);
7563+
} else {
7564+
nft_clear(net, nft_trans_flowtable(trans));
7565+
nf_tables_flowtable_notify(&trans->ctx,
7566+
nft_trans_flowtable(trans),
7567+
&nft_trans_flowtable(trans)->hook_list,
7568+
NFT_MSG_NEWFLOWTABLE);
7569+
}
75037570
nft_trans_destroy(trans);
75047571
break;
75057572
case NFT_MSG_DELFLOWTABLE:
@@ -7558,7 +7625,10 @@ static void nf_tables_abort_release(struct nft_trans *trans)
75587625
nft_obj_destroy(&trans->ctx, nft_trans_obj(trans));
75597626
break;
75607627
case NFT_MSG_NEWFLOWTABLE:
7561-
nf_tables_flowtable_destroy(nft_trans_flowtable(trans));
7628+
if (nft_trans_flowtable_update(trans))
7629+
nft_flowtable_hooks_destroy(&nft_trans_flowtable_hooks(trans));
7630+
else
7631+
nf_tables_flowtable_destroy(nft_trans_flowtable(trans));
75627632
break;
75637633
}
75647634
kfree(trans);
@@ -7665,10 +7735,15 @@ static int __nf_tables_abort(struct net *net, bool autoload)
76657735
nft_trans_destroy(trans);
76667736
break;
76677737
case NFT_MSG_NEWFLOWTABLE:
7668-
trans->ctx.table->use--;
7669-
list_del_rcu(&nft_trans_flowtable(trans)->list);
7670-
nft_unregister_flowtable_net_hooks(net,
7671-
&nft_trans_flowtable(trans)->hook_list);
7738+
if (nft_trans_flowtable_update(trans)) {
7739+
nft_unregister_flowtable_net_hooks(net,
7740+
&nft_trans_flowtable_hooks(trans));
7741+
} else {
7742+
trans->ctx.table->use--;
7743+
list_del_rcu(&nft_trans_flowtable(trans)->list);
7744+
nft_unregister_flowtable_net_hooks(net,
7745+
&nft_trans_flowtable(trans)->hook_list);
7746+
}
76727747
break;
76737748
case NFT_MSG_DELFLOWTABLE:
76747749
trans->ctx.table->use++;

0 commit comments

Comments
 (0)