2 * Copyright (C) 2011 Martin Willi
3 * Copyright (C) 2011 revosec AG
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include "duplicheck_listener.h"
19 #include <threading/mutex.h>
20 #include <utils/hashtable.h>
21 #include <encoding/payloads/delete_payload.h>
22 #include <processing/jobs/delete_ike_sa_job.h>
24 typedef struct private_duplicheck_listener_t private_duplicheck_listener_t
;
27 * Private data of an duplicheck_listener_t object.
29 struct private_duplicheck_listener_t
{
32 * Public duplicheck_listener_t interface.
34 duplicheck_listener_t
public;
37 * Socket to send notifications to
39 duplicheck_notify_t
*notify
;
42 * Mutex to lock hashtables
47 * Hashtable of active IKE_SAs, identification_t => entry_t
52 * Hashtable with active liveness checks, identification_t => entry_t
54 hashtable_t
*checking
;
58 * Entry for hashtables
63 /** IKE_SA identifier */
68 * Destroy a hashtable entry
70 static void entry_destroy(entry_t
*this)
72 this->id
->destroy(this->id
);
73 this->sa
->destroy(this->sa
);
78 * Hashtable hash function
80 static u_int
hash(identification_t
*key
)
82 return chunk_hash(key
->get_encoding(key
));
86 * Hashtable equals function
88 static bool equals(identification_t
*a
, identification_t
*b
)
90 return a
->equals(a
, b
);
93 METHOD(listener_t
, ike_rekey
, bool,
94 private_duplicheck_listener_t
*this, ike_sa_t
*new, ike_sa_t
*old
)
96 this->mutex
->lock(this->mutex
);
97 /* TODO update entires */
98 this->mutex
->unlock(this->mutex
);
102 METHOD(listener_t
, ike_updown
, bool,
103 private_duplicheck_listener_t
*this, ike_sa_t
*ike_sa
, bool up
)
105 identification_t
*id
;
110 sa
= ike_sa
->get_id(ike_sa
);
111 id
= ike_sa
->get_other_id(ike_sa
);
119 this->mutex
->lock(this->mutex
);
120 entry
= this->active
->put(this->active
, entry
->id
, entry
);
121 this->mutex
->unlock(this->mutex
);
124 DBG1(DBG_CFG
, "detected duplicate IKE_SA for '%Y', "
125 "triggering delete for old IKE_SA", id
);
126 job
= (job_t
*)delete_ike_sa_job_create(entry
->sa
, TRUE
);
127 this->mutex
->lock(this->mutex
);
128 entry
= this->checking
->put(this->checking
, entry
->id
, entry
);
129 this->mutex
->unlock(this->mutex
);
130 lib
->processor
->queue_job(lib
->processor
, job
);
133 entry_destroy(entry
);
139 this->mutex
->lock(this->mutex
);
140 entry
= this->active
->remove(this->active
, id
);
143 entry_destroy(entry
);
145 entry
= this->checking
->remove(this->checking
, id
);
146 this->mutex
->unlock(this->mutex
);
149 DBG1(DBG_CFG
, "delete for duplicate IKE_SA '%Y' timed out, "
150 "keeping new IKE_SA", id
);
151 entry_destroy(entry
);
157 METHOD(listener_t
, message_hook
, bool,
158 private_duplicheck_listener_t
*this, ike_sa_t
*ike_sa
,
159 message_t
*message
, bool incoming
)
161 if (incoming
&& !message
->get_request(message
))
163 identification_t
*id
;
166 id
= ike_sa
->get_other_id(ike_sa
);
167 this->mutex
->lock(this->mutex
);
168 entry
= this->checking
->remove(this->checking
, id
);
169 this->mutex
->unlock(this->mutex
);
172 DBG1(DBG_CFG
, "got a response on a duplicate IKE_SA for '%Y', "
173 "deleting new IKE_SA", id
);
174 entry_destroy(entry
);
175 this->mutex
->lock(this->mutex
);
176 entry
= this->active
->remove(this->active
, id
);
177 this->mutex
->unlock(this->mutex
);
180 lib
->processor
->queue_job(lib
->processor
,
181 (job_t
*)delete_ike_sa_job_create(entry
->sa
, TRUE
));
182 entry_destroy(entry
);
184 this->notify
->send(this->notify
, id
);
190 METHOD(duplicheck_listener_t
, destroy
, void,
191 private_duplicheck_listener_t
*this)
193 enumerator_t
*enumerator
;
194 identification_t
*key
;
197 enumerator
= this->active
->create_enumerator(this->active
);
198 while (enumerator
->enumerate(enumerator
, &key
, &value
))
200 entry_destroy(value
);
202 enumerator
->destroy(enumerator
);
204 enumerator
= this->checking
->create_enumerator(this->checking
);
205 while (enumerator
->enumerate(enumerator
, &key
, &value
))
207 entry_destroy(value
);
209 enumerator
->destroy(enumerator
);
211 this->active
->destroy(this->active
);
212 this->checking
->destroy(this->checking
);
213 this->mutex
->destroy(this->mutex
);
220 duplicheck_listener_t
*duplicheck_listener_create(duplicheck_notify_t
*notify
)
222 private_duplicheck_listener_t
*this;
227 .ike_rekey
= _ike_rekey
,
228 .ike_updown
= _ike_updown
,
229 .message
= _message_hook
,
234 .mutex
= mutex_create(MUTEX_TYPE_DEFAULT
),
235 .active
= hashtable_create((hashtable_hash_t
)hash
,
236 (hashtable_equals_t
)equals
, 32),
237 .checking
= hashtable_create((hashtable_hash_t
)hash
,
238 (hashtable_equals_t
)equals
, 2),
241 return &this->public;