diff options
author | Martin Willi <martin@strongswan.org> | 2008-03-13 14:14:44 +0000 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2008-03-13 14:14:44 +0000 |
commit | 552cc11b1f017ce4962fca741f567d098f768574 (patch) | |
tree | 2835ae64c435191e04b5a265b1509c40a2e6766a /src/libstrongswan/utils | |
parent | 2df655134ca29f7a0b7d90ef4783f85eff1ddfd3 (diff) | |
download | strongswan-552cc11b1f017ce4962fca741f567d098f768574.tar.bz2 strongswan-552cc11b1f017ce4962fca741f567d098f768574.tar.xz |
merged the modularization branch (credentials) back to trunk
Diffstat (limited to 'src/libstrongswan/utils')
21 files changed, 1547 insertions, 1420 deletions
diff --git a/src/libstrongswan/utils/enumerator.c b/src/libstrongswan/utils/enumerator.c index 842a2e997..67d0c8d1a 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$ */ #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..4de287890 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$ + */ + +/** + * @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..835544e4d 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,6 +14,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$ */ #include <string.h> @@ -32,7 +27,7 @@ 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 { /** @@ -155,12 +150,27 @@ static int print(FILE *stream, const struct printf_info *info, } } + /** - * register printf() handlers + * arginfo handler for printf() hosts */ -static void __attribute__ ((constructor))print_register() +int arginfo(const struct printf_info *info, size_t n, int *argtypes) { - register_printf_function(PRINTF_HOST, print, arginfo_ptr); + if (n > 0) + { + argtypes[0] = PA_POINTER; + } + return 1; +} + +/** + * return printf hook functions for a host + */ +printf_hook_functions_t host_get_printf_hooks() +{ + printf_hook_functions_t hooks = {print, arginfo}; + + return hooks; } /** diff --git a/src/libstrongswan/utils/host.h b/src/libstrongswan/utils/host.h index ee9aa457f..fd2fe01b1 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,119 @@ 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 object from an address chunk * - * @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 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 object - * - NULL, if family not supported or chunk_t length not 4 bytes. - * - * @ingroup network + * @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 6d969ed16..948472cc8 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$ + * $Id$ */ #define _GNU_SOURCE @@ -36,6 +29,14 @@ #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 +50,11 @@ 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_PUBKEY_SHA1, ID_KEY_ID, + "ID_DER_ASN1_GN_URI", + "ID_PUBKEY_INFO_SHA1", + "ID_PUBKEY_SHA1"); +ENUM_END(id_type_names, ID_PUBKEY_SHA1); /** * X.501 acronyms for well known object identifiers (OIDs) @@ -237,7 +239,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 +248,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 +256,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 +264,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 +285,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 +303,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 +312,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 +325,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 +333,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 +350,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 +370,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 */ @@ -404,7 +406,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 +422,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 +441,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 && known_oid(oid_a) == OID_PKCS9_EMAIL))) { if (strncasecmp(value_a.ptr, value_b.ptr, value_b.len) != 0) { @@ -470,8 +478,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 +499,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 +512,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 && known_oid(oid_a) == OID_PKCS9_EMAIL))) { if (strncasecmp(value_a.ptr, value_b.ptr, value_b.len) != 0) { @@ -550,12 +557,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; } @@ -776,120 +779,107 @@ 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; - + { + return ID_MATCH_NONE; + } /* try a binary comparison first */ if (equals_binary(this, other)) { - if (wildcards) - { - *wildcards = 0; - } - return TRUE; + 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 (memeq(this->encoded.ptr + this->encoded.len - len, + other->encoded.ptr + 1, len)) + { + 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]; @@ -944,12 +934,14 @@ static int print(FILE *stream, const struct printf_info *info, 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); + return fprintf(stream, "\"%s\"", buf); } case ID_DER_ASN1_GN: return fprintf(stream, "(ASN.1 general Name"); case ID_KEY_ID: - return fprintf(stream, "(KEY_ID)"); + case ID_PUBKEY_INFO_SHA1: + case ID_PUBKEY_SHA1: + return fprintf(stream, "%#B", &this->encoded); case ID_DER_ASN1_GN_URI: { proper = sanitize_chunk(this->encoded); @@ -963,11 +955,25 @@ static int print(FILE *stream, const struct printf_info *info, } /** - * register printf() handlers + * arginfo handler + */ +static int arginfo(const struct printf_info *info, size_t n, int *argtypes) +{ + if (n > 0) + { + argtypes[0] = PA_POINTER; + } + return 1; +} + +/** + * 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 +1017,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 +1047,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 +1060,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 +1078,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); @@ -1114,8 +1120,8 @@ identification_t *identification_create_from_string(char *string) 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 +1132,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 +1152,29 @@ 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: default: break; } diff --git a/src/libstrongswan/utils/identification.h b/src/libstrongswan/utils/identification.h index 59c568eaf..31c49c269 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$ + */ + +/** + * @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,16 @@ 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, }; /** @@ -118,110 +145,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 +240,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..4b845d740 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$ + */ + +/** + * @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..149456875 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$ */ +#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! @@ -146,77 +159,103 @@ static void log_stack_frames(void **stack_frames, int stack_frame_count) char **strings; size_t i; - 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; + + /* TODO: this is quite hackish, but it works. A more proper solution + * would execve addr2strongline and pipe the output to DBG1() */ + if (dladdr(stack_frames[i], &info)) + { + char cmd[1024]; + 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+0x%x\e[0m) [%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"); + system(cmd); + fprintf(stderr, "\e[0m"); + } + else +#endif /* HAVE_DLADDR */ + { + fprintf(stderr, " %s\n", strings[i]); + } } 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_create", + "pthread_setspecific", + "mktime", + "tzset", + "inet_ntoa", + "strerror", + "getprotobynumber", + "getservbyport", + "getservbyname", + "register_printf_function", + "syslog", + "vsyslog", + "dlopen", + "getaddrinfo", + "setlocale", + "mysql_init_character_set", + "init_client_errs", + "my_thread_init", }; /** - * 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; } @@ -232,8 +271,9 @@ void report_leaks() { if (!is_whitelisted(hdr->stack_frames, hdr->stack_frame_count)) { - 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,13 +281,13 @@ void report_leaks() switch (leaks) { case 0: - DBG1("No leaks detected"); + fprintf(stderr, "No leaks detected\n"); break; case 1: - DBG1("One leak detected"); + fprintf(stderr, "One leak detected\n"); break; default: - DBG1("%d leaks detected", leaks); + fprintf(stderr, "%d leaks detected\n", leaks); break; } } @@ -334,8 +374,8 @@ void free_hook(void *ptr, const void *caller) uninstall_hooks(); if (hdr->magic != MEMORY_HEADER_MAGIC) { - DBG1("freeing of invalid memory (%p, MAGIC 0x%x != 0x%x):", - ptr, hdr->magic, MEMORY_HEADER_MAGIC); + fprintf(stderr, "freeing of invalid memory (%p, MAGIC 0x%x != 0x%x):\n", + ptr, hdr->magic, MEMORY_HEADER_MAGIC); stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT); log_stack_frames(stack_frames, stack_frame_count); install_hooks(); @@ -380,7 +420,7 @@ void *realloc_hook(void *old, size_t bytes, const void *caller) uninstall_hooks(); if (hdr->magic != MEMORY_HEADER_MAGIC) { - DBG1("reallocation of invalid memory (%p):", old); + fprintf(stderr, "reallocation of invalid memory (%p):\n", old); stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT); log_stack_frames(stack_frames, stack_frame_count); install_hooks(); @@ -407,65 +447,31 @@ void *realloc_hook(void *old, size_t bytes, const void *caller) } /** - * Setup leak detective + * Implementation of leak_detective_t.destroy */ -void __attribute__ ((constructor)) leak_detective_init() +static void destroy(private_leak_detective_t *this) { - if (getenv("LEAK_DETECTIVE_DISABLE") == NULL) - { - install_hooks(); - } -} - -/** - * Clean up leak detective - */ -void __attribute__ ((destructor)) leak_detective_cleanup() -{ - 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 35ba0d7a6..c23576971 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$ + * $Id$ */ /* memrchr is a GNU extension */ diff --git a/src/libstrongswan/utils/lexparser.h b/src/libstrongswan/utils/lexparser.h index db89ae2d2..1c0a9997a 100644 --- a/src/libstrongswan/utils/lexparser.h +++ b/src/libstrongswan/utils/lexparser.h @@ -1,10 +1,3 @@ -/** - * @file lexparser.h - * - * @brief lexical parser for text-based configuration files - * - */ - /* * Copyright (C) 2001-2006 Andreas Steffen, Zuercher Hochschule Winterthur * @@ -18,47 +11,57 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * RCSID $Id$ + * $Id$ */ + +/** + * @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..16913b934 100644 --- a/src/libstrongswan/utils/linked_list.c +++ b/src/libstrongswan/utils/linked_list.c @@ -1,10 +1,3 @@ -/** - * @file linked_list.c - * - * @brief Implementation of linked_list_t. - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi @@ -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$ */ #include <stdlib.h> @@ -157,6 +152,11 @@ struct private_enumerator_t { * next item to enumerate */ element_t *next; + + /** + * current item + */ + element_t *current; }; /** @@ -169,6 +169,7 @@ static bool enumerate(private_enumerator_t *this, void **item) return FALSE; } *item = this->next->value; + this->current = this->next; this->next = this->next->next; return TRUE; } @@ -183,6 +184,7 @@ 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->current = NULL; return &enumerator->enumerator; } @@ -459,34 +461,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 +508,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 +547,67 @@ 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) - { - return INVALID_ARG; - } - - current_element = this->first; - - for (i = 0; i < position;i++) + if (get_last(this, item) == SUCCESS) { - 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) + if (enumerator->current) { - return NOT_FOUND; + remove_element(this, enumerator->current); + enumerator->current = NULL; + enumerator->next = this->first; } - - *item = this->last->value; - - return SUCCESS; } /** @@ -895,9 +829,8 @@ 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.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*,void(*)(void*)))invoke_function; this->public.clone_offset = (linked_list_t * (*)(linked_list_t*,size_t))clone_offset; diff --git a/src/libstrongswan/utils/linked_list.h b/src/libstrongswan/utils/linked_list.h index ac36ef46d..3d7133f9d 100644 --- a/src/libstrongswan/utils/linked_list.h +++ b/src/libstrongswan/utils/linked_list.h @@ -1,10 +1,3 @@ -/** - * @file linked_list.h - * - * @brief Interface of linked_list_t. - * - */ - /* * Copyright (C) 2007 Tobias Brunner * Copyright (C) 2005-2006 Martin Willi @@ -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$ + */ + +/** + * @defgroup linked_list linked_list + * @{ @ingroup utils */ #ifndef LINKED_LIST_H_ @@ -42,51 +42,42 @@ 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. + * Class implementing a double linked list. * * General purpose linked list. This list is not synchronized. - * - * @b Costructors: - * - linked_list_create() - * - * @ingroup utils */ 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 +85,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 +174,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 +192,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 +209,68 @@ 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 */ 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 */ void (*invoke_function) (linked_list_t *this, void (*)(void*)); /** - * @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..f16c5b2c7 --- /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$ + */ + +#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..38302105d 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$ */ #include <stdio.h> diff --git a/src/libstrongswan/utils/optionsfrom.h b/src/libstrongswan/utils/optionsfrom.h index 0014cec36..3a5640907 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$ + */ + +/** + * @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 index c15d108c7..74db0dead 100644 --- a/src/libstrongswan/utils/randomizer.c +++ b/src/libstrongswan/utils/randomizer.c @@ -1,10 +1,3 @@ -/** - * @file randomizer.c - * - * @brief Implementation of randomizer_t. - * - */ - /* * Copyright (C) 2005-2006 Martin Willi * Copyright (C) 2005 Jan Hutter @@ -19,6 +12,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$ */ #include <string.h> @@ -41,25 +36,13 @@ 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. + * Read bytes from the random device */ -static status_t get_bytes_from_device(private_randomizer_t *this,bool pseudo_random, size_t bytes, u_int8_t *buffer) +static status_t read_bytes(private_randomizer_t *this, + bool pseudo_random, size_t bytes, u_int8_t *buffer) { size_t ndone; int device; @@ -91,20 +74,22 @@ static status_t get_bytes_from_device(private_randomizer_t *this,bool pseudo_ran /** * Implementation of randomizer_t.get_random_bytes. */ -static status_t get_random_bytes(private_randomizer_t *this,size_t bytes, u_int8_t *buffer) +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); + return read_bytes(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) +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); + status = read_bytes(this, FALSE, bytes, chunk->ptr); if (status != SUCCESS) { free(chunk->ptr); @@ -115,20 +100,22 @@ static status_t allocate_random_bytes(private_randomizer_t *this, size_t bytes, /** * 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) +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)); + return read_bytes(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) +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); + status = read_bytes(this, TRUE, bytes, chunk->ptr); if (status != SUCCESS) { free(chunk->ptr); @@ -158,8 +145,6 @@ randomizer_t *randomizer_create(void) 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); + return &this->public; } + diff --git a/src/libstrongswan/utils/randomizer.h b/src/libstrongswan/utils/randomizer.h index afbade059..c7aa86b01 100644 --- a/src/libstrongswan/utils/randomizer.h +++ b/src/libstrongswan/utils/randomizer.h @@ -1,10 +1,3 @@ -/** - * @file randomizer.h - * - * @brief Interface of randomizer_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$ + */ + +/** + * @defgroup randomizer randomizer + * @{ @ingroup utils */ #ifndef RANDOMIZER_H_ @@ -43,72 +43,59 @@ typedef struct randomizer_t randomizer_t; #endif /** - * @brief Class used to get random and pseudo random values. - * - * @b Constructors: - * - randomizer_create() - * - * @ingroup utils + * Class used to get random and pseudo random values. */ 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 + * Reads a specific number of bytes from random device. + * + * @param bytes number of bytes to read + * @param buffer pointer to buffer where to write the data in. + * @return SUCCESS, or FAILED */ - status_t (*get_random_bytes) (randomizer_t *this, size_t bytes, u_int8_t *buffer); + status_t (*get_random_bytes) (randomizer_t *this, + size_t bytes, u_int8_t *buffer); /** - * @brief Allocates space and writes in random bytes. + * 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 + * @param bytes number of bytes to allocate + * @param 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); + 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. + * 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 + * @param bytes number of bytes to read + * @param buffer pointer to buffer where to write the data in. + * @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. + * 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 + * @param bytes number of bytes to allocate + * @param 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 + * Destroys a randomizer_t object. */ void (*destroy) (randomizer_t *this); }; /** - * @brief Creates a randomizer_t object. - * - * @return created randomizer_t, or + * Creates a randomizer_t object. * - * @ingroup utils + * @return created randomizer_t */ randomizer_t *randomizer_create(void); -#endif /*RANDOMIZER_H_*/ +#endif /*RANDOMIZER_H_ @} */ |