]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/tests/utils/mock_ipsec.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / libcharon / tests / utils / mock_ipsec.c
CommitLineData
7a5dd544 1/*
d80055ba 2 * Copyright (C) 2016-2017 Tobias Brunner
7a5dd544 3 * Copyright (C) 2008 Martin Willi
19ef2aec
TB
4 *
5 * Copyright (C) secunet Security Networks AG
7a5dd544
TB
6 *
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>.
11 *
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
15 * for more details.
16 */
17
18#include "mock_ipsec.h"
19
d80055ba
TB
20#include <daemon.h>
21#include <collections/hashtable.h>
2b581b59 22#include <collections/array.h>
d80055ba
TB
23
24#include <assert.h>
25
7a5dd544
TB
26typedef struct private_kernel_ipsec_t private_kernel_ipsec_t;
27
28/**
29 * Private data
30 */
31struct private_kernel_ipsec_t {
32
33 /**
34 * Public interface
35 */
36 kernel_ipsec_t public;
37
2b581b59
TB
38 /**
39 * Rekey listener
40 */
41 listener_t listener;
42
7a5dd544
TB
43 /**
44 * Allocated SPI
45 */
46 refcount_t spi;
d80055ba
TB
47
48 /**
49 * Installed SAs
50 */
51 hashtable_t *sas;
7a5dd544
TB
52};
53
d80055ba
TB
54/**
55 * Global instance
56 */
57static private_kernel_ipsec_t *instance;
58
59/**
60 * Data about installed IPsec SAs
61 */
62typedef struct {
63 /**
64 * SPI of the SA
65 */
66 uint32_t spi;
67
68 /**
69 * Associated IKE_SA
70 */
71 ike_sa_t *ike_sa;
72
73 /**
74 * TRUE if this was an allocated SPI
75 */
76 bool alloc;
77
78} entry_t;
79
80/**
81 * Hash an IPsec SA entry
82 */
83static u_int entry_hash(const void *key)
84{
85 entry_t *entry = (entry_t*)key;
86 return chunk_hash_inc(chunk_from_thing(entry->spi),
87 chunk_hash(chunk_from_thing(entry->ike_sa)));
88}
89
90/**
91 * Compare an IPsec SA entry
92 */
93static bool entry_equals(const void *key, const void *other_key)
94{
95 entry_t *a = (entry_t*)key, *b = (entry_t*)other_key;
96 return a->spi == b->spi && a->ike_sa == b->ike_sa;
97}
98
7a5dd544
TB
99METHOD(kernel_ipsec_t, get_spi, status_t,
100 private_kernel_ipsec_t *this, host_t *src, host_t *dst, uint8_t protocol,
101 uint32_t *spi)
102{
d80055ba
TB
103 entry_t *entry;
104
7a5dd544 105 *spi = (uint32_t)ref_get(&this->spi);
d80055ba
TB
106 INIT(entry,
107 .spi = *spi,
108 .ike_sa = charon->bus->get_sa(charon->bus),
109 .alloc = TRUE,
110 );
111 entry = this->sas->put(this->sas, entry, entry);
112 assert(!entry);
7a5dd544
TB
113 return SUCCESS;
114}
115
116METHOD(kernel_ipsec_t, get_cpi, status_t,
117 private_kernel_ipsec_t *this, host_t *src, host_t *dst, uint16_t *cpi)
118{
119 return FAILED;
120}
121
122METHOD(kernel_ipsec_t, add_sa, status_t,
123 private_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
124 kernel_ipsec_add_sa_t *data)
125{
d80055ba
TB
126 entry_t *entry;
127
128 INIT(entry,
129 .spi = id->spi,
130 .ike_sa = charon->bus->get_sa(charon->bus),
131 );
132 if (data->inbound)
133 {
134 entry = this->sas->put(this->sas, entry, entry);
135 assert(entry && entry->alloc);
136 free(entry);
137 }
138 else
139 {
140 entry = this->sas->put(this->sas, entry, entry);
141 assert(!entry);
142 }
7a5dd544
TB
143 return SUCCESS;
144}
145
146METHOD(kernel_ipsec_t, update_sa, status_t,
147 private_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
148 kernel_ipsec_update_sa_t *data)
149{
150 return SUCCESS;
151}
152
153METHOD(kernel_ipsec_t, query_sa, status_t,
154 private_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
155 kernel_ipsec_query_sa_t *data, uint64_t *bytes, uint64_t *packets,
156 time_t *time)
157{
158 return NOT_SUPPORTED;
159}
160
161METHOD(kernel_ipsec_t, del_sa, status_t,
162 private_kernel_ipsec_t *this, kernel_ipsec_sa_id_t *id,
163 kernel_ipsec_del_sa_t *data)
164{
d80055ba
TB
165 entry_t *entry, lookup = {
166 .spi = id->spi,
167 .ike_sa = charon->bus->get_sa(charon->bus),
168 };
169
170 entry = this->sas->remove(this->sas, &lookup);
171 assert(entry);
172 free(entry);
7a5dd544
TB
173 return SUCCESS;
174}
175
2b581b59
TB
176METHOD(listener_t, ike_rekey, bool,
177 listener_t *listener, ike_sa_t *old, ike_sa_t *new)
178{
179 enumerator_t *enumerator;
180 array_t *sas = NULL;
181 entry_t *entry;
182
183 enumerator = instance->sas->create_enumerator(instance->sas);
184 while (enumerator->enumerate(enumerator, &entry, NULL))
185 {
186 if (entry->ike_sa == old)
187 {
188 instance->sas->remove_at(instance->sas, enumerator);
189 array_insert_create(&sas, ARRAY_TAIL, entry);
190 }
191 }
192 enumerator->destroy(enumerator);
193 enumerator = array_create_enumerator(sas);
194 while (enumerator->enumerate(enumerator, &entry))
195 {
196 array_remove_at(sas, enumerator);
197 entry->ike_sa = new;
198 entry = instance->sas->put(instance->sas, entry, entry);
199 assert(!entry);
200 }
201 enumerator->destroy(enumerator);
202 array_destroy(sas);
203 return TRUE;
204}
205
7a5dd544
TB
206METHOD(kernel_ipsec_t, add_policy, status_t,
207 private_kernel_ipsec_t *this, kernel_ipsec_policy_id_t *id,
208 kernel_ipsec_manage_policy_t *data)
209{
210 return SUCCESS;
211}
212
213METHOD(kernel_ipsec_t, query_policy, status_t,
214 private_kernel_ipsec_t *this, kernel_ipsec_policy_id_t *id,
215 kernel_ipsec_query_policy_t *data, time_t *use_time)
216{
217 *use_time = 1;
218 return SUCCESS;
219}
220
221METHOD(kernel_ipsec_t, del_policy, status_t,
222 private_kernel_ipsec_t *this, kernel_ipsec_policy_id_t *id,
223 kernel_ipsec_manage_policy_t *data)
224{
225 return SUCCESS;
226}
227
610745e7
TB
228CALLBACK(destroy_spis, void,
229 entry_t *entry, const void* key)
230{
231 /* only free allocated SPIs, other SAs that were not properly deleted will
232 * cause a leak */
233 if (entry->alloc)
234 {
235 free(entry);
236 }
237}
238
d80055ba
TB
239METHOD(kernel_ipsec_t, destroy, void,
240 private_kernel_ipsec_t *this)
241{
2b581b59 242 charon->bus->remove_listener(charon->bus, &this->listener);
610745e7 243 this->sas->destroy_function(this->sas, destroy_spis);
d80055ba
TB
244 free(this);
245}
246
7a5dd544
TB
247/*
248 * Described in header
249 */
250kernel_ipsec_t *mock_ipsec_create()
251{
252 private_kernel_ipsec_t *this;
253
254 INIT(this,
255 .public = {
256 .get_spi = _get_spi,
257 .get_cpi = _get_cpi,
258 .add_sa = _add_sa,
259 .update_sa = _update_sa,
260 .query_sa = _query_sa,
261 .del_sa = _del_sa,
262 .flush_sas = (void*)return_failed,
263 .add_policy = _add_policy,
264 .query_policy = _query_policy,
265 .del_policy = _del_policy,
266 .flush_policies = (void*)return_failed,
267 .bypass_socket = (void*)return_true,
268 .enable_udp_decap = (void*)return_true,
d80055ba 269 .destroy = _destroy,
7a5dd544 270 },
2b581b59
TB
271 .listener = {
272 .ike_rekey = _ike_rekey,
273 },
d80055ba 274 .sas = hashtable_create(entry_hash, entry_equals, 8),
7a5dd544 275 );
d80055ba
TB
276
277 instance = this;
278
2b581b59
TB
279 charon->bus->add_listener(charon->bus, &this->listener);
280
7a5dd544
TB
281 return &this->public;
282}
d80055ba 283
525cc46c
TB
284
285CALLBACK(filter_sas, bool,
286 void *data, enumerator_t *orig, va_list args)
d80055ba 287{
525cc46c
TB
288 entry_t *entry;
289 ike_sa_t **ike_sa;
290 uint32_t *spi;
291
292 VA_ARGS_VGET(args, ike_sa, spi);
293
294 while (orig->enumerate(orig, &entry, NULL))
d80055ba 295 {
525cc46c
TB
296 if (entry->alloc)
297 {
298 continue;
299 }
300 *ike_sa = entry->ike_sa;
301 *spi = entry->spi;
302 return TRUE;
d80055ba 303 }
525cc46c 304 return FALSE;
d80055ba
TB
305}
306
307/*
308 * Described in header
309 */
310enumerator_t *mock_ipsec_create_sa_enumerator()
311{
312 return enumerator_create_filter(
313 instance->sas->create_enumerator(instance->sas),
525cc46c 314 filter_sas, NULL, NULL);
d80055ba 315}