2 * Copyright (C) 2012 Reto Buerki
3 * Copyright (C) 2012 Adrian-Ken Rueegsegger
4 * Hochschule fuer Technik Rapperswil
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>.
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
17 #include <collections/linked_list.h>
18 #include <threading/mutex.h>
19 #include <utils/debug.h>
21 #include "tkm_kernel_sad.h"
23 typedef struct private_tkm_kernel_sad_t private_tkm_kernel_sad_t
;
26 * Private data of tkm_kernel_sad.
28 struct private_tkm_kernel_sad_t
{
33 tkm_kernel_sad_t
public;
36 * Linked list of SAD entries.
41 * Lock used to protect SA data.
47 typedef struct sad_entry_t sad_entry_t
;
50 * Data structure holding all information of an SAD entry.
60 * Source address of CHILD SA.
65 * Destination address of CHILD SA.
75 * Protocol of CHILD SA (ESP/AH).
82 * Destroy an sad_entry_t object.
84 static void sad_entry_destroy(sad_entry_t
*entry
)
88 DESTROY_IF(entry
->src
);
89 DESTROY_IF(entry
->dst
);
95 * Find a list entry with given src, dst, spi and proto values.
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
)
101 if (entry
->src
== NULL
|| entry
->dst
== NULL
)
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
;
112 * Compare two SAD entries for equality.
114 static bool sad_entry_equal(sad_entry_t
* const left
, sad_entry_t
* const right
)
116 if (left
->src
== NULL
|| left
->dst
== NULL
|| right
->src
== NULL
||
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
;
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
)
133 sad_entry_t
*new_entry
;
136 .src
= (host_t
*)src
,
137 .dst
= (host_t
*)dst
,
142 this->mutex
->lock(this->mutex
);
143 const status_t result
= this->data
->find_first(this->data
,
144 (linked_list_match_t
)sad_entry_equal
,
146 if (result
== NOT_FOUND
)
148 DBG3(DBG_KNL
, "inserting SAD entry (esa: %llu, src: %H, dst: %H, "
149 "spi: %x, proto: %u)", esa_id
, src
, dst
, ntohl(spi
), proto
);
150 new_entry
->src
= src
->clone((host_t
*)src
);
151 new_entry
->dst
= dst
->clone((host_t
*)dst
);
152 this->data
->insert_last(this->data
, new_entry
);
156 DBG1(DBG_KNL
, "SAD entry with esa id %llu already exists!", esa_id
);
159 this->mutex
->unlock(this->mutex
);
160 return result
== NOT_FOUND
;
163 METHOD(tkm_kernel_sad_t
, get_esa_id
, esa_id_type
,
164 private_tkm_kernel_sad_t
* const this, const host_t
* const src
,
165 const host_t
* const dst
, const u_int32_t spi
, const u_int8_t proto
)
168 sad_entry_t
*entry
= NULL
;
170 this->mutex
->lock(this->mutex
);
171 const status_t res
= this->data
->find_first(this->data
,
172 (linked_list_match_t
)sad_entry_match
,
173 (void**)&entry
, src
, dst
, &spi
,
175 if (res
== SUCCESS
&& entry
)
178 DBG3(DBG_KNL
, "getting ESA id of SAD entry (esa: %llu, src: %H, "
179 "dst: %H, spi: %x, proto: %u)", id
, src
, dst
, ntohl(spi
),
184 DBG3(DBG_KNL
, "no SAD entry found");
186 this->mutex
->unlock(this->mutex
);
190 METHOD(tkm_kernel_sad_t
, _remove
, bool,
191 private_tkm_kernel_sad_t
* const this, const esa_id_type esa_id
)
193 sad_entry_t
*current
;
194 bool removed
= FALSE
;
195 this->mutex
->lock(this->mutex
);
196 enumerator_t
*enumerator
= this->data
->create_enumerator(this->data
);
197 while (enumerator
->enumerate(enumerator
, (void **)¤t
))
199 if (current
->esa_id
== esa_id
)
201 this->data
->remove_at(this->data
, enumerator
);
202 sad_entry_destroy(current
);
207 enumerator
->destroy(enumerator
);
211 DBG3(DBG_KNL
, "removed SAD entry (esa: %llu)", esa_id
);
215 DBG1(DBG_KNL
, "no SAD entry with ESA id %llu found!", esa_id
);
217 this->mutex
->unlock(this->mutex
);
223 METHOD(tkm_kernel_sad_t
, destroy
, void,
224 private_tkm_kernel_sad_t
*this)
226 this->mutex
->destroy(this->mutex
);
227 this->data
->destroy_function(this->data
, (void*)sad_entry_destroy
);
234 tkm_kernel_sad_t
*tkm_kernel_sad_create()
236 private_tkm_kernel_sad_t
*this;
241 .get_esa_id
= _get_esa_id
,
245 .mutex
= mutex_create(MUTEX_TYPE_DEFAULT
),
246 .data
= linked_list_create(),
249 return &this->public;