From b262429e0b991ec8dbe7f7694c8f0418023f0fde Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Wed, 24 Mar 2010 15:28:14 +0100 Subject: Include configuration payloads for DNS/WINS server received via DHCP --- src/libcharon/plugins/dhcp/dhcp_provider.c | 18 +++++++- src/libcharon/plugins/dhcp/dhcp_socket.c | 30 ++++++++++++- src/libcharon/plugins/dhcp/dhcp_transaction.c | 62 +++++++++++++++++++++++++++ src/libcharon/plugins/dhcp/dhcp_transaction.h | 17 ++++++++ 4 files changed, 125 insertions(+), 2 deletions(-) (limited to 'src/libcharon') diff --git a/src/libcharon/plugins/dhcp/dhcp_provider.c b/src/libcharon/plugins/dhcp/dhcp_provider.c index a3a289595..dbcceb6ce 100644 --- a/src/libcharon/plugins/dhcp/dhcp_provider.c +++ b/src/libcharon/plugins/dhcp/dhcp_provider.c @@ -131,7 +131,23 @@ METHOD(attribute_provider_t, release_address, bool, METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*, private_dhcp_provider_t *this, identification_t *id, host_t *vip) { - return enumerator_create_empty(); + dhcp_transaction_t *transaction; + + if (!vip) + { + return NULL; + } + this->mutex->lock(this->mutex); + transaction = this->transactions->get(this->transactions, + (void*)hash_id_host(id, vip)); + if (!transaction) + { + this->mutex->unlock(this->mutex); + return NULL; + } + return enumerator_create_cleaner( + transaction->create_attribute_enumerator(transaction), + (void*)this->mutex->unlock, this->mutex); } METHOD(dhcp_provider_t, destroy, void, diff --git a/src/libcharon/plugins/dhcp/dhcp_socket.c b/src/libcharon/plugins/dhcp/dhcp_socket.c index b789e11ec..190024ce6 100644 --- a/src/libcharon/plugins/dhcp/dhcp_socket.c +++ b/src/libcharon/plugins/dhcp/dhcp_socket.c @@ -446,7 +446,7 @@ METHOD(dhcp_socket_t, release, void, */ static void handle_offer(private_dhcp_socket_t *this, dhcp_t *dhcp, int optlen) { - dhcp_transaction_t *transaction; + dhcp_transaction_t *transaction = NULL; enumerator_t *enumerator; host_t *offer, *server; @@ -470,6 +470,34 @@ static void handle_offer(private_dhcp_socket_t *this, dhcp_t *dhcp, int optlen) } } enumerator->destroy(enumerator); + + if (transaction) + { + int optsize, optpos = 0, pos; + dhcp_option_t *option; + + while (optlen > sizeof(dhcp_option_t)) + { + option = (dhcp_option_t*)&dhcp->options[optpos]; + optsize = sizeof(dhcp_option_t) + option->len; + if (option->type == DHCP_OPTEND || optlen < optsize) + { + break; + } + if (option->type == DHCP_DNS_SERVER || + option->type == DHCP_NBNS_SERVER) + { + for (pos = 0; pos + 4 <= option->len; pos += 4) + { + transaction->add_attribute(transaction, option->type == + DHCP_DNS_SERVER ? INTERNAL_IP4_DNS : INTERNAL_IP4_NBNS, + chunk_create((char*)&option->data[pos], 4)); + } + } + optlen -= optsize; + optpos += optsize; + } + } this->mutex->unlock(this->mutex); this->condvar->broadcast(this->condvar); offer->destroy(offer); diff --git a/src/libcharon/plugins/dhcp/dhcp_transaction.c b/src/libcharon/plugins/dhcp/dhcp_transaction.c index 27235ffb9..83f822dd8 100644 --- a/src/libcharon/plugins/dhcp/dhcp_transaction.c +++ b/src/libcharon/plugins/dhcp/dhcp_transaction.c @@ -15,6 +15,8 @@ #include "dhcp_transaction.h" +#include + typedef struct private_dhcp_transaction_t private_dhcp_transaction_t; /** @@ -46,8 +48,21 @@ struct private_dhcp_transaction_t { * discovered DHCP server address */ host_t *server; + + /** + * List of added attributes, as attribute_entry_t + */ + linked_list_t *attributes; }; +/** + * Entry for an added attribute + */ +typedef struct { + configuration_attribute_type_t type; + chunk_t data; +} attribute_entry_t; + METHOD(dhcp_transaction_t, get_id, u_int32_t, private_dhcp_transaction_t *this) { @@ -86,12 +101,56 @@ METHOD(dhcp_transaction_t, get_server, host_t*, return this->server; } +METHOD(dhcp_transaction_t, add_attribute, void, + private_dhcp_transaction_t *this, configuration_attribute_type_t type, + chunk_t data) +{ + attribute_entry_t *entry; + + INIT(entry, + .type = type, + .data = chunk_clone(data), + ); + this->attributes->insert_last(this->attributes, entry); +} + +/** + * Filter function to map entries to type/data + */ +static bool attribute_filter(void *null, attribute_entry_t **entry, + configuration_attribute_type_t *type, + void **dummy, chunk_t *data) +{ + *type = (*entry)->type; + *data = (*entry)->data; + return TRUE; +} + +METHOD(dhcp_transaction_t, create_attribute_enumerator, enumerator_t*, + private_dhcp_transaction_t *this) +{ + return enumerator_create_filter( + this->attributes->create_enumerator(this->attributes), + (void*)attribute_filter, NULL, NULL); +} + +/** + * Clean up an attribute entry + */ +static void attribute_entry_destroy(attribute_entry_t *entry) +{ + free(entry->data.ptr); + free(entry); +} + METHOD(dhcp_transaction_t, destroy, void, private_dhcp_transaction_t *this) { this->identity->destroy(this->identity); DESTROY_IF(this->address); DESTROY_IF(this->server); + this->attributes->destroy_function(this->attributes, + (void*)attribute_entry_destroy); free(this); } @@ -111,10 +170,13 @@ dhcp_transaction_t *dhcp_transaction_create(u_int32_t id, .get_address = _get_address, .set_server = _set_server, .get_server = _get_server, + .add_attribute = _add_attribute, + .create_attribute_enumerator = _create_attribute_enumerator, .destroy = _destroy, }, .id = id, .identity = identity->clone(identity), + .attributes = linked_list_create(), ); return &this->public; diff --git a/src/libcharon/plugins/dhcp/dhcp_transaction.h b/src/libcharon/plugins/dhcp/dhcp_transaction.h index e20572064..19c163f88 100644 --- a/src/libcharon/plugins/dhcp/dhcp_transaction.h +++ b/src/libcharon/plugins/dhcp/dhcp_transaction.h @@ -23,6 +23,7 @@ #include #include +#include typedef struct dhcp_transaction_t dhcp_transaction_t; @@ -73,6 +74,22 @@ struct dhcp_transaction_t { */ host_t* (*get_server)(dhcp_transaction_t *this); + /** + * An an additional attribute to serve to peer. + * + * @param type type of attribute + * @param data attribute data + */ + void (*add_attribute)(dhcp_transaction_t *this, + configuration_attribute_type_t type, chunk_t data); + + /** + * Create an enumerator over added attributes. + * + * @return enumerator over (configuration_attribute_t, chunk_t) + */ + enumerator_t* (*create_attribute_enumerator)(dhcp_transaction_t *this); + /** * Destroy a dhcp_transaction_t. */ -- cgit v1.2.3