netfilter: nf_tables: allow to filter stateful object dumps by type

This patch adds the netlink code to filter out dump of stateful objects,
through the NFTA_OBJ_TYPE netlink attribute.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Pablo Neira Ayuso 2016-11-28 00:06:11 +01:00
Родитель 63aea29060
Коммит a9fea2a3c3
1 изменённых файлов: 50 добавлений и 0 удалений

Просмотреть файл

@ -4183,12 +4183,18 @@ nla_put_failure:
return -1; return -1;
} }
struct nft_obj_filter {
char table[NFT_OBJ_MAXNAMELEN];
u32 type;
};
static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb) static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
{ {
const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
const struct nft_af_info *afi; const struct nft_af_info *afi;
const struct nft_table *table; const struct nft_table *table;
unsigned int idx = 0, s_idx = cb->args[0]; unsigned int idx = 0, s_idx = cb->args[0];
struct nft_obj_filter *filter = cb->data;
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
int family = nfmsg->nfgen_family; int family = nfmsg->nfgen_family;
struct nft_object *obj; struct nft_object *obj;
@ -4213,6 +4219,13 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
if (idx > s_idx) if (idx > s_idx)
memset(&cb->args[1], 0, memset(&cb->args[1], 0,
sizeof(cb->args) - sizeof(cb->args[0])); sizeof(cb->args) - sizeof(cb->args[0]));
if (filter->table[0] &&
strcmp(filter->table, table->name))
goto cont;
if (filter->type != NFT_OBJECT_UNSPEC &&
obj->type->type != filter->type)
goto cont;
if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid, if (nf_tables_fill_obj_info(skb, net, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, cb->nlh->nlmsg_seq,
NFT_MSG_NEWOBJ, NFT_MSG_NEWOBJ,
@ -4233,6 +4246,31 @@ done:
return skb->len; return skb->len;
} }
static int nf_tables_dump_obj_done(struct netlink_callback *cb)
{
kfree(cb->data);
return 0;
}
static struct nft_obj_filter *
nft_obj_filter_alloc(const struct nlattr * const nla[])
{
struct nft_obj_filter *filter;
filter = kzalloc(sizeof(*filter), GFP_KERNEL);
if (!filter)
return ERR_PTR(-ENOMEM);
if (nla[NFTA_OBJ_TABLE])
nla_strlcpy(filter->table, nla[NFTA_OBJ_TABLE],
NFT_TABLE_MAXNAMELEN);
if (nla[NFTA_OBJ_TYPE])
filter->type = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
return filter;
}
static int nf_tables_getobj(struct net *net, struct sock *nlsk, static int nf_tables_getobj(struct net *net, struct sock *nlsk,
struct sk_buff *skb, const struct nlmsghdr *nlh, struct sk_buff *skb, const struct nlmsghdr *nlh,
const struct nlattr * const nla[]) const struct nlattr * const nla[])
@ -4251,7 +4289,19 @@ static int nf_tables_getobj(struct net *net, struct sock *nlsk,
if (nlh->nlmsg_flags & NLM_F_DUMP) { if (nlh->nlmsg_flags & NLM_F_DUMP) {
struct netlink_dump_control c = { struct netlink_dump_control c = {
.dump = nf_tables_dump_obj, .dump = nf_tables_dump_obj,
.done = nf_tables_dump_obj_done,
}; };
if (nla[NFTA_OBJ_TABLE] ||
nla[NFTA_OBJ_TYPE]) {
struct nft_obj_filter *filter;
filter = nft_obj_filter_alloc(nla);
if (IS_ERR(filter))
return -ENOMEM;
c.data = filter;
}
return netlink_dump_start(nlsk, skb, nlh, &c); return netlink_dump_start(nlsk, skb, nlh, &c);
} }