accepting stroke initiation by a name of a child_cfg
[strongswan.git] / src / charon / config / backends / local_backend.c
1 /**
2 * @file local_backend.c
3 *
4 * @brief Implementation of local_backend_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_backend.h"
26
27 #include <daemon.h>
28 #include <utils/linked_list.h>
29
30
31 typedef struct private_local_backend_t private_local_backend_t;
32
33 /**
34 * Private data of an local_backend_t object
35 */
36 struct private_local_backend_t {
37
38 /**
39 * Public part
40 */
41 local_backend_t public;
42
43 /**
44 * list of configs
45 */
46 linked_list_t *cfgs;
47
48 /**
49 * Mutex to exclusivly access list
50 */
51 pthread_mutex_t mutex;
52 };
53
54 /**
55 * implements cfg_store_t.get_ike_cfg.
56 */
57 static ike_cfg_t *get_ike_cfg(private_local_backend_t *this,
58 host_t *my_host, host_t *other_host)
59 {
60 peer_cfg_t *peer;
61 ike_cfg_t *current, *found = NULL;
62 iterator_t *iterator;
63 host_t *my_candidate, *other_candidate;
64 enum {
65 MATCH_NONE = 0x00,
66 MATCH_ANY = 0x01,
67 MATCH_ME = 0x04,
68 MATCH_OTHER = 0x08,
69 } prio, best = MATCH_ANY;
70
71 DBG2(DBG_CFG, "looking for a config for %H...%H",
72 my_host, other_host);
73
74 iterator = this->cfgs->create_iterator_locked(this->cfgs, &this->mutex);
75 while (iterator->iterate(iterator, (void**)&peer))
76 {
77 prio = MATCH_NONE;
78 current = peer->get_ike_cfg(peer);
79 my_candidate = current->get_my_host(current);
80 other_candidate = current->get_other_host(current);
81
82 if (my_candidate->ip_equals(my_candidate, my_host))
83 {
84 prio += MATCH_ME;
85 }
86 else if (my_candidate->is_anyaddr(my_candidate))
87 {
88 prio += MATCH_ANY;
89 }
90
91 if (other_candidate->ip_equals(other_candidate, other_host))
92 {
93 prio += MATCH_OTHER;
94 }
95 else if (other_candidate->is_anyaddr(other_candidate))
96 {
97 prio += MATCH_ANY;
98 }
99
100 DBG2(DBG_CFG, " candidate '%s': %H...%H, prio %d",
101 peer->get_name(peer), my_candidate, other_candidate, prio);
102
103 /* we require at least two MATCH_ANY */
104 if (prio > best)
105 {
106 best = prio;
107 found = current;
108 }
109 }
110 if (found)
111 {
112 found->get_ref(found);
113 }
114 iterator->destroy(iterator);
115 return found;
116 }
117
118 /**
119 * implements cfg_store_t.get_peer.
120 */
121 static peer_cfg_t *get_peer_cfg(private_local_backend_t *this,
122 identification_t *my_id,
123 identification_t *other_id)
124 {
125 peer_cfg_t *current, *found = NULL;
126 iterator_t *iterator;
127 identification_t *my_candidate, *other_candidate;
128 int best = 2 * MAX_WILDCARDS + 1;
129
130 DBG2(DBG_CFG, "looking for a config for %D...%D", my_id, other_id);
131
132 iterator = this->cfgs->create_iterator_locked(this->cfgs, &this->mutex);
133 while (iterator->iterate(iterator, (void**)&current))
134 {
135 int wc1, wc2;
136
137 my_candidate = current->get_my_id(current);
138 other_candidate = current->get_other_id(current);
139
140 if (my_candidate->matches(my_candidate, my_id, &wc1) &&
141 other_id->matches(other_id, other_candidate, &wc2))
142 {
143 int prio = wc1 + wc2;
144
145 DBG2(DBG_CFG, " candidate '%s': %D...%D, prio %d",
146 current->get_name(current), my_candidate, other_candidate, prio);
147
148 if (prio < best)
149 {
150 found = current;
151 best = prio;
152 }
153 }
154 }
155 if (found)
156 {
157 DBG1(DBG_CFG, "found matching config \"%s\": %D...%D, prio %d",
158 found->get_name(found),
159 found->get_my_id(found),
160 found->get_other_id(found),
161 best);
162 found->get_ref(found);
163 }
164 iterator->destroy(iterator);
165 return found;
166 }
167
168 /**
169 * implements cfg_store_t.get_peer_by_name.
170 */
171 static peer_cfg_t *get_peer_cfg_by_name(private_local_backend_t *this,
172 char *name)
173 {
174 iterator_t *i1, *i2;
175 peer_cfg_t *current, *found = NULL;
176 child_cfg_t *child;
177
178 i1 = this->cfgs->create_iterator(this->cfgs, TRUE);
179 while (i1->iterate(i1, (void**)&current))
180 {
181 /* compare peer_cfgs name first */
182 if (streq(current->get_name(current), name))
183 {
184 found = current;
185 found->get_ref(found);
186 break;
187 }
188 /* compare all child_cfg names otherwise */
189 i2 = current->create_child_cfg_iterator(current);
190 while (i2->iterate(i2, (void**)&child))
191 {
192 if (streq(child->get_name(child), name))
193 {
194 found = current;
195 found->get_ref(found);
196 break;
197 }
198 }
199 i2->destroy(i2);
200 if (found)
201 {
202 break;
203 }
204 }
205 i1->destroy(i1);
206 return found;
207 }
208
209 /**
210 * Implementation of local_backend_t.create_peer_cfg_iterator.
211 */
212 static iterator_t* create_peer_cfg_iterator(private_local_backend_t *this)
213 {
214 return this->cfgs->create_iterator_locked(this->cfgs, &this->mutex);
215 }
216
217 /**
218 * Implementation of local_backend_t.add_peer_cfg.
219 */
220 static void add_peer_cfg(private_local_backend_t *this, peer_cfg_t *config)
221 {
222 pthread_mutex_lock(&this->mutex);
223 this->cfgs->insert_last(this->cfgs, config);
224 pthread_mutex_unlock(&this->mutex);
225 }
226
227 /**
228 * Implementation of local_backend_t.destroy.
229 */
230 static void destroy(private_local_backend_t *this)
231 {
232 this->cfgs->destroy_offset(this->cfgs, offsetof(peer_cfg_t, destroy));
233 free(this);
234 }
235
236 /**
237 * Described in header.
238 */
239 local_backend_t *local_backend_create(void)
240 {
241 private_local_backend_t *this = malloc_thing(private_local_backend_t);
242
243 this->public.backend.get_ike_cfg = (ike_cfg_t*(*)(backend_t*, host_t *, host_t *))get_ike_cfg;
244 this->public.backend.get_peer_cfg = (peer_cfg_t*(*)(backend_t*, identification_t *, identification_t *))get_peer_cfg;
245 this->public.create_peer_cfg_iterator = (iterator_t*(*)(local_backend_t*))create_peer_cfg_iterator;
246 this->public.get_peer_cfg_by_name = (peer_cfg_t*(*)(local_backend_t*, char *))get_peer_cfg_by_name;
247 this->public.add_peer_cfg = (void(*)(local_backend_t*, peer_cfg_t *))add_peer_cfg;
248 this->public.destroy = (void(*)(local_backend_t*))destroy;
249
250 /* private variables */
251 this->cfgs = linked_list_create();
252 pthread_mutex_init(&this->mutex, NULL);
253
254 return (&this->public);
255 }