aboutsummaryrefslogtreecommitdiffstats
path: root/Source/charon/config/sa_config.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/charon/config/sa_config.c')
-rw-r--r--Source/charon/config/sa_config.c293
1 files changed, 293 insertions, 0 deletions
diff --git a/Source/charon/config/sa_config.c b/Source/charon/config/sa_config.c
index e69de29bb..deee85bde 100644
--- a/Source/charon/config/sa_config.c
+++ b/Source/charon/config/sa_config.c
@@ -0,0 +1,293 @@
+/**
+ * @file sa_config.c
+ *
+ * @brief Implementation of sa_config_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2005 Jan Hutter, 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.
+ */
+
+#include "sa_config.h"
+
+#include <utils/linked_list.h>
+#include <utils/allocator.h>
+
+typedef struct private_sa_config_t private_sa_config_t;
+
+/**
+ * Private data of an sa_config_t object
+ */
+struct private_sa_config_t {
+
+ /**
+ * Public part
+ */
+ sa_config_t public;
+
+ /**
+ * id to use to identify us
+ */
+ identification_t *my_id;
+
+ /**
+ * allowed id for other
+ */
+ identification_t *other_id;
+
+ /**
+ * authentification method to use
+ */
+ auth_method_t auth_method;
+
+ /**
+ * list for all proposals
+ */
+ linked_list_t *proposals;
+
+ /**
+ * list for traffic selectors
+ */
+ linked_list_t *ts;
+
+ /**
+ * compare two traffic_selectors for equality
+ */
+ bool (*traffic_selector_equals) (private_sa_config_t *this, traffic_selector_t *first, traffic_selector_t *second);
+
+ /**
+ * compare two proposals for equality
+ */
+ bool (*proposal_equals) (private_sa_config_t *this, child_proposal_t *first, child_proposal_t *second);
+};
+
+
+static identification_t *get_my_id(private_sa_config_t *this)
+{
+ return this->my_id;
+}
+
+static identification_t *get_other_id(private_sa_config_t *this)
+{
+ return this->other_id;
+}
+
+static auth_method_t get_auth_method(private_sa_config_t *this)
+{
+ return this->auth_method;
+}
+
+static size_t get_traffic_selectors(private_sa_config_t *this, traffic_selector_t **traffic_selectors)
+{
+ iterator_t *iterator;
+ traffic_selector_t *current_ts;
+ int counter = 0;
+ *traffic_selectors = allocator_alloc(sizeof(traffic_selector_t) * this->ts->get_count(this->ts));
+
+ /* copy all ts from the list in an array */
+ iterator = this->ts->create_iterator(this->ts, TRUE);
+ while (iterator->has_next(iterator))
+ {
+ iterator->current(iterator, (void**)&current_ts);
+ memcpy((*traffic_selectors) + counter, current_ts, sizeof(traffic_selector_t));
+ counter++;
+ }
+ iterator->destroy(iterator);
+ return counter;
+}
+
+static size_t select_traffic_selectors(private_sa_config_t *this, traffic_selector_t *supplied, size_t count, traffic_selector_t **selected)
+{
+ iterator_t *iterator;
+ traffic_selector_t *current_ts;
+ int i, counter = 0;
+ *selected = allocator_alloc(sizeof(traffic_selector_t) * this->ts->get_count(this->ts));
+
+ /* iterate over all stored proposals */
+ iterator = this->ts->create_iterator(this->ts, TRUE);
+ while (iterator->has_next(iterator))
+ {
+ iterator->current(iterator, (void**)&current_ts);
+ for (i = 0; i < count; i++)
+ {
+ /* copy if a supplied one is equal to ours */
+ if (this->traffic_selector_equals(this, &(supplied[i]), current_ts))
+ {
+ memcpy((*selected) + counter, current_ts, sizeof(traffic_selector_t));
+ counter++;
+ }
+ }
+ }
+ iterator->destroy(iterator);
+
+ /* free unused space */
+ *selected = allocator_realloc(*selected, sizeof(traffic_selector_t) * counter);
+ return counter;
+}
+
+static size_t get_proposals(private_sa_config_t *this, child_proposal_t **proposals)
+{
+ iterator_t *iterator;
+ child_proposal_t *current_proposal;
+ int counter = 0;
+ *proposals = allocator_alloc(sizeof(child_proposal_t) * this->proposals->get_count(this->proposals));
+
+ /* copy all proposals from the list in an array */
+ iterator = this->proposals->create_iterator(this->proposals, TRUE);
+ while (iterator->has_next(iterator))
+ {
+ iterator->current(iterator, (void**)&current_proposal);
+ memcpy((*proposals) + counter, current_proposal, sizeof(child_proposal_t));
+ counter++;
+ }
+ iterator->destroy(iterator);
+ return counter;
+}
+
+static child_proposal_t *select_proposal(private_sa_config_t *this, child_proposal_t *supplied, size_t count)
+{
+ iterator_t *iterator;
+ child_proposal_t *current_proposal, *selected_proposal = NULL;
+ int i;
+
+ /* iterate over all stored proposals */
+ iterator = this->proposals->create_iterator(this->proposals, TRUE);
+ while (iterator->has_next(iterator))
+ {
+ iterator->current(iterator, (void**)&current_proposal);
+ /* copy and break if a proposal matches */
+ for (i = 0; i < count; i++)
+ {
+ if (this->proposal_equals(this, &(supplied[i]), current_proposal))
+ {
+ selected_proposal = allocator_alloc(sizeof(child_proposal_t));
+ memcpy(selected_proposal, current_proposal, sizeof(child_proposal_t));
+ break;
+ }
+ }
+ }
+ iterator->destroy(iterator);
+
+ return selected_proposal;
+}
+
+static bool traffic_selector_equals(private_sa_config_t *this, traffic_selector_t *first, traffic_selector_t *second)
+{
+ if (first->protocol == second->protocol)
+ {
+ if (first->begin->equals(first->begin, second->begin) &&
+ first->end->equals(first->end, second->end))
+ {
+ return TRUE;
+
+ }
+ }
+ return FALSE;
+}
+
+static bool proposal_equals(private_sa_config_t *this, child_proposal_t *first, child_proposal_t *second)
+{
+ if (first->ah.is_set && second->ah.is_set)
+ {
+ if ((first->ah.integrity_algorithm != second->ah.integrity_algorithm) ||
+ (first->ah.key_size != second->ah.key_size))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ return FALSE;
+ }
+ if (first->esp.is_set && second->esp.is_set)
+ {
+ if ((first->esp.encryption_algorithm != second->esp.encryption_algorithm) ||
+ (first->esp.key_size != second->esp.key_size))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static void add_traffic_selector(private_sa_config_t *this, traffic_selector_t *traffic_selector)
+{
+ this->ts->insert_last(this->ts, (void*)traffic_selector);
+}
+
+static void add_proposal(private_sa_config_t *this, child_proposal_t *proposal)
+{
+ this->proposals->insert_last(this->ts, (void*)proposal);
+}
+
+/**
+ * Implements sa_config_t.destroy.
+ */
+static status_t destroy(private_sa_config_t *this)
+{
+ child_proposal_t *proposal;
+ traffic_selector_t *traffic_selector;
+
+ /* delete proposals */
+ while(this->proposals->get_count(this->proposals) > 0)
+ {
+ this->proposals->remove_last(this->proposals, (void**)&proposal);
+ allocator_free(proposal);
+ }
+ this->proposals->destroy(this->proposals);
+
+ /* delete traffic selectors */
+ while(this->ts->get_count(this->ts) > 0)
+ {
+ this->ts->remove_last(this->ts, (void**)&traffic_selector);
+ allocator_free(traffic_selector);
+ }
+ this->ts->destroy(this->ts);
+
+ allocator_free(this);
+ return SUCCESS;
+}
+
+/*
+ * Described in header-file
+ */
+sa_config_t *sa_config_create()
+{
+ private_sa_config_t *this = allocator_alloc_thing(private_sa_config_t);
+
+ /* public functions */
+ this->public.get_my_id = (identification_t(*)(sa_config_t*))get_my_id;
+ this->public.get_other_id = (identification_t(*)(sa_config_t*))get_other_id;
+ this->public.get_auth_method = (auth_method_t(*)(sa_config_t*))get_auth_method;
+ this->public.get_traffic_selectors = (size_t(*)(sa_config_t*,traffic_selector_t**))get_traffic_selectors;
+ this->public.select_traffic_selectors = (size_t(*)(sa_config_t*,traffic_selector_t*,size_t,traffic_selector_t**))select_traffic_selectors;
+ this->public.get_proposals = (size_t(*)(sa_config_t*,child_proposal_t**))get_proposals;
+ this->public.select_proposal = (child_proposal_t*(*)(sa_config_t*,child_proposal_t*,size_t))select_proposal;
+ this->public.add_traffic_selector = (void(*)(sa_config_t*,traffic_selector_t*))add_traffic_selector;
+ this->public.add_proposal = (void(*)(sa_config_t*,child_proposal_t*))add_proposal;
+ this->public.destroy = (void(*)(sa_config_t*))destroy;
+
+ /* private variables */
+ this->proposal_equals = proposal_equals;
+ this->traffic_selector_equals = traffic_selector_equals;
+ this->proposals = linked_list_create();
+ this->ts = linked_list_create();
+
+ return (&this->public);
+}