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 |
