ac30afe743cae8b143c817ae771200498ed053eb
[strongswan.git] / src / charon / config / policies / policy.c
1 /**
2 * @file policy.c
3 *
4 * @brief Implementation of policy_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include "policy.h"
24
25 #include <utils/linked_list.h>
26 #include <utils/identification.h>
27 #include <utils/logger.h>
28
29 typedef struct private_policy_t private_policy_t;
30
31 /**
32 * Private data of an policy_t object
33 */
34 struct private_policy_t {
35
36 /**
37 * Public part
38 */
39 policy_t public;
40
41 /**
42 * Name of the policy, used to query it
43 */
44 char *name;
45
46 /**
47 * id to use to identify us
48 */
49 identification_t *my_id;
50
51 /**
52 * allowed id for other
53 */
54 identification_t *other_id;
55
56 /**
57 * list for all proposals
58 */
59 linked_list_t *proposals;
60
61 /**
62 * list for traffic selectors for my site
63 */
64 linked_list_t *my_ts;
65
66 /**
67 * list for traffic selectors for others site
68 */
69 linked_list_t *other_ts;
70
71 /**
72 * select_traffic_selectors for both
73 */
74 linked_list_t *(*select_traffic_selectors) (private_policy_t *,linked_list_t*,linked_list_t*);
75 };
76
77 /**
78 * Implementation of policy_t.get_name
79 */
80 static char *get_name(private_policy_t *this)
81 {
82 return this->name;
83 }
84
85 /**
86 * Implementation of policy_t.get_my_id
87 */
88 static identification_t *get_my_id(private_policy_t *this)
89 {
90 return this->my_id;
91 }
92
93 /**
94 * Implementation of policy_t.get_other_id
95 */
96 static identification_t *get_other_id(private_policy_t *this)
97 {
98 return this->other_id;
99 }
100
101 /**
102 * Implementation of policy_t.update_my_id
103 */
104 static void update_my_id(private_policy_t *this, identification_t *my_id)
105 {
106 this->my_id->destroy(this->my_id);
107 this->my_id = my_id;
108 }
109
110 /**
111 * Implementation of policy_t.update_other_id
112 */
113 static void update_other_id(private_policy_t *this, identification_t *other_id)
114 {
115 this->other_id->destroy(this->other_id);
116 this->other_id = other_id;
117 }
118
119 /**
120 * Helper function which does the work for policy_t.update_my_ts and update_other_ts
121 */
122 static void update_ts(linked_list_t* list, host_t *new_host)
123 {
124 traffic_selector_t *ts;
125 iterator_t *iterator;
126
127 iterator = list->create_iterator(list, TRUE);
128 while (iterator->has_next(iterator))
129 {
130 iterator->current(iterator, (void**)&ts);
131 ts->update_address_range(ts, new_host);
132 }
133 iterator->destroy(iterator);
134 }
135
136 /**
137 * Implementation of policy_t.update_my_id
138 */
139 static void update_my_ts(private_policy_t *this, host_t *my_host)
140 {
141 update_ts(this->my_ts, my_host);
142 }
143
144 /**
145 * Implementation of policy_t.update_other_ts
146 */
147 static void update_other_ts(private_policy_t *this, host_t *my_host)
148 {
149 update_ts(this->other_ts, my_host);
150 }
151
152 /**
153 * Implementation of policy_t.get_my_traffic_selectors
154 */
155 static linked_list_t *get_my_traffic_selectors(private_policy_t *this)
156 {
157 return this->my_ts;
158 }
159
160 /**
161 * Implementation of policy_t.get_other_traffic_selectors
162 */
163 static linked_list_t *get_other_traffic_selectors(private_policy_t *this, traffic_selector_t **traffic_selectors[])
164 {
165 return this->other_ts;
166 }
167
168 /**
169 * Implementation of private_policy_t.select_my_traffic_selectors
170 */
171 static linked_list_t *select_my_traffic_selectors(private_policy_t *this, linked_list_t *supplied)
172 {
173 return this->select_traffic_selectors(this, this->my_ts, supplied);
174 }
175
176 /**
177 * Implementation of private_policy_t.select_other_traffic_selectors
178 */
179 static linked_list_t *select_other_traffic_selectors(private_policy_t *this, linked_list_t *supplied)
180 {
181 return this->select_traffic_selectors(this, this->other_ts, supplied);
182 }
183 /**
184 * Implementation of private_policy_t.select_traffic_selectors
185 */
186 static linked_list_t *select_traffic_selectors(private_policy_t *this, linked_list_t *stored, linked_list_t *supplied)
187 {
188 iterator_t *supplied_iter, *stored_iter;
189 traffic_selector_t *supplied_ts, *stored_ts, *selected_ts;
190 linked_list_t *selected = linked_list_create();
191
192
193 stored_iter = stored->create_iterator(stored, TRUE);
194 supplied_iter = supplied->create_iterator(supplied, TRUE);
195
196 /* iterate over all stored selectors */
197 while (stored_iter->has_next(stored_iter))
198 {
199 stored_iter->current(stored_iter, (void**)&stored_ts);
200
201 supplied_iter->reset(supplied_iter);
202 /* iterate over all supplied traffic selectors */
203 while (supplied_iter->has_next(supplied_iter))
204 {
205 supplied_iter->current(supplied_iter, (void**)&supplied_ts);
206
207 selected_ts = stored_ts->get_subset(stored_ts, supplied_ts);
208 if (selected_ts)
209 {
210 /* got a match, add to list */
211 selected->insert_last(selected, (void*)selected_ts);
212 }
213 }
214 }
215 stored_iter->destroy(stored_iter);
216 supplied_iter->destroy(supplied_iter);
217
218 return selected;
219 }
220
221 /**
222 * Implementation of policy_t.get_proposal_iterator
223 */
224 static linked_list_t *get_proposals(private_policy_t *this)
225 {
226 return this->proposals;
227 }
228
229 /**
230 * Implementation of policy_t.select_proposal
231 */
232 static proposal_t *select_proposal(private_policy_t *this, linked_list_t *proposals)
233 {
234 iterator_t *stored_iter, *supplied_iter;
235 proposal_t *stored, *supplied, *selected;
236
237 stored_iter = this->proposals->create_iterator(this->proposals, TRUE);
238 supplied_iter = proposals->create_iterator(proposals, TRUE);
239
240 /* compare all stored proposals with all supplied. Stored ones are preferred. */
241 while (stored_iter->has_next(stored_iter))
242 {
243 supplied_iter->reset(supplied_iter);
244 stored_iter->current(stored_iter, (void**)&stored);
245
246 while (supplied_iter->has_next(supplied_iter))
247 {
248 supplied_iter->current(supplied_iter, (void**)&supplied);
249 selected = stored->select(stored, supplied);
250 if (selected)
251 {
252 /* they match, return */
253 stored_iter->destroy(stored_iter);
254 supplied_iter->destroy(supplied_iter);
255 return selected;
256 }
257 }
258 }
259
260 /* no proposal match :-(, will result in a NO_PROPOSAL_CHOSEN... */
261 stored_iter->destroy(stored_iter);
262 supplied_iter->destroy(supplied_iter);
263
264 return NULL;
265 }
266
267 /**
268 * Implementation of policy_t.add_my_traffic_selector
269 */
270 static void add_my_traffic_selector(private_policy_t *this, traffic_selector_t *traffic_selector)
271 {
272 this->my_ts->insert_last(this->my_ts, (void*)traffic_selector);
273 }
274
275 /**
276 * Implementation of policy_t.add_other_traffic_selector
277 */
278 static void add_other_traffic_selector(private_policy_t *this, traffic_selector_t *traffic_selector)
279 {
280 this->other_ts->insert_last(this->other_ts, (void*)traffic_selector);
281 }
282
283 /**
284 * Implementation of policy_t.add_proposal
285 */
286 static void add_proposal(private_policy_t *this, proposal_t *proposal)
287 {
288 this->proposals->insert_last(this->proposals, (void*)proposal);
289 }
290
291 /**
292 * Implementation of policy_t.get_soft_lifetime
293 */
294 static u_int32_t get_soft_lifetime(policy_t *this)
295 {
296 return 0; /*5 + random() % 5; */
297 }
298
299 /**
300 * Implementation of policy_t.get_hard_lifetime
301 */
302 static u_int32_t get_hard_lifetime(policy_t *this)
303 {
304 return 0; /*20; */
305 }
306
307 /**
308 * Implements policy_t.clone.
309 */
310 static policy_t *clone(private_policy_t *this)
311 {
312 private_policy_t *clone = (private_policy_t*)policy_create(this->name,
313 this->my_id->clone(this->my_id),
314 this->other_id->clone(this->other_id));
315 iterator_t *iterator;
316 proposal_t *proposal;
317 traffic_selector_t *ts;
318
319 /* clone all proposals */
320 iterator = this->proposals->create_iterator(this->proposals, TRUE);
321 while (iterator->has_next(iterator))
322 {
323 iterator->current(iterator, (void**)&proposal);
324 proposal = proposal->clone(proposal);
325 clone->proposals->insert_last(clone->proposals, (void*)proposal);
326 }
327 iterator->destroy(iterator);
328
329 /* clone all local traffic selectors */
330 iterator = this->my_ts->create_iterator(this->my_ts, TRUE);
331 while (iterator->has_next(iterator))
332 {
333 iterator->current(iterator, (void**)&ts);
334 ts = ts->clone(ts);
335 clone->my_ts->insert_last(clone->my_ts, (void*)ts);
336 }
337 iterator->destroy(iterator);
338
339 /* clone all remote traffic selectors */
340 iterator = this->other_ts->create_iterator(this->other_ts, TRUE);
341 while (iterator->has_next(iterator))
342 {
343 iterator->current(iterator, (void**)&ts);
344 ts = ts->clone(ts);
345 clone->other_ts->insert_last(clone->other_ts, (void*)ts);
346 }
347 iterator->destroy(iterator);
348
349 return &clone->public;
350 }
351
352 /**
353 * Implements policy_t.destroy.
354 */
355 static status_t destroy(private_policy_t *this)
356 {
357 proposal_t *proposal;
358 traffic_selector_t *traffic_selector;
359
360
361 /* delete proposals */
362 while(this->proposals->remove_last(this->proposals, (void**)&proposal) == SUCCESS)
363 {
364 proposal->destroy(proposal);
365 }
366 this->proposals->destroy(this->proposals);
367
368 /* delete traffic selectors */
369 while(this->my_ts->remove_last(this->my_ts, (void**)&traffic_selector) == SUCCESS)
370 {
371 traffic_selector->destroy(traffic_selector);
372 }
373 this->my_ts->destroy(this->my_ts);
374
375 /* delete traffic selectors */
376 while(this->other_ts->remove_last(this->other_ts, (void**)&traffic_selector) == SUCCESS)
377 {
378 traffic_selector->destroy(traffic_selector);
379 }
380 this->other_ts->destroy(this->other_ts);
381
382 /* delete ids */
383 this->my_id->destroy(this->my_id);
384 this->other_id->destroy(this->other_id);
385
386 free(this->name);
387 free(this);
388 return SUCCESS;
389 }
390
391 /*
392 * Described in header-file
393 */
394 policy_t *policy_create(char *name, identification_t *my_id, identification_t *other_id)
395 {
396 private_policy_t *this = malloc_thing(private_policy_t);
397
398 /* public functions */
399 this->public.get_name = (char *(*)(policy_t*))get_name;
400 this->public.get_my_id = (identification_t*(*)(policy_t*))get_my_id;
401 this->public.get_other_id = (identification_t*(*)(policy_t*))get_other_id;
402 this->public.update_my_id = (void(*)(policy_t*,identification_t*))update_my_id;
403 this->public.update_other_id = (void(*)(policy_t*,identification_t*))update_other_id;
404 this->public.update_my_ts = (void(*)(policy_t*,host_t*))update_my_ts;
405 this->public.update_other_ts = (void(*)(policy_t*,host_t*))update_other_ts;
406 this->public.get_my_traffic_selectors = (linked_list_t*(*)(policy_t*))get_my_traffic_selectors;
407 this->public.select_my_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*))select_my_traffic_selectors;
408 this->public.get_other_traffic_selectors = (linked_list_t*(*)(policy_t*))get_other_traffic_selectors;
409 this->public.select_other_traffic_selectors = (linked_list_t*(*)(policy_t*,linked_list_t*))select_other_traffic_selectors;
410 this->public.get_proposals = (linked_list_t*(*)(policy_t*))get_proposals;
411 this->public.select_proposal = (proposal_t*(*)(policy_t*,linked_list_t*))select_proposal;
412 this->public.add_my_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_my_traffic_selector;
413 this->public.add_other_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_other_traffic_selector;
414 this->public.add_proposal = (void(*)(policy_t*,proposal_t*))add_proposal;
415 this->public.get_soft_lifetime = (u_int32_t (*) (policy_t *))get_soft_lifetime;
416 this->public.get_hard_lifetime = (u_int32_t (*) (policy_t *))get_hard_lifetime;
417 this->public.clone = (policy_t*(*)(policy_t*))clone;
418 this->public.destroy = (void(*)(policy_t*))destroy;
419
420 /* apply init values */
421 this->my_id = my_id;
422 this->other_id = other_id;
423 this->name = strdup(name);
424
425 /* init private members*/
426 this->select_traffic_selectors = select_traffic_selectors;
427 this->proposals = linked_list_create();
428 this->my_ts = linked_list_create();
429 this->other_ts = linked_list_create();
430
431 return (&this->public);
432 }