2 * Copyright (C) 2008 Tobias Brunner
3 * Copyright (C) 2005-2007 Martin Willi
4 * Copyright (C) 2005 Jan Hutter
5 * Hochschule fuer Technik Rapperswil
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 #include "child_cfg.h"
24 ENUM(mode_names
, MODE_TRANSPORT
, MODE_BEET
,
32 ENUM(action_names
, ACTION_NONE
, ACTION_RESTART
,
38 ENUM_BEGIN(ipcomp_transform_names
, IPCOMP_NONE
, IPCOMP_NONE
,
40 ENUM_NEXT(ipcomp_transform_names
, IPCOMP_OUI
, IPCOMP_LZJH
, IPCOMP_NONE
,
45 ENUM_END(ipcomp_transform_names
, IPCOMP_LZJH
);
47 typedef struct private_child_cfg_t private_child_cfg_t
;
50 * Private data of an child_cfg_t object
52 struct private_child_cfg_t
{
60 * Number of references hold by others to this child_cfg
65 * Name of the child_cfg, used to query it
70 * list for all proposals
72 linked_list_t
*proposals
;
75 * list for traffic selectors for my site
80 * list for traffic selectors for others site
82 linked_list_t
*other_ts
;
95 * Mode to propose for a initiated CHILD: tunnel/transport
100 * action to take on DPD
105 * action to take on CHILD_SA close
107 action_t close_action
;
110 * Time before an SA gets invalid
115 * Time before an SA gets rekeyed
120 * Time, which specifies the range of a random value
121 * substracted from rekeytime.
132 * Implementation of child_cfg_t.get_name
134 static char *get_name(private_child_cfg_t
*this)
140 * Implementation of child_cfg_t.add_proposal
142 static void add_proposal(private_child_cfg_t
*this, proposal_t
*proposal
)
144 this->proposals
->insert_last(this->proposals
, proposal
);
148 * Implementation of child_cfg_t.get_proposals
150 static linked_list_t
* get_proposals(private_child_cfg_t
*this, bool strip_dh
)
152 enumerator_t
*enumerator
;
154 linked_list_t
*proposals
= linked_list_create();
156 enumerator
= this->proposals
->create_enumerator(this->proposals
);
157 while (enumerator
->enumerate(enumerator
, ¤t
))
159 current
= current
->clone(current
);
162 current
->strip_dh(current
);
164 proposals
->insert_last(proposals
, current
);
166 enumerator
->destroy(enumerator
);
172 * Implementation of child_cfg_t.get_name
174 static proposal_t
* select_proposal(private_child_cfg_t
*this,
175 linked_list_t
*proposals
, bool strip_dh
)
177 enumerator_t
*stored_enum
, *supplied_enum
;
178 proposal_t
*stored
, *supplied
, *selected
= NULL
;
180 stored_enum
= this->proposals
->create_enumerator(this->proposals
);
181 supplied_enum
= proposals
->create_enumerator(proposals
);
183 /* compare all stored proposals with all supplied. Stored ones are preferred. */
184 while (stored_enum
->enumerate(stored_enum
, &stored
))
186 stored
= stored
->clone(stored
);
187 while (supplied_enum
->enumerate(supplied_enum
, &supplied
))
191 stored
->strip_dh(stored
);
193 selected
= stored
->select(stored
, supplied
);
196 DBG2(DBG_CFG
, "received proposals: %#P", proposals
);
197 DBG2(DBG_CFG
, "configured proposals: %#P", this->proposals
);
198 DBG2(DBG_CFG
, "selected proposal: %P", selected
);
202 stored
->destroy(stored
);
207 supplied_enum
->destroy(supplied_enum
);
208 supplied_enum
= proposals
->create_enumerator(proposals
);
210 stored_enum
->destroy(stored_enum
);
211 supplied_enum
->destroy(supplied_enum
);
212 if (selected
== NULL
)
214 DBG1(DBG_CFG
, "received proposals: %#P", proposals
);
215 DBG1(DBG_CFG
, "configured proposals: %#P", this->proposals
);
221 * Implementation of child_cfg_t.get_name
223 static void add_traffic_selector(private_child_cfg_t
*this, bool local
,
224 traffic_selector_t
*ts
)
228 this->my_ts
->insert_last(this->my_ts
, ts
);
232 this->other_ts
->insert_last(this->other_ts
, ts
);
237 * Implementation of child_cfg_t.get_name
239 static linked_list_t
* get_traffic_selectors(private_child_cfg_t
*this, bool local
,
240 linked_list_t
*supplied
,
243 enumerator_t
*e1
, *e2
;
244 traffic_selector_t
*ts1
, *ts2
, *selected
;
245 linked_list_t
*result
= linked_list_create();
249 e1
= this->my_ts
->create_enumerator(this->my_ts
);
253 e1
= this->other_ts
->create_enumerator(this->other_ts
);
256 /* no list supplied, just fetch the stored traffic selectors */
257 if (supplied
== NULL
)
259 DBG2(DBG_CFG
, "proposing traffic selectors for %s:",
260 local ?
"us" : "other");
261 while (e1
->enumerate(e1
, &ts1
))
263 /* we make a copy of the TS, this allows us to update dynamic TS' */
264 selected
= ts1
->clone(ts1
);
267 selected
->set_address(selected
, host
);
269 DBG2(DBG_CFG
, " %R (derived from %R)", selected
, ts1
);
270 result
->insert_last(result
, selected
);
276 DBG2(DBG_CFG
, "selecting traffic selectors for %s:",
277 local ?
"us" : "other");
278 e2
= supplied
->create_enumerator(supplied
);
279 /* iterate over all stored selectors */
280 while (e1
->enumerate(e1
, &ts1
))
282 /* we make a copy of the TS, as we have to update dynamic TS' */
283 ts1
= ts1
->clone(ts1
);
286 ts1
->set_address(ts1
, host
);
289 /* iterate over all supplied traffic selectors */
290 while (e2
->enumerate(e2
, &ts2
))
292 selected
= ts1
->get_subset(ts1
, ts2
);
295 DBG2(DBG_CFG
, " config: %R, received: %R => match: %R",
297 result
->insert_last(result
, selected
);
301 DBG2(DBG_CFG
, " config: %R, received: %R => no match",
306 e2
= supplied
->create_enumerator(supplied
);
313 /* remove any redundant traffic selectors in the list */
314 e1
= result
->create_enumerator(result
);
315 e2
= result
->create_enumerator(result
);
316 while (e1
->enumerate(e1
, &ts1
))
318 while (e2
->enumerate(e2
, &ts2
))
322 if (ts2
->is_contained_in(ts2
, ts1
))
324 result
->remove_at(result
, e2
);
327 e1
= result
->create_enumerator(result
);
330 if (ts1
->is_contained_in(ts1
, ts2
))
332 result
->remove_at(result
, e1
);
335 e2
= result
->create_enumerator(result
);
348 * Implementation of child_cfg_t.get_name
350 static char* get_updown(private_child_cfg_t
*this)
356 * Implementation of child_cfg_t.get_name
358 static bool get_hostaccess(private_child_cfg_t
*this)
360 return this->hostaccess
;
364 * Implementation of child_cfg_t.get_name
366 static u_int32_t
get_lifetime(private_child_cfg_t
*this, bool rekey
)
370 if (this->jitter
== 0)
372 return this->rekeytime
;
374 return this->rekeytime
- (random() % this->jitter
);
376 return this->lifetime
;
380 * Implementation of child_cfg_t.get_mode
382 static mode_t
get_mode(private_child_cfg_t
*this)
388 * Implementation of child_cfg_t.get_dpd_action
390 static action_t
get_dpd_action(private_child_cfg_t
*this)
392 return this->dpd_action
;
396 * Implementation of child_cfg_t.get_close_action
398 static action_t
get_close_action(private_child_cfg_t
*this)
400 return this->close_action
;
404 * Implementation of child_cfg_t.get_dh_group.
406 static diffie_hellman_group_t
get_dh_group(private_child_cfg_t
*this)
408 enumerator_t
*enumerator
;
409 proposal_t
*proposal
;
410 u_int16_t dh_group
= MODP_NONE
;
412 enumerator
= this->proposals
->create_enumerator(this->proposals
);
413 while (enumerator
->enumerate(enumerator
, &proposal
))
415 if (proposal
->get_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
, &dh_group
, NULL
))
420 enumerator
->destroy(enumerator
);
425 * Implementation of child_cfg_t.use_ipcomp.
427 static bool use_ipcomp(private_child_cfg_t
*this)
429 return this->use_ipcomp
;
433 * Implementation of child_cfg_t.get_name
435 static child_cfg_t
* get_ref(private_child_cfg_t
*this)
437 ref_get(&this->refcount
);
438 return &this->public;
442 * Implements child_cfg_t.destroy.
444 static void destroy(private_child_cfg_t
*this)
446 if (ref_put(&this->refcount
))
448 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
449 this->my_ts
->destroy_offset(this->my_ts
, offsetof(traffic_selector_t
, destroy
));
450 this->other_ts
->destroy_offset(this->other_ts
, offsetof(traffic_selector_t
, destroy
));
461 * Described in header-file
463 child_cfg_t
*child_cfg_create(char *name
, u_int32_t lifetime
,
464 u_int32_t rekeytime
, u_int32_t jitter
,
465 char *updown
, bool hostaccess
, mode_t mode
,
466 action_t dpd_action
, action_t close_action
, bool ipcomp
)
468 private_child_cfg_t
*this = malloc_thing(private_child_cfg_t
);
470 this->public.get_name
= (char* (*) (child_cfg_t
*))get_name
;
471 this->public.add_traffic_selector
= (void (*)(child_cfg_t
*,bool,traffic_selector_t
*))add_traffic_selector
;
472 this->public.get_traffic_selectors
= (linked_list_t
*(*)(child_cfg_t
*,bool,linked_list_t
*,host_t
*))get_traffic_selectors
;
473 this->public.add_proposal
= (void (*) (child_cfg_t
*,proposal_t
*))add_proposal
;
474 this->public.get_proposals
= (linked_list_t
* (*) (child_cfg_t
*,bool))get_proposals
;
475 this->public.select_proposal
= (proposal_t
* (*) (child_cfg_t
*,linked_list_t
*,bool))select_proposal
;
476 this->public.get_updown
= (char* (*) (child_cfg_t
*))get_updown
;
477 this->public.get_hostaccess
= (bool (*) (child_cfg_t
*))get_hostaccess
;
478 this->public.get_mode
= (mode_t (*) (child_cfg_t
*))get_mode
;
479 this->public.get_dpd_action
= (action_t (*) (child_cfg_t
*))get_dpd_action
;
480 this->public.get_close_action
= (action_t (*) (child_cfg_t
*))get_close_action
;
481 this->public.get_lifetime
= (u_int32_t (*) (child_cfg_t
*,bool))get_lifetime
;
482 this->public.get_dh_group
= (diffie_hellman_group_t(*)(child_cfg_t
*)) get_dh_group
;
483 this->public.use_ipcomp
= (bool (*) (child_cfg_t
*))use_ipcomp
;
484 this->public.get_ref
= (child_cfg_t
* (*) (child_cfg_t
*))get_ref
;
485 this->public.destroy
= (void (*) (child_cfg_t
*))destroy
;
487 this->name
= strdup(name
);
488 this->lifetime
= lifetime
;
489 this->rekeytime
= rekeytime
;
490 this->jitter
= jitter
;
491 this->updown
= updown ?
strdup(updown
) : NULL
;
492 this->hostaccess
= hostaccess
;
494 this->dpd_action
= dpd_action
;
495 this->close_action
= close_action
;
496 this->use_ipcomp
= ipcomp
;
498 this->proposals
= linked_list_create();
499 this->my_ts
= linked_list_create();
500 this->other_ts
= linked_list_create();
502 return &this->public;