2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #include "backend_manager.h"
20 #include <sys/types.h>
24 #include <utils/linked_list.h>
25 #include <utils/mutex.h>
28 typedef struct private_backend_manager_t private_backend_manager_t
;
31 * Private data of an backend_manager_t object.
33 struct private_backend_manager_t
{
36 * Public part of backend_manager_t object.
38 backend_manager_t
public;
41 * list of registered backends
43 linked_list_t
*backends
;
54 typedef enum ike_cfg_match_t
{
62 * data to pass nested IKE enumerator
65 private_backend_manager_t
*this;
71 * data to pass nested peer enumerator
74 private_backend_manager_t
*this;
76 identification_t
*other
;
80 * inner enumerator constructor for IKE cfgs
82 static enumerator_t
*ike_enum_create(backend_t
*backend
, ike_data_t
*data
)
84 return backend
->create_ike_cfg_enumerator(backend
, data
->me
, data
->other
);
88 * inner enumerator constructor for Peer cfgs
90 static enumerator_t
*peer_enum_create(backend_t
*backend
, peer_data_t
*data
)
92 return backend
->create_peer_cfg_enumerator(backend
, data
->me
, data
->other
);
95 * inner enumerator constructor for all Peer cfgs
97 static enumerator_t
*peer_enum_create_all(backend_t
*backend
)
99 return backend
->create_peer_cfg_enumerator(backend
, NULL
, NULL
);
103 * get a match of a candidate ike_cfg for two hosts
105 static ike_cfg_match_t
get_match(ike_cfg_t
*cand
, host_t
*me
, host_t
*other
)
107 host_t
*me_cand
, *other_cand
;
108 ike_cfg_match_t match
= MATCH_NONE
;
110 me_cand
= host_create_from_dns(cand
->get_my_addr(cand
),
111 me
->get_family(me
), 0);
116 if (me_cand
->ip_equals(me_cand
, me
))
120 else if (me_cand
->is_anyaddr(me_cand
))
124 me_cand
->destroy(me_cand
);
126 other_cand
= host_create_from_dns(cand
->get_other_addr(cand
),
127 other
->get_family(other
), 0);
132 if (other_cand
->ip_equals(other_cand
, other
))
134 match
+= MATCH_OTHER
;
136 else if (other_cand
->is_anyaddr(other_cand
))
140 other_cand
->destroy(other_cand
);
145 * implements backend_manager_t.get_ike_cfg.
147 static ike_cfg_t
*get_ike_cfg(private_backend_manager_t
*this,
148 host_t
*me
, host_t
*other
)
150 ike_cfg_t
*current
, *found
= NULL
;
151 enumerator_t
*enumerator
;
152 ike_cfg_match_t match
, best
= MATCH_ANY
;
155 data
= malloc_thing(ike_data_t
);
160 DBG2(DBG_CFG
, "looking for an ike config for %H...%H", me
, other
);
162 this->lock
->read_lock(this->lock
);
163 enumerator
= enumerator_create_nested(
164 this->backends
->create_enumerator(this->backends
),
165 (void*)ike_enum_create
, data
, (void*)free
);
166 while (enumerator
->enumerate(enumerator
, (void**)¤t
))
168 match
= get_match(current
, me
, other
);
172 DBG2(DBG_CFG
, " candidate: %s...%s, prio %d",
173 current
->get_my_addr(current
),
174 current
->get_other_addr(current
), match
);
179 found
->get_ref(found
);
184 enumerator
->destroy(enumerator
);
185 this->lock
->unlock(this->lock
);
188 DBG2(DBG_CFG
, "found matching ike config: %s...%s with prio %d",
189 found
->get_my_addr(found
), found
->get_other_addr(found
), best
);
195 static enumerator_t
*create_peer_cfg_enumerator(private_backend_manager_t
*this)
197 this->lock
->read_lock(this->lock
);
198 return enumerator_create_nested(
199 this->backends
->create_enumerator(this->backends
),
200 (void*)peer_enum_create_all
, this->lock
,
201 (void*)this->lock
->unlock
);
205 * implements backend_manager_t.get_peer_cfg.
207 static peer_cfg_t
*get_peer_cfg(private_backend_manager_t
*this, host_t
*me
,
208 host_t
*other
, identification_t
*my_id
,
209 identification_t
*other_id
, auth_info_t
*auth
)
211 peer_cfg_t
*current
, *found
= NULL
;
212 enumerator_t
*enumerator
;
213 id_match_t best_peer
= ID_MATCH_NONE
;
214 ike_cfg_match_t best_ike
= MATCH_NONE
;
217 DBG2(DBG_CFG
, "looking for a peer config for %H[%D]...%H[%D]",
218 me
, my_id
, other
, other_id
);
220 data
= malloc_thing(peer_data_t
);
223 data
->other
= other_id
;
225 this->lock
->read_lock(this->lock
);
226 enumerator
= enumerator_create_nested(
227 this->backends
->create_enumerator(this->backends
),
228 (void*)peer_enum_create
, data
, (void*)free
);
229 while (enumerator
->enumerate(enumerator
, ¤t
))
231 identification_t
*my_cand
, *other_cand
;
232 id_match_t m1
, m2
, match_peer
;
233 ike_cfg_match_t match_ike
;
235 my_cand
= current
->get_my_id(current
);
236 other_cand
= current
->get_other_id(current
);
238 /* own ID may have wildcards in both, config and request (missing IDr) */
239 m1
= my_cand
->matches(my_cand
, my_id
);
242 m1
= my_id
->matches(my_id
, my_cand
);
244 m2
= other_id
->matches(other_id
, other_cand
);
246 match_peer
= m1
+ m2
;
247 match_ike
= get_match(current
->get_ike_cfg(current
), me
, other
);
249 if (m1
&& m2
&& match_ike
&&
250 auth
->complies(auth
, current
->get_auth(current
)))
252 DBG2(DBG_CFG
, " candidate \"%s\": %D...%D with prio %d.%d",
253 current
->get_name(current
), my_cand
, other_cand
,
254 match_peer
, match_ike
);
255 if (match_peer
> best_peer
&& match_ike
>= best_ike
)
259 found
->get_ref(found
);
260 best_peer
= match_peer
;
261 best_ike
= match_ike
;
267 DBG1(DBG_CFG
, "found matching peer config \"%s\": %D...%D with prio %d.%d",
268 found
->get_name(found
), found
->get_my_id(found
),
269 found
->get_other_id(found
), best_peer
, best_ike
);
271 enumerator
->destroy(enumerator
);
272 this->lock
->unlock(this->lock
);
277 * implements backend_manager_t.get_peer_cfg_by_name.
279 static peer_cfg_t
*get_peer_cfg_by_name(private_backend_manager_t
*this, char *name
)
282 peer_cfg_t
*config
= NULL
;
283 enumerator_t
*enumerator
;
285 this->lock
->read_lock(this->lock
);
286 enumerator
= this->backends
->create_enumerator(this->backends
);
287 while (config
== NULL
&& enumerator
->enumerate(enumerator
, (void**)&backend
))
289 config
= backend
->get_peer_cfg_by_name(backend
, name
);
291 enumerator
->destroy(enumerator
);
292 this->lock
->unlock(this->lock
);
297 * Implementation of backend_manager_t.remove_backend.
299 static void remove_backend(private_backend_manager_t
*this, backend_t
*backend
)
301 this->lock
->write_lock(this->lock
);
302 this->backends
->remove(this->backends
, backend
, NULL
);
303 this->lock
->unlock(this->lock
);
307 * Implementation of backend_manager_t.add_backend.
309 static void add_backend(private_backend_manager_t
*this, backend_t
*backend
)
311 this->lock
->write_lock(this->lock
);
312 this->backends
->insert_last(this->backends
, backend
);
313 this->lock
->unlock(this->lock
);
317 * Implementation of backend_manager_t.destroy.
319 static void destroy(private_backend_manager_t
*this)
321 this->backends
->destroy(this->backends
);
322 this->lock
->destroy(this->lock
);
327 * Described in header-file
329 backend_manager_t
*backend_manager_create()
331 private_backend_manager_t
*this = malloc_thing(private_backend_manager_t
);
333 this->public.get_ike_cfg
= (ike_cfg_t
* (*)(backend_manager_t
*, host_t
*, host_t
*))get_ike_cfg
;
334 this->public.get_peer_cfg
= (peer_cfg_t
* (*)(backend_manager_t
*,host_t
*,host_t
*,identification_t
*,identification_t
*,auth_info_t
*))get_peer_cfg
;
335 this->public.get_peer_cfg_by_name
= (peer_cfg_t
* (*)(backend_manager_t
*,char*))get_peer_cfg_by_name
;
336 this->public.create_peer_cfg_enumerator
= (enumerator_t
* (*)(backend_manager_t
*))create_peer_cfg_enumerator
;
337 this->public.add_backend
= (void(*)(backend_manager_t
*, backend_t
*backend
))add_backend
;
338 this->public.remove_backend
= (void(*)(backend_manager_t
*, backend_t
*backend
))remove_backend
;
339 this->public.destroy
= (void (*)(backend_manager_t
*))destroy
;
341 this->backends
= linked_list_create();
342 this->lock
= rwlock_create(RWLOCK_DEFAULT
);
344 return &this->public;