diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2008-07-09 21:02:41 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2008-07-09 21:02:41 +0000 |
commit | db67c87db3c9089ea8d2e14f617bf3d9e2af261f (patch) | |
tree | 665c0caea83d34c11c1517c4c57137bb58cba6fb /src/libstrongswan/utils | |
parent | 1c088a8b6237ec67f63c23f97a0f2dc4e99af869 (diff) | |
download | vyos-strongswan-db67c87db3c9089ea8d2e14f617bf3d9e2af261f.tar.gz vyos-strongswan-db67c87db3c9089ea8d2e14f617bf3d9e2af261f.zip |
[svn-upgrade] Integrating new upstream version, strongswan (4.2.4)
Diffstat (limited to 'src/libstrongswan/utils')
21 files changed, 1841 insertions, 1768 deletions
diff --git a/src/libstrongswan/utils/enumerator.c b/src/libstrongswan/utils/enumerator.c index 842a2e997..cac5d73fa 100644 --- a/src/libstrongswan/utils/enumerator.c +++ b/src/libstrongswan/utils/enumerator.c @@ -1,10 +1,3 @@ -/** - * @file enumerator.c - * - * @brief Implementation of enumerator_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,10 +11,20 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: enumerator.c 3589 2008-03-13 14:14:44Z martin $ */ #include "enumerator.h" +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stdio.h> +#include <dirent.h> +#include <errno.h> + +#include <debug.h> /** * Implementation of enumerator_create_empty().enumerate @@ -42,3 +45,350 @@ enumerator_t* enumerator_create_empty() return this; } +/** + * Enumerator implementation for directory enumerator + */ +typedef struct { + /** implements enumerator_t */ + enumerator_t public; + /** directory handle */ + DIR *dir; + /** absolute path of current file */ + char full[PATH_MAX]; + /** where directory part of full ends and relative file gets written */ + char *full_end; +} dir_enum_t; + +/** + * Implementation of enumerator_create_directory().destroy + */ +static void destroy_dir_enum(dir_enum_t *this) +{ + closedir(this->dir); + free(this); +} + +/** + * Implementation of enumerator_create_directory().enumerate + */ +static bool enumerate_dir_enum(dir_enum_t *this, char **relative, + char **absolute, struct stat *st) +{ + struct dirent *entry = readdir(this->dir); + size_t len, remaining; + + if (!entry) + { + return FALSE; + } + if (streq(entry->d_name, ".") || streq(entry->d_name, "..")) + { + return enumerate_dir_enum(this, relative, absolute, st); + } + if (relative) + { + *relative = entry->d_name; + } + if (absolute || st) + { + remaining = sizeof(this->full) - (this->full_end - this->full); + len = snprintf(this->full_end, remaining, "%s", entry->d_name); + if (len < 0 || len >= remaining) + { + DBG1("buffer too small to enumerate file '%s'", entry->d_name); + return FALSE; + } + if (absolute) + { + *absolute = this->full; + } + if (st) + { + if (stat(this->full, st)) + { + DBG1("stat() on '%s' failed: %s", this->full, strerror(errno)); + return FALSE; + } + } + } + return TRUE; +} + +/** + * See header + */ +enumerator_t* enumerator_create_directory(char *path) +{ + size_t len; + dir_enum_t *this = malloc_thing(dir_enum_t); + this->public.enumerate = (void*)enumerate_dir_enum; + this->public.destroy = (void*)destroy_dir_enum; + + if (*path == '\0') + { + path = "./"; + } + len = snprintf(this->full, sizeof(this->full)-1, "%s", path); + if (len < 0 || len >= sizeof(this->full)-1) + { + DBG1("path string %s too long", path); + free(this); + return NULL; + } + /* append a '/' if not already done */ + if (this->full[len-1] != '/') + { + this->full[len++] = '/'; + this->full[len] = '\0'; + } + this->full_end = &this->full[len]; + + this->dir = opendir(path); + if (this->dir == NULL) + { + DBG1("opening directory %s failed: %s", path, strerror(errno)); + free(this); + return NULL; + } + return &this->public; +} + +/** + * enumerator for nested enumerations + */ +typedef struct { + /* implements enumerator_t */ + enumerator_t public; + /* outer enumerator */ + enumerator_t *outer; + /* inner enumerator */ + enumerator_t *inner; + /* constructor for inner enumerator */ + enumerator_t *(*create_inner)(void *outer, void *data); + /* data to pass to constructor above */ + void *data; + /* destructor for data */ + void (*destroy_data)(void *data); +} nested_enumerator_t; + + +/** + * Implementation of enumerator_create_nested().enumerate() + */ +static bool enumerate_nested(nested_enumerator_t *this, void *v1, void *v2, + void *v3, void *v4, void *v5) +{ + while (TRUE) + { + while (this->inner == NULL) + { + void *outer; + + if (!this->outer->enumerate(this->outer, &outer)) + { + return FALSE; + } + this->inner = this->create_inner(outer, this->data); + } + if (this->inner->enumerate(this->inner, v1, v2, v3, v4, v5)) + { + return TRUE; + } + this->inner->destroy(this->inner); + this->inner = NULL; + } +} + +/** + * Implementation of enumerator_create_nested().destroy() + **/ +static void destroy_nested(nested_enumerator_t *this) +{ + if (this->destroy_data) + { + this->destroy_data(this->data); + } + DESTROY_IF(this->inner); + this->outer->destroy(this->outer); + free(this); +} + +/** + * See header + */ +enumerator_t *enumerator_create_nested(enumerator_t *outer, + enumerator_t *(inner_constructor)(void *outer, void *data), + void *data, void (*destroy_data)(void *data)) +{ + nested_enumerator_t *enumerator = malloc_thing(nested_enumerator_t); + + enumerator->public.enumerate = (void*)enumerate_nested; + enumerator->public.destroy = (void*)destroy_nested; + enumerator->outer = outer; + enumerator->inner = NULL; + enumerator->create_inner = (void*)inner_constructor; + enumerator->data = data; + enumerator->destroy_data = destroy_data; + + return &enumerator->public; +} + +/** + * enumerator for filtered enumerator + */ +typedef struct { + enumerator_t public; + enumerator_t *unfiltered; + void *data; + bool (*filter)(void *data, ...); + void (*destructor)(void *data); +} filter_enumerator_t; + +/** + * Implementation of enumerator_create_filter().destroy + */ +void destroy_filter(filter_enumerator_t *this) +{ + if (this->destructor) + { + this->destructor(this->data); + } + this->unfiltered->destroy(this->unfiltered); + free(this); +} + +/** + * Implementation of enumerator_create_filter().enumerate + */ +bool enumerate_filter(filter_enumerator_t *this, void *o1, void *o2, + void *o3, void *o4, void *o5) +{ + void *i1, *i2, *i3, *i4, *i5; + + while (this->unfiltered->enumerate(this->unfiltered, &i1, &i2, &i3, &i4, &i5)) + { + if (this->filter(this->data, &i1, o1, &i2, o2, &i3, o3, &i4, o4, &i5, o5)) + { + return TRUE; + } + } + return FALSE; +} + +/** + * see header + */ +enumerator_t *enumerator_create_filter(enumerator_t *unfiltered, + bool (*filter)(void *data, ...), + void *data, void (*destructor)(void *data)) +{ + filter_enumerator_t *this = malloc_thing(filter_enumerator_t); + + this->public.enumerate = (void*)enumerate_filter; + this->public.destroy = (void*)destroy_filter; + this->unfiltered = unfiltered; + this->filter = filter; + this->data = data; + this->destructor = destructor; + + return &this->public; +} + +/** + * enumerator for cleaner enumerator + */ +typedef struct { + enumerator_t public; + enumerator_t *wrapped; + void (*cleanup)(void *data); + void *data; +} cleaner_enumerator_t; + +/** + * Implementation of enumerator_create_cleanup().destroy + */ +static void destroy_cleaner(cleaner_enumerator_t *this) +{ + this->cleanup(this->data); + this->wrapped->destroy(this->wrapped); + free(this); +} + +/** + * Implementation of enumerator_create_cleaner().enumerate + */ +static bool enumerate_cleaner(cleaner_enumerator_t *this, void *v1, void *v2, + void *v3, void *v4, void *v5) +{ + return this->wrapped->enumerate(this->wrapped, v1, v2, v3, v4, v5); +} + +/** + * see header + */ +enumerator_t *enumerator_create_cleaner(enumerator_t *wrapped, + void (*cleanup)(void *data), void *data) +{ + cleaner_enumerator_t *this = malloc_thing(cleaner_enumerator_t); + + this->public.enumerate = (void*)enumerate_cleaner; + this->public.destroy = (void*)destroy_cleaner; + this->wrapped = wrapped; + this->cleanup = cleanup; + this->data = data; + + return &this->public; +} + +/** + * enumerator for single enumerator + */ +typedef struct { + enumerator_t public; + void *item; + void (*cleanup)(void *item); + bool done; +} single_enumerator_t; + +/** + * Implementation of enumerator_create_single().destroy + */ +static void destroy_single(single_enumerator_t *this) +{ + if (this->cleanup) + { + this->cleanup(this->item); + } + free(this); +} + +/** + * Implementation of enumerator_create_single().enumerate + */ +static bool enumerate_single(single_enumerator_t *this, void **item) +{ + if (this->done) + { + return FALSE; + } + *item = this->item; + this->done = TRUE; + return TRUE; +} + +/** + * see header + */ +enumerator_t *enumerator_create_single(void *item, void (*cleanup)(void *item)) +{ + single_enumerator_t *this = malloc_thing(single_enumerator_t); + + this->public.enumerate = (void*)enumerate_single; + this->public.destroy = (void*)destroy_single; + this->item = item; + this->cleanup = cleanup; + this->done = FALSE; + + return &this->public; +} + diff --git a/src/libstrongswan/utils/enumerator.h b/src/libstrongswan/utils/enumerator.h index df1d78206..6b91fee72 100644 --- a/src/libstrongswan/utils/enumerator.h +++ b/src/libstrongswan/utils/enumerator.h @@ -1,10 +1,3 @@ -/** - * @file enumerator.h - * - * @brief Interface of enumerator_t. - * - */ - /* * Copyright (C) 2007 Martin Willi * Hochschule fuer Technik Rapperswil @@ -18,22 +11,29 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: enumerator.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup enumerator enumerator + * @{ @ingroup utils */ #ifndef ENUMERATOR_H_ #define ENUMERATOR_H_ -#include <library.h> - typedef struct enumerator_t enumerator_t; +#include <library.h> + /** - * @brief Enumerate is simpler, but more flexible than iterator. + * Enumerate is simpler, but more flexible than iterator. */ struct enumerator_t { /** - * @brief Enumerate collection. + * Enumerate collection. * * The enumerate function takes a variable argument list containing * pointers where the enumerated values get written. @@ -44,14 +44,104 @@ struct enumerator_t { bool (*enumerate)(enumerator_t *this, ...); /** - * @brief Destroy a enumerator instance. + * Destroy a enumerator instance. */ void (*destroy)(enumerator_t *this); }; /** - * @brief Create an enumerator which enumerates over nothing + * Create an enumerator which enumerates over nothing + * + * @return an enumerator over no values */ enumerator_t* enumerator_create_empty(); -#endif /* ENUMERATOR_H_ */ +/** + * Create an enumerator which enumerates over a single item + * + * @param item item to enumerate + * @param cleanup cleanup function called on destroy with the item + * @return an enumerator over a single value + */ +enumerator_t *enumerator_create_single(void *item, void (*cleanup)(void *item)); + +/** + * Create an enumerator over files/subdirectories in a directory. + * + * This enumerator_t.enumerate() function returns a (to the directory) relative + * filename (as a char*), an absolute filename (as a char*) and a file status + * (to a struct stat), which all may be NULL. "." and ".." entries are + * skipped. Example: + * + * @code + char *rel, *abs; + struct stat st; + enumerator_t *e; + + e = enumerator_create_directory("/tmp"); + if (e) + { + while (e->enumerate(e, &rel, &abs, &st)) + { + if (S_ISDIR(st.st_mode) && *rel != '.') + { + printf("%s\n", abs); + } + } + e->destroy(e); + } + @endcode + * + * @param path path of the directory + * @return the directory enumerator, NULL on failure + */ +enumerator_t* enumerator_create_directory(char *path); + +/** + * Creates an enumerator which enumerates over enumerated enumerators :-). + * + * The variable argument list of enumeration values is limit to 5. + * + * @param outer outer enumerator + * @param inner_constructor constructor to inner enumerator + * @param data data to pass to each inner_constructor call + * @param destroy_data destructor to pass to data + * @return the nested enumerator + */ +enumerator_t *enumerator_create_nested(enumerator_t *outer, + enumerator_t *(inner_constructor)(void *outer, void *data), + void *data, void (*destroy_data)(void *data)); + +/** + * Creates an enumerator which filters output of another enumerator. + * + * The filter function receives the user supplied "data" followed by a + * unfiltered enumeration item, followed by an output pointer where to write + * the filtered data. Then the next input/output pair follows. + * It returns TRUE to deliver the + * values to the caller of enumerate(), FALSE to filter this enumeration. + * + * The variable argument list of enumeration values is limit to 5. + * + * @param unfiltered unfiltered enumerator to wrap, gets destroyed + * @param filter filter function + * @param data user data to supply to filter + * @param destructor destructor function to clean up data after use + * @return the filtered enumerator + */ +enumerator_t *enumerator_create_filter(enumerator_t *unfiltered, + bool (*filter)(void *data, ...), + void *data, void (*destructor)(void *data)); + +/** + * Create an enumerator wrapper which does a cleanup on destroy. + * + * @param wrapped wrapped enumerator + * @param cleanup cleanup function called on destroy + * @param data user data to supply to cleanup + * @return the enumerator with cleanup + */ +enumerator_t *enumerator_create_cleaner(enumerator_t *wrapped, + void (*cleanup)(void *data), void *data); + +#endif /* ENUMERATOR_H_ @} */ diff --git a/src/libstrongswan/utils/fetcher.c b/src/libstrongswan/utils/fetcher.c deleted file mode 100644 index 7a06999aa..000000000 --- a/src/libstrongswan/utils/fetcher.c +++ /dev/null @@ -1,424 +0,0 @@ -/** - * @file fetcher.c - * - * @brief Implementation of fetcher_t. - * - */ - -/* - * Copyright (C) 2007 Andreas Steffen - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <fetcher://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifdef LIBCURL -#include <curl/curl.h> -#endif /* LIBCURL */ - -#ifdef LIBLDAP -#ifndef LDAP_DEPRECATED -#define LDAP_DEPRECATED 1 -#endif -#include <ldap.h> -#endif /* LIBLDAP */ - -#include <library.h> -#include <debug.h> - -#include "fetcher.h" - -typedef struct private_fetcher_t private_fetcher_t; - -/** - * @brief Private Data of a fetcher_t object. - */ -struct private_fetcher_t { - /** - * Public data - */ - fetcher_t public; - - /** - * URI of the information source - */ - const char *uri; - -#ifdef LIBCURL - /** - * we use libcurl from http://curl.haxx.se/ as a fetcher - */ - CURL* curl; -#endif /* LIBCURL */ - -#ifdef LIBLDAP - /** - * we use libldap from http://www.openssl.org/ as a fetcher - */ - LDAP *ldap; - LDAPURLDesc *lurl; -#endif /* LIBLDAP */ -}; - -/** - * writes data into a dynamically resizeable chunk_t - * needed for libcurl responses - */ -static size_t curl_write_buffer(void *ptr, size_t size, size_t nmemb, void *data) -{ - size_t realsize = size * nmemb; - chunk_t *mem = (chunk_t*)data; - - mem->ptr = (u_char *)realloc(mem->ptr, mem->len + realsize); - if (mem->ptr) { - memcpy(&(mem->ptr[mem->len]), ptr, realsize); - mem->len += realsize; - } - return realsize; -} - -/** - * Implements fetcher_t.get for curl methods - */ -static chunk_t curl_get(private_fetcher_t *this) -{ - chunk_t response = chunk_empty; - -#ifdef LIBCURL - if (this->curl) - { - CURLcode res; - chunk_t curl_response = chunk_empty; - char curl_error_buffer[CURL_ERROR_SIZE]; - - curl_easy_setopt(this->curl, CURLOPT_URL, this->uri); - curl_easy_setopt(this->curl, CURLOPT_WRITEFUNCTION, curl_write_buffer); - curl_easy_setopt(this->curl, CURLOPT_WRITEDATA, (void *)&curl_response); - curl_easy_setopt(this->curl, CURLOPT_ERRORBUFFER, &curl_error_buffer); - curl_easy_setopt(this->curl, CURLOPT_FAILONERROR, TRUE); - curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, FETCHER_TIMEOUT); - curl_easy_setopt(this->curl, CURLOPT_NOSIGNAL, TRUE); - - DBG1("sending curl request to '%s'...", this->uri); - res = curl_easy_perform(this->curl); - - if (res == CURLE_OK) - { - DBG1("received valid curl response"); - response = chunk_clone(curl_response); - } - else - { - DBG1("curl request failed: %s", curl_error_buffer); - } - curl_free(curl_response.ptr); - } -#else - DBG1("warning: libcurl fetching not compiled in"); -#endif /* LIBCURL */ - return response; -} - -/** - * Implements fetcher_t.post. - */ -static chunk_t http_post(private_fetcher_t *this, const char *request_type, chunk_t request) -{ - chunk_t response = chunk_empty; - -#ifdef LIBCURL - if (this->curl) - { - CURLcode res; - struct curl_slist *headers = NULL; - chunk_t curl_response = chunk_empty; - char curl_error_buffer[CURL_ERROR_SIZE]; - char content_type[BUF_LEN]; - - /* set content type header */ - snprintf(content_type, BUF_LEN, "Content-Type: %s", request_type); - headers = curl_slist_append(headers, content_type); - - /* set options */ - curl_easy_setopt(this->curl, CURLOPT_HTTPHEADER, headers); - curl_easy_setopt(this->curl, CURLOPT_URL, this->uri); - curl_easy_setopt(this->curl, CURLOPT_WRITEFUNCTION, curl_write_buffer); - curl_easy_setopt(this->curl, CURLOPT_WRITEDATA, (void *)&curl_response); - curl_easy_setopt(this->curl, CURLOPT_POSTFIELDS, request.ptr); - curl_easy_setopt(this->curl, CURLOPT_POSTFIELDSIZE, request.len); - curl_easy_setopt(this->curl, CURLOPT_ERRORBUFFER, &curl_error_buffer); - curl_easy_setopt(this->curl, CURLOPT_FAILONERROR, TRUE); - curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, FETCHER_TIMEOUT); - curl_easy_setopt(this->curl, CURLOPT_NOSIGNAL, TRUE); - - DBG1("sending http post request to '%s'...", this->uri); - res = curl_easy_perform(this->curl); - - if (res == CURLE_OK) - { - DBG1("received valid http response"); - response = chunk_clone(curl_response); - } - else - { - DBG1("http post request using libcurl failed: %s", curl_error_buffer); - } - curl_slist_free_all(headers); - curl_free(curl_response.ptr); - } -#else - DBG1("warning: libcurl fetching not compiled in"); -#endif /* LIBCURL */ - return response; -} - -#ifdef LIBLDAP -/** - * Parses the result returned by an ldap query - */ -static chunk_t ldap_parse(LDAP *ldap, LDAPMessage *result) -{ - chunk_t response = chunk_empty; - err_t ugh = NULL; - - LDAPMessage *entry = ldap_first_entry(ldap, result); - - if (entry != NULL) - { - BerElement *ber = NULL; - char *attr; - - attr = ldap_first_attribute(ldap, entry, &ber); - - if (attr != NULL) - { - struct berval **values = ldap_get_values_len(ldap, entry, attr); - - if (values != NULL) - { - if (values[0] != NULL) - { - response.len = values[0]->bv_len; - response.ptr = malloc(response.len); - memcpy(response.ptr, values[0]->bv_val, response.len); - - if (values[1] != NULL) - { - ugh = "more than one value was fetched - first selected"; - } - } - else - { - ugh = "no values in attribute"; - } - ldap_value_free_len(values); - } - else - { - ugh = ldap_err2string(ldap_result2error(ldap, entry, 0)); - } - ldap_memfree(attr); - } - else - { - ugh = ldap_err2string(ldap_result2error(ldap, entry, 0)); - } - ber_free(ber, 0); - } - else - { - ugh = ldap_err2string(ldap_result2error(ldap, result, 0)); - } - if (ugh) - { - DBG1("ldap request failed: %s", ugh); - } - return response; -} -#endif /* LIBLDAP */ - -/** - * Implements fetcher_t.get for curl methods - */ -static chunk_t ldap_get(private_fetcher_t *this) -{ - chunk_t response = chunk_empty; - -#ifdef LIBLDAP - if (this->ldap) - { - err_t ugh = NULL; - int rc; - int ldap_version = LDAP_VERSION3; - - struct timeval timeout; - - timeout.tv_sec = FETCHER_TIMEOUT; - timeout.tv_usec = 0; - - ldap_set_option(this->ldap, LDAP_OPT_PROTOCOL_VERSION, &ldap_version); - ldap_set_option(this->ldap, LDAP_OPT_NETWORK_TIMEOUT, &timeout); - - DBG1("sending ldap request to '%s'...", this->uri); - - rc = ldap_simple_bind_s(this->ldap, NULL, NULL); - if (rc == LDAP_SUCCESS) - { - LDAPMessage *result; - - timeout.tv_sec = FETCHER_TIMEOUT; - timeout.tv_usec = 0; - - rc = ldap_search_st(this->ldap, this->lurl->lud_dn, - this->lurl->lud_scope, - this->lurl->lud_filter, - this->lurl->lud_attrs, - 0, &timeout, &result); - - if (rc == LDAP_SUCCESS) - { - response = ldap_parse(this->ldap, result); - if (response.ptr) - { - DBG1("received valid ldap response"); - } - ldap_msgfree(result); - } - else - { - ugh = ldap_err2string(rc); - } - } - else - { - ugh = ldap_err2string(rc); - } - ldap_unbind_s(this->ldap); - - if (ugh) - { - DBG1("ldap request failed: %s", ugh); - } - } -#else /* !LIBLDAP */ - DBG1("warning: libldap fetching not compiled in"); -#endif /* !LIBLDAP */ - return response; -} - -/** - * Implements fetcher_t.destroy - */ -static void destroy(private_fetcher_t *this) -{ -#ifdef LIBCURL - if (this->curl) - { - curl_easy_cleanup(this->curl); - } -#endif /* LIBCURL */ - -#ifdef LIBLDAP - if (this->lurl) - { - ldap_free_urldesc(this->lurl); - } -#endif /* LIBLDAP */ - - free(this); -} - -/* - * Described in header. - */ -fetcher_t *fetcher_create(const char *uri) -{ - private_fetcher_t *this = malloc_thing(private_fetcher_t); - - /* initialize */ - this->uri = uri; - -#ifdef LIBCURL - this->curl = NULL; -#endif /* LIBCURL */ - -#ifdef LIBLDAP - this->lurl = NULL; - this->ldap = NULL; -#endif /* LIBLDAP */ - - if (strlen(uri) >= 4 && strncasecmp(uri, "ldap", 4) == 0) - { -#ifdef LIBLDAP - int rc = ldap_url_parse(uri, &this->lurl); - - if (rc == LDAP_SUCCESS) - { - this->ldap = ldap_init(this->lurl->lud_host, - this->lurl->lud_port); - } - else - { - DBG1("ldap: %s", ldap_err2string(rc)); - this->ldap = NULL; - } -#endif /* LIBLDAP */ - this->public.get = (chunk_t (*) (fetcher_t*))ldap_get; - } - else - { -#ifdef LIBCURL - this->curl = curl_easy_init(); - if (this->curl == NULL) - { - DBG1("curl_easy_init_failed()"); - } -#endif /* LIBCURL */ - this->public.get = (chunk_t (*) (fetcher_t*))curl_get; - } - - /* public functions */ - this->public.post = (chunk_t (*) (fetcher_t*,const char*,chunk_t))http_post; - this->public.destroy = (void (*) (fetcher_t*))destroy; - - return &this->public; -} - -/** - * Described in header. - */ -void fetcher_initialize(void) -{ -#ifdef LIBCURL - CURLcode res; - - /* initialize libcurl */ - DBG1("initializing libcurl"); - res = curl_global_init(CURL_GLOBAL_NOTHING); - if (res != CURLE_OK) - { - DBG1("libcurl could not be initialized: %s", curl_easy_strerror(res)); - } -#endif /* LIBCURL */ -} - -/** - * Described in header. - */ -void fetcher_finalize(void) -{ -#ifdef LIBCURL - /* finalize libcurl */ - DBG1("finalizing libcurl"); - curl_global_cleanup(); -#endif /* LIBCURL */ -} - diff --git a/src/libstrongswan/utils/fetcher.h b/src/libstrongswan/utils/fetcher.h deleted file mode 100644 index 47b43a0b7..000000000 --- a/src/libstrongswan/utils/fetcher.h +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @file fetcher.h - * - * @brief Interface of fetcher_t. - * - */ - -/* - * Copyright (C) 2007 Andreas Steffen - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <fetcher://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef FETCHER_H_ -#define FETCHER_H_ - -typedef struct fetcher_t fetcher_t; - -#include <chunk.h> - -#define FETCHER_TIMEOUT 10 /* seconds */ - -/** - * @brief Fetches information from an URI (http, file, ftp, etc.) - * - * @ingroup utils - */ -struct fetcher_t { - - /** - * @brief Get information via a get request. - * - * @param this calling object - * @param uri uri specifying the information source - * @return chunk_t containing the information - */ - chunk_t (*get) (fetcher_t *this); - - /** - * @brief Get information via a get request. - * - * @param this calling object - * @param uri uri specifying the information source - * @param type content type of http post request - * @param request binary data for http post request - * @return chunk_t containing the information - */ - chunk_t (*post) (fetcher_t *this, const char *type, chunk_t request); - - /** - * @brief Destroys the fetcher_t object. - * - * @param this fetcher_t to destroy - */ - void (*destroy) (fetcher_t *this); - -}; - -/** - * @brief Create a fetcher_t object. - * - * @return created fetcher_t object - * - * @ingroup utils - */ -fetcher_t* fetcher_create(const char *uri); - -/** - * @brief Initializes the fetcher_t class - * - * call this function only once in the main program - * - * @ingroup utils - */ -void fetcher_initialize(void); - -/** - * @brief Finalizes the fetcher_t class - * - * call this function only once befor exiting the main program - * - * @ingroup utils - */ -void fetcher_finalize(void); - -#endif /*FETCHER_H_*/ diff --git a/src/libstrongswan/utils/host.c b/src/libstrongswan/utils/host.c index 68e9c9500..eb87f27bc 100644 --- a/src/libstrongswan/utils/host.c +++ b/src/libstrongswan/utils/host.c @@ -1,10 +1,3 @@ -/** - * @file host.c - * - * @brief Implementation of host_t. - * - */ - /* * Copyright (C) 2006-2007 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger @@ -21,18 +14,23 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: host.c 4056 2008-06-11 07:44:23Z martin $ */ +#define _GNU_SOURCE +#include <netdb.h> #include <string.h> #include <printf.h> #include "host.h" +#include <debug.h> typedef struct private_host_t private_host_t; /** - * @brief Private Data of a host object. + * Private Data of a host object. */ struct private_host_t { /** @@ -111,56 +109,79 @@ static int print(FILE *stream, const struct printf_info *info, const void *const *args) { private_host_t *this = *((private_host_t**)(args[0])); - char buffer[INET6_ADDRSTRLEN]; - void *address; - u_int16_t port; + char buffer[INET6_ADDRSTRLEN + 16]; if (this == NULL) { - return fprintf(stream, "(null)"); + snprintf(buffer, sizeof(buffer), "(null)"); } - - if (is_anyaddr(this)) + else if (is_anyaddr(this)) { - return fprintf(stream, "%%any"); + snprintf(buffer, sizeof(buffer), "%%any"); } - - switch (this->address.sa_family) + else { - case AF_INET: - address = &this->address4.sin_addr; - port = this->address4.sin_port; - break; - case AF_INET6: - address = &this->address6.sin6_addr; - port = this->address6.sin6_port; - break; - default: - return fprintf(stream, "(family not supported)"); - } + void *address; + u_int16_t port; + int len; + + address = &this->address6.sin6_addr; + port = this->address6.sin6_port; + + switch (this->address.sa_family) + { + case AF_INET: + address = &this->address4.sin_addr; + port = this->address4.sin_port; + /* fall */ + case AF_INET6: - if (inet_ntop(this->address.sa_family, address, - buffer, sizeof(buffer)) == NULL) - { - return fprintf(stream, "(address conversion failed)"); + if (inet_ntop(this->address.sa_family, address, + buffer, sizeof(buffer)) == NULL) + { + snprintf(buffer, sizeof(buffer), + "(address conversion failed)"); + } + else if (info->alt) + { + len = strlen(buffer); + snprintf(buffer + len, sizeof(buffer) - len, + "[%d]", ntohs(port)); + } + break; + default: + snprintf(buffer, sizeof(buffer), "(family not supported)"); + break; + } } - - if (info->alt) + if (info->left) { - return fprintf(stream, "%s[%d]", buffer, ntohs(port)); + return fprintf(stream, "%-*s", info->width, buffer); } - else + return fprintf(stream, "%*s", info->width, buffer); +} + + +/** + * arginfo handler for printf() hosts + */ +int arginfo(const struct printf_info *info, size_t n, int *argtypes) +{ + if (n > 0) { - return fprintf(stream, "%s", buffer); + argtypes[0] = PA_POINTER; } + return 1; } /** - * register printf() handlers + * return printf hook functions for a host */ -static void __attribute__ ((constructor))print_register() +printf_hook_functions_t host_get_printf_hooks() { - register_printf_function(PRINTF_HOST, print, arginfo_ptr); + printf_hook_functions_t hooks = {print, arginfo}; + + return hooks; } /** @@ -433,6 +454,61 @@ host_t *host_create_from_string(char *string, u_int16_t port) /* * Described in header. */ +host_t *host_create_from_dns(char *string, int af, u_int16_t port) +{ + private_host_t *this; + struct hostent host, *ptr; + char buf[512]; + int err, ret; + + if (strchr(string, ':')) + { /* gethostbyname does not like IPv6 addresses, fallback */ + return host_create_from_string(string, port); + } + + if (af) + { + ret = gethostbyname2_r(string, af, &host, buf, sizeof(buf), &ptr, &err); + } + else + { + ret = gethostbyname_r(string, &host, buf, sizeof(buf), &ptr, &err); + } + if (ret != 0) + { + DBG1("resolving '%s' failed: %s", string, hstrerror(err)); + return NULL; + } + if (ptr == NULL) + { + DBG1("resolving '%s' failed", string); + } + this = host_create_empty(); + this->address.sa_family = host.h_addrtype; + switch (this->address.sa_family) + { + case AF_INET: + memcpy(&this->address4.sin_addr.s_addr, + host.h_addr_list[0], host.h_length); + this->address4.sin_port = htons(port); + this->socklen = sizeof(struct sockaddr_in); + break; + case AF_INET6: + memcpy(&this->address6.sin6_addr.s6_addr, + host.h_addr_list[0], host.h_length); + this->address6.sin6_port = htons(port); + this->socklen = sizeof(struct sockaddr_in6); + break; + default: + free(this); + return NULL; + } + return &this->public; +} + +/* + * Described in header. + */ host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port) { private_host_t *this = host_create_empty(); diff --git a/src/libstrongswan/utils/host.h b/src/libstrongswan/utils/host.h index ee9aa457f..6a1d824c6 100644 --- a/src/libstrongswan/utils/host.h +++ b/src/libstrongswan/utils/host.h @@ -1,14 +1,7 @@ -/** - * @file host.h - * - * @brief Interface of host_t. - * - */ - /* + * Copyright (C) 2005-2008 Martin Willi * Copyright (C) 2006-2007 Tobias Brunner * Copyright (C) 2006 Daniel Roethlisberger - * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -23,6 +16,11 @@ * for more details. */ +/** + * @defgroup host host + * @{ @ingroup utils + */ + #ifndef HOST_H_ #define HOST_H_ @@ -49,42 +47,31 @@ enum host_diff_t { }; /** - * @brief Representates a Host + * Representates a Host * * Host object, identifies a address:port pair and defines some * useful functions on it. - * - * @b Constructors: - * - host_create() - * - host_create_from_chunk() - * - host_create_from_sockaddr() - * - * @todo Add IPv6 support - * - * @ingroup utils */ struct host_t { /** - * @brief Build a clone of this host object. + * Build a clone of this host object. * - * @param this object to clone - * @return cloned host + * @return cloned host */ host_t *(*clone) (host_t *this); /** - * @brief Get a pointer to the internal sockaddr struct. + * Get a pointer to the internal sockaddr struct. * * This is used for sending and receiving via sockets. * - * @param this object to clone - * @return pointer to the internal sockaddr structure + * @return pointer to the internal sockaddr structure */ sockaddr_t *(*get_sockaddr) (host_t *this); /** - * @brief Get the length of the sockaddr struct. + * Get the length of the sockaddr struct. * * Depending on the family, the length of the sockaddr struct * is different. Use this function to get the length of the sockaddr @@ -92,140 +79,129 @@ struct host_t { * * This is used for sending and receiving via sockets. * - * @param this object to clone - * @return length of the sockaddr struct + * @return length of the sockaddr struct */ socklen_t *(*get_sockaddr_len) (host_t *this); /** - * @brief Gets the family of the address + * Gets the family of the address * - * @param this calling object - * @return family + * @return family */ int (*get_family) (host_t *this); /** - * @brief Checks if the ip address of host is set to default route. + * Checks if the ip address of host is set to default route. * - * @param this calling object - * @return - * - TRUE if host has IP 0.0.0.0 for default route - * - FALSE otherwise + * @return TRUE if host is 0.0.0.0 or 0::0, FALSE otherwise */ bool (*is_anyaddr) (host_t *this); /** - * @brief get the address of this host as chunk_t + * Get the address of this host as chunk_t * * Returned chunk points to internal data. * - * @param this object - * @return address string, + * @return address string, */ chunk_t (*get_address) (host_t *this); /** - * @brief get the port of this host + * Get the port of this host * - * @param this object to clone - * @return port number + * @return port number */ u_int16_t (*get_port) (host_t *this); /** - * @brief set the port of this host + * Set the port of this host * - * @param this object to clone - * @param port port numer + * @param port port numer */ void (*set_port) (host_t *this, u_int16_t port); /** - * @brief Compare the ips of two hosts hosts. + * Compare the ips of two hosts hosts. * - * @param this object to compare - * @param other the other to compare - * @return TRUE if addresses are equal. + * @param other the other to compare + * @return TRUE if addresses are equal. */ bool (*ip_equals) (host_t *this, host_t *other); /** - * @brief Compare two hosts, with port. + * Compare two hosts, with port. * - * @param this object to compare - * @param other the other to compare - * @return TRUE if addresses and ports are equal. + * @param other the other to compare + * @return TRUE if addresses and ports are equal. */ bool (*equals) (host_t *this, host_t *other); /** - * @brief Compare two hosts and return the differences. + * Compare two hosts and return the differences. * - * @param this object to compare - * @param other the other to compare - * @return differences in a combination of host_diff_t's + * @param other the other to compare + * @return differences in a combination of host_diff_t's */ host_diff_t (*get_differences) (host_t *this, host_t *other); /** - * @brief Destroy this host object - * - * @param this calling - * @return SUCCESS in any case + * Destroy this host object. */ void (*destroy) (host_t *this); }; /** - * @brief Constructor to create a host_t object from an address string. + * Constructor to create a host_t object from an address string. * * @param string string of an address, such as "152.96.193.130" * @param port port number - * @return - * - host_t object - * - NULL, if string not an address. - * - * @ingroup network + * @return host_t, NULL if string not an address. */ host_t *host_create_from_string(char *string, u_int16_t port); /** - * @brief Constructor to create a host_t object from an address chunk + * Constructor to create a host_t from a DNS name. * - * @param family Address family to use for this object, such as AF_INET or AF_INET6 - * @param address address as 4 byte chunk_t in networ order + * @param string hostname to resolve + * @param family family to prefer, 0 for first match * @param port port number - * @return - * - host_t object - * - NULL, if family not supported or chunk_t length not 4 bytes. - * - * @ingroup network + * @return host_t, NULL lookup failed + */ +host_t *host_create_from_dns(char *string, int family, u_int16_t port); + +/** + * Constructor to create a host_t object from an address chunk + * + * @param family Address family, such as AF_INET or AF_INET6 + * @param address address as chunk_t in networ order + * @param port port number + * @return host_t, NULL if family not supported/chunk invalid */ host_t *host_create_from_chunk(int family, chunk_t address, u_int16_t port); /** - * @brief Constructor to create a host_t object from a sockaddr struct + * Constructor to create a host_t object from a sockaddr struct * * @param sockaddr sockaddr struct which contains family, address and port - * @return - * - host_t object - * - NULL, if family not supported. - * - * @ingroup network + * @return host_t, NULL if family not supported */ host_t *host_create_from_sockaddr(sockaddr_t *sockaddr); /** - * @brief Create a host without an address, a "any" host. + * Create a host without an address, a "any" host. * * @param family family of the any host - * @return - * - host_t object - * - NULL, if family not supported. - * - * @ingroup network + * @return host_t, NULL if family not supported */ host_t *host_create_any(int family); -#endif /*HOST_H_*/ +/** + * Get printf hooks for a host. + * + * Arguments are: + * host_t *host + * Use #-modifier to include port number + */ +printf_hook_functions_t host_get_printf_hooks(); + +#endif /* HOST_H_ @}*/ diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c index 18f6d6824..39d49bf6c 100644 --- a/src/libstrongswan/utils/identification.c +++ b/src/libstrongswan/utils/identification.c @@ -1,12 +1,5 @@ -/** - * @file identification.c - * - * @brief Implementation of identification_t. - * - */ - /* - * Copyright (C) 2005-2006 Martin Willi + * Copyright (C) 2005-2008 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil * @@ -20,7 +13,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: identification.c 3256 2007-10-07 13:42:43Z andreas $ + * $Id: identification.c 4064 2008-06-13 15:10:01Z martin $ */ #define _GNU_SOURCE @@ -34,8 +27,17 @@ #include "identification.h" +#include <asn1/oid.h> #include <asn1/asn1.h> +ENUM_BEGIN(id_match_names, ID_MATCH_NONE, ID_MATCH_MAX_WILDCARDS, + "MATCH_NONE", + "MATCH_ANY", + "MATCH_MAX_WILDCARDS"); +ENUM_NEXT(id_match_names, ID_MATCH_PERFECT, ID_MATCH_PERFECT, ID_MATCH_MAX_WILDCARDS, + "MATCH_PERFECT"); +ENUM_END(id_match_names, ID_MATCH_PERFECT); + ENUM_BEGIN(id_type_names, ID_ANY, ID_KEY_ID, "ID_ANY", "ID_IPV4_ADDR", @@ -49,10 +51,12 @@ ENUM_BEGIN(id_type_names, ID_ANY, ID_KEY_ID, "ID_DER_ASN1_DN", "ID_DER_ASN1_GN", "ID_KEY_ID"); -ENUM_NEXT(id_type_names, ID_DER_ASN1_GN_URI, ID_DER_ASN1_GN_URI, ID_KEY_ID, - "ID_DER_ASN1_GN_URI"); -ENUM_END(id_type_names, ID_DER_ASN1_GN_URI); - +ENUM_NEXT(id_type_names, ID_DER_ASN1_GN_URI, ID_CERT_DER_SHA1, ID_KEY_ID, + "ID_DER_ASN1_GN_URI", + "ID_PUBKEY_INFO_SHA1", + "ID_PUBKEY_SHA1", + "ID_CERT_DER_SHA1"); +ENUM_END(id_type_names, ID_CERT_DER_SHA1); /** * X.501 acronyms for well known object identifiers (OIDs) @@ -237,7 +241,7 @@ static chunk_t sanitize_chunk(chunk_t chunk) /** * Pointer is set to the first RDN in a DN */ -static status_t init_rdn(chunk_t dn, chunk_t *rdn, chunk_t *attribute, bool *next) +static bool init_rdn(chunk_t dn, chunk_t *rdn, chunk_t *attribute, bool *next) { *rdn = chunk_empty; *attribute = chunk_empty; @@ -246,7 +250,7 @@ static status_t init_rdn(chunk_t dn, chunk_t *rdn, chunk_t *attribute, bool *nex if (*dn.ptr != ASN1_SEQUENCE) { /* DN is not a SEQUENCE */ - return FAILED; + return FALSE; } rdn->len = asn1_length(&dn); @@ -254,7 +258,7 @@ static status_t init_rdn(chunk_t dn, chunk_t *rdn, chunk_t *attribute, bool *nex if (rdn->len == ASN1_INVALID_LENGTH) { /* Invalid RDN length */ - return FAILED; + return FALSE; } rdn->ptr = dn.ptr; @@ -262,13 +266,13 @@ static status_t init_rdn(chunk_t dn, chunk_t *rdn, chunk_t *attribute, bool *nex /* are there any RDNs ? */ *next = rdn->len > 0; - return SUCCESS; + return TRUE; } /** * Fetches the next RDN in a DN */ -static status_t get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, chunk_t *value, asn1_t *type, bool *next) +static bool get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, chunk_t *value, asn1_t *type, bool *next) { chunk_t body; @@ -283,13 +287,13 @@ static status_t get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, ch if (*rdn->ptr != ASN1_SET) { /* RDN is not a SET */ - return FAILED; + return FALSE; } attribute->len = asn1_length(rdn); if (attribute->len == ASN1_INVALID_LENGTH) { /* Invalid attribute length */ - return FAILED; + return FALSE; } attribute->ptr = rdn->ptr; /* advance to start of next RDN */ @@ -301,7 +305,7 @@ static status_t get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, ch if (*attribute->ptr != ASN1_SEQUENCE) { /* attributeTypeAndValue is not a SEQUENCE */ - return FAILED; + return FALSE; } /* extract the attribute body */ @@ -310,7 +314,7 @@ static status_t get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, ch if (body.len == ASN1_INVALID_LENGTH) { /* Invalid attribute body length */ - return FAILED; + return FALSE; } body.ptr = attribute->ptr; @@ -323,7 +327,7 @@ static status_t get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, ch if (*body.ptr != ASN1_OID) { /* attributeType is not an OID */ - return FAILED; + return FALSE; } /* extract OID */ oid->len = asn1_length(&body); @@ -331,7 +335,7 @@ static status_t get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, ch if (oid->len == ASN1_INVALID_LENGTH) { /* Invalid attribute OID length */ - return FAILED; + return FALSE; } oid->ptr = body.ptr; @@ -348,19 +352,19 @@ static status_t get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid, ch if (value->len == ASN1_INVALID_LENGTH) { /* Invalid attribute string length */ - return FAILED; + return FALSE; } value->ptr = body.ptr; /* are there any RDNs left? */ *next = rdn->len > 0 || attribute->len > 0; - return SUCCESS; + return TRUE; } /** * Parses an ASN.1 distinguished name int its OID/value pairs */ -static status_t dntoa(chunk_t dn, chunk_t *str) +static bool dntoa(chunk_t dn, chunk_t *str) { chunk_t rdn, oid, attribute, value, proper; asn1_t type; @@ -368,17 +372,17 @@ static status_t dntoa(chunk_t dn, chunk_t *str) bool next; bool first = TRUE; - status_t status = init_rdn(dn, &rdn, &attribute, &next); - - if (status != SUCCESS) - return status; + if (!init_rdn(dn, &rdn, &attribute, &next)) + { + return FALSE; + } while (next) { - status = get_next_rdn(&rdn, &attribute, &oid, &value, &type, &next); - - if (status != SUCCESS) - return status; + if (!get_next_rdn(&rdn, &attribute, &oid, &value, &type, &next)) + { + return FALSE; + } if (first) { /* first OID/value pair */ @@ -390,7 +394,7 @@ static status_t dntoa(chunk_t dn, chunk_t *str) } /* print OID */ - oid_code = known_oid(oid); + oid_code = asn1_known_oid(oid); if (oid_code == OID_UNKNOWN) { update_chunk(str, snprintf(str->ptr,str->len,"0x#B", &oid)); @@ -404,7 +408,7 @@ static status_t dntoa(chunk_t dn, chunk_t *str) update_chunk(str, snprintf(str->ptr,str->len,"=%.*s", (int)proper.len, proper.ptr)); chunk_free(&proper); } - return SUCCESS; + return TRUE; } /** @@ -420,15 +424,17 @@ static bool same_dn(chunk_t a, chunk_t b) /* same lengths for the DNs */ if (a.len != b.len) + { return FALSE; - + } /* try a binary comparison first */ if (memeq(a.ptr, b.ptr, b.len)) + { return TRUE; - + } /* initialize DN parsing */ - if (init_rdn(a, &rdn_a, &attribute_a, &next_a) != SUCCESS - || init_rdn(b, &rdn_b, &attribute_b, &next_b) != SUCCESS) + if (!init_rdn(a, &rdn_a, &attribute_a, &next_a) || + !init_rdn(b, &rdn_b, &attribute_b, &next_b)) { return FALSE; } @@ -437,23 +443,27 @@ static bool same_dn(chunk_t a, chunk_t b) while (next_a && next_b) { /* parse next RDNs and check for errors */ - if (get_next_rdn(&rdn_a, &attribute_a, &oid_a, &value_a, &type_a, &next_a) != SUCCESS - || get_next_rdn(&rdn_b, &attribute_b, &oid_b, &value_b, &type_b, &next_b) != SUCCESS) + if (!get_next_rdn(&rdn_a, &attribute_a, &oid_a, &value_a, &type_a, &next_a) || + !get_next_rdn(&rdn_b, &attribute_b, &oid_b, &value_b, &type_b, &next_b)) { return FALSE; } /* OIDs must agree */ - if (oid_a.len != oid_b.len || memcmp(oid_a.ptr, oid_b.ptr, oid_b.len) != 0) + if (oid_a.len != oid_b.len || !memeq(oid_a.ptr, oid_b.ptr, oid_b.len)) + { return FALSE; + } /* same lengths for values */ if (value_a.len != value_b.len) + { return FALSE; + } /* printableStrings and email RDNs require uppercase comparison */ - if (type_a == type_b && (type_a == ASN1_PRINTABLESTRING - || (type_a == ASN1_IA5STRING && known_oid(oid_a) == OID_PKCS9_EMAIL))) + if (type_a == type_b && (type_a == ASN1_PRINTABLESTRING || + (type_a == ASN1_IA5STRING && asn1_known_oid(oid_a) == OID_PKCS9_EMAIL))) { if (strncasecmp(value_a.ptr, value_b.ptr, value_b.len) != 0) { @@ -470,8 +480,9 @@ static bool same_dn(chunk_t a, chunk_t b) } /* both DNs must have same number of RDNs */ if (next_a || next_b) + { return FALSE; - + } /* the two DNs are equal! */ return TRUE; } @@ -490,14 +501,11 @@ bool match_dn(chunk_t a, chunk_t b, int *wildcards) bool next_a, next_b; /* initialize wildcard counter */ - if (wildcards) - { - *wildcards = 0; - } + *wildcards = 0; /* initialize DN parsing */ - if (init_rdn(a, &rdn_a, &attribute_a, &next_a) != SUCCESS - || init_rdn(b, &rdn_b, &attribute_b, &next_b) != SUCCESS) + if (!init_rdn(a, &rdn_a, &attribute_a, &next_a) || + !init_rdn(b, &rdn_b, &attribute_b, &next_b)) { return FALSE; } @@ -506,31 +514,32 @@ bool match_dn(chunk_t a, chunk_t b, int *wildcards) while (next_a && next_b) { /* parse next RDNs and check for errors */ - if (get_next_rdn(&rdn_a, &attribute_a, &oid_a, &value_a, &type_a, &next_a) != SUCCESS - || get_next_rdn(&rdn_b, &attribute_b, &oid_b, &value_b, &type_b, &next_b) != SUCCESS) + if (!get_next_rdn(&rdn_a, &attribute_a, &oid_a, &value_a, &type_a, &next_a) || + !get_next_rdn(&rdn_b, &attribute_b, &oid_b, &value_b, &type_b, &next_b)) { return FALSE; } /* OIDs must agree */ if (oid_a.len != oid_b.len || memcmp(oid_a.ptr, oid_b.ptr, oid_b.len) != 0) + { return FALSE; + } /* does rdn_b contain a wildcard? */ if (value_b.len == 1 && *value_b.ptr == '*') { - if (wildcards) - { - (*wildcards)++; - } + (*wildcards)++; continue; } /* same lengths for values */ if (value_a.len != value_b.len) + { return FALSE; + } /* printableStrings and email RDNs require uppercase comparison */ - if (type_a == type_b && (type_a == ASN1_PRINTABLESTRING - || (type_a == ASN1_IA5STRING && known_oid(oid_a) == OID_PKCS9_EMAIL))) + if (type_a == type_b && (type_a == ASN1_PRINTABLESTRING || + (type_a == ASN1_IA5STRING && asn1_known_oid(oid_a) == OID_PKCS9_EMAIL))) { if (strncasecmp(value_a.ptr, value_b.ptr, value_b.len) != 0) { @@ -550,12 +559,8 @@ bool match_dn(chunk_t a, chunk_t b, int *wildcards) { return FALSE; } - /* the two DNs match! */ - if (wildcards) - { - *wildcards = min(*wildcards, MAX_WILDCARDS); - } + *wildcards = min(*wildcards, ID_MATCH_ONE_WILDCARD - ID_MATCH_MAX_WILDCARDS); return TRUE; } @@ -645,7 +650,8 @@ static status_t atodn(char *src, chunk_t *dn) { name.len -= whitespace; rdn_type = (x501rdns[i].type == ASN1_PRINTABLESTRING - && !is_printablestring(name))? ASN1_T61STRING : x501rdns[i].type; + && !asn1_is_printablestring(name)) + ? ASN1_T61STRING : x501rdns[i].type; if (rdn_count < RDN_MAX) { @@ -675,7 +681,7 @@ static status_t atodn(char *src, chunk_t *dn) /* build the distinguished name sequence */ { int i; - u_char *pos = build_asn1_object(dn, ASN1_SEQUENCE, dn_len); + u_char *pos = asn1_build_object(dn, ASN1_SEQUENCE, dn_len); for (i = 0; i < rdn_count; i++) { @@ -776,198 +782,189 @@ static bool equals_strcasecmp(private_identification_t *this, /** * Default implementation of identification_t.matches. */ -static bool matches_binary(private_identification_t *this, - private_identification_t *other, int *wildcards) +static id_match_t matches_binary(private_identification_t *this, + private_identification_t *other) { if (other->type == ID_ANY) { - if (wildcards) - { - *wildcards = MAX_WILDCARDS; - } - return TRUE; + return ID_MATCH_ANY; } - if (wildcards) + if (this->type == other->type && + chunk_equals(this->encoded, other->encoded)) { - *wildcards = 0; + return ID_MATCH_PERFECT; } - return this->type == other->type && - chunk_equals(this->encoded, other->encoded); + return ID_MATCH_NONE; } /** * Special implementation of identification_t.matches for ID_RFC822_ADDR/ID_FQDN. * Checks for a wildcard in other-string, and compares it against this-string. */ -static bool matches_string(private_identification_t *this, - private_identification_t *other, int *wildcards) +static id_match_t matches_string(private_identification_t *this, + private_identification_t *other) { u_int len = other->encoded.len; if (other->type == ID_ANY) { - if (wildcards) - { - *wildcards = MAX_WILDCARDS; - } - return TRUE; + return ID_MATCH_ANY; } - if (this->type != other->type) - return FALSE; - - /* try a binary comparison first */ - if (equals_binary(this, other)) { - if (wildcards) - { - *wildcards = 0; - } - return TRUE; + return ID_MATCH_NONE; + } + /* try a equals check first */ + if (equals_strcasecmp(this, other)) + { + return ID_MATCH_PERFECT; } - if (len == 0 || this->encoded.len < len) - return FALSE; + { + return ID_MATCH_NONE; + } /* check for single wildcard at the head of the string */ if (*other->encoded.ptr == '*') { - if (wildcards) - { - *wildcards = 1; - } - /* single asterisk matches any string */ if (len-- == 1) - return TRUE; - - if (memeq(this->encoded.ptr + this->encoded.len - len, other->encoded.ptr + 1, len)) - return TRUE; + { /* not better than ID_ANY */ + return ID_MATCH_ANY; + } + if (strncasecmp(this->encoded.ptr + this->encoded.len - len, + other->encoded.ptr + 1, len) == 0) + { + return ID_MATCH_ONE_WILDCARD; + } } - - return FALSE; + return ID_MATCH_NONE; } /** * Special implementation of identification_t.matches for ID_ANY. * ANY matches only another ANY, but nothing other */ -static bool matches_any(private_identification_t *this, - private_identification_t *other, int *wildcards) +static id_match_t matches_any(private_identification_t *this, + private_identification_t *other) { - if (wildcards) + if (other->type == ID_ANY) { - *wildcards = 0; + return ID_MATCH_ANY; } - return other->type == ID_ANY; + return ID_MATCH_NONE; } /** - * Special implementation of identification_t.matches for ID_DER_ASN1_DN. - * ANY matches any, even ANY, thats why its there... + * Special implementation of identification_t.matches for ID_DER_ASN1_DN */ -static bool matches_dn(private_identification_t *this, - private_identification_t *other, int *wildcards) +static id_match_t matches_dn(private_identification_t *this, + private_identification_t *other) { + int wc; + if (other->type == ID_ANY) { - if (wildcards) - { - *wildcards = MAX_WILDCARDS; - } - return TRUE; + return ID_MATCH_ANY; } if (this->type == other->type) { - return match_dn(this->encoded, other->encoded, wildcards); + if (match_dn(this->encoded, other->encoded, &wc)) + { + return ID_MATCH_PERFECT - wc; + } } - return FALSE; + return ID_MATCH_NONE; } /** * output handler in printf() */ static int print(FILE *stream, const struct printf_info *info, - const void *const *args) + const void *const *args) { private_identification_t *this = *((private_identification_t**)(args[0])); char buf[BUF_LEN]; chunk_t proper, buf_chunk = chunk_from_buf(buf); - int written; if (this == NULL) { - return fprintf(stream, "(null)"); + return fprintf(stream, "%*s", info->width, "(null)"); } switch (this->type) { case ID_ANY: - return fprintf(stream, "%%any"); + snprintf(buf, sizeof(buf), "%%any"); + break; case ID_IPV4_ADDR: if (this->encoded.len < sizeof(struct in_addr) || inet_ntop(AF_INET, this->encoded.ptr, buf, sizeof(buf)) == NULL) { - return fprintf(stream, "(invalid ID_IPV4_ADDR)"); - } - else - { - return fprintf(stream, "%s", buf); + snprintf(buf, sizeof(buf), "(invalid ID_IPV4_ADDR)"); } + break; case ID_IPV6_ADDR: if (this->encoded.len < sizeof(struct in6_addr) || inet_ntop(AF_INET6, this->encoded.ptr, buf, INET6_ADDRSTRLEN) == NULL) { - return fprintf(stream, "(invalid ID_IPV6_ADDR)"); - } - else - { - return fprintf(stream, "%s", buf); + snprintf(buf, sizeof(buf), "(invalid ID_IPV6_ADDR)"); } + break; case ID_FQDN: - { - proper = sanitize_chunk(this->encoded); - written = fprintf(stream, "%.*s", proper.len, proper.ptr); - chunk_free(&proper); - return written; - } case ID_RFC822_ADDR: - { + case ID_DER_ASN1_GN_URI: proper = sanitize_chunk(this->encoded); - written = fprintf(stream, "%.*s", proper.len, proper.ptr); + snprintf(buf, sizeof(buf), "%.*s", proper.len, proper.ptr); chunk_free(&proper); - return written; - } + break; case ID_DER_ASN1_DN: - { - snprintf(buf, sizeof(buf), "%.*s", this->encoded.len, this->encoded.ptr); - /* TODO: whats returned on failure?*/ - dntoa(this->encoded, &buf_chunk); - return fprintf(stream, "%s", buf); - } + if (!dntoa(this->encoded, &buf_chunk)) + { + snprintf(buf, sizeof(buf), "(invalid ID_DER_ASN1_DN)"); + } + break; case ID_DER_ASN1_GN: - return fprintf(stream, "(ASN.1 general Name"); + snprintf(buf, sizeof(buf), "(ASN.1 general Name"); + break; case ID_KEY_ID: - return fprintf(stream, "(KEY_ID)"); - case ID_DER_ASN1_GN_URI: - { - proper = sanitize_chunk(this->encoded); - written = fprintf(stream, "%.*s", proper.len, proper.ptr); - chunk_free(&proper); - return written; - } + case ID_PUBKEY_INFO_SHA1: + case ID_PUBKEY_SHA1: + case ID_CERT_DER_SHA1: + snprintf(buf, sizeof(buf), "%#B", &this->encoded); + break; default: - return fprintf(stream, "(unknown ID type: %d)", this->type); + snprintf(buf, sizeof(buf), "(unknown ID type: %d)", this->type); + break; + } + if (info->left) + { + return fprintf(stream, "%-*s", info->width, buf); + } + return fprintf(stream, "%*s", info->width, buf); +} + +/** + * arginfo handler + */ +static int arginfo(const struct printf_info *info, size_t n, int *argtypes) +{ + if (n > 0) + { + argtypes[0] = PA_POINTER; } + return 1; } /** - * register printf() handlers + * Get printf hook functions */ -static void __attribute__ ((constructor))print_register() +printf_hook_functions_t identification_get_printf_hooks() { - register_printf_function(PRINTF_IDENTIFICATION, print, arginfo_ptr); + printf_hook_functions_t hook = {print, arginfo}; + + return hook; } /** @@ -1011,7 +1008,7 @@ static private_identification_t *identification_create(void) this->public.destroy = (void (*) (identification_t*))destroy; /* we use these as defaults, the may be overloaded for special ID types */ this->public.equals = (bool (*) (identification_t*,identification_t*))equals_binary; - this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_binary; + this->public.matches = (id_match_t (*) (identification_t*,identification_t*))matches_binary; this->encoded = chunk_empty; @@ -1041,7 +1038,7 @@ identification_t *identification_create_from_string(char *string) } this->type = ID_DER_ASN1_DN; this->public.equals = (bool (*) (identification_t*,identification_t*))equals_dn; - this->public.matches = (bool (*) (identification_t*,identification_t*,int*))matches_dn; + this->public.matches = (id_match_t (*) (identification_t*,identification_t*))matches_dn; return &this->public; } else if (strchr(string, '@') == NULL) @@ -1054,8 +1051,8 @@ identification_t *identification_create_from_string(char *string) { /* any ID will be accepted */ this->type = ID_ANY; - this->public.matches = (bool (*) - (identification_t*,identification_t*,int*))matches_any; + this->public.matches = (id_match_t (*) + (identification_t*,identification_t*))matches_any; return &this->public; } else @@ -1072,8 +1069,8 @@ identification_t *identification_create_from_string(char *string) this->type = ID_FQDN; this->encoded.ptr = strdup(string); this->encoded.len = strlen(string); - this->public.matches = (bool (*) - (identification_t*,identification_t*,int*))matches_string; + this->public.matches = (id_match_t (*) + (identification_t*,identification_t*))matches_string; this->public.equals = (bool (*) (identification_t*,identification_t*))equals_strcasecmp; return &(this->public); @@ -1105,17 +1102,19 @@ identification_t *identification_create_from_string(char *string) { if (*(string + 1) == '#') { - /* TODO: Pluto handles '#' as hex encoded ID_KEY_ID. */ - free(this); - return NULL; + string += 2; + this->type = ID_KEY_ID; + this->encoded = chunk_from_hex( + chunk_create(string, strlen(string)), NULL); + return &(this->public); } else { this->type = ID_FQDN; this->encoded.ptr = strdup(string + 1); this->encoded.len = strlen(string + 1); - this->public.matches = (bool (*) - (identification_t*,identification_t*,int*))matches_string; + this->public.matches = (id_match_t (*) + (identification_t*,identification_t*))matches_string; this->public.equals = (bool (*) (identification_t*,identification_t*))equals_strcasecmp; return &(this->public); @@ -1126,8 +1125,8 @@ identification_t *identification_create_from_string(char *string) this->type = ID_RFC822_ADDR; this->encoded.ptr = strdup(string); this->encoded.len = strlen(string); - this->public.matches = (bool (*) - (identification_t*,identification_t*,int*))matches_string; + this->public.matches = (id_match_t (*) + (identification_t*,identification_t*))matches_string; this->public.equals = (bool (*) (identification_t*,identification_t*))equals_strcasecmp; return &(this->public); @@ -1146,27 +1145,30 @@ identification_t *identification_create_from_encoding(id_type_t type, chunk_t en switch (type) { case ID_ANY: - this->public.matches = (bool (*) - (identification_t*,identification_t*,int*))matches_any; + this->public.matches = (id_match_t (*) + (identification_t*,identification_t*))matches_any; break; case ID_FQDN: case ID_RFC822_ADDR: - this->public.matches = (bool (*) - (identification_t*,identification_t*,int*))matches_string; + this->public.matches = (id_match_t (*) + (identification_t*,identification_t*))matches_string; this->public.equals = (bool (*) (identification_t*,identification_t*))equals_strcasecmp; break; case ID_DER_ASN1_DN: this->public.equals = (bool (*) (identification_t*,identification_t*))equals_dn; - this->public.matches = (bool (*) - (identification_t*,identification_t*,int*))matches_dn; + this->public.matches = (id_match_t (*) + (identification_t*,identification_t*))matches_dn; break; case ID_IPV4_ADDR: case ID_IPV6_ADDR: case ID_DER_ASN1_GN: case ID_KEY_ID: case ID_DER_ASN1_GN_URI: + case ID_PUBKEY_INFO_SHA1: + case ID_PUBKEY_SHA1: + case ID_CERT_DER_SHA1: default: break; } diff --git a/src/libstrongswan/utils/identification.h b/src/libstrongswan/utils/identification.h index 59c568eaf..591909411 100644 --- a/src/libstrongswan/utils/identification.h +++ b/src/libstrongswan/utils/identification.h @@ -1,10 +1,3 @@ -/** - * @file identification.h - * - * @brief Interface of identification_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: identification.h 3838 2008-04-18 11:24:45Z tobias $ + */ + +/** + * @defgroup identification identification + * @{ @ingroup utils */ @@ -27,15 +27,33 @@ typedef enum id_type_t id_type_t; typedef struct identification_t identification_t; +typedef enum id_match_t id_match_t; #include <library.h> -#define MAX_WILDCARDS 14 +/** + * Matches returned from identification_t.match + */ +enum id_match_t { + /* no match */ + ID_MATCH_NONE = 0, + /* match to %any ID */ + ID_MATCH_ANY = 1, + /* match with maximum allowed wildcards */ + ID_MATCH_MAX_WILDCARDS = 2, + /* match with only one wildcard */ + ID_MATCH_ONE_WILDCARD = 19, + /* perfect match, won't get better */ + ID_MATCH_PERFECT = 20, +}; /** - * @brief ID Types in a ID payload. - * - * @ingroup utils + * enum names for id_match_t. + */ +extern enum_name_t *id_match_names; + +/** + * ID Types in a ID payload. */ enum id_type_t { @@ -109,7 +127,21 @@ enum id_type_t { * private type which represents a GeneralName of type URI */ ID_DER_ASN1_GN_URI = 201, - + + /** + * SHA1 hash over PKCS#1 subjectPublicKeyInfo + */ + ID_PUBKEY_INFO_SHA1, + + /** + * SHA1 hash over PKCS#1 subjectPublicKey + */ + ID_PUBKEY_SHA1, + + /** + * SHA1 hash of the binary DER encoding of a certificate + */ + ID_CERT_DER_SHA1, }; /** @@ -118,110 +150,84 @@ enum id_type_t { extern enum_name_t *id_type_names; /** - * @brief Generic identification, such as used in ID payload. - * - * The following types are possible: - * - ID_IPV4_ADDR - * - ID_FQDN - * - ID_RFC822_ADDR - * - ID_IPV6_ADDR - * - ID_DER_ASN1_DN - * - ID_DER_ASN1_GN - * - ID_KEY_ID - * - ID_DER_ASN1_GN_URI - * - * @b Constructors: - * - identification_create_from_string() - * - identification_create_from_encoding() + * Generic identification, such as used in ID payload. * * @todo Support for ID_DER_ASN1_GN is minimal right now. Comparison * between them and ID_IPV4_ADDR/RFC822_ADDR would be nice. - * - * @ingroup utils */ struct identification_t { /** - * @brief Get the encoding of this id, to send over + * Get the encoding of this id, to send over * the network. * - * @warning Result points to internal data, do NOT free! + * Result points to internal data, do not free. * - * @param this the identification_t object * @return a chunk containing the encoded bytes */ chunk_t (*get_encoding) (identification_t *this); /** - * @brief Get the type of this identification. + * Get the type of this identification. * - * @param this the identification_t object * @return id_type_t */ id_type_t (*get_type) (identification_t *this); /** - * @brief Check if two identification_t objects are equal. + * Check if two identification_t objects are equal. * - * @param this the identification_t object * @param other other identification_t object * @return TRUE if the IDs are equal */ bool (*equals) (identification_t *this, identification_t *other); /** - * @brief Check if an ID matches a wildcard ID. + * Check if an ID matches a wildcard ID. * * An identification_t may contain wildcards, such as * *@strongswan.org. This call checks if a given ID * (e.g. tester@strongswan.org) belongs to a such wildcard - * ID. Returns TRUE if + * ID. Returns > 0 if * - IDs are identical * - other is of type ID_ANY * - other contains a wildcard and matches this + * + * The larger the return value is, the better is the match. Zero means + * no match at all, 1 means a bad match, and 2 a slightly better match. * - * @param this the ID without wildcard - * @param other the ID containing a wildcard + * @param other the ID containing one or more wildcards * @param wildcards returns the number of wildcards, may be NULL - * @return TRUE if match is found + * @return match value as described above */ - bool (*matches) (identification_t *this, identification_t *other, int *wildcards); + id_match_t (*matches) (identification_t *this, identification_t *other); /** - * @brief Check if an ID is a wildcard ID. + * Check if an ID is a wildcard ID. * * If the ID represents multiple IDs (with wildcards, or * as the type ID_ANY), TRUE is returned. If it is unique, * FALSE is returned. * - * @param this identification_t object * @return TRUE if ID contains wildcards */ bool (*contains_wildcards) (identification_t *this); /** - * @brief Clone a identification_t instance. + * Clone a identification_t instance. * - * @param this the identification_t object to clone * @return clone of this */ identification_t *(*clone) (identification_t *this); /** - * @brief Destroys a identification_t object. - * - * @param this identification_t object + * Destroys a identification_t object. */ void (*destroy) (identification_t *this); }; /** - * @brief Creates an identification_t object from a string. - * - * @param string input string, which will be converted - * @return - * - created identification_t object, or - * - NULL if unsupported string supplied. + * Creates an identification_t object from a string. * * The input string may be e.g. one of the following: * - ID_IPV4_ADDR: 192.168.0.1 @@ -239,23 +245,29 @@ struct identification_t { * ND, UID, DC, CN, S, SN, serialNumber, C, L, ST, O, OU, T, D, * N, G, I, ID, EN, EmployeeNumber, E, Email, emailAddress, UN, * unstructuredName, TCGID. - * - * @ingroup utils + * + * @param string input string, which will be converted + * @return created identification_t, NULL if not supported. */ identification_t * identification_create_from_string(char *string); /** - * @brief Creates an identification_t object from an encoded chunk. - * - * @param type type of this id, such as ID_IPV4_ADDR - * @param encoded encoded bytes, such as from identification_t.get_encoding - * @return identification_t object + * Creates an identification_t object from an encoded chunk. * * In contrast to identification_create_from_string(), this constructor never * returns NULL, even when the conversion to a string representation fails. - * - * @ingroup utils + * + * @param type type of this id, such as ID_IPV4_ADDR + * @param encoded encoded bytes, such as from identification_t.get_encoding + * @return identification_t */ identification_t * identification_create_from_encoding(id_type_t type, chunk_t encoded); -#endif /* IDENTIFICATION_H_ */ +/** + * Get the printf hook functions. + * + * @return printf hook functions + */ +printf_hook_functions_t identification_get_printf_hooks(); + +#endif /* IDENTIFICATION_H_ @} */ diff --git a/src/libstrongswan/utils/iterator.h b/src/libstrongswan/utils/iterator.h index b4ff85bfb..a1bdad1d6 100644 --- a/src/libstrongswan/utils/iterator.h +++ b/src/libstrongswan/utils/iterator.h @@ -1,10 +1,3 @@ -/** - * @file iterator.h - * - * @brief Interface iterator_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,13 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: iterator.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup iterator iterator + * @{ @ingroup utils */ #ifndef ITERATOR_H_ @@ -29,13 +29,11 @@ typedef enum hook_result_t hook_result_t; /** - * @brief Return value of an iterator hook. + * Return value of an iterator hook. * * Returning HOOK_AGAIN is useful to "inject" additional elements in an * iteration, HOOK_NEXT is the normal iterator behavior, and HOOK_SKIP may * be used to filter elements out. - * - * @ingroup utils */ enum hook_result_t { @@ -56,14 +54,12 @@ enum hook_result_t { }; /** - * @brief Iterator hook function prototype. + * Iterator hook function prototype. * * @param param user supplied parameter * @param in the value the hook receives from the iterator * @param out the value supplied as a result to the iterator * @return a hook_result_t - * - * @ingroup utils */ typedef hook_result_t (iterator_hook_t)(void *param, void *in, void **out); @@ -71,44 +67,34 @@ typedef hook_result_t (iterator_hook_t)(void *param, void *in, void **out); typedef struct iterator_t iterator_t; /** - * @brief Iterator interface, allows iteration over collections. + * Iterator interface, allows iteration over collections. * * iterator_t defines an interface for iterating over collections. * It allows searching, deleting, updating and inserting. * - * @b Constructors: - * - via linked_list_t.create_iterator, or - * - any other class which supports the iterator_t interface - * - * @see linked_list_t - * - * @ingroup utils + * @deprecated Use enumerator instead. */ struct iterator_t { /** - * @brief Return number of list items. + * Return number of list items. * - * @param this calling object * @return number of list items */ int (*get_count) (iterator_t *this); /** - * @brief Iterate over all items. + * Iterate over all items. * * The easy way to iterate over items. * - * @param this calling object - * @param[out] value item - * @return - * - TRUE, if there was an element available, - * - FALSE otherwise + * @param value item + * @return TRUE, if there was an element available, FALSE otherwise */ bool (*iterate) (iterator_t *this, void** value); /** - * @brief Hook a function into the iterator. + * Hook a function into the iterator. * * Sometimes it is useful to hook in an iterator. The hook function is * called before any successful return of iterate(). It takes the @@ -119,80 +105,67 @@ struct iterator_t { * If an iterator is hooked, only the iterate() method is valid, * all other methods behave undefined. * - * @param this calling object - * @param hook iterator hook which manipulates the iterated value - * @param param user supplied parameter to pass back to the hook + * @param hook iterator hook which manipulates the iterated value + * @param param user supplied parameter to pass back to the hook */ void (*set_iterator_hook) (iterator_t *this, iterator_hook_t *hook, void *param); /** - * @brief Inserts a new item before the given iterator position. + * Inserts a new item before the given iterator position. * * The iterator position is not changed after inserting * - * @param this calling iterator - * @param[in] item value to insert in list + * @param item value to insert in list */ void (*insert_before) (iterator_t *this, void *item); /** - * @brief Inserts a new item after the given iterator position. + * Inserts a new item after the given iterator position. * * The iterator position is not changed after inserting. * - * @param this calling iterator - * @param[in] item value to insert in list + * @param this calling iterator + * @param item value to insert in list */ void (*insert_after) (iterator_t *this, void *item); /** - * @brief Replace the current item at current iterator position. + * Replace the current item at current iterator position. * * The iterator position is not changed after replacing. * - * @param this calling iterator - * @param[out] old_item old value will be written here(can be NULL) - * @param[in] new_item new value - * - * @return - * - SUCCESS - * - FAILED if iterator is on an invalid position + * @param this calling iterator + * @param old old value will be written here(can be NULL) + * @param new new value + * @return SUCCESS, FAILED if iterator is on an invalid position */ - status_t (*replace) (iterator_t *this, void **old_item, void *new_item); + status_t (*replace) (iterator_t *this, void **old, void *new); /** - * @brief Removes an element from list at the given iterator position. + * Removes an element from list at the given iterator position. * * The iterator is set the the following position: * - to the item before, if available * - it gets reseted, otherwise * - * @param this calling object - * @return - * - SUCCESS - * - FAILED if iterator is on an invalid position + * @return SUCCESS, FAILED if iterator is on an invalid position */ status_t (*remove) (iterator_t *this); /** - * @brief Resets the iterator position. + * Resets the iterator position. * * After reset, the iterator_t objects doesn't point to an element. * A call to iterator_t.has_next is necessary to do any other operations * with the resetted iterator. - * - * @param this calling object */ void (*reset) (iterator_t *this); /** - * @brief Destroys an iterator. - * - * @param this iterator to destroy - * + * Destroys an iterator. */ void (*destroy) (iterator_t *this); }; -#endif /*ITERATOR_H_*/ +#endif /*ITERATOR_H_ @} */ diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c index dab18fd5c..cff5a1c81 100644 --- a/src/libstrongswan/utils/leak_detective.c +++ b/src/libstrongswan/utils/leak_detective.c @@ -1,11 +1,5 @@ -/** - * @file leak_detective.c - * - * @brief Allocation hooks to find memory leaks. - */ - /* - * Copyright (C) 2006 Martin Willi + * Copyright (C) 2006-2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -17,8 +11,15 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: leak_detective.c 4044 2008-06-06 15:05:54Z martin $ */ +#ifdef HAVE_DLADDR +# define _GNU_SOURCE +# include <dlfcn.h> +#endif /* HAVE_DLADDR */ + #include <stddef.h> #include <string.h> #include <stdio.h> @@ -33,6 +34,7 @@ #include <pthread.h> #include <netdb.h> #include <printf.h> +#include <locale.h> #ifdef HAVE_BACKTRACE # include <execinfo.h> #endif /* HAVE_BACKTRACE */ @@ -42,7 +44,18 @@ #include <library.h> #include <debug.h> -#ifdef LEAK_DETECTIVE +typedef struct private_leak_detective_t private_leak_detective_t; + +/** + * private data of leak_detective + */ +struct private_leak_detective_t { + + /** + * public functions + */ + leak_detective_t public; +}; /** * Magic value which helps to detect memory corruption. Yummy! @@ -50,6 +63,11 @@ #define MEMORY_HEADER_MAGIC 0x7ac0be11 /** + * Magic written to tail of allocation + */ +#define MEMORY_TAIL_MAGIC 0xcafebabe + +/** * Pattern which is filled in memory before freeing it */ #define MEMORY_FREE_PATTERN 0xFF @@ -66,25 +84,26 @@ static void *malloc_hook(size_t, const void *); static void *realloc_hook(void *, size_t, const void *); static void free_hook(void*, const void *); +void *(*old_malloc_hook)(size_t, const void *); +void *(*old_realloc_hook)(void *, size_t, const void *); +void (*old_free_hook)(void*, const void *); + static u_int count_malloc = 0; static u_int count_free = 0; static u_int count_realloc = 0; typedef struct memory_header_t memory_header_t; +typedef struct memory_tail_t memory_tail_t; /** * Header which is prepended to each allocated memory block */ struct memory_header_t { - /** - * Magci byte which must(!) hold MEMORY_HEADER_MAGIC - */ - u_int32_t magic; /** * Number of bytes following after the header */ - size_t bytes; + u_int bytes; /** * Stack frames at the time of allocation @@ -105,7 +124,25 @@ struct memory_header_t { * Pointer to next entry in linked list */ memory_header_t *next; -}; + + /** + * magic bytes to detect bad free or heap underflow, MEMORY_HEADER_MAGIC + */ + u_int32_t magic; + +}__attribute__((__packed__)); + +/** + * tail appended to each allocated memory block + */ +struct memory_tail_t { + + /** + * Magic bytes to detect heap overflow, MEMORY_TAIL_MAGIC + */ + u_int32_t magic; + +}__attribute__((__packed__)); /** * first mem header is just a dummy to chain @@ -120,22 +157,11 @@ static memory_header_t first_header = { }; /** - * standard hooks, used to temparily remove hooking - */ -static void *old_malloc_hook, *old_realloc_hook, *old_free_hook; - -/** * are the hooks currently installed? */ static bool installed = FALSE; /** - * Mutex to exclusivly uninstall hooks, access heap list - */ -static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - - -/** * log stack frames queried by backtrace() * TODO: Dump symbols of static functions. This could be done with * the addr2line utility or the GNU BFD Library... @@ -143,80 +169,140 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static void log_stack_frames(void **stack_frames, int stack_frame_count) { #ifdef HAVE_BACKTRACE - char **strings; size_t i; + char **strings; + + strings = backtrace_symbols(stack_frames, stack_frame_count); - strings = backtrace_symbols (stack_frames, stack_frame_count); - - DBG1(" dumping %d stack frame addresses", stack_frame_count); - + fprintf(stderr, " dumping %d stack frame addresses:\n", stack_frame_count); for (i = 0; i < stack_frame_count; i++) { - DBG1(" %s", strings[i]); +#ifdef HAVE_DLADDR + Dl_info info; + + if (dladdr(stack_frames[i], &info)) + { + char cmd[1024]; + FILE *output; + char c; + void *ptr = stack_frames[i]; + + if (strstr(info.dli_fname, ".so")) + { + ptr = (void*)(stack_frames[i] - info.dli_fbase); + } + snprintf(cmd, sizeof(cmd), "addr2line -e %s %p", info.dli_fname, ptr); + if (info.dli_sname) + { + fprintf(stderr, " \e[33m%s\e[0m @ %p (\e[31m%s\e[0m+0x%x) [%p]\n", + info.dli_fname, info.dli_fbase, info.dli_sname, + stack_frames[i] - info.dli_saddr, stack_frames[i]); + } + else + { + fprintf(stderr, " \e[33m%s\e[0m @ %p [%p]\n", info.dli_fname, + info.dli_fbase, stack_frames[i]); + } + fprintf(stderr, " -> \e[32m"); + output = popen(cmd, "r"); + if (output) + { + while (TRUE) + { + c = getc(output); + if (c == '\n' || c == EOF) + { + break; + } + fputc(c, stderr); + } + } + else + { +#endif /* HAVE_DLADDR */ + fprintf(stderr, " %s\n", strings[i]); +#ifdef HAVE_DLADDR + } + fprintf(stderr, "\n\e[0m"); + } +#endif /* HAVE_DLADDR */ } free (strings); #endif /* HAVE_BACKTRACE */ } /** - * Whitelist, which contains address ranges in stack frames ignored when leaking. - * - * This is necessary, as some function use allocation hacks (static buffers) - * and so on, which we want to suppress on leak reports. + * Leak report white list * - * The range_size is calculated using the readelf utility, e.g.: - * readelf -s /lib/glibc.so.6 - * The values are for glibc-2.4 and may or may not be correct on other systems. + * List of functions using static allocation buffers or should be suppressed + * otherwise on leak report. */ -typedef struct whitelist_t whitelist_t; - -struct whitelist_t { - void* range_start; - size_t range_size; -}; - -#ifdef LIBCURL -/* dummy declaration for whitelisting */ -void *Curl_getaddrinfo(void); -#endif /* LIBCURL */ - -whitelist_t whitelist[] = { - {pthread_create, 2542}, - {pthread_setspecific, 217}, - {mktime, 60}, - {tzset, 123}, - {inet_ntoa, 249}, - {strerror, 180}, - {getprotobynumber, 291}, - {getservbyport, 311}, - {register_printf_function, 159}, - {syslog, 44}, - {vsyslog, 41}, - {dlopen, 109}, -# ifdef LIBCURL - /* from /usr/lib/libcurl.so.3 */ - {Curl_getaddrinfo, 480}, -# endif /* LIBCURL */ +char *whitelist[] = { + /* pthread stuff */ + "pthread_create", + "pthread_setspecific", + /* glibc functions */ + "mktime", + "__gmtime_r", + "tzset", + "inet_ntoa", + "strerror", + "getprotobynumber", + "getservbyport", + "getservbyname", + "gethostbyname_r", + "gethostbyname2_r", + "getpwnam_r", + "getgrnam_r", + "register_printf_function", + "syslog", + "vsyslog", + "getaddrinfo", + "setlocale", + /* ignore dlopen, as we do not dlclose to get proper leak reports */ + "dlopen", + "dlerror", + /* mysql functions */ + "mysql_init_character_set", + "init_client_errs", + "my_thread_init", + /* fastcgi library */ + "FCGX_Init", + /* libxml */ + "xmlInitCharEncodingHandlers", + "xmlInitParser", + "xmlInitParserCtxt", + /* ClearSilver */ + "nerr_init", + /* OpenSSL */ + "RSA_new_method", + "DH_new_method", }; /** - * Check if this stack frame is whitelisted. + * check if a stack frame contains functions listed above */ static bool is_whitelisted(void **stack_frames, int stack_frame_count) { int i, j; +#ifdef HAVE_DLADDR for (i=0; i< stack_frame_count; i++) { - for (j=0; j<sizeof(whitelist)/sizeof(whitelist_t); j++) - { - if (stack_frames[i] >= whitelist[j].range_start && - stack_frames[i] <= (whitelist[j].range_start + whitelist[j].range_size)) + Dl_info info; + + if (dladdr(stack_frames[i], &info) && info.dli_sname) + { + for (j = 0; j < sizeof(whitelist)/sizeof(char*); j++) { - return TRUE; + if (streq(info.dli_sname, whitelist[j])) + { + return TRUE; + } } } } +#endif /* HAVE_DLADDR */ return FALSE; } @@ -226,14 +312,19 @@ static bool is_whitelisted(void **stack_frames, int stack_frame_count) void report_leaks() { memory_header_t *hdr; - int leaks = 0; + int leaks = 0, whitelisted = 0; for (hdr = first_header.next; hdr != NULL; hdr = hdr->next) { - if (!is_whitelisted(hdr->stack_frames, hdr->stack_frame_count)) + if (is_whitelisted(hdr->stack_frames, hdr->stack_frame_count)) + { + whitelisted++; + } + else { - DBG1("Leak (%d bytes at %p):", hdr->bytes, hdr + 1); - log_stack_frames(hdr->stack_frames, hdr->stack_frame_count); + fprintf(stderr, "Leak (%d bytes at %p):\n", hdr->bytes, hdr + 1); + /* skip the first frame, contains leak detective logic */ + log_stack_frames(hdr->stack_frames + 1, hdr->stack_frame_count - 1); leaks++; } } @@ -241,15 +332,16 @@ void report_leaks() switch (leaks) { case 0: - DBG1("No leaks detected"); + fprintf(stderr, "No leaks detected"); break; case 1: - DBG1("One leak detected"); + fprintf(stderr, "One leak detected"); break; default: - DBG1("%d leaks detected", leaks); + fprintf(stderr, "%d leaks detected", leaks); break; } + fprintf(stderr, ", %d suppressed by whitelist\n", whitelisted); } /** @@ -289,17 +381,28 @@ static void uninstall_hooks() void *malloc_hook(size_t bytes, const void *caller) { memory_header_t *hdr; + memory_tail_t *tail; + pthread_t thread_id = pthread_self(); + int oldpolicy; + struct sched_param oldparams, params; + + pthread_getschedparam(thread_id, &oldpolicy, &oldparams); + + params.__sched_priority = sched_get_priority_max(SCHED_FIFO); + pthread_setschedparam(thread_id, SCHED_FIFO, ¶ms); - pthread_mutex_lock(&mutex); count_malloc++; uninstall_hooks(); - hdr = malloc(bytes + sizeof(memory_header_t)); + hdr = malloc(sizeof(memory_header_t) + bytes + sizeof(memory_tail_t)); + tail = ((void*)hdr) + bytes + sizeof(memory_header_t); /* set to something which causes crashes */ - memset(hdr, MEMORY_ALLOC_PATTERN, bytes + sizeof(memory_header_t)); + memset(hdr, MEMORY_ALLOC_PATTERN, + sizeof(memory_header_t) + bytes + sizeof(memory_tail_t)); hdr->magic = MEMORY_HEADER_MAGIC; hdr->bytes = bytes; hdr->stack_frame_count = backtrace(hdr->stack_frames, STACK_FRAMES_COUNT); + tail->magic = MEMORY_TAIL_MAGIC; install_hooks(); /* insert at the beginning of the list */ @@ -310,7 +413,9 @@ void *malloc_hook(size_t bytes, const void *caller) } hdr->previous = &first_header; first_header.next = hdr; - pthread_mutex_unlock(&mutex); + + pthread_setschedparam(thread_id, oldpolicy, &oldparams); + return hdr + 1; } @@ -321,41 +426,53 @@ void free_hook(void *ptr, const void *caller) { void *stack_frames[STACK_FRAMES_COUNT]; int stack_frame_count; - memory_header_t *hdr = ptr - sizeof(memory_header_t); - + memory_header_t *hdr; + memory_tail_t *tail; + pthread_t thread_id = pthread_self(); + int oldpolicy; + struct sched_param oldparams, params; + /* allow freeing of NULL */ if (ptr == NULL) { return; } + hdr = ptr - sizeof(memory_header_t); + tail = ptr + hdr->bytes; + + pthread_getschedparam(thread_id, &oldpolicy, &oldparams); + + params.__sched_priority = sched_get_priority_max(SCHED_FIFO); + pthread_setschedparam(thread_id, SCHED_FIFO, ¶ms); - pthread_mutex_lock(&mutex); count_free++; uninstall_hooks(); - if (hdr->magic != MEMORY_HEADER_MAGIC) + if (hdr->magic != MEMORY_HEADER_MAGIC || + tail->magic != MEMORY_TAIL_MAGIC) { - DBG1("freeing of invalid memory (%p, MAGIC 0x%x != 0x%x):", - ptr, hdr->magic, MEMORY_HEADER_MAGIC); + fprintf(stderr, "freeing invalid memory (%p): " + "header magic 0x%x, tail magic 0x%x:\n", + ptr, hdr->magic, tail->magic); stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT); log_stack_frames(stack_frames, stack_frame_count); - install_hooks(); - pthread_mutex_unlock(&mutex); - return; } - - /* remove item from list */ - if (hdr->next) + else { - hdr->next->previous = hdr->previous; - } - hdr->previous->next = hdr->next; + /* remove item from list */ + if (hdr->next) + { + hdr->next->previous = hdr->previous; + } + hdr->previous->next = hdr->next; + + /* clear MAGIC, set mem to something remarkable */ + memset(hdr, MEMORY_FREE_PATTERN, hdr->bytes + sizeof(memory_header_t)); - /* clear MAGIC, set mem to something remarkable */ - memset(hdr, MEMORY_FREE_PATTERN, hdr->bytes + sizeof(memory_header_t)); + free(hdr); + } - free(hdr); install_hooks(); - pthread_mutex_unlock(&mutex); + pthread_setschedparam(thread_id, oldpolicy, &oldparams); } /** @@ -366,7 +483,11 @@ void *realloc_hook(void *old, size_t bytes, const void *caller) memory_header_t *hdr; void *stack_frames[STACK_FRAMES_COUNT]; int stack_frame_count; - + memory_tail_t *tail; + pthread_t thread_id = pthread_self(); + int oldpolicy; + struct sched_param oldparams, params; + /* allow reallocation of NULL */ if (old == NULL) { @@ -374,27 +495,34 @@ void *realloc_hook(void *old, size_t bytes, const void *caller) } hdr = old - sizeof(memory_header_t); + tail = old + hdr->bytes; + + pthread_getschedparam(thread_id, &oldpolicy, &oldparams); + + params.__sched_priority = sched_get_priority_max(SCHED_FIFO); + pthread_setschedparam(thread_id, SCHED_FIFO, ¶ms); - pthread_mutex_lock(&mutex); count_realloc++; uninstall_hooks(); - if (hdr->magic != MEMORY_HEADER_MAGIC) + if (hdr->magic != MEMORY_HEADER_MAGIC || + tail->magic != MEMORY_TAIL_MAGIC) { - DBG1("reallocation of invalid memory (%p):", old); + fprintf(stderr, "reallocating invalid memory (%p): " + "header magic 0x%x, tail magic 0x%x:\n", + old, hdr->magic, tail->magic); stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT); log_stack_frames(stack_frames, stack_frame_count); - install_hooks(); - pthread_mutex_unlock(&mutex); - raise(SIGKILL); - return NULL; } - - hdr = realloc(hdr, bytes + sizeof(memory_header_t)); - + /* clear tail magic, allocate, set tail magic */ + memset(&tail->magic, MEMORY_ALLOC_PATTERN, sizeof(tail->magic)); + hdr = realloc(hdr, sizeof(memory_header_t) + bytes + sizeof(memory_tail_t)); + tail = ((void*)hdr) + bytes + sizeof(memory_header_t); + tail->magic = MEMORY_TAIL_MAGIC; + /* update statistics */ hdr->bytes = bytes; hdr->stack_frame_count = backtrace(hdr->stack_frames, STACK_FRAMES_COUNT); - + /* update header of linked list neighbours */ if (hdr->next) { @@ -402,70 +530,36 @@ void *realloc_hook(void *old, size_t bytes, const void *caller) } hdr->previous->next = hdr; install_hooks(); - pthread_mutex_unlock(&mutex); + pthread_setschedparam(thread_id, oldpolicy, &oldparams); return hdr + 1; } /** - * Setup leak detective - */ -void __attribute__ ((constructor)) leak_detective_init() -{ - if (getenv("LEAK_DETECTIVE_DISABLE") == NULL) - { - install_hooks(); - } -} - -/** - * Clean up leak detective + * Implementation of leak_detective_t.destroy */ -void __attribute__ ((destructor)) leak_detective_cleanup() +static void destroy(private_leak_detective_t *this) { - if (getenv("LEAK_DETECTIVE_DISABLE") == NULL) + if (installed) { uninstall_hooks(); report_leaks(); } + free(this); } -/** - * Log memory allocation statistics +/* + * see header file */ -void leak_detective_status(FILE *stream) +leak_detective_t *leak_detective_create() { - u_int blocks = 0; - size_t bytes = 0; - memory_header_t *hdr = &first_header; + private_leak_detective_t *this = malloc_thing(private_leak_detective_t); - if (getenv("LEAK_DETECTIVE_DISABLE")) - { - return; - } + this->public.destroy = (void(*)(leak_detective_t*))destroy; - pthread_mutex_lock(&mutex); - while ((hdr = hdr->next)) + if (getenv("LEAK_DETECTIVE_DISABLE") == NULL) { - blocks++; - bytes += hdr->bytes; + install_hooks(); } - pthread_mutex_unlock(&mutex); - - fprintf(stream, "allocation statistics:\n"); - fprintf(stream, " call stats: malloc: %d, free: %d, realloc: %d\n", - count_malloc, count_free, count_realloc); - fprintf(stream, " allocated %d blocks, total size %d bytes (avg. %d bytes)\n", - blocks, bytes, bytes/blocks); -} - -#else /* !LEAK_DETECTION */ - -/** - * Dummy when !using LEAK_DETECTIVE - */ -void leak_detective_status(FILE *stream) -{ - + return &this->public; } -#endif /* LEAK_DETECTION */ diff --git a/src/libstrongswan/utils/leak_detective.h b/src/libstrongswan/utils/leak_detective.h index d4016b06e..763814726 100644 --- a/src/libstrongswan/utils/leak_detective.h +++ b/src/libstrongswan/utils/leak_detective.h @@ -1,11 +1,5 @@ -/** - * @file leak_detective.h - * - * @brief malloc/free hooks to detect leaks. - */ - /* - * Copyright (C) 2006 Martin Willi + * Copyright (C) 2008 Martin Willi * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -19,17 +13,41 @@ * for more details. */ +/** + * @defgroup leak_detective leak_detective + * @{ @ingroup utils + */ + #ifndef LEAK_DETECTIVE_H_ #define LEAK_DETECTIVE_H_ /** - * Log status information about allocation + * Maximum depth stack frames to register */ -void leak_detective_status(FILE *stream); +#define STACK_FRAMES_COUNT 20 + +typedef struct leak_detective_t leak_detective_t; /** - * Max number of stack frames to include in a backtrace. + * Leak detective finds leaks and bad frees using malloc hooks. + * + * Currently leaks are reported to stderr on destruction. + * + * @todo Build an API for leak detective, allowing leak enumeration, statistics + * and dynamic whitelisting. + */ +struct leak_detective_t { + + /** + * Destroy a leak_detective instance. + */ + void (*destroy)(leak_detective_t *this); +}; + +/** + * Create a leak_detective instance. */ -#define STACK_FRAMES_COUNT 30 +leak_detective_t *leak_detective_create(); + +#endif /* LEAK_DETECTIVE_H_ @}*/ -#endif /* LEAK_DETECTIVE_H_ */ diff --git a/src/libstrongswan/utils/lexparser.c b/src/libstrongswan/utils/lexparser.c index 7cc89fc90..8b7b3b547 100644 --- a/src/libstrongswan/utils/lexparser.c +++ b/src/libstrongswan/utils/lexparser.c @@ -1,12 +1,5 @@ -/** - * @file lexparser.c - * - * @brief lexical parser for text-based configuration files - * - */ - /* - * Copyright (C) 2001-2006 Andreas Steffen, Zuercher Hochschule Winterthur + * Copyright (C) 2001-2006 Andreas Steffen * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -18,7 +11,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: lexparser.c 3353 2007-11-19 12:27:08Z martin $ + * $Id: lexparser.c 3872 2008-04-25 07:04:59Z andreas $ */ /* memrchr is a GNU extension */ @@ -55,6 +48,14 @@ bool extract_token(chunk_t *token, const char termination, chunk_t *src) { u_char *eot = memchr(src->ptr, termination, src->len); + if (termination == ' ') + { + u_char *eot_tab = memchr(src->ptr, '\t', src->len); + + /* check if a tab instead of a space terminates the token */ + eot = ( eot_tab == NULL || (eot && eot < eot_tab) ) ? eot : eot_tab; + } + /* initialize empty token */ *token = chunk_empty; diff --git a/src/libstrongswan/utils/lexparser.h b/src/libstrongswan/utils/lexparser.h index 775898139..7d54ca22e 100644 --- a/src/libstrongswan/utils/lexparser.h +++ b/src/libstrongswan/utils/lexparser.h @@ -1,12 +1,7 @@ -/** - * @file lexparser.h - * - * @brief lexical parser for text-based configuration files - * - */ - /* - * Copyright (C) 2001-2006 Andreas Steffen, Zuercher Hochschule Winterthur + * Copyright (C) 2001-2008 Andreas Steffen + * + * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -18,47 +13,57 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id: lexparser.h 3346 2007-11-16 20:23:29Z andreas $ + * $Id: lexparser.h 3876 2008-04-26 09:24:14Z andreas $ + */ + +/** + * @defgroup lexparser lexparser + * @{ @ingroup utils */ +#ifndef LEXPARSER_H_ +#define LEXPARSER_H_ + #include <library.h> /** - * @brief Eats whitespace + * Eats whitespace */ bool eat_whitespace(chunk_t *src); /** - * @brief Compare null-terminated pattern with chunk + * Compare null-terminated pattern with chunk */ bool match(const char *pattern, const chunk_t *ch); /** - * @brief Extracts a token ending with the first occurence a given termination symbol + * Extracts a token ending with the first occurence a given termination symbol */ bool extract_token(chunk_t *token, const char termination, chunk_t *src); /** - * @brief Extracts a token ending with the last occurence a given termination symbol + * Extracts a token ending with the last occurence a given termination symbol */ bool extract_last_token(chunk_t *token, const char termination, chunk_t *src); /** - * @brief Fetches a new text line terminated by \n or \r\n + * Fetches a new text line terminated by \n or \r\n */ bool fetchline(chunk_t *src, chunk_t *line); /** - * @brief Extracts a value that might be single or double quoted + * Extracts a value that might be single or double quoted */ err_t extract_value(chunk_t *value, chunk_t *line); /** - * @brief extracts a name: value pair from a text line + * extracts a name: value pair from a text line */ err_t extract_name_value(chunk_t *name, chunk_t *value, chunk_t *line); /** - * @brief extracts a parameter: value from a text line + * extracts a parameter: value from a text line */ err_t extract_parameter_value(chunk_t *name, chunk_t *value, chunk_t *line); + +#endif /* LEXPARSER_H_ @} */ diff --git a/src/libstrongswan/utils/linked_list.c b/src/libstrongswan/utils/linked_list.c index 63e1bcfbf..80c4e6f9f 100644 --- a/src/libstrongswan/utils/linked_list.c +++ b/src/libstrongswan/utils/linked_list.c @@ -1,12 +1,5 @@ -/** - * @file linked_list.c - * - * @brief Implementation of linked_list_t. - * - */ - /* - * Copyright (C) 2007 Tobias Brunner + * Copyright (C) 2007-2008 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -20,6 +13,8 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: linked_list.c 3841 2008-04-18 11:48:53Z tobias $ */ #include <stdlib.h> @@ -154,9 +149,14 @@ struct private_enumerator_t { enumerator_t enumerator; /** - * next item to enumerate + * associated linked list */ - element_t *next; + private_linked_list_t *list; + + /** + * current item + */ + element_t *current; }; /** @@ -164,12 +164,23 @@ struct private_enumerator_t { */ static bool enumerate(private_enumerator_t *this, void **item) { - if (this->next == NULL) + if (!this->current) { - return FALSE; + if (!this->list->first) + { + return FALSE; + } + this->current = this->list->first; } - *item = this->next->value; - this->next = this->next->next; + else + { + if (!this->current->next) + { + return FALSE; + } + this->current = this->current->next; + } + *item = this->current->value; return TRUE; } @@ -182,7 +193,8 @@ static enumerator_t* create_enumerator(private_linked_list_t *this) enumerator->enumerator.enumerate = (void*)enumerate; enumerator->enumerator.destroy = (void*)free; - enumerator->next = this->first; + enumerator->list = this; + enumerator->current = NULL; return &enumerator->enumerator; } @@ -459,34 +471,37 @@ static void insert_first(private_linked_list_t *this, void *item) } /** - * Implementation of linked_list_t.remove_first. + * unlink an element form the list, returns following element */ -static status_t remove_first(private_linked_list_t *this, void **item) +static element_t* remove_element(private_linked_list_t *this, element_t *element) { - element_t *element = this->first; - - if (element == NULL) + element_t *next, *previous; + + next = element->next; + previous = element->previous; + free(element); + if (next) { - return NOT_FOUND; + next->previous = previous; } - if (element->next != NULL) + else { - element->next->previous = NULL; + this->last = previous; } - this->first = element->next; - - if (item != NULL) + if (previous) + { + previous->next = next; + } + else { - *item = element->value; + this->first = next; } if (--this->count == 0) { + this->first = NULL; this->last = NULL; } - - free(element); - - return SUCCESS; + return next; } /** @@ -503,6 +518,19 @@ static status_t get_first(private_linked_list_t *this, void **item) } /** + * Implementation of linked_list_t.remove_first. + */ +static status_t remove_first(private_linked_list_t *this, void **item) +{ + if (get_first(this, item) == SUCCESS) + { + remove_element(this, this->first); + return SUCCESS; + } + return NOT_FOUND; +} + +/** * Implementation of linked_list_t.insert_last. */ static void insert_last(private_linked_list_t *this, void *item) @@ -529,151 +557,69 @@ static void insert_last(private_linked_list_t *this, void *item) } /** - * Implementation of linked_list_t.remove_last. + * Implementation of linked_list_t.get_last. */ -static status_t remove_last(private_linked_list_t *this, void **item) +static status_t get_last(private_linked_list_t *this, void **item) { - element_t *element = this->last; - - if (element == NULL) + if (this->count == 0) { return NOT_FOUND; } - if (element->previous != NULL) - { - element->previous->next = NULL; - } - this->last = element->previous; - - if (item != NULL) - { - *item = element->value; - } - if (--this->count == 0) - { - this->first = NULL; - } - - free(element); - + *item = this->last->value; return SUCCESS; } /** - * Implementation of linked_list_t.insert_at_position. + * Implementation of linked_list_t.remove_last. */ -static status_t insert_at_position (private_linked_list_t *this,size_t position, void *item) +static status_t remove_last(private_linked_list_t *this, void **item) { - element_t *current_element; - int i; - - if (this->count <= position) + if (get_last(this, item) == SUCCESS) { - return INVALID_ARG; - } - - current_element = this->first; - - for (i = 0; i < position;i++) - { - current_element = current_element->next; - } - - if (current_element == NULL) - { - this->public.insert_last(&(this->public),item); + remove_element(this, this->last); return SUCCESS; } - - element_t *element = element_create(item); - if (current_element->previous == NULL) - { - current_element->previous = element; - element->next = current_element; - this->first = element; - } - else - { - current_element->previous->next = element; - element->previous = current_element->previous; - current_element->previous = element; - element->next = current_element; - } - - - this->count++; - return SUCCESS; + return NOT_FOUND; } /** - * Implementation of linked_list_t.remove_at_position. + * Implementation of linked_list_t.remove. */ -static status_t remove_at_position(private_linked_list_t *this,size_t position, void **item) +static int remove(private_linked_list_t *this, void *item, + bool (*compare)(void *,void*)) { - iterator_t *iterator; - int i; - - if (this->count <= position) - { - return INVALID_ARG; - } + element_t *current = this->first; + int removed = 0; - iterator = this->public.create_iterator(&(this->public),TRUE); - iterator->iterate(iterator, item); - for (i = 0; i < position; i++) + while (current) { - if (!iterator->iterate(iterator, item)) + if ((compare && compare(current->value, item)) || + (!compare && current->value == item)) { - iterator->destroy(iterator); - return INVALID_ARG; + removed++; + current = remove_element(this, current); } - } - iterator->remove(iterator); - iterator->destroy(iterator); - - return SUCCESS; -} - -/** - * Implementation of linked_list_t.get_at_position. - */ -static status_t get_at_position(private_linked_list_t *this,size_t position, void **item) -{ - int i; - iterator_t *iterator; - - if (this->count <= position) - { - return INVALID_ARG; - } - - iterator = this->public.create_iterator(&(this->public),TRUE); - iterator->iterate(iterator, item); - for (i = 0; i < position; i++) - { - if (!iterator->iterate(iterator, item)) + else { - iterator->destroy(iterator); - return INVALID_ARG; + current = current->next; } } - iterator->destroy(iterator); - return SUCCESS; + return removed; } /** - * Implementation of linked_list_t.get_last. + * Implementation of linked_list_t.remove_at. */ -static status_t get_last(private_linked_list_t *this, void **item) +static void remove_at(private_linked_list_t *this, private_enumerator_t *enumerator) { - if (this->count == 0) + element_t *current; + + if (enumerator->current) { - return NOT_FOUND; + current = enumerator->current; + enumerator->current = current->previous; + remove_element(this, current); } - - *item = this->last->value; - - return SUCCESS; } /** @@ -725,14 +671,15 @@ static status_t find_last(private_linked_list_t *this, linked_list_match_t match /** * Implementation of linked_list_t.invoke_offset. */ -static void invoke_offset(private_linked_list_t *this, size_t offset) +static void invoke_offset(private_linked_list_t *this, size_t offset, + void *d1, void *d2, void *d3, void *d4, void *d5) { element_t *current = this->first; while (current) { - void (**method)(void*) = current->value + offset; - (*method)(current->value); + linked_list_invoke_t *method = current->value + offset; + (*method)(current->value, d1, d2, d3, d4, d5); current = current->next; } } @@ -740,13 +687,14 @@ static void invoke_offset(private_linked_list_t *this, size_t offset) /** * Implementation of linked_list_t.invoke_function. */ -static void invoke_function(private_linked_list_t *this, void(*fn)(void*)) +static void invoke_function(private_linked_list_t *this, linked_list_invoke_t fn, + void *d1, void *d2, void *d3, void *d4, void *d5) { element_t *current = this->first; while (current) { - fn(current->value); + fn(current->value, d1, d2, d3, d4, d5); current = current->next; } } @@ -895,11 +843,10 @@ linked_list_t *linked_list_create() this->public.insert_last = (void (*) (linked_list_t *, void *item))insert_last; this->public.remove_first = (status_t (*) (linked_list_t *, void **item))remove_first; this->public.remove_last = (status_t (*) (linked_list_t *, void **item))remove_last; - this->public.insert_at_position = (status_t (*) (linked_list_t *,size_t, void *))insert_at_position; - this->public.remove_at_position = (status_t (*) (linked_list_t *,size_t, void **))remove_at_position; - this->public.get_at_position = (status_t (*) (linked_list_t *,size_t, void **))get_at_position; - this->public.invoke_offset = (void (*)(linked_list_t*,size_t))invoke_offset; - this->public.invoke_function = (void (*)(linked_list_t*,void(*)(void*)))invoke_function; + this->public.remove = (int(*)(linked_list_t*, void *item, bool (*compare)(void *,void*)))remove; + this->public.remove_at = (void(*)(linked_list_t*, enumerator_t *enumerator))remove_at; + this->public.invoke_offset = (void (*)(linked_list_t*,size_t,...))invoke_offset; + this->public.invoke_function = (void (*)(linked_list_t*,linked_list_invoke_t,...))invoke_function; this->public.clone_offset = (linked_list_t * (*)(linked_list_t*,size_t))clone_offset; this->public.clone_function = (linked_list_t * (*)(linked_list_t*,void*(*)(void*)))clone_function; this->public.destroy = (void (*) (linked_list_t *))destroy; diff --git a/src/libstrongswan/utils/linked_list.h b/src/libstrongswan/utils/linked_list.h index ac36ef46d..310e91e3c 100644 --- a/src/libstrongswan/utils/linked_list.h +++ b/src/libstrongswan/utils/linked_list.h @@ -1,12 +1,5 @@ -/** - * @file linked_list.h - * - * @brief Interface of linked_list_t. - * - */ - /* - * Copyright (C) 2007 Tobias Brunner + * Copyright (C) 2007-2008 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter * Hochschule fuer Technik Rapperswil @@ -20,6 +13,13 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. + * + * $Id: linked_list.h 3841 2008-04-18 11:48:53Z tobias $ + */ + +/** + * @defgroup linked_list linked_list + * @{ @ingroup utils */ #ifndef LINKED_LIST_H_ @@ -42,51 +42,50 @@ typedef struct linked_list_t linked_list_t; * @return * - TRUE, if the item matched * - FALSE, otherwise - * @ingroup utils */ typedef bool (*linked_list_match_t)(void *item, ...); /** - * @brief Class implementing a double linked list. - * - * General purpose linked list. This list is not synchronized. + * Method to be invoked on elements in a linked list (used in invoke_* functions) * - * @b Costructors: - * - linked_list_create() + * @param item current list item + * @param ... user supplied data (only pointers, at most 5) + */ +typedef void (*linked_list_invoke_t)(void *item, ...); + +/** + * Class implementing a double linked list. * - * @ingroup utils + * General purpose linked list. This list is not synchronized. */ struct linked_list_t { /** - * @brief Gets the count of items in the list. + * Gets the count of items in the list. * - * @param this calling object * @return number of items in list */ int (*get_count) (linked_list_t *this); /** - * @brief Creates a iterator for the given list. + * Creates a iterator for the given list. * * @warning Created iterator_t object has to get destroyed by the caller. * * @deprecated Iterator is obsolete and will disappear, it is too * complicated to implement. Use enumerator instead. * - * @param this calling object * @param forward iterator direction (TRUE: front to end) * @return new iterator_t object */ iterator_t *(*create_iterator) (linked_list_t *this, bool forward); /** - * @brief Creates a iterator, locking a mutex. + * Creates a iterator, locking a mutex. * * The supplied mutex is acquired immediately, and released * when the iterator gets destroyed. * - * @param this calling object * @param mutex mutex to use for exclusive access * @return new iterator_t object */ @@ -94,113 +93,86 @@ struct linked_list_t { pthread_mutex_t *mutex); /** - * @brief Create an enumerator over the list. + * Create an enumerator over the list. * * The enumerator is a "lightweight" iterator. It only has two methods * and should therefore be much easier to implement. * - * @param this calling object * @return enumerator over list items */ enumerator_t* (*create_enumerator)(linked_list_t *this); /** - * @brief Inserts a new item at the beginning of the list. + * Inserts a new item at the beginning of the list. * - * @param this calling object - * @param[in] item item value to insert in list + * @param item item value to insert in list */ void (*insert_first) (linked_list_t *this, void *item); /** - * @brief Removes the first item in the list and returns its value. + * Removes the first item in the list and returns its value. * - * @param this calling object - * @param[out] item returned value of first item, or NULL - * @return - * - SUCCESS - * - NOT_FOUND, if list is empty + * @param item returned value of first item, or NULL + * @return SUCCESS, or NOT_FOUND if list is empty */ status_t (*remove_first) (linked_list_t *this, void **item); - - /** - * @brief Returns the value of the first list item without removing it. - * - * @param this calling object - * @param[out] item returned value of first item - * @return - * - SUCCESS - * - NOT_FOUND, if list is empty - */ - status_t (*get_first) (linked_list_t *this, void **item); - + /** - * @brief Inserts a new item at the end of the list. - * - * @param this calling object - * @param[in] item value to insert into list + * Remove an item from the list where the enumerator points to. + * + * @param enumerator enumerator with position */ - void (*insert_last) (linked_list_t *this, void *item); + void (*remove_at)(linked_list_t *this, enumerator_t *enumerator); /** - * @brief Inserts a new item at a given position in the list. + * Remove items from the list matching item. * - * @param this calling object - * @param position position starting at 0 to insert new entry - * @param[in] item value to insert into list - * @return - * - SUCCESS - * - INVALID_ARG if position not existing + * If a compare function is given, it is called for each item, where + * the first parameter is the current list item and the second parameter + * is the supplied item parameter. + * If compare is NULL, compare is is done by pointer. + * + * @param item item to remove/pass to comparator + * @param compare compare function, or NULL + * @return number of removed items */ - status_t (*insert_at_position) (linked_list_t *this,size_t position, void *item); + int (*remove)(linked_list_t *this, void *item, bool (*compare)(void *,void*)); /** - * @brief Removes an item from a given position in the list. + * Returns the value of the first list item without removing it. * * @param this calling object - * @param position position starting at 0 to remove entry from - * @param[out] item removed item will be stored at this location - * @return - * - SUCCESS - * - INVALID_ARG if position not existing + * @param item returned value of first item + * @return SUCCESS, NOT_FOUND if list is empty */ - status_t (*remove_at_position) (linked_list_t *this, size_t position, void **item); + status_t (*get_first) (linked_list_t *this, void **item); /** - * @brief Get an item from a given position in the list. + * Inserts a new item at the end of the list. * - * @param this calling object - * @param position position starting at 0 to get entry from - * @param[out] item item will be stored at this location - * @return - * - SUCCESS - * - INVALID_ARG if position not existing + * @param item value to insert into list */ - status_t (*get_at_position) (linked_list_t *this, size_t position, void **item); + void (*insert_last) (linked_list_t *this, void *item); /** - * @brief Removes the last item in the list and returns its value. + * Removes the last item in the list and returns its value. * * @param this calling object - * @param[out] item returned value of last item, or NULL - * @return - * - SUCCESS - * - NOT_FOUND if list is empty + * @param item returned value of last item, or NULL + * @return SUCCESS, NOT_FOUND if list is empty */ status_t (*remove_last) (linked_list_t *this, void **item); /** - * @brief Returns the value of the last list item without removing it. + * Returns the value of the last list item without removing it. * * @param this calling object - * @param[out] item returned value of last item - * @return - * - SUCCESS - * - NOT_FOUND if list is empty + * @param item returned value of last item + * @return SUCCESS, NOT_FOUND if list is empty */ status_t (*get_last) (linked_list_t *this, void **item); - /** @brief Find the first matching element in the list. + /** Find the first matching element in the list. * * The first object passed to the match function is the current list item, * followed by the user supplied data. @@ -210,19 +182,15 @@ struct linked_list_t { * * @warning Only use pointers as user supplied data. * - * @param this calling object * @param match comparison function to call on each object - * @param[out] item - * - the list item, if found - * - NULL, otherwise + * @param item the list item, if found * @param ... user data to supply to match function (limited to 5 arguments) - * @return - * - SUCCESS, if found - * - NOT_FOUND, otherwise + * @return SUCCESS if found, NOT_FOUND otherwise */ - status_t (*find_first) (linked_list_t *this, linked_list_match_t match, void **item, ...); + status_t (*find_first) (linked_list_t *this, linked_list_match_t match, + void **item, ...); - /** @brief Find the last matching element in the list. + /** Find the last matching element in the list. * * The first object passed to the match function is the current list item, * followed by the user supplied data. @@ -232,20 +200,16 @@ struct linked_list_t { * * @warning Only use pointers as user supplied data. * - * @param this calling object * @param match comparison function to call on each object - * @param[out] item - * - the list item, if found - * - NULL, otherwise + * @param item the list item, if found * @param ... user data to supply to match function (limited to 5 arguments) - * @return - * - SUCCESS, if found - * - NOT_FOUND, otherwise + * @return SUCCESS if found, NOT_FOUND otherwise */ - status_t (*find_last) (linked_list_t *this, linked_list_match_t match, void **item, ...); + status_t (*find_last) (linked_list_t *this, linked_list_match_t match, + void **item, ...); /** - * @brief Invoke a method on all of the contained objects. + * Invoke a method on all of the contained objects. * * If a linked list contains objects with function pointers, * invoke() can call a method on each of the objects. The @@ -253,79 +217,70 @@ struct linked_list_t { * which can be evalutated at compile time using the offsetof * macro, e.g.: list->invoke(list, offsetof(object_t, method)); * - * @param this calling object * @param offset offset of the method to invoke on objects + * @param ... user data to supply to called function (limited to 5 arguments) */ - void (*invoke_offset) (linked_list_t *this, size_t offset); + void (*invoke_offset) (linked_list_t *this, size_t offset, ...); /** - * @brief Invoke a function on all of the contained objects. + * Invoke a function on all of the contained objects. * - * @param this calling object - * @param offset offset of the method to invoke on objects + * @param function offset of the method to invoke on objects + * @param ... user data to supply to called function (limited to 5 arguments) */ - void (*invoke_function) (linked_list_t *this, void (*)(void*)); + void (*invoke_function) (linked_list_t *this, linked_list_invoke_t function, ...); /** - * @brief Clones a list and its objects using the objects' clone method. + * Clones a list and its objects using the objects' clone method. * - * @param this calling object * @param offset offset ot the objects clone function * @return cloned list */ linked_list_t *(*clone_offset) (linked_list_t *this, size_t offset); /** - * @brief Clones a list and its objects using a given function. + * Clones a list and its objects using a given function. * - * @param this calling object * @param function function that clones an object * @return cloned list */ linked_list_t *(*clone_function) (linked_list_t *this, void*(*)(void*)); /** - * @brief Destroys a linked_list object. - * - * @param this calling object + * Destroys a linked_list object. */ void (*destroy) (linked_list_t *this); /** - * @brief Destroys a list and its objects using the destructor. + * Destroys a list and its objects using the destructor. * * If a linked list and the contained objects should be destroyed, use * destroy_offset. The supplied offset specifies the destructor to * call on each object. The offset may be calculated using the offsetof * macro, e.g.: list->destroy_offset(list, offsetof(object_t, destroy)); * - * @param this calling object * @param offset offset of the objects destructor */ void (*destroy_offset) (linked_list_t *this, size_t offset); /** - * @brief Destroys a list and its contents using a a cleanup function. + * Destroys a list and its contents using a a cleanup function. * * If a linked list and its contents should get destroyed using a specific * cleanup function, use destroy_function. This is useful when the * list contains malloc()-ed blocks which should get freed, * e.g.: list->destroy_function(list, free); * - * @param this calling object * @param function function to call on each object */ void (*destroy_function) (linked_list_t *this, void (*)(void*)); }; /** - * @brief Creates an empty linked list object. + * Creates an empty linked list object. * * @return linked_list_t object. - * - * @ingroup utils */ linked_list_t *linked_list_create(void); - -#endif /*LINKED_LIST_H_*/ +#endif /*LINKED_LIST_H_ @} */ diff --git a/src/libstrongswan/utils/mutex.c b/src/libstrongswan/utils/mutex.c new file mode 100644 index 000000000..425389b4f --- /dev/null +++ b/src/libstrongswan/utils/mutex.c @@ -0,0 +1,267 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * $Id: mutex.c 3589 2008-03-13 14:14:44Z martin $ + */ + +#include "mutex.h" + +#include <library.h> +#include <debug.h> + +#include <pthread.h> +#include <sys/time.h> +#include <time.h> +#include <errno.h> + + +typedef struct private_mutex_t private_mutex_t; +typedef struct private_n_mutex_t private_n_mutex_t; +typedef struct private_r_mutex_t private_r_mutex_t; +typedef struct private_condvar_t private_condvar_t; + +/** + * private data of mutex + */ +struct private_mutex_t { + + /** + * public functions + */ + mutex_t public; + + /** + * wrapped pthread mutex + */ + pthread_mutex_t mutex; +}; + +/** + * private data of mutex, extended by recursive locking information + */ +struct private_r_mutex_t { + + /** + * public functions + */ + private_mutex_t generic; + + /** + * thread which currently owns mutex + */ + pthread_t thread; + + /** + * times we have locked the lock + */ + int times; +}; + +/** + * private data of condvar + */ +struct private_condvar_t { + + /** + * public functions + */ + condvar_t public; + + /** + * wrapped pthread condvar + */ + pthread_cond_t condvar; +}; + +/** + * Implementation of mutex_t.lock. + */ +static void lock(private_mutex_t *this) +{ + if (pthread_mutex_lock(&this->mutex)) + { + DBG1("!!!! MUTEX %sLOCK ERROR, your code is buggy !!!", ""); + } +} + +/** + * Implementation of mutex_t.unlock. + */ +static void unlock(private_mutex_t *this) +{ + if (pthread_mutex_unlock(&this->mutex)) + { + DBG1("!!!! MUTEX %sLOCK ERROR, your code is buggy !!!", "UN"); + } +} + +/** + * Implementation of mutex_t.lock. + */ +static void lock_r(private_r_mutex_t *this) +{ + pthread_t self = pthread_self(); + + if (this->thread == self) + { + this->times++; + return; + } + lock(&this->generic); + this->thread = self; + this->times = 1; +} + +/** + * Implementation of mutex_t.unlock. + */ +static void unlock_r(private_r_mutex_t *this) +{ + if (--this->times == 0) + { + this->thread = 0; + unlock(&this->generic); + } +} + +/** + * Implementation of mutex_t.destroy + */ +static void mutex_destroy(private_mutex_t *this) +{ + pthread_mutex_destroy(&this->mutex); + free(this); +} + +/* + * see header file + */ +mutex_t *mutex_create(mutex_type_t type) +{ + switch (type) + { + case MUTEX_RECURSIVE: + { + private_r_mutex_t *this = malloc_thing(private_r_mutex_t); + + this->generic.public.lock = (void(*)(mutex_t*))lock_r; + this->generic.public.unlock = (void(*)(mutex_t*))unlock_r; + this->generic.public.destroy = (void(*)(mutex_t*))mutex_destroy; + + pthread_mutex_init(&this->generic.mutex, NULL); + this->thread = 0; + this->times = 0; + + return &this->generic.public; + } + case MUTEX_DEFAULT: + default: + { + private_mutex_t *this = malloc_thing(private_mutex_t); + + this->public.lock = (void(*)(mutex_t*))lock; + this->public.unlock = (void(*)(mutex_t*))unlock; + this->public.destroy = (void(*)(mutex_t*))mutex_destroy; + + pthread_mutex_init(&this->mutex, NULL); + + return &this->public; + } + } +} + +/** + * Implementation of condvar_t.wait. + */ +static void wait(private_condvar_t *this, private_mutex_t *mutex) +{ + pthread_cond_wait(&this->condvar, &mutex->mutex); +} + +/** + * Implementation of condvar_t.timed_wait. + */ +static bool timed_wait(private_condvar_t *this, private_mutex_t *mutex, + u_int timeout) +{ + struct timespec ts; + struct timeval tv; + u_int s, ms; + + gettimeofday(&tv, NULL); + + s = timeout / 1000; + ms = timeout % 1000; + + ts.tv_sec = tv.tv_sec + s; + ts.tv_nsec = tv.tv_usec * 1000 + ms * 1000000; + if (ts.tv_nsec > 1000000000 /* 1s */) + { + ts.tv_nsec -= 1000000000; + ts.tv_sec++; + } + return (pthread_cond_timedwait(&this->condvar, &mutex->mutex, + &ts) == ETIMEDOUT); +} + +/** + * Implementation of condvar_t.signal. + */ +static void signal(private_condvar_t *this) +{ + pthread_cond_signal(&this->condvar); +} + +/** + * Implementation of condvar_t.broadcast. + */ +static void broadcast(private_condvar_t *this) +{ + pthread_cond_broadcast(&this->condvar); +} + +/** + * Implementation of condvar_t.destroy + */ +static void condvar_destroy(private_condvar_t *this) +{ + pthread_cond_destroy(&this->condvar); + free(this); +} + +/* + * see header file + */ +condvar_t *condvar_create(condvar_type_t type) +{ + switch (type) + { + case CONDVAR_DEFAULT: + default: + { + private_condvar_t *this = malloc_thing(private_condvar_t); + + this->public.wait = (void(*)(condvar_t*, mutex_t *mutex))wait; + this->public.timed_wait = (bool(*)(condvar_t*, mutex_t *mutex, u_int timeout))timed_wait; + this->public.signal = (void(*)(condvar_t*))signal; + this->public.broadcast = (void(*)(condvar_t*))broadcast; + this->public.destroy = (void(*)(condvar_t*))condvar_destroy; + + pthread_cond_init(&this->condvar, NULL); + + return &this->public; + } + } +} + diff --git a/src/libstrongswan/utils/mutex.h b/src/libstrongswan/utils/mutex.h new file mode 100644 index 000000000..cf557c35c --- /dev/null +++ b/src/libstrongswan/utils/mutex.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup mutex mutex + * @{ @ingroup utils + */ + +#ifndef MUTEX_H_ +#define MUTEX_H_ + +typedef struct mutex_t mutex_t; +typedef struct condvar_t condvar_t; +typedef enum mutex_type_t mutex_type_t; +typedef enum condvar_type_t condvar_type_t; + +#include <library.h> + +/** + * Type of mutex. + */ +enum mutex_type_t { + /** default mutex */ + MUTEX_DEFAULT = 0, + /** allow recursive locking of the mutex */ + MUTEX_RECURSIVE = 1, +}; + +/** + * Type of condvar. + */ +enum condvar_type_t { + /** default condvar */ + CONDVAR_DEFAULT = 0, +}; + +/** + * Mutex wrapper implements simple, portable and advanced mutex functions. + */ +struct mutex_t { + + /** + * Acquire the lock to the mutex. + */ + void (*lock)(mutex_t *this); + + /** + * Release the lock on the mutex. + */ + void (*unlock)(mutex_t *this); + + /** + * Destroy a mutex instance. + */ + void (*destroy)(mutex_t *this); +}; + +/** + * Condvar wrapper to use in conjunction with mutex_t. + */ +struct condvar_t { + + /** + * Wait on a condvar until it gets signalized. + * + * @param mutex mutex to release while waiting + */ + void (*wait)(condvar_t *this, mutex_t *mutex); + + /** + * Wait on a condvar until it gets signalized, or times out. + * + * @param mutex mutex to release while waiting + * @param timeout timeout im ms + * @return TRUE if timed out, FALSE otherwise + */ + bool (*timed_wait)(condvar_t *this, mutex_t *mutex, u_int timeout); + + /** + * Wake up a single thread in a condvar. + */ + void (*signal)(condvar_t *this); + + /** + * Wake up all threads in a condvar. + */ + void (*broadcast)(condvar_t *this); + + /** + * Destroy a condvar and free its resources. + */ + void (*destroy)(condvar_t *this); +}; + +/** + * Create a mutex instance. + * + * @param type type of mutex to create + * @return unlocked mutex instance + */ +mutex_t *mutex_create(mutex_type_t type); + +/** + * Create a condvar instance. + * + * @param type type of condvar to create + * @return condvar instance + */ +condvar_t *condvar_create(condvar_type_t type); + +#endif /* MUTEX_H_ @}*/ diff --git a/src/libstrongswan/utils/optionsfrom.c b/src/libstrongswan/utils/optionsfrom.c index 39e38cc58..18427e197 100644 --- a/src/libstrongswan/utils/optionsfrom.c +++ b/src/libstrongswan/utils/optionsfrom.c @@ -1,13 +1,5 @@ -/** - * @file optionsfrom.c - * - * @brief read command line options from a file - * - */ - /* * Copyright (C) 2007-2008 Andreas Steffen - * * Hochschule fuer Technik Rapperswil * * This library is free software; you can redistribute it and/or modify it @@ -20,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public * License for more details. * - * RCSID $Id$ + * $Id: optionsfrom.c 3589 2008-03-13 14:14:44Z martin $ */ #include <stdio.h> diff --git a/src/libstrongswan/utils/optionsfrom.h b/src/libstrongswan/utils/optionsfrom.h index 0014cec36..424b9dc61 100644 --- a/src/libstrongswan/utils/optionsfrom.h +++ b/src/libstrongswan/utils/optionsfrom.h @@ -1,10 +1,3 @@ -/** - * @file optionsfrom.h - * - * @brief Read command line options from a file - * - */ - /* * Copyright (C) 2007-2008 Andreas Steffen * @@ -20,7 +13,12 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id$ + * $Id: optionsfrom.h 3589 2008-03-13 14:14:44Z martin $ + */ + +/** + * @defgroup optionsfrom optionsfrom + * @{ @ingroup utils */ #ifndef OPTIONSFROM_H_ @@ -29,41 +27,33 @@ typedef struct options_t options_t; /** - * @brief options object. - * - * @b Constructors: - * - options_create() - * - * @ingroup utils + * Reads additional command line arguments from a file */ struct options_t { + /** - * @brief Check if the PKCS#7 contentType is data + * Check if the PKCS#7 contentType is data * - * @param this calling object * @param filename file containing the options * @param argcp pointer to argc * @param argvp pointer to argv[] * @param optind current optind, number of next argument * @return TRUE if optionsfrom parsing successful */ - bool (*from) (options_t * this, char *filename, int *argcp, char **argvp[], int optind); + bool (*from) (options_t * this, char *filename, + int *argcp, char **argvp[], int optind); /** - * @brief Destroys the options_t object. - * - * @param this options_t object to destroy + * Destroys the options_t object. */ void (*destroy) (options_t *this); }; /** - * @brief Create an options object. + * Create an options object. * * @return created options_t object - * - * @ingroup utils */ options_t *options_create(void); -#endif /*OPTIONSFROM_H_*/ +#endif /*OPTIONSFROM_H_ @} */ diff --git a/src/libstrongswan/utils/randomizer.c b/src/libstrongswan/utils/randomizer.c deleted file mode 100644 index c15d108c7..000000000 --- a/src/libstrongswan/utils/randomizer.c +++ /dev/null @@ -1,165 +0,0 @@ -/** - * @file randomizer.c - * - * @brief Implementation of randomizer_t. - * - */ - -/* - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <unistd.h> - -#include "randomizer.h" - - -typedef struct private_randomizer_t private_randomizer_t; - -/** - * Private data of an randomizer_t object. - */ -struct private_randomizer_t { - - /** - * Public randomizer_t interface. - */ - randomizer_t public; - - /** - * @brief Reads a specific number of bytes from random or pseudo random device. - * - * @param this calling object - * @param pseudo_random TRUE, if from pseudo random bytes should be read, - * FALSE for true random bytes - * @param bytes number of bytes to read - * @param[out] buffer pointer to buffer where to write the data in. - * Size of buffer has to be at least bytes. - */ - status_t (*get_bytes_from_device) (private_randomizer_t *this,bool pseudo_random, size_t bytes, u_int8_t *buffer); -}; - - -/** - * Implementation of private_randomizer_t.get_bytes_from_device. - */ -static status_t get_bytes_from_device(private_randomizer_t *this,bool pseudo_random, size_t bytes, u_int8_t *buffer) -{ - size_t ndone; - int device; - size_t got; - char * device_name; - - device_name = pseudo_random ? DEV_URANDOM : DEV_RANDOM; - - device = open(device_name, 0); - if (device < 0) { - return FAILED; - } - ndone = 0; - - /* read until nbytes are read */ - while (ndone < bytes) - { - got = read(device, buffer + ndone, bytes - ndone); - if (got <= 0) { - close(device); - return FAILED; - } - ndone += got; - } - close(device); - return SUCCESS; -} - -/** - * Implementation of randomizer_t.get_random_bytes. - */ -static status_t get_random_bytes(private_randomizer_t *this,size_t bytes, u_int8_t *buffer) -{ - return this->get_bytes_from_device(this, FALSE, bytes, buffer); -} - -/** - * Implementation of randomizer_t.allocate_random_bytes. - */ -static status_t allocate_random_bytes(private_randomizer_t *this, size_t bytes, chunk_t *chunk) -{ - status_t status; - chunk->len = bytes; - chunk->ptr = malloc(bytes); - status = this->get_bytes_from_device(this, FALSE, bytes, chunk->ptr); - if (status != SUCCESS) - { - free(chunk->ptr); - } - return status; -} - -/** - * Implementation of randomizer_t.get_pseudo_random_bytes. - */ -static status_t get_pseudo_random_bytes(private_randomizer_t *this,size_t bytes, u_int8_t *buffer) -{ - return (this->get_bytes_from_device(this, TRUE, bytes, buffer)); -} - -/** - * Implementation of randomizer_t.allocate_pseudo_random_bytes. - */ -static status_t allocate_pseudo_random_bytes(private_randomizer_t *this, size_t bytes, chunk_t *chunk) -{ - status_t status; - chunk->len = bytes; - chunk->ptr = malloc(bytes); - status = this->get_bytes_from_device(this, TRUE, bytes, chunk->ptr); - if (status != SUCCESS) - { - free(chunk->ptr); - } - return status; -} - -/** - * Implementation of randomizer_t.destroy. - */ -static void destroy(private_randomizer_t *this) -{ - free(this); -} - -/* - * Described in header. - */ -randomizer_t *randomizer_create(void) -{ - private_randomizer_t *this = malloc_thing(private_randomizer_t); - - /* public functions */ - this->public.get_random_bytes = (status_t (*) (randomizer_t *,size_t, u_int8_t *)) get_random_bytes; - this->public.allocate_random_bytes = (status_t (*) (randomizer_t *,size_t, chunk_t *)) allocate_random_bytes; - this->public.get_pseudo_random_bytes = (status_t (*) (randomizer_t *,size_t, u_int8_t *)) get_pseudo_random_bytes; - this->public.allocate_pseudo_random_bytes = (status_t (*) (randomizer_t *,size_t, chunk_t *)) allocate_pseudo_random_bytes; - this->public.destroy = (void (*) (randomizer_t *))destroy; - - /* private functions */ - this->get_bytes_from_device = get_bytes_from_device; - - return &(this->public); -} diff --git a/src/libstrongswan/utils/randomizer.h b/src/libstrongswan/utils/randomizer.h deleted file mode 100644 index afbade059..000000000 --- a/src/libstrongswan/utils/randomizer.h +++ /dev/null @@ -1,114 +0,0 @@ -/** - * @file randomizer.h - * - * @brief Interface of randomizer_t. - * - */ - -/* - * Copyright (C) 2005-2006 Martin Willi - * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - */ - -#ifndef RANDOMIZER_H_ -#define RANDOMIZER_H_ - -typedef struct randomizer_t randomizer_t; - -#include <library.h> - -#ifndef DEV_RANDOM -/** - * Device to read real random bytes - */ -# define DEV_RANDOM "/dev/random" -#endif - -#ifndef DEV_URANDOM -/** - * Device to read pseudo random bytes - */ -# define DEV_URANDOM "/dev/urandom" -#endif - -/** - * @brief Class used to get random and pseudo random values. - * - * @b Constructors: - * - randomizer_create() - * - * @ingroup utils - */ -struct randomizer_t { - - /** - * @brief Reads a specific number of bytes from random device. - * - * @param this calling randomizer_t object - * @param bytes number of bytes to read - * @param[out] buffer pointer to buffer where to write the data in. - * Size of buffer has to be at least bytes. - * @return SUCCESS, or FAILED - */ - status_t (*get_random_bytes) (randomizer_t *this, size_t bytes, u_int8_t *buffer); - - /** - * @brief Allocates space and writes in random bytes. - * - * @param this calling randomizer_t object - * @param bytes number of bytes to allocate - * @param[out] chunk chunk which will hold the allocated random bytes - * @return SUCCESS, or FAILED - */ - status_t (*allocate_random_bytes) (randomizer_t *this, size_t bytes, chunk_t *chunk); - - /** - * @brief Reads a specific number of bytes from pseudo random device. - * - * @param this calling randomizer_t object - * @param bytes number of bytes to read - * @param[out] buffer pointer to buffer where to write the data in. - * size of buffer has to be at least bytes. - * @return SUCCESS, or FAILED - */ - status_t (*get_pseudo_random_bytes) (randomizer_t *this,size_t bytes, u_int8_t *buffer); - - /** - * @brief Allocates space and writes in pseudo random bytes. - * - * @param this calling randomizer_t object - * @param bytes number of bytes to allocate - * @param[out] chunk chunk which will hold the allocated random bytes - * @return SUCCESS, or FAILED - */ - status_t (*allocate_pseudo_random_bytes) (randomizer_t *this, size_t bytes, chunk_t *chunk); - - /** - * @brief Destroys a randomizer_t object. - * - * @param this randomizer_t object to destroy - */ - void (*destroy) (randomizer_t *this); -}; - -/** - * @brief Creates a randomizer_t object. - * - * @return created randomizer_t, or - * - * @ingroup utils - */ -randomizer_t *randomizer_create(void); - -#endif /*RANDOMIZER_H_*/ |