merged the modularization branch (credentials) back to trunk

This commit is contained in:
Martin Willi
2008-03-13 14:14:44 +00:00
parent 2df655134c
commit 552cc11b1f
495 changed files with 30378 additions and 23843 deletions
+357 -7
View File
@@ -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;
}
+104 -14
View File
@@ -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_ @} */
-424
View File
@@ -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 */
}
-95
View File
@@ -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_*/
+21 -11
View File
@@ -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;
}
/**
+53 -87
View File
@@ -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_ @}*/
+157 -149
View File
@@ -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)
{
if (wildcards)
{
*wildcards = 0;
}
return other->type == ID_ANY;
}
/**
* Special implementation of identification_t.matches for ID_DER_ASN1_DN.
* ANY matches any, even ANY, thats why its there...
*/
static bool matches_dn(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 (other->type == ID_ANY)
{
if (wildcards)
{
*wildcards = MAX_WILDCARDS;
}
return TRUE;
return ID_MATCH_ANY;
}
return ID_MATCH_NONE;
}
/**
* Special implementation of identification_t.matches for ID_DER_ASN1_DN
*/
static id_match_t matches_dn(private_identification_t *this,
private_identification_t *other)
{
int wc;
if (other->type == ID_ANY)
{
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 void __attribute__ ((constructor))print_register()
static int arginfo(const struct printf_info *info, size_t n, int *argtypes)
{
register_printf_function(PRINTF_IDENTIFICATION, print, arginfo_ptr);
if (n > 0)
{
argtypes[0] = PA_POINTER;
}
return 1;
}
/**
* Get printf hook functions
*/
printf_hook_functions_t identification_get_printf_hooks()
{
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;
}
+72 -65
View File
@@ -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. [email protected]) 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_ @} */
+34 -61
View File
@@ -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_ @} */
+114 -108
View File
@@ -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"))
this->public.destroy = (void(*)(leak_detective_t*))destroy;
if (getenv("LEAK_DETECTIVE_DISABLE") == NULL)
{
return;
install_hooks();
}
pthread_mutex_lock(&mutex);
while ((hdr = hdr->next))
{
blocks++;
bytes += hdr->bytes;
}
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);
return &this->public;
}
#else /* !LEAK_DETECTION */
/**
* Dummy when !using LEAK_DETECTIVE
*/
void leak_detective_status(FILE *stream)
{
}
#endif /* LEAK_DETECTION */
+30 -12
View File
@@ -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.
*/
#define STACK_FRAMES_COUNT 30
struct leak_detective_t {
/**
* Destroy a leak_detective instance.
*/
void (*destroy)(leak_detective_t *this);
};
/**
* Create a leak_detective instance.
*/
leak_detective_t *leak_detective_create();
#endif /* LEAK_DETECTIVE_H_ @}*/
#endif /* LEAK_DETECTIVE_H_ */
+2 -9
View File
@@ -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 */
+19 -16
View File
@@ -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_ @} */
+94 -161
View File
@@ -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)
{
*item = element->value;
previous->next = next;
}
else
{
this->first = next;
}
if (--this->count == 0)
{
this->first = NULL;
this->last = NULL;
}
free(element);
return SUCCESS;
return next;
}
/**
@@ -502,6 +507,19 @@ static status_t get_first(private_linked_list_t *this, void **item)
return SUCCESS;
}
/**
* 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.
*/
@@ -528,139 +546,6 @@ static void insert_last(private_linked_list_t *this, void *item)
this->count++;
}
/**
* Implementation of linked_list_t.remove_last.
*/
static status_t remove_last(private_linked_list_t *this, void **item)
{
element_t *element = this->last;
if (element == NULL)
{
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);
return SUCCESS;
}
/**
* Implementation of linked_list_t.insert_at_position.
*/
static status_t insert_at_position (private_linked_list_t *this,size_t position, 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++)
{
current_element = current_element->next;
}
if (current_element == NULL)
{
this->public.insert_last(&(this->public),item);
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;
}
/**
* Implementation of linked_list_t.remove_at_position.
*/
static status_t remove_at_position(private_linked_list_t *this,size_t position, void **item)
{
iterator_t *iterator;
int i;
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))
{
iterator->destroy(iterator);
return INVALID_ARG;
}
}
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))
{
iterator->destroy(iterator);
return INVALID_ARG;
}
}
iterator->destroy(iterator);
return SUCCESS;
}
/**
* Implementation of linked_list_t.get_last.
*/
@@ -670,12 +555,61 @@ static status_t get_last(private_linked_list_t *this, void **item)
{
return NOT_FOUND;
}
*item = this->last->value;
return SUCCESS;
}
/**
* Implementation of linked_list_t.remove_last.
*/
static status_t remove_last(private_linked_list_t *this, void **item)
{
if (get_last(this, item) == SUCCESS)
{
remove_element(this, this->last);
return SUCCESS;
}
return NOT_FOUND;
}
/**
* Implementation of linked_list_t.remove.
*/
static int remove(private_linked_list_t *this, void *item,
bool (*compare)(void *,void*))
{
element_t *current = this->first;
int removed = 0;
while (current)
{
if ((compare && compare(current->value, item)) ||
(!compare && current->value == item))
{
removed++;
current = remove_element(this, current);
}
else
{
current = current->next;
}
}
return removed;
}
/**
* Implementation of linked_list_t.remove_at.
*/
static void remove_at(private_linked_list_t *this, private_enumerator_t *enumerator)
{
if (enumerator->current)
{
remove_element(this, enumerator->current);
enumerator->current = NULL;
enumerator->next = this->first;
}
}
/**
* Implementation of linked_list_t.find_first.
*/
@@ -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;
+69 -124
View File
@@ -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.
* Remove an item from the list where the enumerator points to.
*
* @param enumerator enumerator with position
*/
void (*remove_at)(linked_list_t *this, enumerator_t *enumerator);
/**
* Remove items from the list matching item.
*
* 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
*/
int (*remove)(linked_list_t *this, void *item, bool (*compare)(void *,void*));
/**
* 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
* @param 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.
* Inserts a new item at the end of the list.
*
* @param this calling object
* @param[in] item value to insert into list
* @param item value to insert into list
*/
void (*insert_last) (linked_list_t *this, void *item);
/**
* @brief Inserts a new item at a given position in the list.
*
* @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
*/
status_t (*insert_at_position) (linked_list_t *this,size_t position, void *item);
/**
* @brief Removes an item from a given position in the list.
*
* @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
*/
status_t (*remove_at_position) (linked_list_t *this, size_t position, void **item);
/**
* @brief Get an item from a given position in the list.
* Removes the last item in the list and returns its value.
*
* @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
*/
status_t (*get_at_position) (linked_list_t *this, size_t position, void **item);
/**
* @brief 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_ @} */
+267
View File
@@ -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;
}
}
}
+123
View File
@@ -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_ @}*/
+1 -9
View File
@@ -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>
+14 -24
View File
@@ -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_ @} */
+19 -34
View File
@@ -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;
}
+33 -46
View File
@@ -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.
* Creates a randomizer_t object.
*
* @return created randomizer_t, or
*
* @ingroup utils
* @return created randomizer_t
*/
randomizer_t *randomizer_create(void);
#endif /*RANDOMIZER_H_*/
#endif /*RANDOMIZER_H_ @} */