235 lines
5.1 KiB
C
235 lines
5.1 KiB
C
/*
|
|
* Copyright (C) 2012 Martin Willi
|
|
* Copyright (C) 2012 revosec AG
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at your
|
|
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* for more details.
|
|
*/
|
|
|
|
#include "stroke_handler.h"
|
|
|
|
#include <daemon.h>
|
|
#include <collections/linked_list.h>
|
|
#include <threading/rwlock.h>
|
|
|
|
typedef struct private_stroke_handler_t private_stroke_handler_t;
|
|
|
|
/**
|
|
* Private data of an stroke_handler_t object.
|
|
*/
|
|
struct private_stroke_handler_t {
|
|
|
|
/**
|
|
* Public stroke_handler_t interface.
|
|
*/
|
|
stroke_handler_t public;
|
|
|
|
/**
|
|
* List of connection specific attributes, as attributes_t
|
|
*/
|
|
linked_list_t *attrs;
|
|
|
|
/**
|
|
* rwlock to lock access to pools
|
|
*/
|
|
rwlock_t *lock;
|
|
};
|
|
|
|
/**
|
|
* Attributes assigned to a connection
|
|
*/
|
|
typedef struct {
|
|
/** name of the connection */
|
|
char *name;
|
|
/** list of DNS attributes, as host_t */
|
|
linked_list_t *dns;
|
|
} attributes_t;
|
|
|
|
/**
|
|
* Destroy an attributes_t entry
|
|
*/
|
|
static void attributes_destroy(attributes_t *this)
|
|
{
|
|
this->dns->destroy_offset(this->dns, offsetof(host_t, destroy));
|
|
free(this->name);
|
|
free(this);
|
|
}
|
|
|
|
CALLBACK(attr_filter, bool,
|
|
void *lock, enumerator_t *orig, va_list args)
|
|
{
|
|
configuration_attribute_type_t *type;
|
|
chunk_t *data;
|
|
host_t *host;
|
|
|
|
VA_ARGS_VGET(args, type, data);
|
|
|
|
while (orig->enumerate(orig, &host))
|
|
{
|
|
switch (host->get_family(host))
|
|
{
|
|
case AF_INET:
|
|
*type = INTERNAL_IP4_DNS;
|
|
break;
|
|
case AF_INET6:
|
|
*type = INTERNAL_IP6_DNS;
|
|
break;
|
|
default:
|
|
continue;
|
|
}
|
|
if (host->is_anyaddr(host))
|
|
{
|
|
*data = chunk_empty;
|
|
}
|
|
else
|
|
{
|
|
*data = host->get_address(host);
|
|
}
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
|
|
private_stroke_handler_t *this, ike_sa_t *ike_sa,
|
|
linked_list_t *vips)
|
|
{
|
|
peer_cfg_t *peer_cfg;
|
|
enumerator_t *enumerator;
|
|
attributes_t *attr;
|
|
|
|
ike_sa = charon->bus->get_sa(charon->bus);
|
|
if (ike_sa)
|
|
{
|
|
peer_cfg = ike_sa->get_peer_cfg(ike_sa);
|
|
this->lock->read_lock(this->lock);
|
|
enumerator = this->attrs->create_enumerator(this->attrs);
|
|
while (enumerator->enumerate(enumerator, &attr))
|
|
{
|
|
if (streq(attr->name, peer_cfg->get_name(peer_cfg)))
|
|
{
|
|
enumerator->destroy(enumerator);
|
|
return enumerator_create_filter(
|
|
attr->dns->create_enumerator(attr->dns),
|
|
attr_filter, this->lock,
|
|
(void*)this->lock->unlock);
|
|
}
|
|
}
|
|
enumerator->destroy(enumerator);
|
|
this->lock->unlock(this->lock);
|
|
}
|
|
return enumerator_create_empty();
|
|
}
|
|
|
|
METHOD(stroke_handler_t, add_attributes, void,
|
|
private_stroke_handler_t *this, stroke_msg_t *msg)
|
|
{
|
|
if (msg->add_conn.me.dns)
|
|
{
|
|
enumerator_t *enumerator;
|
|
attributes_t *attr = NULL;
|
|
host_t *host;
|
|
char *token;
|
|
|
|
enumerator = enumerator_create_token(msg->add_conn.me.dns, ",", " ");
|
|
while (enumerator->enumerate(enumerator, &token))
|
|
{
|
|
if (streq(token, "%config") || streq(token, "%config4"))
|
|
{
|
|
host = host_create_any(AF_INET);
|
|
}
|
|
else if (streq(token, "%config6"))
|
|
{
|
|
host = host_create_any(AF_INET6);
|
|
}
|
|
else
|
|
{
|
|
host = host_create_from_string(token, 0);
|
|
}
|
|
if (host)
|
|
{
|
|
if (!attr)
|
|
{
|
|
INIT(attr,
|
|
.name = strdup(msg->add_conn.name),
|
|
.dns = linked_list_create(),
|
|
);
|
|
}
|
|
attr->dns->insert_last(attr->dns, host);
|
|
}
|
|
else
|
|
{
|
|
DBG1(DBG_CFG, "ignoring invalid DNS address '%s'", token);
|
|
}
|
|
}
|
|
enumerator->destroy(enumerator);
|
|
if (attr)
|
|
{
|
|
this->lock->write_lock(this->lock);
|
|
this->attrs->insert_last(this->attrs, attr);
|
|
this->lock->unlock(this->lock);
|
|
}
|
|
}
|
|
}
|
|
|
|
METHOD(stroke_handler_t, del_attributes, void,
|
|
private_stroke_handler_t *this, stroke_msg_t *msg)
|
|
{
|
|
enumerator_t *enumerator;
|
|
attributes_t *attr;
|
|
|
|
this->lock->write_lock(this->lock);
|
|
enumerator = this->attrs->create_enumerator(this->attrs);
|
|
while (enumerator->enumerate(enumerator, &attr))
|
|
{
|
|
if (streq(msg->del_conn.name, attr->name))
|
|
{
|
|
this->attrs->remove_at(this->attrs, enumerator);
|
|
attributes_destroy(attr);
|
|
break;
|
|
}
|
|
}
|
|
enumerator->destroy(enumerator);
|
|
this->lock->unlock(this->lock);
|
|
}
|
|
|
|
METHOD(stroke_handler_t, destroy, void,
|
|
private_stroke_handler_t *this)
|
|
{
|
|
this->lock->destroy(this->lock);
|
|
this->attrs->destroy_function(this->attrs, (void*)attributes_destroy);
|
|
free(this);
|
|
}
|
|
|
|
/**
|
|
* See header
|
|
*/
|
|
stroke_handler_t *stroke_handler_create()
|
|
{
|
|
private_stroke_handler_t *this;
|
|
|
|
INIT(this,
|
|
.public = {
|
|
.handler = {
|
|
.handle = (void*)return_false,
|
|
.release = (void*)return_false,
|
|
.create_attribute_enumerator = _create_attribute_enumerator,
|
|
},
|
|
.add_attributes = _add_attributes,
|
|
.del_attributes = _del_attributes,
|
|
.destroy = _destroy,
|
|
},
|
|
.attrs = linked_list_create(),
|
|
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
|
|
);
|
|
|
|
return &this->public;
|
|
}
|