]>
Commit | Line | Data |
---|---|---|
13e4a62f MW |
1 | /** |
2 | * @file local_policy_store.c | |
60356f33 | 3 | * |
13e4a62f | 4 | * @brief Implementation of local_policy_store_t. |
60356f33 | 5 | * |
13e4a62f MW |
6 | */ |
7 | ||
8 | /* | |
9 | * Copyright (C) 2006 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 | ||
5238c9af MW |
23 | #include <string.h> |
24 | ||
13e4a62f MW |
25 | #include "local_policy_store.h" |
26 | ||
60356f33 | 27 | #include <daemon.h> |
13e4a62f | 28 | #include <utils/linked_list.h> |
13e4a62f MW |
29 | |
30 | ||
31 | typedef struct private_local_policy_store_t private_local_policy_store_t; | |
32 | ||
33 | /** | |
34 | * Private data of an local_policy_store_t object | |
35 | */ | |
36 | struct private_local_policy_store_t { | |
37 | ||
38 | /** | |
39 | * Public part | |
40 | */ | |
41 | local_policy_store_t public; | |
42 | ||
43 | /** | |
44 | * list of policy_t's | |
45 | */ | |
46 | linked_list_t *policies; | |
47 | ||
9fe14f4b MW |
48 | /** |
49 | * Mutex to exclusivly access list | |
50 | */ | |
51 | pthread_mutex_t mutex; | |
13e4a62f MW |
52 | }; |
53 | ||
54 | /** | |
55 | * Implementation of policy_store_t.add_policy. | |
56 | */ | |
57 | static void add_policy(private_local_policy_store_t *this, policy_t *policy) | |
58 | { | |
9fe14f4b | 59 | pthread_mutex_lock(&(this->mutex)); |
13e4a62f | 60 | this->policies->insert_last(this->policies, (void*)policy); |
9fe14f4b | 61 | pthread_mutex_unlock(&(this->mutex)); |
13e4a62f MW |
62 | } |
63 | ||
13e4a62f | 64 | /** |
8dfbe71b | 65 | * Check if a policy contains traffic selectors |
13e4a62f | 66 | */ |
8dfbe71b MW |
67 | static bool contains_traffic_selectors(policy_t *policy, bool mine, |
68 | linked_list_t *ts, host_t *host) | |
69 | { | |
70 | linked_list_t *selected; | |
71 | bool contains = FALSE; | |
8dfbe71b MW |
72 | |
73 | if (mine) | |
74 | { | |
75 | selected = policy->select_my_traffic_selectors(policy, ts, host); | |
76 | } | |
77 | else | |
78 | { | |
79 | selected = policy->select_other_traffic_selectors(policy, ts, host); | |
80 | } | |
81 | if (selected->get_count(selected)) | |
82 | { | |
83 | contains = TRUE; | |
84 | } | |
55bbff11 | 85 | selected->destroy_offset(selected, offsetof(traffic_selector_t, destroy)); |
8dfbe71b MW |
86 | return contains; |
87 | } | |
88 | ||
89 | /** | |
90 | * Implementation of policy_store_t.get_policy. | |
91 | */ | |
92 | static policy_t *get_policy(private_local_policy_store_t *this, | |
93 | identification_t *my_id, identification_t *other_id, | |
94 | linked_list_t *my_ts, linked_list_t *other_ts, | |
f27f6296 | 95 | host_t *my_host, host_t *other_host) |
13e4a62f | 96 | { |
9fe14f4b | 97 | typedef enum { |
c361cc8c | 98 | PRIO_UNDEFINED = 0x00, |
0cde6c41 MW |
99 | PRIO_TS_MISMATCH = 0x01, |
100 | PRIO_ID_ANY = 0x02, | |
c361cc8c | 101 | PRIO_ID_MATCH = PRIO_ID_ANY + MAX_WILDCARDS, |
9fe14f4b MW |
102 | } prio_t; |
103 | ||
104 | prio_t best_prio = PRIO_UNDEFINED; | |
105 | ||
13e4a62f | 106 | iterator_t *iterator; |
9fe14f4b MW |
107 | policy_t *candidate; |
108 | policy_t *found = NULL; | |
0cde6c41 | 109 | traffic_selector_t *ts; |
13e4a62f | 110 | |
0cde6c41 MW |
111 | DBG1(DBG_CFG, "searching policy for '%D'...'%D'", my_id, other_id); |
112 | iterator = my_ts->create_iterator(my_ts, TRUE); | |
113 | while (iterator->iterate(iterator, (void**)&ts)) | |
114 | { | |
115 | DBG1(DBG_CFG, " local TS: %R", ts); | |
116 | } | |
117 | iterator->destroy(iterator); | |
118 | iterator = other_ts->create_iterator(other_ts, TRUE); | |
119 | while (iterator->iterate(iterator, (void**)&ts)) | |
120 | { | |
121 | DBG1(DBG_CFG, " remote TS: %R", ts); | |
122 | } | |
123 | iterator->destroy(iterator); | |
9fe14f4b MW |
124 | |
125 | pthread_mutex_lock(&(this->mutex)); | |
13e4a62f | 126 | iterator = this->policies->create_iterator(this->policies, TRUE); |
c361cc8c | 127 | |
9fe14f4b | 128 | /* determine closest matching policy */ |
191a26a6 | 129 | while (iterator->iterate(iterator, (void**)&candidate)) |
13e4a62f | 130 | { |
9fe14f4b MW |
131 | identification_t *candidate_my_id; |
132 | identification_t *candidate_other_id; | |
c361cc8c | 133 | int wildcards; |
9fe14f4b MW |
134 | |
135 | candidate_my_id = candidate->get_my_id(candidate); | |
136 | candidate_other_id = candidate->get_other_id(candidate); | |
137 | ||
c361cc8c AS |
138 | /* my_id is either %any or if set must match exactly */ |
139 | if (candidate_my_id->matches(candidate_my_id, my_id, &wildcards)) | |
13e4a62f | 140 | { |
9fe14f4b MW |
141 | prio_t prio = PRIO_UNDEFINED; |
142 | ||
c361cc8c | 143 | /* wildcard match for other_id */ |
02b3101b | 144 | if (!other_id->matches(other_id, candidate_other_id, &wildcards)) |
9fe14f4b | 145 | { |
02b3101b | 146 | continue; |
9fe14f4b | 147 | } |
02b3101b | 148 | prio = PRIO_ID_MATCH - wildcards; |
8dfbe71b MW |
149 | |
150 | /* only accept if traffic selectors match */ | |
151 | if (!contains_traffic_selectors(candidate, TRUE, my_ts, my_host) || | |
152 | !contains_traffic_selectors(candidate, FALSE, other_ts, other_host)) | |
153 | { | |
b83806d8 | 154 | DBG2(DBG_CFG, "candidate '%s' inacceptable due traffic " |
60356f33 | 155 | "selector mismatch", candidate->get_name(candidate)); |
0cde6c41 | 156 | prio = PRIO_TS_MISMATCH; |
8dfbe71b | 157 | } |
9fe14f4b | 158 | |
1f916061 | 159 | DBG2(DBG_CFG, "candidate policy '%s': '%D'...'%D' (prio=%d)", |
60356f33 MW |
160 | candidate->get_name(candidate), |
161 | candidate_my_id, candidate_other_id, prio); | |
9fe14f4b MW |
162 | |
163 | if (prio > best_prio) | |
164 | { | |
165 | found = candidate; | |
166 | best_prio = prio; | |
167 | } | |
13e4a62f MW |
168 | } |
169 | } | |
170 | iterator->destroy(iterator); | |
171 | ||
13e4a62f MW |
172 | if (found) |
173 | { | |
1f916061 | 174 | DBG1(DBG_CFG, "found matching policy '%s': '%D'...'%D' (prio=%d)", |
db7ef624 MW |
175 | found->get_name(found), found->get_my_id(found), |
176 | found->get_other_id(found), best_prio); | |
8dfbe71b MW |
177 | /* give out a new reference to it */ |
178 | found->get_ref(found); | |
9fe14f4b MW |
179 | } |
180 | pthread_mutex_unlock(&(this->mutex)); | |
181 | return found; | |
182 | } | |
183 | ||
184 | /** | |
185 | * Implementation of policy_store_t.get_policy_by_name. | |
186 | */ | |
187 | static policy_t *get_policy_by_name(private_local_policy_store_t *this, char *name) | |
188 | { | |
189 | iterator_t *iterator; | |
190 | policy_t *current, *found = NULL; | |
191 | ||
b83806d8 | 192 | DBG2(DBG_CFG, "looking for policy '%s'", name); |
9fe14f4b MW |
193 | |
194 | pthread_mutex_lock(&(this->mutex)); | |
195 | iterator = this->policies->create_iterator(this->policies, TRUE); | |
191a26a6 | 196 | while (iterator->iterate(iterator, (void **)¤t)) |
9fe14f4b | 197 | { |
9fe14f4b MW |
198 | if (strcmp(current->get_name(current), name) == 0) |
199 | { | |
8dfbe71b | 200 | found = current; |
9fe14f4b | 201 | } |
13e4a62f | 202 | } |
9fe14f4b MW |
203 | iterator->destroy(iterator); |
204 | pthread_mutex_unlock(&(this->mutex)); | |
205 | ||
8dfbe71b MW |
206 | /* give out a new reference */ |
207 | found->get_ref(found); | |
13e4a62f MW |
208 | return found; |
209 | } | |
210 | ||
9fe14f4b MW |
211 | /** |
212 | * Implementation of policy_store_t.delete_policy. | |
213 | */ | |
214 | static status_t delete_policy(private_local_policy_store_t *this, char *name) | |
215 | { | |
216 | iterator_t *iterator; | |
217 | policy_t *current; | |
218 | bool found = FALSE; | |
219 | ||
220 | pthread_mutex_lock(&(this->mutex)); | |
221 | iterator = this->policies->create_iterator(this->policies, TRUE); | |
191a26a6 | 222 | while (iterator->iterate(iterator, (void **)¤t)) |
9fe14f4b | 223 | { |
9fe14f4b MW |
224 | if (strcmp(current->get_name(current), name) == 0) |
225 | { | |
226 | /* remove policy from list, and destroy it */ | |
227 | iterator->remove(iterator); | |
228 | current->destroy(current); | |
229 | found = TRUE; | |
230 | /* we do not break here, as there may be multipe policies */ | |
231 | } | |
232 | } | |
233 | iterator->destroy(iterator); | |
234 | pthread_mutex_unlock(&(this->mutex)); | |
235 | if (found) | |
236 | { | |
237 | return SUCCESS; | |
238 | } | |
239 | return NOT_FOUND; | |
240 | } | |
241 | ||
60356f33 MW |
242 | /** |
243 | * Implementation of policy_store_t.create_iterator. | |
244 | */ | |
245 | static iterator_t* create_iterator(private_local_policy_store_t *this) | |
246 | { | |
247 | return this->policies->create_iterator_locked(this->policies, | |
248 | &this->mutex); | |
249 | } | |
250 | ||
13e4a62f MW |
251 | /** |
252 | * Implementation of policy_store_t.destroy. | |
253 | */ | |
254 | static void destroy(private_local_policy_store_t *this) | |
255 | { | |
9fe14f4b | 256 | pthread_mutex_lock(&(this->mutex)); |
55bbff11 | 257 | this->policies->destroy_offset(this->policies, offsetof(policy_t, destroy)); |
9fe14f4b | 258 | pthread_mutex_unlock(&(this->mutex)); |
13e4a62f MW |
259 | free(this); |
260 | } | |
261 | ||
262 | /** | |
263 | * Described in header. | |
264 | */ | |
f768bdc3 | 265 | local_policy_store_t *local_policy_store_create(void) |
13e4a62f MW |
266 | { |
267 | private_local_policy_store_t *this = malloc_thing(private_local_policy_store_t); | |
268 | ||
29137c0c AS |
269 | this->public.policy_store.add_policy = (void (*) (policy_store_t*,policy_t*))add_policy; |
270 | this->public.policy_store.get_policy = (policy_t* (*) (policy_store_t*,identification_t*,identification_t*, | |
f27f6296 | 271 | linked_list_t*,linked_list_t*,host_t*,host_t*))get_policy; |
29137c0c AS |
272 | this->public.policy_store.get_policy_by_name = (policy_t* (*) (policy_store_t*,char*))get_policy_by_name; |
273 | this->public.policy_store.delete_policy = (status_t (*) (policy_store_t*,char*))delete_policy; | |
274 | this->public.policy_store.create_iterator = (iterator_t* (*) (policy_store_t*))create_iterator; | |
275 | this->public.policy_store.destroy = (void (*) (policy_store_t*))destroy; | |
13e4a62f MW |
276 | |
277 | /* private variables */ | |
278 | this->policies = linked_list_create(); | |
9fe14f4b | 279 | pthread_mutex_init(&(this->mutex), NULL); |
13e4a62f MW |
280 | |
281 | return (&this->public); | |
282 | } |