2 * Copyright (C) 2005-2007 Martin Willi
3 * Copyright (C) 2005 Jan Hutter
4 * Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 #include "child_cfg.h"
23 ENUM(mode_names
, MODE_TRANSPORT
, MODE_BEET
,
31 ENUM(action_names
, ACTION_NONE
, ACTION_RESTART
,
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 * action to take on DPD/passive close
95 * Time before an SA gets invalid
100 * Time before an SA gets rekeyed
105 * Time, which specifies the range of a random value
106 * substracted from rekeytime.
112 * Implementation of child_cfg_t.get_name
114 static char *get_name(private_child_cfg_t
*this)
120 * Implementation of child_cfg_t.add_proposal
122 static void add_proposal(private_child_cfg_t
*this, proposal_t
*proposal
)
124 this->proposals
->insert_last(this->proposals
, proposal
);
128 * Implementation of child_cfg_t.get_proposals
130 static linked_list_t
* get_proposals(private_child_cfg_t
*this, bool strip_dh
)
132 enumerator_t
*enumerator
;
134 linked_list_t
*proposals
= linked_list_create();
136 enumerator
= this->proposals
->create_enumerator(this->proposals
);
137 while (enumerator
->enumerate(enumerator
, ¤t
))
139 current
= current
->clone(current
);
142 current
->strip_dh(current
);
144 proposals
->insert_last(proposals
, current
);
146 enumerator
->destroy(enumerator
);
152 * Implementation of child_cfg_t.get_name
154 static proposal_t
* select_proposal(private_child_cfg_t
*this,
155 linked_list_t
*proposals
, bool strip_dh
)
157 enumerator_t
*stored_enum
, *supplied_enum
;
158 proposal_t
*stored
, *supplied
, *selected
= NULL
;
160 stored_enum
= this->proposals
->create_enumerator(this->proposals
);
161 supplied_enum
= proposals
->create_enumerator(proposals
);
163 /* compare all stored proposals with all supplied. Stored ones are preferred. */
164 while (stored_enum
->enumerate(stored_enum
, &stored
))
166 stored
= stored
->clone(stored
);
167 while (supplied_enum
->enumerate(supplied_enum
, &supplied
))
171 stored
->strip_dh(stored
);
173 selected
= stored
->select(stored
, supplied
);
179 stored
->destroy(stored
);
184 supplied_enum
->destroy(supplied_enum
);
185 supplied_enum
= proposals
->create_enumerator(proposals
);
187 stored_enum
->destroy(stored_enum
);
188 supplied_enum
->destroy(supplied_enum
);
193 * Implementation of child_cfg_t.get_name
195 static void add_traffic_selector(private_child_cfg_t
*this, bool local
,
196 traffic_selector_t
*ts
)
200 this->my_ts
->insert_last(this->my_ts
, ts
);
204 this->other_ts
->insert_last(this->other_ts
, ts
);
209 * Implementation of child_cfg_t.get_name
211 static linked_list_t
* get_traffic_selectors(private_child_cfg_t
*this, bool local
,
212 linked_list_t
*supplied
,
215 enumerator_t
*e1
, *e2
;
216 traffic_selector_t
*ts1
, *ts2
, *selected
;
217 linked_list_t
*result
= linked_list_create();
221 e1
= this->my_ts
->create_enumerator(this->my_ts
);
225 e1
= this->other_ts
->create_enumerator(this->other_ts
);
228 /* no list supplied, just fetch the stored traffic selectors */
229 if (supplied
== NULL
)
231 DBG2(DBG_CFG
, "proposing traffic selectors for %s:",
232 local ?
"us" : "other");
233 while (e1
->enumerate(e1
, &ts1
))
235 /* we make a copy of the TS, this allows us to update dynamic TS' */
236 selected
= ts1
->clone(ts1
);
239 selected
->set_address(selected
, host
);
241 DBG2(DBG_CFG
, " %R (derived from %R)", selected
, ts1
);
242 result
->insert_last(result
, selected
);
248 DBG2(DBG_CFG
, "selecting traffic selectors for %s:",
249 local ?
"us" : "other");
250 e2
= supplied
->create_enumerator(supplied
);
251 /* iterate over all stored selectors */
252 while (e1
->enumerate(e1
, &ts1
))
254 /* we make a copy of the TS, as we have to update dynamic TS' */
255 ts1
= ts1
->clone(ts1
);
258 ts1
->set_address(ts1
, host
);
261 /* iterate over all supplied traffic selectors */
262 while (e2
->enumerate(e2
, &ts2
))
264 selected
= ts1
->get_subset(ts1
, ts2
);
267 DBG2(DBG_CFG
, " config: %R, received: %R => match: %R",
269 result
->insert_last(result
, selected
);
273 DBG2(DBG_CFG
, " config: %R, received: %R => no match",
278 e2
= supplied
->create_enumerator(supplied
);
285 /* remove any redundant traffic selectors in the list */
286 e1
= result
->create_enumerator(result
);
287 e2
= result
->create_enumerator(result
);
288 while (e1
->enumerate(e1
, &ts1
))
290 while (e2
->enumerate(e2
, &ts2
))
294 if (ts2
->is_contained_in(ts2
, ts1
))
296 result
->remove_at(result
, e2
);
299 e1
= result
->create_enumerator(result
);
302 if (ts1
->is_contained_in(ts1
, ts2
))
304 result
->remove_at(result
, e1
);
307 e2
= result
->create_enumerator(result
);
320 * Implementation of child_cfg_t.get_name
322 static char* get_updown(private_child_cfg_t
*this)
328 * Implementation of child_cfg_t.get_name
330 static bool get_hostaccess(private_child_cfg_t
*this)
332 return this->hostaccess
;
336 * Implementation of child_cfg_t.get_name
338 static u_int32_t
get_lifetime(private_child_cfg_t
*this, bool rekey
)
342 if (this->jitter
== 0)
344 return this->rekeytime
;
346 return this->rekeytime
- (random() % this->jitter
);
348 return this->lifetime
;
352 * Implementation of child_cfg_t.get_mode
354 static mode_t
get_mode(private_child_cfg_t
*this)
360 * Implementation of child_cfg_t.get_action
362 static action_t
get_action(private_child_cfg_t
*this)
368 * Implementation of child_cfg_t.get_dh_group.
370 static diffie_hellman_group_t
get_dh_group(private_child_cfg_t
*this)
372 enumerator_t
*enumerator
;
373 proposal_t
*proposal
;
374 u_int16_t dh_group
= MODP_NONE
;
376 enumerator
= this->proposals
->create_enumerator(this->proposals
);
377 while (enumerator
->enumerate(enumerator
, &proposal
))
379 if (proposal
->get_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
, &dh_group
, NULL
))
384 enumerator
->destroy(enumerator
);
389 * Implementation of child_cfg_t.get_name
391 static void get_ref(private_child_cfg_t
*this)
393 ref_get(&this->refcount
);
397 * Implements child_cfg_t.destroy.
399 static void destroy(private_child_cfg_t
*this)
401 if (ref_put(&this->refcount
))
403 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
404 this->my_ts
->destroy_offset(this->my_ts
, offsetof(traffic_selector_t
, destroy
));
405 this->other_ts
->destroy_offset(this->other_ts
, offsetof(traffic_selector_t
, destroy
));
416 * Described in header-file
418 child_cfg_t
*child_cfg_create(char *name
, u_int32_t lifetime
,
419 u_int32_t rekeytime
, u_int32_t jitter
,
420 char *updown
, bool hostaccess
, mode_t mode
,
423 private_child_cfg_t
*this = malloc_thing(private_child_cfg_t
);
425 this->public.get_name
= (char* (*) (child_cfg_t
*))get_name
;
426 this->public.add_traffic_selector
= (void (*)(child_cfg_t
*,bool,traffic_selector_t
*))add_traffic_selector
;
427 this->public.get_traffic_selectors
= (linked_list_t
*(*)(child_cfg_t
*,bool,linked_list_t
*,host_t
*))get_traffic_selectors
;
428 this->public.add_proposal
= (void (*) (child_cfg_t
*,proposal_t
*))add_proposal
;
429 this->public.get_proposals
= (linked_list_t
* (*) (child_cfg_t
*,bool))get_proposals
;
430 this->public.select_proposal
= (proposal_t
* (*) (child_cfg_t
*,linked_list_t
*,bool))select_proposal
;
431 this->public.get_updown
= (char* (*) (child_cfg_t
*))get_updown
;
432 this->public.get_hostaccess
= (bool (*) (child_cfg_t
*))get_hostaccess
;
433 this->public.get_mode
= (mode_t (*) (child_cfg_t
*))get_mode
;
434 this->public.get_action
= (action_t (*) (child_cfg_t
*))get_action
;
435 this->public.get_lifetime
= (u_int32_t (*) (child_cfg_t
*,bool))get_lifetime
;
436 this->public.get_dh_group
= (diffie_hellman_group_t(*)(child_cfg_t
*)) get_dh_group
;
437 this->public.get_ref
= (void (*) (child_cfg_t
*))get_ref
;
438 this->public.destroy
= (void (*) (child_cfg_t
*))destroy
;
440 this->name
= strdup(name
);
441 this->lifetime
= lifetime
;
442 this->rekeytime
= rekeytime
;
443 this->jitter
= jitter
;
444 this->updown
= updown ?
strdup(updown
) : NULL
;
445 this->hostaccess
= hostaccess
;
447 this->action
= action
;
449 this->proposals
= linked_list_create();
450 this->my_ts
= linked_list_create();
451 this->other_ts
= linked_list_create();
453 return &this->public;