Annotation of embedaddon/strongswan/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2012 Andreas Steffen
3: * HSR Hochschule fuer Technik Rapperswil
4: *
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>.
9: *
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
13: * for more details.
14: */
15:
16: #include "tnc_pdp_connections.h"
17:
18: #include <collections/linked_list.h>
19: #include <utils/debug.h>
20: #include <threading/rwlock.h>
21: #include <processing/jobs/callback_job.h>
22:
23: #include <daemon.h>
24:
25: /**
26: * Default PDP connection timeout, in s
27: */
28: #define DEFAULT_TIMEOUT 30
29:
30: typedef struct private_tnc_pdp_connections_t private_tnc_pdp_connections_t;
31: typedef struct entry_t entry_t;
32:
33: /**
34: * Private data of tnc_pdp_connections_t
35: */
36: struct private_tnc_pdp_connections_t {
37:
38: /**
39: * Implements tnc_pdp_connections_t interface
40: */
41: tnc_pdp_connections_t public;
42:
43: /**
44: * TNC PEP RADIUS Connections
45: */
46: linked_list_t *list;
47:
48: /**
49: * Lock to access PEP connection list
50: */
51: rwlock_t *lock;
52:
53: /**
54: * Connection timeout before we kill non-completed connections, in s
55: */
56: int timeout;
57: };
58:
59: /**
60: * Data entry for a TNC PEP RADIUS connection
61: */
62: struct entry_t {
63:
64: /**
65: * NAS identifier of PEP
66: */
67: chunk_t nas_id;
68:
69: /**
70: * User name of TNC Client
71: */
72: chunk_t user_name;
73:
74: /**
75: * EAP method state
76: */
77: eap_method_t *method;
78:
79: /**
80: * IKE SA used for bus communication
81: */
82: ike_sa_t *ike_sa;
83:
84: /**
85: * Timestamp this entry has been created
86: */
87: time_t created;
88: };
89:
90: /**
91: * Free the memory allocated to a data entry
92: */
93: static void free_entry(entry_t *this)
94: {
95: this->method->destroy(this->method);
96: this->ike_sa->destroy(this->ike_sa);
97: free(this->nas_id.ptr);
98: free(this->user_name.ptr);
99: free(this);
100: }
101:
102: /**
103: * Find a matching data entry
104: */
105: static bool equals_entry( entry_t *this, chunk_t nas_id, chunk_t user_name)
106: {
107: bool no_nas_id = !this->nas_id.ptr && !nas_id.ptr;
108:
109: return (chunk_equals(this->nas_id, nas_id) || no_nas_id) &&
110: chunk_equals(this->user_name, user_name);
111: }
112:
113: /**
114: * Find a matching data entry
115: */
116: static void dbg_nas_user(chunk_t nas_id, chunk_t user_name, bool not, char *op)
117: {
118: if (nas_id.len)
119: {
120: DBG1(DBG_CFG, "%s RADIUS connection for user '%.*s' NAS '%.*s'",
121: not ? "could not find" : op, (int)user_name.len,
122: user_name.ptr, (int)nas_id.len, nas_id.ptr);
123: }
124: else
125: {
126: DBG1(DBG_CFG, "%s RADIUS connection for user '%.*s'",
127: not ? "could not find" : op, (int)user_name.len,
128: user_name.ptr);
129: }
130: }
131:
132: /**
133: * Check if any connection has timed out
134: */
135: static job_requeue_t check_timeouts(private_tnc_pdp_connections_t *this)
136: {
137: enumerator_t *enumerator;
138: entry_t *entry;
139: time_t now;
140:
141: now = time_monotonic(NULL);
142:
143: this->lock->write_lock(this->lock);
144: enumerator = this->list->create_enumerator(this->list);
145: while (enumerator->enumerate(enumerator, &entry))
146: {
147: if (entry->created + this->timeout <= now)
148: {
149: DBG1(DBG_CFG, "RADIUS connection timed out after %d seconds",
150: this->timeout);
151: this->list->remove_at(this->list, enumerator);
152: free_entry(entry);
153: }
154: }
155: enumerator->destroy(enumerator);
156: this->lock->unlock(this->lock);
157:
158: return JOB_REQUEUE_NONE;
159: }
160:
161: METHOD(tnc_pdp_connections_t, add, void,
162: private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name,
163: identification_t *peer, eap_method_t *method)
164: {
165: enumerator_t *enumerator;
166: entry_t *entry;
167: ike_sa_id_t *ike_sa_id;
168: ike_sa_t *ike_sa;
169: bool found = FALSE;
170:
171: ike_sa_id = ike_sa_id_create(IKEV2_MAJOR_VERSION, 0, 0, FALSE);
172: ike_sa = ike_sa_create(ike_sa_id, FALSE, IKEV2);
173: ike_sa_id->destroy(ike_sa_id);
174: ike_sa->set_other_id(ike_sa, peer);
175:
176: this->lock->read_lock(this->lock);
177: enumerator = this->list->create_enumerator(this->list);
178: while (enumerator->enumerate(enumerator, &entry))
179: {
180: if (equals_entry(entry, nas_id, user_name))
181: {
182: found = TRUE;
183: entry->method->destroy(entry->method);
184: entry->ike_sa->destroy(entry->ike_sa);
185: DBG1(DBG_CFG, "removed stale RADIUS connection");
186: entry->method = method;
187: entry->ike_sa = ike_sa;
188: entry->created = time_monotonic(NULL);
189: break;
190: }
191: }
192: enumerator->destroy(enumerator);
193: this->lock->unlock(this->lock);
194:
195: if (!found)
196: {
197: INIT(entry,
198: .nas_id = chunk_clone(nas_id),
199: .user_name = chunk_clone(user_name),
200: .method = method,
201: .ike_sa = ike_sa,
202: .created = time_monotonic(NULL),
203: );
204: this->lock->write_lock(this->lock);
205: this->list->insert_last(this->list, entry);
206: this->lock->unlock(this->lock);
207: }
208:
209: /* schedule timeout checking */
210: lib->scheduler->schedule_job_ms(lib->scheduler,
211: (job_t*)callback_job_create((callback_job_cb_t)check_timeouts,
212: this, NULL, (callback_job_cancel_t)return_false),
213: this->timeout * 1000);
214:
215: dbg_nas_user(nas_id, user_name, FALSE, "created");
216: }
217:
218: METHOD(tnc_pdp_connections_t, remove_, void,
219: private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name)
220: {
221: enumerator_t *enumerator;
222: entry_t *entry;
223:
224: this->lock->write_lock(this->lock);
225: enumerator = this->list->create_enumerator(this->list);
226: while (enumerator->enumerate(enumerator, &entry))
227: {
228: if (equals_entry(entry, nas_id, user_name))
229: {
230: free_entry(entry);
231: this->list->remove_at(this->list, enumerator);
232: dbg_nas_user(nas_id, user_name, FALSE, "removed");
233: break;
234: }
235: }
236: enumerator->destroy(enumerator);
237: this->lock->unlock(this->lock);
238: }
239:
240: METHOD(tnc_pdp_connections_t, get_state, eap_method_t*,
241: private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name,
242: ike_sa_t **ike_sa)
243: {
244: enumerator_t *enumerator;
245: entry_t *entry;
246: eap_method_t *found = NULL;
247:
248: this->lock->read_lock(this->lock);
249: enumerator = this->list->create_enumerator(this->list);
250: while (enumerator->enumerate(enumerator, &entry))
251: {
252: if (equals_entry(entry, nas_id, user_name))
253: {
254: found = entry->method;
255: *ike_sa = entry->ike_sa;
256: break;
257: }
258: }
259: enumerator->destroy(enumerator);
260: if (!found)
261: {
262: this->lock->unlock(this->lock);
263: }
264:
265: dbg_nas_user(nas_id, user_name, !found, "found");
266: return found;
267: }
268:
269: METHOD(tnc_pdp_connections_t, unlock, void,
270: private_tnc_pdp_connections_t *this)
271: {
272: this->lock->unlock(this->lock);
273: }
274:
275: METHOD(tnc_pdp_connections_t, destroy, void,
276: private_tnc_pdp_connections_t *this)
277: {
278: this->lock->destroy(this->lock);
279: this->list->destroy_function(this->list, (void*)free_entry);
280: free(this);
281: }
282:
283: /*
284: * see header file
285: */
286: tnc_pdp_connections_t *tnc_pdp_connections_create(void)
287: {
288: private_tnc_pdp_connections_t *this;
289:
290: INIT(this,
291: .public = {
292: .add = _add,
293: .remove = _remove_,
294: .get_state = _get_state,
295: .unlock = _unlock,
296: .destroy = _destroy,
297: },
298: .list = linked_list_create(),
299: .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
300: .timeout = lib->settings->get_int(lib->settings,
301: "%s.plugins.tnc-pdp.timeout", DEFAULT_TIMEOUT, lib->ns),
302: );
303:
304: return &this->public;
305: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>