aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlabel/netlabel_domainhash.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/netlabel/netlabel_domainhash.c')
-rw-r--r--net/netlabel/netlabel_domainhash.c183
1 files changed, 37 insertions, 146 deletions
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c
index 0489a1378101..f56d7a8ac7b7 100644
--- a/net/netlabel/netlabel_domainhash.c
+++ b/net/netlabel/netlabel_domainhash.c
@@ -354,160 +354,51 @@ struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain)
354} 354}
355 355
356/** 356/**
357 * netlbl_domhsh_dump - Dump the domain hash table into a sk_buff 357 * netlbl_domhsh_walk - Iterate through the domain mapping hash table
358 * @skip_bkt: the number of buckets to skip at the start
359 * @skip_chain: the number of entries to skip in the first iterated bucket
360 * @callback: callback for each entry
361 * @cb_arg: argument for the callback function
358 * 362 *
359 * Description: 363 * Description:
360 * Dump the domain hash table into a buffer suitable for returning to an 364 * Interate over the domain mapping hash table, skipping the first @skip_bkt
361 * application in response to a NetLabel management DOMAIN message. This 365 * buckets and @skip_chain entries. For each entry in the table call
362 * function may fail if another process is growing the hash table at the same 366 * @callback, if @callback returns a negative value stop 'walking' through the
363 * time. The returned sk_buff has room at the front of the sk_buff for 367 * table and return. Updates the values in @skip_bkt and @skip_chain on
364 * @headroom bytes. See netlabel.h for the DOMAIN message format. Returns a 368 * return. Returns zero on succcess, negative values on failure.
365 * pointer to a sk_buff on success, NULL on error.
366 * 369 *
367 */ 370 */
368struct sk_buff *netlbl_domhsh_dump(size_t headroom) 371int netlbl_domhsh_walk(u32 *skip_bkt,
372 u32 *skip_chain,
373 int (*callback) (struct netlbl_dom_map *entry, void *arg),
374 void *cb_arg)
369{ 375{
370 struct sk_buff *skb = NULL; 376 int ret_val = -ENOENT;
371 ssize_t buf_len; 377 u32 iter_bkt;
372 u32 bkt_iter; 378 struct netlbl_dom_map *iter_entry;
373 u32 dom_cnt = 0; 379 u32 chain_cnt = 0;
374 struct netlbl_domhsh_tbl *hsh_tbl;
375 struct netlbl_dom_map *list_iter;
376 ssize_t tmp_len;
377 380
378 buf_len = NETLBL_LEN_U32;
379 rcu_read_lock(); 381 rcu_read_lock();
380 hsh_tbl = rcu_dereference(netlbl_domhsh); 382 for (iter_bkt = *skip_bkt;
381 for (bkt_iter = 0; bkt_iter < hsh_tbl->size; bkt_iter++) 383 iter_bkt < rcu_dereference(netlbl_domhsh)->size;
382 list_for_each_entry_rcu(list_iter, 384 iter_bkt++, chain_cnt = 0) {
383 &hsh_tbl->tbl[bkt_iter], list) { 385 list_for_each_entry_rcu(iter_entry,
384 buf_len += NETLBL_LEN_U32 + 386 &netlbl_domhsh->tbl[iter_bkt],
385 nla_total_size(strlen(list_iter->domain) + 1); 387 list)
386 switch (list_iter->type) { 388 if (iter_entry->valid) {
387 case NETLBL_NLTYPE_UNLABELED: 389 if (chain_cnt++ < *skip_chain)
388 break; 390 continue;
389 case NETLBL_NLTYPE_CIPSOV4: 391 ret_val = callback(iter_entry, cb_arg);
390 buf_len += 2 * NETLBL_LEN_U32; 392 if (ret_val < 0) {
391 break; 393 chain_cnt--;
392 } 394 goto walk_return;
393 dom_cnt++; 395 }
394 }
395
396 skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC);
397 if (skb == NULL)
398 goto dump_failure;
399
400 if (nla_put_u32(skb, NLA_U32, dom_cnt) != 0)
401 goto dump_failure;
402 buf_len -= NETLBL_LEN_U32;
403 hsh_tbl = rcu_dereference(netlbl_domhsh);
404 for (bkt_iter = 0; bkt_iter < hsh_tbl->size; bkt_iter++)
405 list_for_each_entry_rcu(list_iter,
406 &hsh_tbl->tbl[bkt_iter], list) {
407 tmp_len = nla_total_size(strlen(list_iter->domain) +
408 1);
409 if (buf_len < NETLBL_LEN_U32 + tmp_len)
410 goto dump_failure;
411 if (nla_put_string(skb,
412 NLA_STRING,
413 list_iter->domain) != 0)
414 goto dump_failure;
415 if (nla_put_u32(skb, NLA_U32, list_iter->type) != 0)
416 goto dump_failure;
417 buf_len -= NETLBL_LEN_U32 + tmp_len;
418 switch (list_iter->type) {
419 case NETLBL_NLTYPE_UNLABELED:
420 break;
421 case NETLBL_NLTYPE_CIPSOV4:
422 if (buf_len < 2 * NETLBL_LEN_U32)
423 goto dump_failure;
424 if (nla_put_u32(skb,
425 NLA_U32,
426 list_iter->type_def.cipsov4->type) != 0)
427 goto dump_failure;
428 if (nla_put_u32(skb,
429 NLA_U32,
430 list_iter->type_def.cipsov4->doi) != 0)
431 goto dump_failure;
432 buf_len -= 2 * NETLBL_LEN_U32;
433 break;
434 } 396 }
435 } 397 }
436 rcu_read_unlock();
437
438 return skb;
439
440dump_failure:
441 rcu_read_unlock();
442 kfree_skb(skb);
443 return NULL;
444}
445
446/**
447 * netlbl_domhsh_dump_default - Dump the default domain mapping into a sk_buff
448 *
449 * Description:
450 * Dump the default domain mapping into a buffer suitable for returning to an
451 * application in response to a NetLabel management DEFDOMAIN message. This
452 * function may fail if another process is changing the default domain mapping
453 * at the same time. The returned sk_buff has room at the front of the
454 * skb_buff for @headroom bytes. See netlabel.h for the DEFDOMAIN message
455 * format. Returns a pointer to a sk_buff on success, NULL on error.
456 *
457 */
458struct sk_buff *netlbl_domhsh_dump_default(size_t headroom)
459{
460 struct sk_buff *skb;
461 ssize_t buf_len;
462 struct netlbl_dom_map *entry;
463
464 buf_len = NETLBL_LEN_U32;
465 rcu_read_lock();
466 entry = rcu_dereference(netlbl_domhsh_def);
467 if (entry != NULL)
468 switch (entry->type) {
469 case NETLBL_NLTYPE_UNLABELED:
470 break;
471 case NETLBL_NLTYPE_CIPSOV4:
472 buf_len += 2 * NETLBL_LEN_U32;
473 break;
474 }
475
476 skb = netlbl_netlink_alloc_skb(headroom, buf_len, GFP_ATOMIC);
477 if (skb == NULL)
478 goto dump_default_failure;
479
480 if (entry != rcu_dereference(netlbl_domhsh_def))
481 goto dump_default_failure;
482 if (entry != NULL) {
483 if (nla_put_u32(skb, NLA_U32, entry->type) != 0)
484 goto dump_default_failure;
485 buf_len -= NETLBL_LEN_U32;
486 switch (entry->type) {
487 case NETLBL_NLTYPE_UNLABELED:
488 break;
489 case NETLBL_NLTYPE_CIPSOV4:
490 if (buf_len < 2 * NETLBL_LEN_U32)
491 goto dump_default_failure;
492 if (nla_put_u32(skb,
493 NLA_U32,
494 entry->type_def.cipsov4->type) != 0)
495 goto dump_default_failure;
496 if (nla_put_u32(skb,
497 NLA_U32,
498 entry->type_def.cipsov4->doi) != 0)
499 goto dump_default_failure;
500 buf_len -= 2 * NETLBL_LEN_U32;
501 break;
502 }
503 } else
504 nla_put_u32(skb, NLA_U32, NETLBL_NLTYPE_NONE);
505 rcu_read_unlock();
506
507 return skb;
508 398
509dump_default_failure: 399walk_return:
510 rcu_read_unlock(); 400 rcu_read_unlock();
511 kfree_skb(skb); 401 *skip_bkt = iter_bkt;
512 return NULL; 402 *skip_chain = chain_cnt;
403 return ret_val;
513} 404}