aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2014-07-16 11:35:18 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2014-07-22 06:08:54 -0400
commit5b96af7713546fca812682fed13cfad26d69fed7 (patch)
tree78d218088b6a2b8cf2db2f0d37d7f6d594f79e7e
parent85f5b3086a04c459f9147859fcbf7bdc7578c378 (diff)
netfilter: nf_tables: simplify set dump through netlink
This patch uses the cb->data pointer that allows us to store the context when dumping the set list. Thus, we don't need to parse the original netlink message containing the dump request for each recvmsg() call when dumping the set list. The different function flavours depending on the dump criteria has been also merged into one single generic function. This saves us ~100 lines of code. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--net/netfilter/nf_tables_api.c131
1 files changed, 27 insertions, 104 deletions
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 8746ff9a8357..ecffb26e2f20 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -2247,80 +2247,7 @@ err:
2247 return err; 2247 return err;
2248} 2248}
2249 2249
2250static int nf_tables_dump_sets_table(struct nft_ctx *ctx, struct sk_buff *skb, 2250static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
2251 struct netlink_callback *cb)
2252{
2253 const struct nft_set *set;
2254 unsigned int idx = 0, s_idx = cb->args[0];
2255
2256 if (cb->args[1])
2257 return skb->len;
2258
2259 rcu_read_lock();
2260 cb->seq = ctx->net->nft.base_seq;
2261
2262 list_for_each_entry_rcu(set, &ctx->table->sets, list) {
2263 if (idx < s_idx)
2264 goto cont;
2265 if (nf_tables_fill_set(skb, ctx, set, NFT_MSG_NEWSET,
2266 NLM_F_MULTI) < 0) {
2267 cb->args[0] = idx;
2268 goto done;
2269 }
2270 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
2271cont:
2272 idx++;
2273 }
2274 cb->args[1] = 1;
2275done:
2276 rcu_read_unlock();
2277 return skb->len;
2278}
2279
2280static int nf_tables_dump_sets_family(struct nft_ctx *ctx, struct sk_buff *skb,
2281 struct netlink_callback *cb)
2282{
2283 const struct nft_set *set;
2284 unsigned int idx, s_idx = cb->args[0];
2285 struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2];
2286
2287 if (cb->args[1])
2288 return skb->len;
2289
2290 rcu_read_lock();
2291 cb->seq = ctx->net->nft.base_seq;
2292
2293 list_for_each_entry_rcu(table, &ctx->afi->tables, list) {
2294 if (cur_table) {
2295 if (cur_table != table)
2296 continue;
2297
2298 cur_table = NULL;
2299 }
2300 ctx->table = table;
2301 idx = 0;
2302 list_for_each_entry_rcu(set, &ctx->table->sets, list) {
2303 if (idx < s_idx)
2304 goto cont;
2305 if (nf_tables_fill_set(skb, ctx, set, NFT_MSG_NEWSET,
2306 NLM_F_MULTI) < 0) {
2307 cb->args[0] = idx;
2308 cb->args[2] = (unsigned long) table;
2309 goto done;
2310 }
2311 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
2312cont:
2313 idx++;
2314 }
2315 }
2316 cb->args[1] = 1;
2317done:
2318 rcu_read_unlock();
2319 return skb->len;
2320}
2321
2322static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
2323 struct netlink_callback *cb)
2324{ 2251{
2325 const struct nft_set *set; 2252 const struct nft_set *set;
2326 unsigned int idx, s_idx = cb->args[0]; 2253 unsigned int idx, s_idx = cb->args[0];
@@ -2328,6 +2255,7 @@ static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
2328 struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2]; 2255 struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2];
2329 struct net *net = sock_net(skb->sk); 2256 struct net *net = sock_net(skb->sk);
2330 int cur_family = cb->args[3]; 2257 int cur_family = cb->args[3];
2258 struct nft_ctx *ctx = cb->data, ctx_set;
2331 2259
2332 if (cb->args[1]) 2260 if (cb->args[1])
2333 return skb->len; 2261 return skb->len;
@@ -2336,28 +2264,34 @@ static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
2336 cb->seq = net->nft.base_seq; 2264 cb->seq = net->nft.base_seq;
2337 2265
2338 list_for_each_entry_rcu(afi, &net->nft.af_info, list) { 2266 list_for_each_entry_rcu(afi, &net->nft.af_info, list) {
2267 if (ctx->afi && ctx->afi != afi)
2268 continue;
2269
2339 if (cur_family) { 2270 if (cur_family) {
2340 if (afi->family != cur_family) 2271 if (afi->family != cur_family)
2341 continue; 2272 continue;
2342 2273
2343 cur_family = 0; 2274 cur_family = 0;
2344 } 2275 }
2345
2346 list_for_each_entry_rcu(table, &afi->tables, list) { 2276 list_for_each_entry_rcu(table, &afi->tables, list) {
2277 if (ctx->table && ctx->table != table)
2278 continue;
2279
2347 if (cur_table) { 2280 if (cur_table) {
2348 if (cur_table != table) 2281 if (cur_table != table)
2349 continue; 2282 continue;
2350 2283
2351 cur_table = NULL; 2284 cur_table = NULL;
2352 } 2285 }
2353
2354 ctx->table = table;
2355 ctx->afi = afi;
2356 idx = 0; 2286 idx = 0;
2357 list_for_each_entry_rcu(set, &ctx->table->sets, list) { 2287 list_for_each_entry_rcu(set, &table->sets, list) {
2358 if (idx < s_idx) 2288 if (idx < s_idx)
2359 goto cont; 2289 goto cont;
2360 if (nf_tables_fill_set(skb, ctx, set, 2290
2291 ctx_set = *ctx;
2292 ctx_set.table = table;
2293 ctx_set.afi = afi;
2294 if (nf_tables_fill_set(skb, &ctx_set, set,
2361 NFT_MSG_NEWSET, 2295 NFT_MSG_NEWSET,
2362 NLM_F_MULTI) < 0) { 2296 NLM_F_MULTI) < 0) {
2363 cb->args[0] = idx; 2297 cb->args[0] = idx;
@@ -2379,31 +2313,10 @@ done:
2379 return skb->len; 2313 return skb->len;
2380} 2314}
2381 2315
2382static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb) 2316static int nf_tables_dump_sets_done(struct netlink_callback *cb)
2383{ 2317{
2384 const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); 2318 kfree(cb->data);
2385 struct nlattr *nla[NFTA_SET_MAX + 1]; 2319 return 0;
2386 struct nft_ctx ctx;
2387 int err, ret;
2388
2389 err = nlmsg_parse(cb->nlh, sizeof(*nfmsg), nla, NFTA_SET_MAX,
2390 nft_set_policy);
2391 if (err < 0)
2392 return err;
2393
2394 err = nft_ctx_init_from_setattr(&ctx, cb->skb, cb->nlh, (void *)nla);
2395 if (err < 0)
2396 return err;
2397
2398 if (ctx.table == NULL) {
2399 if (ctx.afi == NULL)
2400 ret = nf_tables_dump_sets_all(&ctx, skb, cb);
2401 else
2402 ret = nf_tables_dump_sets_family(&ctx, skb, cb);
2403 } else
2404 ret = nf_tables_dump_sets_table(&ctx, skb, cb);
2405
2406 return ret;
2407} 2320}
2408 2321
2409#define NFT_SET_INACTIVE (1 << 15) /* Internal set flag */ 2322#define NFT_SET_INACTIVE (1 << 15) /* Internal set flag */
@@ -2426,7 +2339,17 @@ static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb,
2426 if (nlh->nlmsg_flags & NLM_F_DUMP) { 2339 if (nlh->nlmsg_flags & NLM_F_DUMP) {
2427 struct netlink_dump_control c = { 2340 struct netlink_dump_control c = {
2428 .dump = nf_tables_dump_sets, 2341 .dump = nf_tables_dump_sets,
2342 .done = nf_tables_dump_sets_done,
2429 }; 2343 };
2344 struct nft_ctx *ctx_dump;
2345
2346 ctx_dump = kmalloc(sizeof(*ctx_dump), GFP_KERNEL);
2347 if (ctx_dump == NULL)
2348 return -ENOMEM;
2349
2350 *ctx_dump = ctx;
2351 c.data = ctx_dump;
2352
2430 return netlink_dump_start(nlsk, skb, nlh, &c); 2353 return netlink_dump_start(nlsk, skb, nlh, &c);
2431 } 2354 }
2432 2355