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