merged the modularization branch (credentials) back to trunk
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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_ @} */
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
@@ -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_*/
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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_ @}*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_ @} */
|
||||
|
||||
@@ -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_ @} */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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_ @} */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_ @} */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,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>
|
||||
|
||||
@@ -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_ @} */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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_ @} */
|
||||
|
||||
Reference in New Issue
Block a user