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 * Mutex to lock hashtables
42 * Hashtable of active IKE_SAs, identification_t => entry_t
47 * Hashtable with active liveness checks, identification_t => entry_t
49 hashtable_t
*checking
;
53 * Entry for hashtables
58 /** IKE_SA identifier */
63 * Destroy a hashtable entry
65 static void entry_destroy(entry_t
*this)
67 this->id
->destroy(this->id
);
68 this->sa
->destroy(this->sa
);
73 * Hashtable hash function
75 static u_int
hash(identification_t
*key
)
77 return chunk_hash(key
->get_encoding(key
));
81 * Hashtable equals function
83 static bool equals(identification_t
*a
, identification_t
*b
)
85 return a
->equals(a
, b
);
88 METHOD(listener_t
, ike_rekey
, bool,
89 private_duplicheck_listener_t
*this, ike_sa_t
*new, ike_sa_t
*old
)
91 this->mutex
->lock(this->mutex
);
92 /* TODO update entires */
93 this->mutex
->unlock(this->mutex
);
97 METHOD(listener_t
, ike_updown
, bool,
98 private_duplicheck_listener_t
*this, ike_sa_t
*ike_sa
, bool up
)
100 identification_t
*id
;
105 sa
= ike_sa
->get_id(ike_sa
);
106 id
= ike_sa
->get_other_id(ike_sa
);
114 this->mutex
->lock(this->mutex
);
115 entry
= this->active
->put(this->active
, entry
->id
, entry
);
116 this->mutex
->unlock(this->mutex
);
119 DBG1(DBG_CFG
, "detected duplicate IKE_SA for '%Y', "
120 "triggering delete for old IKE_SA", id
);
121 job
= (job_t
*)delete_ike_sa_job_create(entry
->sa
, TRUE
);
122 this->mutex
->lock(this->mutex
);
123 entry
= this->checking
->put(this->checking
, entry
->id
, entry
);
124 this->mutex
->unlock(this->mutex
);
125 lib
->processor
->queue_job(lib
->processor
, job
);
128 entry_destroy(entry
);
134 this->mutex
->lock(this->mutex
);
135 entry
= this->active
->remove(this->active
, id
);
138 entry_destroy(entry
);
140 entry
= this->checking
->remove(this->checking
, id
);
141 this->mutex
->unlock(this->mutex
);
144 DBG1(DBG_CFG
, "delete for duplicate IKE_SA '%Y' timed out, "
145 "keeping new IKE_SA", id
);
146 entry_destroy(entry
);
152 METHOD(listener_t
, message_hook
, bool,
153 private_duplicheck_listener_t
*this, ike_sa_t
*ike_sa
,
154 message_t
*message
, bool incoming
)
156 if (incoming
&& !message
->get_request(message
))
158 identification_t
*id
;
161 id
= ike_sa
->get_other_id(ike_sa
);
162 this->mutex
->lock(this->mutex
);
163 entry
= this->checking
->remove(this->checking
, id
);
164 this->mutex
->unlock(this->mutex
);
167 DBG1(DBG_CFG
, "got a response on a duplicate IKE_SA for '%Y', "
168 "deleting new IKE_SA", id
);
169 entry_destroy(entry
);
170 this->mutex
->lock(this->mutex
);
171 entry
= this->active
->remove(this->active
, id
);
172 this->mutex
->unlock(this->mutex
);
175 lib
->processor
->queue_job(lib
->processor
,
176 (job_t
*)delete_ike_sa_job_create(entry
->sa
, TRUE
));
177 entry_destroy(entry
);
184 METHOD(duplicheck_listener_t
, destroy
, void,
185 private_duplicheck_listener_t
*this)
187 enumerator_t
*enumerator
;
188 identification_t
*key
;
191 enumerator
= this->active
->create_enumerator(this->active
);
192 while (enumerator
->enumerate(enumerator
, &key
, &value
))
194 entry_destroy(value
);
196 enumerator
->destroy(enumerator
);
198 enumerator
= this->checking
->create_enumerator(this->checking
);
199 while (enumerator
->enumerate(enumerator
, &key
, &value
))
201 entry_destroy(value
);
203 enumerator
->destroy(enumerator
);
205 this->active
->destroy(this->active
);
206 this->checking
->destroy(this->checking
);
207 this->mutex
->destroy(this->mutex
);
214 duplicheck_listener_t
*duplicheck_listener_create()
216 private_duplicheck_listener_t
*this;
221 .ike_rekey
= _ike_rekey
,
222 .ike_updown
= _ike_updown
,
223 .message
= _message_hook
,
227 .mutex
= mutex_create(MUTEX_TYPE_DEFAULT
),
228 .active
= hashtable_create((hashtable_hash_t
)hash
,
229 (hashtable_equals_t
)equals
, 32),
230 .checking
= hashtable_create((hashtable_hash_t
)hash
,
231 (hashtable_equals_t
)equals
, 2),
234 return &this->public;