restructured file layout
[strongswan.git] / src / charon / config / child_cfg.c
1 /**
2 * @file child_cfg.c
3 *
4 * @brief Implementation of child_cfg_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005-2007 Martin Willi
10 * Copyright (C) 2005 Jan Hutter
11 * Hochschule fuer Technik Rapperswil
12 *
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>.
17 *
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
21 * for more details.
22 */
23
24
25 #include "child_cfg.h"
26
27 #include <daemon.h>
28
29 ENUM(mode_names, MODE_TRANSPORT, MODE_BEET,
30 "TRANSPORT",
31 "TUNNEL",
32 "2",
33 "3",
34 "BEET",
35 );
36
37 typedef struct private_child_cfg_t private_child_cfg_t;
38
39 /**
40 * Private data of an child_cfg_t object
41 */
42 struct private_child_cfg_t {
43
44 /**
45 * Public part
46 */
47 child_cfg_t public;
48
49 /**
50 * Number of references hold by others to this child_cfg
51 */
52 refcount_t refcount;
53
54 /**
55 * Name of the child_cfg, used to query it
56 */
57 char *name;
58
59 /**
60 * list for all proposals
61 */
62 linked_list_t *proposals;
63
64 /**
65 * list for traffic selectors for my site
66 */
67 linked_list_t *my_ts;
68
69 /**
70 * list for traffic selectors for others site
71 */
72 linked_list_t *other_ts;
73
74 /**
75 * updown script
76 */
77 char *updown;
78
79 /**
80 * allow host access
81 */
82 bool hostaccess;
83
84 /**
85 * Mode to propose for a initiated CHILD: tunnel/transport
86 */
87 mode_t mode;
88
89 /**
90 * Time before an SA gets invalid
91 */
92 u_int32_t lifetime;
93
94 /**
95 * Time before an SA gets rekeyed
96 */
97 u_int32_t rekeytime;
98
99 /**
100 * Time, which specifies the range of a random value
101 * substracted from rekeytime.
102 */
103 u_int32_t jitter;
104 };
105
106 /**
107 * Implementation of child_cfg_t.get_name
108 */
109 static char *get_name(private_child_cfg_t *this)
110 {
111 return this->name;
112 }
113
114 /**
115 * Implementation of child_cfg_t.add_proposal
116 */
117 static void add_proposal(private_child_cfg_t *this, proposal_t *proposal)
118 {
119 this->proposals->insert_last(this->proposals, proposal);
120 }
121
122 /**
123 * Implementation of child_cfg_t.get_proposals
124 */
125 static linked_list_t* get_proposals(private_child_cfg_t *this)
126 {
127 iterator_t *iterator;
128 proposal_t *current;
129 linked_list_t *proposals = linked_list_create();
130
131 iterator = this->proposals->create_iterator(this->proposals, TRUE);
132 while (iterator->iterate(iterator, (void**)&current))
133 {
134 current = current->clone(current);
135 proposals->insert_last(proposals, current);
136 }
137 iterator->destroy(iterator);
138
139 return proposals;
140 }
141
142 /**
143 * Implementation of child_cfg_t.get_name
144 */
145 static proposal_t* select_proposal(private_child_cfg_t*this, linked_list_t *proposals)
146 {
147 iterator_t *stored_iter, *supplied_iter;
148 proposal_t *stored, *supplied, *selected = NULL;
149
150 stored_iter = this->proposals->create_iterator(this->proposals, TRUE);
151 supplied_iter = proposals->create_iterator(proposals, TRUE);
152
153 /* compare all stored proposals with all supplied. Stored ones are preferred. */
154 while (stored_iter->iterate(stored_iter, (void**)&stored))
155 {
156 supplied_iter->reset(supplied_iter);
157 while (supplied_iter->iterate(supplied_iter, (void**)&supplied))
158 {
159 selected = stored->select(stored, supplied);
160 if (selected)
161 {
162 break;
163 }
164 }
165 if (selected)
166 {
167 break;
168 }
169 }
170 stored_iter->destroy(stored_iter);
171 supplied_iter->destroy(supplied_iter);
172 return selected;
173 }
174
175 /**
176 * Implementation of child_cfg_t.get_name
177 */
178 static void add_traffic_selector(private_child_cfg_t *this, bool local,
179 traffic_selector_t *ts)
180 {
181 if (local)
182 {
183 this->my_ts->insert_last(this->my_ts, ts);
184 }
185 else
186 {
187 this->other_ts->insert_last(this->other_ts, ts);
188 }
189 }
190
191 /**
192 * Implementation of child_cfg_t.get_name
193 */
194 static linked_list_t* get_traffic_selectors(private_child_cfg_t *this, bool local,
195 linked_list_t *supplied,
196 host_t *host)
197 {
198 iterator_t *i1, *i2;
199 traffic_selector_t *ts1, *ts2, *selected;
200 linked_list_t *result = linked_list_create();
201
202 if (local)
203 {
204 i1 = this->my_ts->create_iterator(this->my_ts, TRUE);
205 }
206 else
207 {
208 i1 = this->other_ts->create_iterator(this->other_ts, FALSE);
209 }
210
211 /* no list supplied, just fetch the stored traffic selectors */
212 if (supplied == NULL)
213 {
214 while (i1->iterate(i1, (void**)&ts1))
215 {
216 /* we make a copy of the TS, this allows us to update dynamic TS' */
217 ts1 = ts1->clone(ts1);
218 if (host)
219 {
220 ts1->set_address(ts1, host);
221 }
222 result->insert_last(result, ts1);
223 }
224 i1->destroy(i1);
225 }
226 else
227 {
228 DBG2(DBG_CFG, "selecting traffic selectors");
229 i2 = supplied->create_iterator(supplied, TRUE);
230 /* iterate over all stored selectors */
231 while (i1->iterate(i1, (void**)&ts1))
232 {
233 /* we make a copy of the TS, as we have to update dynamic TS' */
234 ts1 = ts1->clone(ts1);
235 if (host)
236 {
237 ts1->set_address(ts1, host);
238 }
239
240 i2->reset(i2);
241 /* iterate over all supplied traffic selectors */
242 while (i2->iterate(i2, (void**)&ts2))
243 {
244 DBG2(DBG_CFG, "stored %R <=> %R received", ts1, ts2);
245 selected = ts1->get_subset(ts1, ts2);
246 if (selected)
247 {
248 result->insert_last(result, selected);
249 DBG2(DBG_CFG, "found traffic selector for %s: %R",
250 local ? "us" : "other", selected);
251 }
252 }
253 ts1->destroy(ts1);
254 }
255 i1->destroy(i1);
256 i2->destroy(i2);
257 }
258
259 /* remove any redundant traffic selectors in the list */
260 i1 = result->create_iterator(result, TRUE);
261 i2 = result->create_iterator(result, TRUE);
262 while (i1->iterate(i1, (void**)&ts1))
263 {
264 while (i2->iterate(i2, (void**)&ts2))
265 {
266 if (ts1 != ts2)
267 {
268 if (ts2->is_contained_in(ts2, ts1))
269 {
270 i2->remove(i2);
271 ts2->destroy(ts2);
272 i1->reset(i1);
273 break;
274 }
275 if (ts1->is_contained_in(ts1, ts2))
276 {
277 i1->remove(i1);
278 ts1->destroy(ts1);
279 i2->reset(i2);
280 break;
281 }
282 }
283 }
284 }
285 i1->destroy(i1);
286 i2->destroy(i2);
287
288 return result;
289 }
290
291 /**
292 * Implementation of child_cfg_t.get_name
293 */
294 static char* get_updown(private_child_cfg_t *this)
295 {
296 return this->updown;
297 }
298
299 /**
300 * Implementation of child_cfg_t.get_name
301 */
302 static bool get_hostaccess(private_child_cfg_t *this)
303 {
304 return this->hostaccess;
305 }
306
307 /**
308 * Implementation of child_cfg_t.get_name
309 */
310 static u_int32_t get_lifetime(private_child_cfg_t *this, bool rekey)
311 {
312 if (rekey)
313 {
314 if (this->jitter == 0)
315 {
316 return this->rekeytime;
317 }
318 return this->rekeytime - (random() % this->jitter);
319 }
320 return this->lifetime;
321 }
322
323 /**
324 * Implementation of child_cfg_t.get_name
325 */
326 static mode_t get_mode(private_child_cfg_t *this)
327 {
328 return this->mode;
329 }
330
331 /**
332 * Implementation of child_cfg_t.get_name
333 */
334 static void get_ref(private_child_cfg_t *this)
335 {
336 ref_get(&this->refcount);
337 }
338
339 /**
340 * Implements child_cfg_t.destroy.
341 */
342 static void destroy(private_child_cfg_t *this)
343 {
344 if (ref_put(&this->refcount))
345 {
346 this->proposals->destroy_offset(this->proposals, offsetof(proposal_t, destroy));
347 this->my_ts->destroy_offset(this->my_ts, offsetof(traffic_selector_t, destroy));
348 this->other_ts->destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
349 if (this->updown)
350 {
351 free(this->updown);
352 }
353 free(this->name);
354 free(this);
355 }
356 }
357
358 /*
359 * Described in header-file
360 */
361 child_cfg_t *child_cfg_create(char *name, u_int32_t lifetime,
362 u_int32_t rekeytime, u_int32_t jitter,
363 char *updown, bool hostaccess, mode_t mode)
364 {
365 private_child_cfg_t *this = malloc_thing(private_child_cfg_t);
366
367 /* public functions */
368 this->public.get_name = (char* (*) (child_cfg_t*))get_name;
369 this->public.add_traffic_selector = (void (*)(child_cfg_t*,bool,traffic_selector_t*))add_traffic_selector;
370 this->public.get_traffic_selectors = (linked_list_t*(*)(child_cfg_t*,bool,linked_list_t*,host_t*))get_traffic_selectors;
371 this->public.add_proposal = (void (*) (child_cfg_t*,proposal_t*))add_proposal;
372 this->public.get_proposals = (linked_list_t* (*) (child_cfg_t*))get_proposals;
373 this->public.select_proposal = (proposal_t* (*) (child_cfg_t*,linked_list_t*))select_proposal;
374 this->public.get_updown = (char* (*) (child_cfg_t*))get_updown;
375 this->public.get_hostaccess = (bool (*) (child_cfg_t*))get_hostaccess;
376 this->public.get_mode = (mode_t (*) (child_cfg_t *))get_mode;
377 this->public.get_lifetime = (u_int32_t (*) (child_cfg_t *,bool))get_lifetime;
378 this->public.get_ref = (void (*) (child_cfg_t*))get_ref;
379 this->public.destroy = (void (*) (child_cfg_t*))destroy;
380
381 /* apply init values */
382 this->name = strdup(name);
383 this->lifetime = lifetime;
384 this->rekeytime = rekeytime;
385 this->jitter = jitter;
386 this->updown = updown ? strdup(updown) : NULL;
387 this->hostaccess = hostaccess;
388 this->mode = mode;
389
390 /* initialize private members*/
391 this->refcount = 1;
392 this->proposals = linked_list_create();
393 this->my_ts = linked_list_create();
394 this->other_ts = linked_list_create();
395
396 return &this->public;
397 }