Request limits from TKM on init
[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 * rwlocks for context id lists
49 */
50 rwlock_t *locks[TKM_CTX_MAX];
51
52 };
53
54 /**
55 * Check if given kind is a valid context kind value.
56 *
57 * @param kind context kind to check
58 * @return TRUE if given kind is a valid context kind,
59 * FALSE otherwise
60 */
61 static bool is_valid_kind(const tkm_context_kind_t kind)
62 {
63 return (int)kind >= 0 && kind < TKM_CTX_MAX;
64 };
65
66 METHOD(tkm_id_manager_t, acquire_id, int,
67 private_tkm_id_manager_t * const this, const tkm_context_kind_t kind)
68 {
69 int j, id = 0;
70
71 if (!is_valid_kind(kind))
72 {
73 DBG1(DBG_LIB, "tried to acquire id for invalid context kind '%d'",
74 kind);
75 return 0;
76 }
77
78 this->locks[kind]->write_lock(this->locks[kind]);
79 for (j = 0; j < TKM_LIMIT; j++)
80 {
81 if (this->ctxids[kind][j])
82 {
83 this->ctxids[kind][j] = false;
84 id = j + 1;
85 break;
86 }
87 }
88 this->locks[kind]->unlock(this->locks[kind]);
89
90 if (!id)
91 {
92 DBG1(DBG_LIB, "acquiring %N context id failed",
93 tkm_context_kind_names, kind);
94 }
95
96 return id;
97 }
98
99 METHOD(tkm_id_manager_t, release_id, bool,
100 private_tkm_id_manager_t * const this, const tkm_context_kind_t kind,
101 const int id)
102 {
103 const int idx = id - 1;
104
105 if (!is_valid_kind(kind))
106 {
107 DBG1(DBG_LIB, "tried to release id %d for invalid context kind '%d'",
108 id, kind);
109 return FALSE;
110 }
111
112 this->locks[kind]->write_lock(this->locks[kind]);
113 this->ctxids[kind][idx] = true;
114 this->locks[kind]->unlock(this->locks[kind]);
115
116 return TRUE;
117 }
118
119
120 METHOD(tkm_id_manager_t, destroy, void,
121 private_tkm_id_manager_t *this)
122 {
123 int i;
124 for (i = 0; i < TKM_CTX_MAX; i++)
125 {
126 free(this->ctxids[i]);
127 this->locks[i]->destroy(this->locks[i]);
128 }
129 free(this);
130 }
131
132 /*
133 * see header file
134 */
135 tkm_id_manager_t *tkm_id_manager_create()
136 {
137 private_tkm_id_manager_t *this;
138 int i, j;
139
140 INIT(this,
141 .public = {
142 .acquire_id = _acquire_id,
143 .release_id = _release_id,
144 .destroy = _destroy,
145 },
146 );
147
148 for (i = 0; i < TKM_CTX_MAX; i++)
149 {
150 this->ctxids[i] = malloc(TKM_LIMIT * sizeof(bool));
151 this->locks[i] = rwlock_create(RWLOCK_TYPE_DEFAULT);
152 for (j = 0; j < TKM_LIMIT; j++)
153 {
154 /* available id slots are in true state (is_available) */
155 this->ctxids[i][j] = true;
156 }
157 }
158
159 return &this->public;
160 }