4 * @brief Implementation of child_cfg_t.
9 * Copyright (C) 2005-2007 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 #include "child_cfg.h"
29 ENUM(mode_names
, MODE_TRANSPORT
, MODE_BEET
,
37 typedef struct private_child_cfg_t private_child_cfg_t
;
40 * Private data of an child_cfg_t object
42 struct private_child_cfg_t
{
50 * Number of references hold by others to this child_cfg
55 * Name of the child_cfg, used to query it
60 * list for all proposals
62 linked_list_t
*proposals
;
65 * list for traffic selectors for my site
70 * list for traffic selectors for others site
72 linked_list_t
*other_ts
;
85 * Mode to propose for a initiated CHILD: tunnel/transport
90 * Time before an SA gets invalid
95 * Time before an SA gets rekeyed
100 * Time, which specifies the range of a random value
101 * substracted from rekeytime.
107 * Implementation of child_cfg_t.get_name
109 static char *get_name(private_child_cfg_t
*this)
115 * Implementation of child_cfg_t.add_proposal
117 static void add_proposal(private_child_cfg_t
*this, proposal_t
*proposal
)
119 this->proposals
->insert_last(this->proposals
, proposal
);
123 * strip out DH groups from a proposal
125 static void strip_dh_from_proposal(proposal_t
*proposal
)
127 iterator_t
*iterator
;
130 iterator
= proposal
->create_algorithm_iterator(proposal
, DIFFIE_HELLMAN_GROUP
);
131 while (iterator
->iterate(iterator
, (void**)&algo
))
133 iterator
->remove(iterator
);
136 iterator
->destroy(iterator
);
140 * Implementation of child_cfg_t.get_proposals
142 static linked_list_t
* get_proposals(private_child_cfg_t
*this, bool strip_dh
)
144 iterator_t
*iterator
;
146 linked_list_t
*proposals
= linked_list_create();
148 iterator
= this->proposals
->create_iterator(this->proposals
, TRUE
);
149 while (iterator
->iterate(iterator
, (void**)¤t
))
151 current
= current
->clone(current
);
154 strip_dh_from_proposal(current
);
156 proposals
->insert_last(proposals
, current
);
158 iterator
->destroy(iterator
);
164 * Implementation of child_cfg_t.get_name
166 static proposal_t
* select_proposal(private_child_cfg_t
*this,
167 linked_list_t
*proposals
, bool strip_dh
)
169 iterator_t
*stored_iter
, *supplied_iter
;
170 proposal_t
*stored
, *supplied
, *selected
= NULL
;
172 stored_iter
= this->proposals
->create_iterator(this->proposals
, TRUE
);
173 supplied_iter
= proposals
->create_iterator(proposals
, TRUE
);
175 /* compare all stored proposals with all supplied. Stored ones are preferred. */
176 while (stored_iter
->iterate(stored_iter
, (void**)&stored
))
178 supplied_iter
->reset(supplied_iter
);
179 while (supplied_iter
->iterate(supplied_iter
, (void**)&supplied
))
183 /* remove DH groups on a copy */
184 stored
= stored
->clone(stored
);
185 strip_dh_from_proposal(stored
);
186 selected
= stored
->select(stored
, supplied
);
187 stored
->destroy(stored
);
191 selected
= stored
->select(stored
, supplied
);
203 stored_iter
->destroy(stored_iter
);
204 supplied_iter
->destroy(supplied_iter
);
209 * Implementation of child_cfg_t.get_name
211 static void add_traffic_selector(private_child_cfg_t
*this, bool local
,
212 traffic_selector_t
*ts
)
216 this->my_ts
->insert_last(this->my_ts
, ts
);
220 this->other_ts
->insert_last(this->other_ts
, ts
);
225 * Implementation of child_cfg_t.get_name
227 static linked_list_t
* get_traffic_selectors(private_child_cfg_t
*this, bool local
,
228 linked_list_t
*supplied
,
232 traffic_selector_t
*ts1
, *ts2
, *selected
;
233 linked_list_t
*result
= linked_list_create();
237 i1
= this->my_ts
->create_iterator(this->my_ts
, TRUE
);
241 i1
= this->other_ts
->create_iterator(this->other_ts
, FALSE
);
244 /* no list supplied, just fetch the stored traffic selectors */
245 if (supplied
== NULL
)
247 while (i1
->iterate(i1
, (void**)&ts1
))
249 /* we make a copy of the TS, this allows us to update dynamic TS' */
250 ts1
= ts1
->clone(ts1
);
253 ts1
->set_address(ts1
, host
);
255 result
->insert_last(result
, ts1
);
261 DBG2(DBG_CFG
, "selecting traffic selectors");
262 i2
= supplied
->create_iterator(supplied
, TRUE
);
263 /* iterate over all stored selectors */
264 while (i1
->iterate(i1
, (void**)&ts1
))
266 /* we make a copy of the TS, as we have to update dynamic TS' */
267 ts1
= ts1
->clone(ts1
);
270 ts1
->set_address(ts1
, host
);
274 /* iterate over all supplied traffic selectors */
275 while (i2
->iterate(i2
, (void**)&ts2
))
277 DBG2(DBG_CFG
, "stored %R <=> %R received", ts1
, ts2
);
278 selected
= ts1
->get_subset(ts1
, ts2
);
281 result
->insert_last(result
, selected
);
282 DBG2(DBG_CFG
, "found traffic selector for %s: %R",
283 local ?
"us" : "other", selected
);
292 /* remove any redundant traffic selectors in the list */
293 i1
= result
->create_iterator(result
, TRUE
);
294 i2
= result
->create_iterator(result
, TRUE
);
295 while (i1
->iterate(i1
, (void**)&ts1
))
297 while (i2
->iterate(i2
, (void**)&ts2
))
301 if (ts2
->is_contained_in(ts2
, ts1
))
308 if (ts1
->is_contained_in(ts1
, ts2
))
325 * Implementation of child_cfg_t.get_name
327 static char* get_updown(private_child_cfg_t
*this)
333 * Implementation of child_cfg_t.get_name
335 static bool get_hostaccess(private_child_cfg_t
*this)
337 return this->hostaccess
;
341 * Implementation of child_cfg_t.get_name
343 static u_int32_t
get_lifetime(private_child_cfg_t
*this, bool rekey
)
347 if (this->jitter
== 0)
349 return this->rekeytime
;
351 return this->rekeytime
- (random() % this->jitter
);
353 return this->lifetime
;
357 * Implementation of child_cfg_t.get_name
359 static mode_t
get_mode(private_child_cfg_t
*this)
365 * Implementation of child_cfg_t.get_dh_group.
367 static diffie_hellman_group_t
get_dh_group(private_child_cfg_t
*this)
369 iterator_t
*iterator
;
370 proposal_t
*proposal
;
372 diffie_hellman_group_t dh_group
= MODP_NONE
;
374 iterator
= this->proposals
->create_iterator(this->proposals
, TRUE
);
375 while (iterator
->iterate(iterator
, (void**)&proposal
))
377 if (proposal
->get_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
, &algo
))
379 dh_group
= algo
->algorithm
;
383 iterator
->destroy(iterator
);
388 * Implementation of child_cfg_t.get_name
390 static void get_ref(private_child_cfg_t
*this)
392 ref_get(&this->refcount
);
396 * Implements child_cfg_t.destroy.
398 static void destroy(private_child_cfg_t
*this)
400 if (ref_put(&this->refcount
))
402 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
403 this->my_ts
->destroy_offset(this->my_ts
, offsetof(traffic_selector_t
, destroy
));
404 this->other_ts
->destroy_offset(this->other_ts
, offsetof(traffic_selector_t
, destroy
));
415 * Described in header-file
417 child_cfg_t
*child_cfg_create(char *name
, u_int32_t lifetime
,
418 u_int32_t rekeytime
, u_int32_t jitter
,
419 char *updown
, bool hostaccess
, mode_t mode
)
421 private_child_cfg_t
*this = malloc_thing(private_child_cfg_t
);
423 /* public functions */
424 this->public.get_name
= (char* (*) (child_cfg_t
*))get_name
;
425 this->public.add_traffic_selector
= (void (*)(child_cfg_t
*,bool,traffic_selector_t
*))add_traffic_selector
;
426 this->public.get_traffic_selectors
= (linked_list_t
*(*)(child_cfg_t
*,bool,linked_list_t
*,host_t
*))get_traffic_selectors
;
427 this->public.add_proposal
= (void (*) (child_cfg_t
*,proposal_t
*))add_proposal
;
428 this->public.get_proposals
= (linked_list_t
* (*) (child_cfg_t
*,bool))get_proposals
;
429 this->public.select_proposal
= (proposal_t
* (*) (child_cfg_t
*,linked_list_t
*,bool))select_proposal
;
430 this->public.get_updown
= (char* (*) (child_cfg_t
*))get_updown
;
431 this->public.get_hostaccess
= (bool (*) (child_cfg_t
*))get_hostaccess
;
432 this->public.get_mode
= (mode_t (*) (child_cfg_t
*))get_mode
;
433 this->public.get_lifetime
= (u_int32_t (*) (child_cfg_t
*,bool))get_lifetime
;
434 this->public.get_dh_group
= (diffie_hellman_group_t(*)(child_cfg_t
*)) get_dh_group
;
435 this->public.get_ref
= (void (*) (child_cfg_t
*))get_ref
;
436 this->public.destroy
= (void (*) (child_cfg_t
*))destroy
;
438 /* apply init values */
439 this->name
= strdup(name
);
440 this->lifetime
= lifetime
;
441 this->rekeytime
= rekeytime
;
442 this->jitter
= jitter
;
443 this->updown
= updown ?
strdup(updown
) : NULL
;
444 this->hostaccess
= hostaccess
;
447 /* initialize private members*/
449 this->proposals
= linked_list_create();
450 this->my_ts
= linked_list_create();
451 this->other_ts
= linked_list_create();
453 return &this->public;