extended interface_manager (more work needed here)
[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 backen_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 backend_t.get_peer.
120 */
121 static peer_cfg_t *get_peer_cfg(private_local_backend_t *this,
122 identification_t *my_id, identification_t *other_id,
123 identification_t *other_ca, char *other_group,
124 host_t *my_host, host_t *other_host)
125 {
126 peer_cfg_t *current, *found = NULL;
127 iterator_t *iterator;
128 identification_t *my_candidate, *other_candidate;
129 int best = 2 * MAX_WILDCARDS + 1;
130
131 DBG2(DBG_CFG, "looking for a config for %D...%D", my_id, other_id);
132
133 iterator = this->cfgs->create_iterator_locked(this->cfgs, &this->mutex);
134 while (iterator->iterate(iterator, (void**)&current))
135 {
136 int wc1, wc2;
137
138 my_candidate = current->get_my_id(current);
139 other_candidate = current->get_other_id(current);
140
141 if (my_candidate->matches(my_candidate, my_id, &wc1) &&
142 other_id->matches(other_id, other_candidate, &wc2))
143 {
144 int prio = wc1 + wc2;
145
146 DBG2(DBG_CFG, " candidate '%s': %D...%D, prio %d",
147 current->get_name(current), my_candidate, other_candidate, prio);
148
149 if (prio < best)
150 {
151 found = current;
152 best = prio;
153 }
154 }
155 }
156 if (found)
157 {
158 DBG1(DBG_CFG, "found matching config \"%s\": %D...%D, prio %d",
159 found->get_name(found),
160 found->get_my_id(found),
161 found->get_other_id(found),
162 best);
163 found->get_ref(found);
164 }
165 iterator->destroy(iterator);
166 return found;
167 }
168
169 /**
170 * Implementation of backend_t.is_writable.
171 */
172 static bool is_writeable(private_local_backend_t *this)
173 {
174 return TRUE;
175 }
176
177 /**
178 * Implementation of writable_backend_t.create_iterator.
179 */
180 static iterator_t* create_iterator(private_local_backend_t *this)
181 {
182 return this->cfgs->create_iterator_locked(this->cfgs, &this->mutex);
183 }
184
185 /**
186 * Implementation of writable_backend_t.add_peer_cfg.
187 */
188 static void add_cfg(private_local_backend_t *this, peer_cfg_t *config)
189 {
190 pthread_mutex_lock(&this->mutex);
191 this->cfgs->insert_last(this->cfgs, config);
192 pthread_mutex_unlock(&this->mutex);
193 }
194
195 /**
196 * Implementation of backend_t.destroy.
197 */
198 static void destroy(private_local_backend_t *this)
199 {
200 this->cfgs->destroy_offset(this->cfgs, offsetof(peer_cfg_t, destroy));
201 free(this);
202 }
203
204 /**
205 * Described in header.
206 */
207 backend_t *backend_create(void)
208 {
209 private_local_backend_t *this = malloc_thing(private_local_backend_t);
210
211 this->public.backend.backend.get_ike_cfg = (ike_cfg_t*(*)(backend_t*, host_t *, host_t *))get_ike_cfg;
212 this->public.backend.backend.get_peer_cfg = (peer_cfg_t*(*)(backend_t*,identification_t*,identification_t*,identification_t*,char*,host_t*,host_t*))get_peer_cfg;
213 this->public.backend.backend.is_writeable = (bool(*)(backend_t*))is_writeable;
214 this->public.backend.backend.destroy = (void(*)(backend_t*))destroy;
215 this->public.backend.create_iterator = (iterator_t*(*)(writeable_backend_t*))create_iterator;
216 this->public.backend.add_cfg = (void(*)(writeable_backend_t*, peer_cfg_t *))add_cfg;
217
218 /* private variables */
219 this->cfgs = linked_list_create();
220 pthread_mutex_init(&this->mutex, NULL);
221
222 return &this->public.backend.backend;
223 }