]>
Commit | Line | Data |
---|---|---|
1e13904f AKR |
1 | /* |
2 | * Copyright (C) 2012 Reto Buerki | |
3 | * Copyright (C) 2012 Adrian-Ken Rueegsegger | |
4 | * Hochschule fuer Technik Rapperswil | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify it | |
7 | * under the terms of the GNU General Public License as published by the | |
8 | * Free Software Foundation; either version 2 of the License, or (at your | |
9 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, but | |
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
13 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | * for more details. | |
15 | */ | |
16 | ||
17 | #include <collections/linked_list.h> | |
18 | #include <threading/mutex.h> | |
19 | #include <utils/debug.h> | |
20 | ||
21 | #include "tkm_kernel_sad.h" | |
22 | ||
23 | typedef struct private_tkm_kernel_sad_t private_tkm_kernel_sad_t; | |
24 | ||
25 | /** | |
26 | * Private data of tkm_kernel_sad. | |
27 | */ | |
28 | struct private_tkm_kernel_sad_t { | |
29 | ||
30 | /** | |
31 | * Public functions. | |
32 | */ | |
33 | tkm_kernel_sad_t public; | |
34 | ||
35 | /** | |
36 | * Linked list of SAD entries. | |
37 | */ | |
38 | linked_list_t *data; | |
39 | ||
40 | /** | |
41 | * Lock used to protect SA data. | |
42 | */ | |
43 | mutex_t *mutex; | |
44 | ||
45 | }; | |
46 | ||
47 | typedef struct sad_entry_t sad_entry_t; | |
48 | ||
49 | /** | |
50 | * Data structure holding all information of an SAD entry. | |
51 | */ | |
52 | struct sad_entry_t { | |
53 | ||
54 | /** | |
55 | * ESA identifier. | |
56 | */ | |
57 | esa_id_type esa_id; | |
58 | ||
59 | /** | |
60 | * Source address of CHILD SA. | |
61 | */ | |
62 | host_t *src; | |
63 | ||
64 | /** | |
65 | * Destination address of CHILD SA. | |
66 | */ | |
67 | host_t *dst; | |
68 | ||
69 | /** | |
70 | * SPI of CHILD SA. | |
71 | */ | |
72 | u_int32_t spi; | |
73 | ||
74 | /** | |
75 | * Protocol of CHILD SA (ESP/AH). | |
76 | */ | |
77 | u_int8_t proto; | |
78 | ||
79 | }; | |
80 | ||
81 | /** | |
82 | * Destroy an sad_entry_t object. | |
83 | */ | |
84 | static void sad_entry_destroy(sad_entry_t *entry) | |
85 | { | |
86 | if (entry) | |
87 | { | |
88 | DESTROY_IF(entry->src); | |
89 | DESTROY_IF(entry->dst); | |
90 | free(entry); | |
91 | } | |
92 | } | |
93 | ||
94 | /** | |
95 | * Find a list entry with given src, dst, spi and proto values. | |
96 | */ | |
97 | static bool sad_entry_match(sad_entry_t * const entry, const host_t * const src, | |
98 | const host_t * const dst, const u_int32_t * const spi, | |
99 | const u_int8_t * const proto) | |
100 | { | |
101 | if (entry->src == NULL || entry->dst == NULL) | |
102 | { | |
103 | return FALSE; | |
104 | } | |
105 | ||
106 | return src->ip_equals(entry->src, (host_t *)src) && | |
107 | dst->ip_equals(entry->dst, (host_t *)dst) && | |
108 | entry->spi == *spi && entry->proto == *proto; | |
109 | } | |
110 | ||
111 | /** | |
112 | * Compare two SAD entries for equality. | |
113 | */ | |
114 | static bool sad_entry_equal(sad_entry_t * const left, sad_entry_t * const right) | |
115 | { | |
116 | if (left->src == NULL || left->dst == NULL || right->src == NULL || | |
117 | right->dst == NULL) | |
118 | { | |
119 | return FALSE; | |
120 | } | |
121 | return left->esa_id == right->esa_id && | |
122 | left->src->ip_equals(left->src, right->src) && | |
123 | left->dst->ip_equals(left->dst, right->dst) && | |
124 | left->spi == right->spi && left->proto == right->proto; | |
125 | } | |
126 | ||
127 | METHOD(tkm_kernel_sad_t, insert, bool, | |
128 | private_tkm_kernel_sad_t * const this, const esa_id_type esa_id, | |
129 | const host_t * const src, const host_t * const dst, const u_int32_t spi, | |
130 | const u_int8_t proto) | |
131 | { | |
7cc6fa1a | 132 | status_t result; |
1e13904f | 133 | sad_entry_t *new_entry; |
7cc6fa1a | 134 | |
1e13904f AKR |
135 | INIT(new_entry, |
136 | .esa_id = esa_id, | |
137 | .src = (host_t *)src, | |
138 | .dst = (host_t *)dst, | |
139 | .spi = spi, | |
140 | .proto = proto, | |
141 | ); | |
142 | ||
143 | this->mutex->lock(this->mutex); | |
7cc6fa1a AKR |
144 | result = this->data->find_first(this->data, |
145 | (linked_list_match_t)sad_entry_equal, NULL, | |
146 | new_entry); | |
1e13904f AKR |
147 | if (result == NOT_FOUND) |
148 | { | |
149 | DBG3(DBG_KNL, "inserting SAD entry (esa: %llu, src: %H, dst: %H, " | |
150 | "spi: %x, proto: %u)", esa_id, src, dst, ntohl(spi), proto); | |
151 | new_entry->src = src->clone((host_t *)src); | |
152 | new_entry->dst = dst->clone((host_t *)dst); | |
153 | this->data->insert_last(this->data, new_entry); | |
154 | } | |
155 | else | |
156 | { | |
157 | DBG1(DBG_KNL, "SAD entry with esa id %llu already exists!", esa_id); | |
158 | free(new_entry); | |
159 | } | |
160 | this->mutex->unlock(this->mutex); | |
161 | return result == NOT_FOUND; | |
162 | } | |
163 | ||
164 | METHOD(tkm_kernel_sad_t, get_esa_id, esa_id_type, | |
165 | private_tkm_kernel_sad_t * const this, const host_t * const src, | |
166 | const host_t * const dst, const u_int32_t spi, const u_int8_t proto) | |
167 | { | |
168 | esa_id_type id = 0; | |
169 | sad_entry_t *entry = NULL; | |
170 | ||
171 | this->mutex->lock(this->mutex); | |
172 | const status_t res = this->data->find_first(this->data, | |
173 | (linked_list_match_t)sad_entry_match, | |
174 | (void**)&entry, src, dst, &spi, | |
175 | &proto); | |
176 | if (res == SUCCESS && entry) | |
177 | { | |
178 | id = entry->esa_id; | |
179 | DBG3(DBG_KNL, "getting ESA id of SAD entry (esa: %llu, src: %H, " | |
180 | "dst: %H, spi: %x, proto: %u)", id, src, dst, ntohl(spi), | |
181 | proto); | |
182 | } | |
183 | else | |
184 | { | |
185 | DBG3(DBG_KNL, "no SAD entry found"); | |
186 | } | |
187 | this->mutex->unlock(this->mutex); | |
188 | return id; | |
189 | } | |
190 | ||
191 | METHOD(tkm_kernel_sad_t, _remove, bool, | |
192 | private_tkm_kernel_sad_t * const this, const esa_id_type esa_id) | |
193 | { | |
194 | sad_entry_t *current; | |
195 | bool removed = FALSE; | |
7cc6fa1a AKR |
196 | enumerator_t *enumerator; |
197 | ||
1e13904f | 198 | this->mutex->lock(this->mutex); |
7cc6fa1a | 199 | enumerator = this->data->create_enumerator(this->data); |
1e13904f AKR |
200 | while (enumerator->enumerate(enumerator, (void **)¤t)) |
201 | { | |
202 | if (current->esa_id == esa_id) | |
203 | { | |
204 | this->data->remove_at(this->data, enumerator); | |
205 | sad_entry_destroy(current); | |
206 | removed = TRUE; | |
207 | break; | |
208 | } | |
209 | } | |
210 | enumerator->destroy(enumerator); | |
211 | ||
212 | if (removed) | |
213 | { | |
214 | DBG3(DBG_KNL, "removed SAD entry (esa: %llu)", esa_id); | |
215 | } | |
216 | else | |
217 | { | |
218 | DBG1(DBG_KNL, "no SAD entry with ESA id %llu found!", esa_id); | |
219 | } | |
220 | this->mutex->unlock(this->mutex); | |
221 | ||
222 | return removed; | |
223 | } | |
224 | ||
225 | ||
226 | METHOD(tkm_kernel_sad_t, destroy, void, | |
227 | private_tkm_kernel_sad_t *this) | |
228 | { | |
229 | this->mutex->destroy(this->mutex); | |
230 | this->data->destroy_function(this->data, (void*)sad_entry_destroy); | |
231 | free(this); | |
232 | } | |
233 | ||
234 | /* | |
235 | * see header file | |
236 | */ | |
237 | tkm_kernel_sad_t *tkm_kernel_sad_create() | |
238 | { | |
239 | private_tkm_kernel_sad_t *this; | |
240 | ||
241 | INIT(this, | |
242 | .public = { | |
243 | .insert = _insert, | |
244 | .get_esa_id = _get_esa_id, | |
245 | .remove = __remove, | |
246 | .destroy = _destroy, | |
247 | }, | |
248 | .mutex = mutex_create(MUTEX_TYPE_DEFAULT), | |
249 | .data = linked_list_create(), | |
250 | ); | |
251 | ||
252 | return &this->public; | |
253 | } |