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