- show connection templates in status & statusall
[strongswan.git] / src / charon / config / connections / local_connection_store.c
1 /**
2 * @file local_connection_store.c
3 *
4 * @brief Implementation of local_connection_store_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include <string.h>
24
25 #include "local_connection_store.h"
26
27 #include <utils/linked_list.h>
28 #include <utils/logger_manager.h>
29
30
31 typedef struct private_local_connection_store_t private_local_connection_store_t;
32
33 /**
34 * Private data of an local_connection_store_t object
35 */
36 struct private_local_connection_store_t {
37
38 /**
39 * Public part
40 */
41 local_connection_store_t public;
42
43 /**
44 * stored connection
45 */
46 linked_list_t *connections;
47
48 /**
49 * Assigned logger
50 */
51 logger_t *logger;
52 };
53
54
55 /**
56 * Implementation of connection_store_t.get_connection_by_hosts.
57 */
58 static connection_t *get_connection_by_hosts(private_local_connection_store_t *this, host_t *my_host, host_t *other_host)
59 {
60 typedef enum {
61 PRIO_UNDEFINED= 0x00,
62 PRIO_ADDR_ANY= 0x01,
63 PRIO_ADDR_MATCH= 0x02
64 } prio_t;
65
66 prio_t best_prio = PRIO_UNDEFINED;
67
68 iterator_t *iterator;
69 connection_t *candidate;
70 connection_t *found = NULL;
71
72 this->logger->log(this->logger, CONTROL|LEVEL1, "searching connection for host pair %s...%s",
73 my_host->get_address(my_host), other_host->get_address(other_host));
74
75 iterator = this->connections->create_iterator(this->connections, TRUE);
76
77 /* determine closest matching connection */
78 while (iterator->has_next(iterator))
79 {
80 host_t *candidate_my_host;
81 host_t *candidate_other_host;
82
83 iterator->current(iterator, (void**)&candidate);
84
85 candidate_my_host = candidate->get_my_host(candidate);
86 candidate_other_host = candidate->get_other_host(candidate);
87
88 /* my_host addresses must match*/
89 if (my_host->ip_equals(my_host, candidate_my_host))
90 {
91 prio_t prio = PRIO_UNDEFINED;
92
93 /* exact match of peer host address or wildcard address? */
94 if (other_host->ip_equals(other_host, candidate_other_host))
95 {
96 prio |= PRIO_ADDR_MATCH;
97 }
98 else if (candidate_other_host->is_anyaddr(candidate_other_host))
99 {
100 prio |= PRIO_ADDR_ANY;
101 }
102
103 this->logger->log(this->logger, CONTROL|LEVEL2,
104 "candidate connection \"%s\": %s...%s (prio=%d)",
105 candidate->get_name(candidate),
106 candidate_my_host->get_address(candidate_my_host),
107 candidate_other_host->get_address(candidate_other_host),
108 prio);
109
110 if (prio > best_prio)
111 {
112 found = candidate;
113 best_prio = prio;
114 }
115 }
116 }
117 iterator->destroy(iterator);
118
119 if (found)
120 {
121 host_t *found_my_host = found->get_my_host(found);
122 host_t *found_other_host = found->get_other_host(found);
123
124 this->logger->log(this->logger, CONTROL|LEVEL1,
125 "found matching connection \"%s\": %s...%s (prio=%d)",
126 found->get_name(found),
127 found_my_host->get_address(found_my_host),
128 found_other_host->get_address(found_other_host),
129 best_prio);
130
131 found = found->clone(found);
132 if (best_prio & PRIO_ADDR_ANY)
133 {
134 /* replace %any by the peer's address */
135 found->update_other_host(found, other_host->clone(other_host));
136 }
137 }
138 return found;
139 }
140
141 /**
142 * Implementation of connection_store_t.get_connection_by_ids.
143 */
144 static connection_t *get_connection_by_ids(private_local_connection_store_t *this, identification_t *my_id, identification_t *other_id)
145 {
146 iterator_t *iterator;
147 connection_t *current, *found = NULL;
148
149 this->logger->log(this->logger, CONTROL|LEVEL1, "getting config for ids %s - %s",
150 my_id->get_string(my_id), other_id->get_string(other_id));
151
152 iterator = this->connections->create_iterator(this->connections, TRUE);
153 while (iterator->has_next(iterator))
154 {
155 identification_t *config_my_id, *config_other_id;
156
157 iterator->current(iterator, (void**)&current);
158
159 config_my_id = current->get_my_id(current);
160 config_other_id = current->get_other_id(current);
161
162 /* first check if ids are equal
163 * TODO: Add wildcard checks */
164 if (config_other_id->equals(config_other_id, other_id) &&
165 config_my_id->equals(config_my_id, my_id))
166 {
167 this->logger->log(this->logger, CONTROL|LEVEL2, "config entry with remote id %s",
168 config_other_id->get_string(config_other_id));
169 found = current->clone(current);
170 break;
171 }
172 }
173 iterator->destroy(iterator);
174
175 return found;
176 }
177
178 /**
179 * Implementation of connection_store_t.get_connection_by_name.
180 */
181 static connection_t *get_connection_by_name(private_local_connection_store_t *this, char *name)
182 {
183 iterator_t *iterator;
184 connection_t *current, *found = NULL;
185
186 iterator = this->connections->create_iterator(this->connections, TRUE);
187 while (iterator->has_next(iterator))
188 {
189 iterator->current(iterator, (void**)&current);
190 if (strcmp(name, current->get_name(current)) == 0)
191 {
192 found = current->clone(current);
193 break;
194 }
195 }
196 iterator->destroy(iterator);
197
198 return found;
199 }
200
201 /**
202 * Implementation of connection_store_t.add_connection.
203 */
204 static status_t add_connection(private_local_connection_store_t *this, connection_t *connection)
205 {
206 this->connections->insert_last(this->connections, connection);
207 return SUCCESS;
208 }
209
210 /**
211 * Implementation of connection_store_t.log_connections.
212 */
213 void log_connections(private_local_connection_store_t *this, logger_t *logger, char *name)
214 {
215 iterator_t *iterator;
216 connection_t *current, *found = NULL;
217
218 if (logger == NULL)
219 {
220 logger = this->logger;
221 }
222
223 logger->log(logger, CONTROL, "templates:");
224
225 iterator = this->connections->create_iterator(this->connections, TRUE);
226 while (iterator->has_next(iterator))
227 {
228 iterator->current(iterator, (void**)&current);
229 if (!name || strcmp(name, current->get_name(current)) == 0)
230 {
231 identification_t *my_id, *other_id;
232 host_t *my_host, *other_host;
233 my_id = current->get_my_id(current);
234 other_id = current->get_other_id(current);
235 my_host = current->get_my_host(current);
236 other_host = current->get_other_host(current);
237 logger->log(logger, CONTROL, " \"%s\": %s[%s]...%s[%s]",
238 current->get_name(current),
239 my_host->get_address(my_host), my_id->get_string(my_id),
240 other_host->get_address(other_host), other_id->get_string(other_id));
241 }
242 }
243 iterator->destroy(iterator);
244 }
245
246 /**
247 * Implementation of connection_store_t.destroy.
248 */
249 static void destroy (private_local_connection_store_t *this)
250 {
251 connection_t *connection;
252
253 while (this->connections->remove_last(this->connections, (void**)&connection) == SUCCESS)
254 {
255 connection->destroy(connection);
256 }
257 this->connections->destroy(this->connections);
258 free(this);
259 }
260
261 /**
262 * Described in header.
263 */
264 local_connection_store_t * local_connection_store_create(void)
265 {
266 private_local_connection_store_t *this = malloc_thing(private_local_connection_store_t);
267
268 this->public.connection_store.get_connection_by_hosts = (connection_t*(*)(connection_store_t*,host_t*,host_t*))get_connection_by_hosts;
269 this->public.connection_store.get_connection_by_ids = (connection_t*(*)(connection_store_t*,identification_t*,identification_t*))get_connection_by_ids;
270 this->public.connection_store.get_connection_by_name = (connection_t*(*)(connection_store_t*,char*))get_connection_by_name;
271 this->public.connection_store.add_connection = (status_t(*)(connection_store_t*,connection_t*))add_connection;
272 this->public.connection_store.log_connections = (void(*)(connection_store_t*,logger_t*,char*))log_connections;
273 this->public.connection_store.destroy = (void(*)(connection_store_t*))destroy;
274
275 /* private variables */
276 this->connections = linked_list_create();
277 this->logger = logger_manager->get_logger(logger_manager, CONFIG);
278
279 return (&this->public);
280 }