Add initial TKM Diffie-Hellman implementation
[strongswan.git] / src / charon-tkm / src / tkm / tkm_id_manager.c
1 /*
2 * Copyright (C) 2012 Reto Buerki
3 * Copyright (C) 2012 Adrian-Ken Rueegsegger
4 * Hochschule fuer Technik Rapperswil
5 *
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>.
10 *
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
14 * for more details.
15 */
16
17 #include "tkm_id_manager.h"
18
19 #include <utils/debug.h>
20 #include <collections/linked_list.h>
21 #include <threading/rwlock.h>
22
23 ENUM_BEGIN(tkm_context_kind_names, TKM_CTX_NONCE, TKM_CTX_NONCE,
24 "NONCE_CONTEXT");
25 ENUM_END(tkm_context_kind_names, TKM_CTX_NONCE);
26
27 typedef struct private_tkm_id_manager_t private_tkm_id_manager_t;
28
29 /**
30 * private data of tkm_id_manager
31 */
32 struct private_tkm_id_manager_t {
33
34 /**
35 * public functions
36 */
37 tkm_id_manager_t public;
38
39 /**
40 * Next free context id values.
41 */
42 int nextids[TKM_CTX_MAX];
43
44 /**
45 * Per-kind list of acquired context ids
46 */
47 linked_list_t *ctxids[TKM_CTX_MAX];
48
49 /**
50 * rwlocks for context id lists
51 */
52 rwlock_t *locks[TKM_CTX_MAX];
53
54 };
55
56 /**
57 * Check if given kind is a valid context kind value.
58 *
59 * @param kind context kind to check
60 * @return TRUE if given kind is a valid context kind,
61 * FALSE otherwise
62 */
63 static bool is_valid_kind(const tkm_context_kind_t kind)
64 {
65 return (int)kind >= 0 && kind < TKM_CTX_MAX;
66 };
67
68 METHOD(tkm_id_manager_t, acquire_id, int,
69 private_tkm_id_manager_t * const this, const tkm_context_kind_t kind)
70 {
71 int *current;
72 int id = 0;
73
74 if (!is_valid_kind(kind))
75 {
76 DBG1(DBG_LIB, "tried to acquire id for invalid context kind '%d'",
77 kind);
78 return 0;
79 }
80
81 this->locks[kind]->write_lock(this->locks[kind]);
82
83 id = this->nextids[kind];
84 current = malloc(sizeof(int));
85 *current = id;
86 this->ctxids[kind]->insert_last(this->ctxids[kind], current);
87 this->nextids[kind]++;
88
89 this->locks[kind]->unlock(this->locks[kind]);
90
91 if (!id)
92 {
93 DBG1(DBG_LIB, "acquiring %N context id failed",
94 tkm_context_kind_names, kind);
95 }
96
97 return id;
98 }
99
100 METHOD(tkm_id_manager_t, release_id, bool,
101 private_tkm_id_manager_t * const this, const tkm_context_kind_t kind,
102 const int id)
103 {
104 enumerator_t *enumerator;
105 int *current;
106 bool found = FALSE;
107
108 if (!is_valid_kind(kind))
109 {
110 DBG1(DBG_LIB, "tried to release id %d for invalid context kind '%d'",
111 id, kind);
112 return FALSE;
113 }
114
115 this->locks[kind]->write_lock(this->locks[kind]);
116 enumerator = this->ctxids[kind]->create_enumerator(this->ctxids[kind]);
117 while (enumerator->enumerate(enumerator, &current))
118 {
119 if (*current == id)
120 {
121 this->ctxids[kind]->remove_at(this->ctxids[kind], enumerator);
122 found = TRUE;
123 break;
124 }
125 }
126 enumerator->destroy(enumerator);
127 this->locks[kind]->unlock(this->locks[kind]);
128
129 if (!found)
130 {
131 DBG3(DBG_LIB, "releasing non-existent %N context id %d, nothing to do",
132 tkm_context_kind_names, kind, id);
133 }
134
135 return TRUE;
136 }
137
138
139 METHOD(tkm_id_manager_t, destroy, void,
140 private_tkm_id_manager_t *this)
141 {
142 int i;
143
144 for (i = 0; i < TKM_CTX_MAX; i++)
145 {
146 this->ctxids[i]->destroy(this->ctxids[i]);
147 this->locks[i]->destroy(this->locks[i]);
148 }
149 free(this);
150 }
151
152 /*
153 * see header file
154 */
155 tkm_id_manager_t *tkm_id_manager_create()
156 {
157 private_tkm_id_manager_t *this;
158 int i;
159
160 INIT(this,
161 .public = {
162 .acquire_id = _acquire_id,
163 .release_id = _release_id,
164 .destroy = _destroy,
165 },
166 );
167
168 for (i = 0; i < TKM_CTX_MAX; i++)
169 {
170 this->nextids[i] = 1;
171 this->ctxids[i] = linked_list_create();
172 this->locks[i] = rwlock_create(RWLOCK_TYPE_DEFAULT);
173 }
174
175 return &this->public;
176 }