diff options
Diffstat (limited to 'net/netlabel/netlabel_domainhash.c')
-rw-r--r-- | net/netlabel/netlabel_domainhash.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index 5fadf10e5ddf..7a10bbe02c13 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c | |||
@@ -483,6 +483,73 @@ int netlbl_domhsh_remove_entry(struct netlbl_dom_map *entry, | |||
483 | } | 483 | } |
484 | 484 | ||
485 | /** | 485 | /** |
486 | * netlbl_domhsh_remove_af4 - Removes an address selector entry | ||
487 | * @domain: the domain | ||
488 | * @addr: IPv4 address | ||
489 | * @mask: IPv4 address mask | ||
490 | * @audit_info: NetLabel audit information | ||
491 | * | ||
492 | * Description: | ||
493 | * Removes an individual address selector from a domain mapping and potentially | ||
494 | * the entire mapping if it is empty. Returns zero on success, negative values | ||
495 | * on failure. | ||
496 | * | ||
497 | */ | ||
498 | int netlbl_domhsh_remove_af4(const char *domain, | ||
499 | const struct in_addr *addr, | ||
500 | const struct in_addr *mask, | ||
501 | struct netlbl_audit *audit_info) | ||
502 | { | ||
503 | struct netlbl_dom_map *entry_map; | ||
504 | struct netlbl_af4list *entry_addr; | ||
505 | struct netlbl_af4list *iter4; | ||
506 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
507 | struct netlbl_af6list *iter6; | ||
508 | #endif /* IPv6 */ | ||
509 | struct netlbl_domaddr4_map *entry; | ||
510 | |||
511 | rcu_read_lock(); | ||
512 | |||
513 | if (domain) | ||
514 | entry_map = netlbl_domhsh_search(domain); | ||
515 | else | ||
516 | entry_map = netlbl_domhsh_search_def(domain); | ||
517 | if (entry_map == NULL || entry_map->type != NETLBL_NLTYPE_ADDRSELECT) | ||
518 | goto remove_af4_failure; | ||
519 | |||
520 | spin_lock(&netlbl_domhsh_lock); | ||
521 | entry_addr = netlbl_af4list_remove(addr->s_addr, mask->s_addr, | ||
522 | &entry_map->type_def.addrsel->list4); | ||
523 | spin_unlock(&netlbl_domhsh_lock); | ||
524 | |||
525 | if (entry_addr == NULL) | ||
526 | goto remove_af4_failure; | ||
527 | netlbl_af4list_foreach_rcu(iter4, &entry_map->type_def.addrsel->list4) | ||
528 | goto remove_af4_single_addr; | ||
529 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
530 | netlbl_af6list_foreach_rcu(iter6, &entry_map->type_def.addrsel->list6) | ||
531 | goto remove_af4_single_addr; | ||
532 | #endif /* IPv6 */ | ||
533 | /* the domain mapping is empty so remove it from the mapping table */ | ||
534 | netlbl_domhsh_remove_entry(entry_map, audit_info); | ||
535 | |||
536 | remove_af4_single_addr: | ||
537 | rcu_read_unlock(); | ||
538 | /* yick, we can't use call_rcu here because we don't have a rcu head | ||
539 | * pointer but hopefully this should be a rare case so the pause | ||
540 | * shouldn't be a problem */ | ||
541 | synchronize_rcu(); | ||
542 | entry = netlbl_domhsh_addr4_entry(entry_addr); | ||
543 | cipso_v4_doi_putdef(entry->type_def.cipsov4); | ||
544 | kfree(entry); | ||
545 | return 0; | ||
546 | |||
547 | remove_af4_failure: | ||
548 | rcu_read_unlock(); | ||
549 | return -ENOENT; | ||
550 | } | ||
551 | |||
552 | /** | ||
486 | * netlbl_domhsh_remove - Removes an entry from the domain hash table | 553 | * netlbl_domhsh_remove - Removes an entry from the domain hash table |
487 | * @domain: the domain to remove | 554 | * @domain: the domain to remove |
488 | * @audit_info: NetLabel audit information | 555 | * @audit_info: NetLabel audit information |