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
);
199 stored
->destroy(stored
);
204 supplied_enum
->destroy(supplied_enum
);
205 supplied_enum
= proposals
->create_enumerator(proposals
);
207 stored_enum
->destroy(stored_enum
);
208 supplied_enum
->destroy(supplied_enum
);
213 * Implementation of child_cfg_t.get_name
215 static void add_traffic_selector(private_child_cfg_t
*this, bool local
,
216 traffic_selector_t
*ts
)
220 this->my_ts
->insert_last(this->my_ts
, ts
);
224 this->other_ts
->insert_last(this->other_ts
, ts
);
229 * Implementation of child_cfg_t.get_name
231 static linked_list_t
* get_traffic_selectors(private_child_cfg_t
*this, bool local
,
232 linked_list_t
*supplied
,
235 enumerator_t
*e1
, *e2
;
236 traffic_selector_t
*ts1
, *ts2
, *selected
;
237 linked_list_t
*result
= linked_list_create();
241 e1
= this->my_ts
->create_enumerator(this->my_ts
);
245 e1
= this->other_ts
->create_enumerator(this->other_ts
);
248 /* no list supplied, just fetch the stored traffic selectors */
249 if (supplied
== NULL
)
251 DBG2(DBG_CFG
, "proposing traffic selectors for %s:",
252 local ?
"us" : "other");
253 while (e1
->enumerate(e1
, &ts1
))
255 /* we make a copy of the TS, this allows us to update dynamic TS' */
256 selected
= ts1
->clone(ts1
);
259 selected
->set_address(selected
, host
);
261 DBG2(DBG_CFG
, " %R (derived from %R)", selected
, ts1
);
262 result
->insert_last(result
, selected
);
268 DBG2(DBG_CFG
, "selecting traffic selectors for %s:",
269 local ?
"us" : "other");
270 e2
= supplied
->create_enumerator(supplied
);
271 /* iterate over all stored selectors */
272 while (e1
->enumerate(e1
, &ts1
))
274 /* we make a copy of the TS, as we have to update dynamic TS' */
275 ts1
= ts1
->clone(ts1
);
278 ts1
->set_address(ts1
, host
);
281 /* iterate over all supplied traffic selectors */
282 while (e2
->enumerate(e2
, &ts2
))
284 selected
= ts1
->get_subset(ts1
, ts2
);
287 DBG2(DBG_CFG
, " config: %R, received: %R => match: %R",
289 result
->insert_last(result
, selected
);
293 DBG2(DBG_CFG
, " config: %R, received: %R => no match",
298 e2
= supplied
->create_enumerator(supplied
);
305 /* remove any redundant traffic selectors in the list */
306 e1
= result
->create_enumerator(result
);
307 e2
= result
->create_enumerator(result
);
308 while (e1
->enumerate(e1
, &ts1
))
310 while (e2
->enumerate(e2
, &ts2
))
314 if (ts2
->is_contained_in(ts2
, ts1
))
316 result
->remove_at(result
, e2
);
319 e1
= result
->create_enumerator(result
);
322 if (ts1
->is_contained_in(ts1
, ts2
))
324 result
->remove_at(result
, e1
);
327 e2
= result
->create_enumerator(result
);
340 * Implementation of child_cfg_t.get_name
342 static char* get_updown(private_child_cfg_t
*this)
348 * Implementation of child_cfg_t.get_name
350 static bool get_hostaccess(private_child_cfg_t
*this)
352 return this->hostaccess
;
356 * Implementation of child_cfg_t.get_name
358 static u_int32_t
get_lifetime(private_child_cfg_t
*this, bool rekey
)
362 if (this->jitter
== 0)
364 return this->rekeytime
;
366 return this->rekeytime
- (random() % this->jitter
);
368 return this->lifetime
;
372 * Implementation of child_cfg_t.get_mode
374 static mode_t
get_mode(private_child_cfg_t
*this)
380 * Implementation of child_cfg_t.get_dpd_action
382 static action_t
get_dpd_action(private_child_cfg_t
*this)
384 return this->dpd_action
;
388 * Implementation of child_cfg_t.get_close_action
390 static action_t
get_close_action(private_child_cfg_t
*this)
392 return this->close_action
;
396 * Implementation of child_cfg_t.get_dh_group.
398 static diffie_hellman_group_t
get_dh_group(private_child_cfg_t
*this)
400 enumerator_t
*enumerator
;
401 proposal_t
*proposal
;
402 u_int16_t dh_group
= MODP_NONE
;
404 enumerator
= this->proposals
->create_enumerator(this->proposals
);
405 while (enumerator
->enumerate(enumerator
, &proposal
))
407 if (proposal
->get_algorithm(proposal
, DIFFIE_HELLMAN_GROUP
, &dh_group
, NULL
))
412 enumerator
->destroy(enumerator
);
417 * Implementation of child_cfg_t.use_ipcomp.
419 static bool use_ipcomp(private_child_cfg_t
*this)
421 return this->use_ipcomp
;
425 * Implementation of child_cfg_t.get_name
427 static child_cfg_t
* get_ref(private_child_cfg_t
*this)
429 ref_get(&this->refcount
);
430 return &this->public;
434 * Implements child_cfg_t.destroy.
436 static void destroy(private_child_cfg_t
*this)
438 if (ref_put(&this->refcount
))
440 this->proposals
->destroy_offset(this->proposals
, offsetof(proposal_t
, destroy
));
441 this->my_ts
->destroy_offset(this->my_ts
, offsetof(traffic_selector_t
, destroy
));
442 this->other_ts
->destroy_offset(this->other_ts
, offsetof(traffic_selector_t
, destroy
));
453 * Described in header-file
455 child_cfg_t
*child_cfg_create(char *name
, u_int32_t lifetime
,
456 u_int32_t rekeytime
, u_int32_t jitter
,
457 char *updown
, bool hostaccess
, mode_t mode
,
458 action_t dpd_action
, action_t close_action
, bool ipcomp
)
460 private_child_cfg_t
*this = malloc_thing(private_child_cfg_t
);
462 this->public.get_name
= (char* (*) (child_cfg_t
*))get_name
;
463 this->public.add_traffic_selector
= (void (*)(child_cfg_t
*,bool,traffic_selector_t
*))add_traffic_selector
;
464 this->public.get_traffic_selectors
= (linked_list_t
*(*)(child_cfg_t
*,bool,linked_list_t
*,host_t
*))get_traffic_selectors
;
465 this->public.add_proposal
= (void (*) (child_cfg_t
*,proposal_t
*))add_proposal
;
466 this->public.get_proposals
= (linked_list_t
* (*) (child_cfg_t
*,bool))get_proposals
;
467 this->public.select_proposal
= (proposal_t
* (*) (child_cfg_t
*,linked_list_t
*,bool))select_proposal
;
468 this->public.get_updown
= (char* (*) (child_cfg_t
*))get_updown
;
469 this->public.get_hostaccess
= (bool (*) (child_cfg_t
*))get_hostaccess
;
470 this->public.get_mode
= (mode_t (*) (child_cfg_t
*))get_mode
;
471 this->public.get_dpd_action
= (action_t (*) (child_cfg_t
*))get_dpd_action
;
472 this->public.get_close_action
= (action_t (*) (child_cfg_t
*))get_close_action
;
473 this->public.get_lifetime
= (u_int32_t (*) (child_cfg_t
*,bool))get_lifetime
;
474 this->public.get_dh_group
= (diffie_hellman_group_t(*)(child_cfg_t
*)) get_dh_group
;
475 this->public.use_ipcomp
= (bool (*) (child_cfg_t
*))use_ipcomp
;
476 this->public.get_ref
= (child_cfg_t
* (*) (child_cfg_t
*))get_ref
;
477 this->public.destroy
= (void (*) (child_cfg_t
*))destroy
;
479 this->name
= strdup(name
);
480 this->lifetime
= lifetime
;
481 this->rekeytime
= rekeytime
;
482 this->jitter
= jitter
;
483 this->updown
= updown ?
strdup(updown
) : NULL
;
484 this->hostaccess
= hostaccess
;
486 this->dpd_action
= dpd_action
;
487 this->close_action
= close_action
;
488 this->use_ipcomp
= ipcomp
;
490 this->proposals
= linked_list_create();
491 this->my_ts
= linked_list_create();
492 this->other_ts
= linked_list_create();
494 return &this->public;