diff options
author | Huw Davies <huw@codeweavers.com> | 2016-06-27 22:02:47 +0300 |
---|---|---|
committer | Paul Moore <paul@paul-moore.com> | 2016-06-27 22:02:47 +0300 |
commit | a5e34490c3160e09814403d040765b0ae0003121 (patch) | |
tree | 3e8cffeaa467500e092f56edf92c546468e29976 /net/ipv6/calipso.c | |
parent | cb72d38211eacda2dd90b09540542b6582da614e (diff) | |
download | linux-a5e34490c3160e09814403d040765b0ae0003121.tar.xz |
netlabel: Add support for querying a CALIPSO DOI.
Query a specified DOI through the NLBL_CALIPSO_C_LIST command.
It requires the attribute:
NLBL_CALIPSO_A_DOI.
The reply will contain:
NLBL_CALIPSO_A_MTYPE
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
Diffstat (limited to 'net/ipv6/calipso.c')
-rw-r--r-- | net/ipv6/calipso.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c index aa44310120be..128cc6945e34 100644 --- a/net/ipv6/calipso.c +++ b/net/ipv6/calipso.c @@ -144,9 +144,77 @@ static void calipso_doi_free(struct calipso_doi *doi_def) kfree(doi_def); } +/** + * calipso_doi_free_rcu - Frees a DOI definition via the RCU pointer + * @entry: the entry's RCU field + * + * Description: + * This function is designed to be used as a callback to the call_rcu() + * function so that the memory allocated to the DOI definition can be released + * safely. + * + */ +static void calipso_doi_free_rcu(struct rcu_head *entry) +{ + struct calipso_doi *doi_def; + + doi_def = container_of(entry, struct calipso_doi, rcu); + calipso_doi_free(doi_def); +} + +/** + * calipso_doi_getdef - Returns a reference to a valid DOI definition + * @doi: the DOI value + * + * Description: + * Searches for a valid DOI definition and if one is found it is returned to + * the caller. Otherwise NULL is returned. The caller must ensure that + * calipso_doi_putdef() is called when the caller is done. + * + */ +static struct calipso_doi *calipso_doi_getdef(u32 doi) +{ + struct calipso_doi *doi_def; + + rcu_read_lock(); + doi_def = calipso_doi_search(doi); + if (!doi_def) + goto doi_getdef_return; + if (!atomic_inc_not_zero(&doi_def->refcount)) + doi_def = NULL; + +doi_getdef_return: + rcu_read_unlock(); + return doi_def; +} + +/** + * calipso_doi_putdef - Releases a reference for the given DOI definition + * @doi_def: the DOI definition + * + * Description: + * Releases a DOI definition reference obtained from calipso_doi_getdef(). + * + */ +static void calipso_doi_putdef(struct calipso_doi *doi_def) +{ + if (!doi_def) + return; + + if (!atomic_dec_and_test(&doi_def->refcount)) + return; + spin_lock(&calipso_doi_list_lock); + list_del_rcu(&doi_def->list); + spin_unlock(&calipso_doi_list_lock); + + call_rcu(&doi_def->rcu, calipso_doi_free_rcu); +} + static const struct netlbl_calipso_ops ops = { .doi_add = calipso_doi_add, .doi_free = calipso_doi_free, + .doi_getdef = calipso_doi_getdef, + .doi_putdef = calipso_doi_putdef, }; /** |