keep a list of RADIUS connections with EAP method states
[strongswan.git] / src / libcharon / plugins / tnc_pdp / tnc_pdp_connections.c
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 <utils/linked_list.h>
19 #include <debug.h>
20
21 typedef struct private_tnc_pdp_connections_t private_tnc_pdp_connections_t;
22 typedef struct entry_t entry_t;
23
24 /**
25 * Private data of tnc_pdp_connections_t
26 */
27 struct private_tnc_pdp_connections_t {
28
29 /**
30 * Implements tnc_pdp_connections_t interface
31 */
32 tnc_pdp_connections_t public;
33
34 /**
35 * List of TNC PEP RADIUS Connections
36 */
37 linked_list_t *list;
38 };
39
40 /**
41 * Data entry for a TNC PEP RADIUS connection
42 */
43 struct entry_t {
44
45 /**
46 * NAS identifier of PEP
47 */
48 chunk_t nas_id;
49
50 /**
51 * User name of TNC Client
52 */
53 chunk_t user_name;
54
55 /**
56 * EAP method state
57 */
58 eap_method_t *method;
59 };
60
61 /**
62 * Free the memory allocated to a data entry
63 */
64 static void free_entry(entry_t *this)
65 {
66 this->method->destroy(this->method);
67 free(this->nas_id.ptr);
68 free(this->user_name.ptr);
69 free(this);
70 }
71
72 /**
73 * Find a matching data entry
74 */
75 static bool equals_entry( entry_t *this, chunk_t nas_id, chunk_t user_name)
76 {
77 bool no_nas_id = !this->nas_id.ptr && !nas_id.ptr;
78
79 return (chunk_equals(this->nas_id, nas_id) || no_nas_id) &&
80 chunk_equals(this->user_name, user_name);
81 }
82
83 /**
84 * Find a matching data entry
85 */
86 static void dbg_nas_user(chunk_t nas_id, chunk_t user_name, bool not, char *op)
87 {
88 if (nas_id.len)
89 {
90 DBG1(DBG_CFG, "%s RADIUS connection for user '%.*s' NAS '%.*s'",
91 not ? "could not find" : op, user_name.len, user_name.ptr,
92 nas_id.len, nas_id.ptr);
93 }
94 else
95 {
96 DBG1(DBG_CFG, "%s RADIUS connection for user '%.*s'",
97 not ? "could not find" : op, user_name.len, user_name.ptr);
98 }
99 }
100
101 METHOD(tnc_pdp_connections_t, add, void,
102 private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name,
103 eap_method_t *method)
104 {
105 enumerator_t *enumerator;
106 entry_t *entry;
107 bool found = FALSE;
108
109 enumerator = this->list->create_enumerator(this->list);
110 while (enumerator->enumerate(enumerator, &entry))
111 {
112 if (equals_entry(entry, nas_id, user_name))
113 {
114 found = TRUE;
115 entry->method->destroy(entry->method);
116 DBG1(DBG_CFG, "removed stale TNC PEP RADIUS connection");
117 entry->method = method;
118 break;
119 }
120 }
121 enumerator->destroy(enumerator);
122
123 if (!found)
124 {
125 entry = malloc_thing(entry_t);
126 entry->nas_id = chunk_clone(nas_id);
127 entry->user_name = chunk_clone(user_name);
128 entry->method = method;
129 this->list->insert_last(this->list, entry);
130 }
131 dbg_nas_user(nas_id, user_name, FALSE, "created");
132 }
133
134 METHOD(tnc_pdp_connections_t, remove_, void,
135 private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name)
136 {
137 enumerator_t *enumerator;
138 entry_t *entry;
139
140 enumerator = this->list->create_enumerator(this->list);
141 while (enumerator->enumerate(enumerator, &entry))
142 {
143 if (equals_entry(entry, nas_id, user_name))
144 {
145 free_entry(entry);
146 this->list->remove_at(this->list, enumerator);
147 dbg_nas_user(nas_id, user_name, FALSE, "removed");
148 break;
149 }
150 }
151 enumerator->destroy(enumerator);
152 }
153
154 METHOD(tnc_pdp_connections_t, get_method, eap_method_t*,
155 private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name)
156 {
157 enumerator_t *enumerator;
158 entry_t *entry;
159 eap_method_t *found = NULL;
160
161 enumerator = this->list->create_enumerator(this->list);
162 while (enumerator->enumerate(enumerator, &entry))
163 {
164 if (equals_entry(entry, nas_id, user_name))
165 {
166 found = entry->method;
167 break;
168 }
169 }
170 enumerator->destroy(enumerator);
171
172 dbg_nas_user(nas_id, user_name, !found, "found");
173 return found;
174 }
175
176 METHOD(tnc_pdp_connections_t, destroy, void,
177 private_tnc_pdp_connections_t *this)
178 {
179 this->list->destroy_function(this->list, (void*)free_entry);
180 free(this);
181 }
182
183 /*
184 * see header file
185 */
186 tnc_pdp_connections_t *tnc_pdp_connections_create(void)
187 {
188 private_tnc_pdp_connections_t *this;
189
190 INIT(this,
191 .public = {
192 .add = _add,
193 .remove = _remove_,
194 .get_method = _get_method,
195 .destroy = _destroy,
196 },
197 .list = linked_list_create(),
198 );
199
200 return &this->public;
201 }
202