Use ikev2 keymat proxy
[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 #define TKM_LIMIT 100
24
25 ENUM_BEGIN(tkm_context_kind_names, TKM_CTX_NONCE, TKM_CTX_DH,
26 "NONCE_CONTEXT",
27 "DH_CONTEXT");
28 ENUM_END(tkm_context_kind_names, TKM_CTX_DH);
29
30 typedef struct private_tkm_id_manager_t private_tkm_id_manager_t;
31
32 /**
33 * private data of tkm_id_manager
34 */
35 struct private_tkm_id_manager_t {
36
37 /**
38 * public functions
39 */
40 tkm_id_manager_t public;
41
42 /**
43 * Per-kind array of free context ids
44 */
45 bool* ctxids[TKM_CTX_MAX];
46
47 /**
48 * Per-kind context limits.
49 */
50 tkm_limits_t limits;
51
52 /**
53 * rwlocks for context id lists
54 */
55 rwlock_t *locks[TKM_CTX_MAX];
56
57 };
58
59 /**
60 * Check if given kind is a valid context kind value.
61 *
62 * @param kind context kind to check
63 * @return TRUE if given kind is a valid context kind,
64 * FALSE otherwise
65 */
66 static bool is_valid_kind(const tkm_context_kind_t kind)
67 {
68 return (int)kind >= 0 && kind < TKM_CTX_MAX;
69 };
70
71 METHOD(tkm_id_manager_t, acquire_id, int,
72 private_tkm_id_manager_t * const this, const tkm_context_kind_t kind)
73 {
74 int id = 0;
75 uint64_t j;
76
77 if (!is_valid_kind(kind))
78 {
79 DBG1(DBG_LIB, "tried to acquire id for invalid context kind '%d'",
80 kind);
81 return 0;
82 }
83
84 this->locks[kind]->write_lock(this->locks[kind]);
85 for (j = 0; j < this->limits[kind]; j++)
86 {
87 if (this->ctxids[kind][j])
88 {
89 this->ctxids[kind][j] = false;
90 id = j + 1;
91 break;
92 }
93 }
94 this->locks[kind]->unlock(this->locks[kind]);
95
96 if (!id)
97 {
98 DBG1(DBG_LIB, "acquiring %N context id failed",
99 tkm_context_kind_names, kind);
100 }
101
102 return id;
103 }
104
105 METHOD(tkm_id_manager_t, release_id, bool,
106 private_tkm_id_manager_t * const this, const tkm_context_kind_t kind,
107 const int id)
108 {
109 const int idx = id - 1;
110
111 if (!is_valid_kind(kind))
112 {
113 DBG1(DBG_LIB, "tried to release id %d for invalid context kind '%d'",
114 id, kind);
115 return FALSE;
116 }
117
118 this->locks[kind]->write_lock(this->locks[kind]);
119 this->ctxids[kind][idx] = true;
120 this->locks[kind]->unlock(this->locks[kind]);
121
122 return TRUE;
123 }
124
125
126 METHOD(tkm_id_manager_t, destroy, void,
127 private_tkm_id_manager_t *this)
128 {
129 int i;
130 for (i = 0; i < TKM_CTX_MAX; i++)
131 {
132 free(this->ctxids[i]);
133 this->locks[i]->destroy(this->locks[i]);
134 }
135 free(this);
136 }
137
138 /*
139 * see header file
140 */
141 tkm_id_manager_t *tkm_id_manager_create(const tkm_limits_t limits)
142 {
143 private_tkm_id_manager_t *this;
144 int i;
145 uint64_t j;
146
147 INIT(this,
148 .public = {
149 .acquire_id = _acquire_id,
150 .release_id = _release_id,
151 .destroy = _destroy,
152 },
153 );
154
155 for (i = 0; i < TKM_CTX_MAX; i++)
156 {
157 this->limits[i] = limits[i];
158 this->ctxids[i] = malloc(limits[i] * sizeof(bool));
159 this->locks[i] = rwlock_create(RWLOCK_TYPE_DEFAULT);
160 for (j = 0; j < limits[i]; j++)
161 {
162 /* available id slots are in true state (is_available) */
163 this->ctxids[i][j] = true;
164 }
165 DBG2(DBG_LIB, "%N initialized, %llu slot(s)",
166 tkm_context_kind_names, i, limits[i]);
167 }
168
169 return &this->public;
170 }