1 /*******************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /*******************************************************************************/
11 #include <stdlib.h>
12 #include <stdbool.h>
13 #include <string.h>
14
15 #include <asc_config.h>
16
17 #include "asc_security_core/logger.h"
18 #include "asc_security_core/utils/string_utils.h"
19
20 #include "asc_security_core/components_factory_declarations.h"
21 #include "asc_security_core/components_manager.h"
22
23 static bool _components_manager_initialized = false;
24 static uintptr_t _components_manager_global_context;
25
26 static void components_manager_do_lcm_action(component_state_enum_t to_state, component_state_enum_t from_state);
27 static int _get_owner_enumerator(component_id_t owner_id);
28
components_manager_init(void)29 asc_result_t components_manager_init(void)
30 {
31 asc_result_t result = ASC_RESULT_OK;
32
33 if (_components_manager_initialized) {
34 log_debug("Aleady initialized");
35 return ASC_RESULT_INITIALIZED;
36 }
37
38 log_debug("Init");
39 int index = 0;
40 component_load_function_t *func_ptr = NULL;
41 component_load_function_t **init_array = components_factory_get_load_array();
42
43 if (init_array == NULL) {
44 log_fatal("Unable to get components init array");
45 return ASC_RESULT_EXCEPTION;
46 }
47 _components_manager_initialized = true;
48
49 while ((func_ptr = init_array[index++])) {
50 component_load_function_t func = *func_ptr;
51
52 if (func) {
53 asc_result_t ret = func();
54 if (ret != ASC_RESULT_OK) {
55 result = ret;
56 log_fatal("Unable to load component with index=[%d]", index-1);
57 }
58 }
59 }
60
61 #ifdef ASC_DYNAMIC_FACTORY_ENABLED
62 asc_result_t result_dyn = components_factory_load_dynamic(NULL);
63 if (result_dyn != ASC_RESULT_OK && result_dyn != ASC_RESULT_EMPTY) {
64 result = result_dyn;
65 }
66 #endif
67
68 components_manager_do_lcm_action(COMPONENT_INITIALIZED, COMPONENT_LOADED);
69 components_manager_do_lcm_action(COMPONENT_SUBSCRIBED, COMPONENT_INITIALIZED);
70 components_manager_do_lcm_action(COMPONENT_RUNNING, COMPONENT_SUBSCRIBED);
71
72 return result;
73 }
74
components_manager_deinit(void)75 asc_result_t components_manager_deinit(void)
76 {
77 if (!_components_manager_initialized) {
78 log_debug("Unintialized");
79 return ASC_RESULT_IMPOSSIBLE;
80 }
81 _components_manager_initialized = false;
82 log_debug("Deinit");
83 components_manager_do_lcm_action(COMPONENT_STOPED, COMPONENT_RUNNING);
84 components_manager_do_lcm_action(COMPONENT_UNSUBSCRIBED, COMPONENT_UNDEFINED);
85 components_manager_do_lcm_action(COMPONENT_LOADED, COMPONENT_UNDEFINED);
86
87 #ifdef ASC_DYNAMIC_FACTORY_ENABLED
88 components_factory_unload_dynamic(); // must be before components_factory_unload();
89 #endif
90 components_factory_unload();
91 _components_manager_global_context = 0;
92 return ASC_RESULT_OK;
93 }
94
components_manager_global_context_set(uintptr_t ctx)95 void components_manager_global_context_set(uintptr_t ctx)
96 {
97 _components_manager_global_context = ctx;
98 }
99
components_manager_global_context_get(void)100 uintptr_t components_manager_global_context_get(void)
101 {
102 return _components_manager_global_context;
103 }
104
105 #ifdef ASC_COMPONENT_CONFIGURATION
components_manager_set_log_level(component_id_t id,int set)106 bool components_manager_set_log_level(component_id_t id, int set)
107 {
108 unsigned int level = (set < 0) ? ASC_LOG_LEVEL : (unsigned int)set;
109
110 if (level > ASC_LOG_LEVEL) {
111 log_error("Requested log level=[%u] is above than compiled=[%u]", level, ASC_LOG_LEVEL);
112 return false;
113 }
114 if (!id) {
115 id = components_manager_get_id(ManagerCore);
116 }
117 component_info_t *info = components_manager_get_info(id);
118
119 if (info) {
120 info->log_level = level;
121 return true;
122 }
123 return false;
124 }
125
components_manager_get_log_level(component_id_t id)126 unsigned int components_manager_get_log_level(component_id_t id)
127 {
128 if (!id) {
129 id = components_manager_get_id(ManagerCore);
130 }
131 component_info_t *info = components_manager_get_info(id);
132
133 // return debug if no info or not initialized yet to not lost the log print
134 if (!info || info->state == COMPONENT_UNLOADED) {
135 return LOG_LEVEL_DEBUG;
136 }
137
138 return info->log_level;
139 }
140
components_manager_set_log_level_all(int set)141 bool components_manager_set_log_level_all(int set)
142 {
143 unsigned int level = (set < 0) ? ASC_LOG_LEVEL : (unsigned int)set;
144
145 if (level > ASC_LOG_LEVEL) {
146 log_error("Requested log level=[%u] is above than compiled=[%u]", level, ASC_LOG_LEVEL);
147 return false;
148 }
149 for (int index = 0; index < COMPONENTS_COUNT; index++) {
150 g_component_factory[index].component.info.log_level = level;
151 }
152 return true;
153 }
154 #endif
155
components_manager_get_component(component_id_t id)156 component_t *components_manager_get_component(component_id_t id)
157 {
158 for (int index = 0; index < COMPONENTS_COUNT; index++) {
159 if (g_component_factory[index].component.info.id == id) {
160 return &g_component_factory[index].component;
161 }
162 }
163 return NULL;
164 }
165
components_manager_get_id_by_name(const char * name,size_t len)166 component_id_t components_manager_get_id_by_name(const char *name, size_t len)
167 {
168 if (str_isempty(name)) {
169 return 0;
170 }
171
172 for (int index = 0; index < COMPONENTS_COUNT; index++) {
173
174 if (!str_ncmp(g_component_factory[index].component.info.name,
175 str_len(g_component_factory[index].component.info.name), name, len)) {
176 return g_component_factory[index].component.info.id;
177 }
178 }
179 return 0;
180 }
181
components_manager_get_info(component_id_t id)182 component_info_t *components_manager_get_info(component_id_t id)
183 {
184 component_t *component = components_manager_get_component(id);
185
186 return component ? &component->info : NULL;
187 }
188
__components_manager_get_ctx(component_id_t id)189 void *__components_manager_get_ctx(component_id_t id)
190 {
191 component_t *component = components_manager_get_component(id);
192
193 return component ? component->info.ctx : NULL;
194 }
195
__components_manager_set_ctx(component_id_t id,void * ctx)196 void __components_manager_set_ctx(component_id_t id, void *ctx)
197 {
198 component_t *component = components_manager_get_component(id);
199
200 if (component) {
201 component->info.ctx = ctx;
202 }
203 }
204
components_manager_get_last_result(component_id_t id)205 asc_result_t components_manager_get_last_result(component_id_t id)
206 {
207 component_t *component = components_manager_get_component(id);
208
209 return component ? component->info.last_result : ASC_RESULT_UNINITIALIZED;
210 }
211
components_manager_get_name(component_id_t id)212 const char *components_manager_get_name(component_id_t id)
213 {
214 component_t *component = components_manager_get_component(id);
215
216 return component ? component->info.name : "";
217 }
218
components_manager_start(component_id_t id,component_id_t owner_id)219 asc_result_t components_manager_start(component_id_t id, component_id_t owner_id)
220 {
221 asc_result_t result = ASC_RESULT_OK;
222 component_t *component = components_manager_get_component(id);
223 int owner_enumerator = -1;
224 component_state_enum_t cur_state = COMPONENT_UNLOADED;
225 component_ops_t *ops = NULL;
226 lcm_func_t func = NULL;
227
228 if (!component) {
229 return ASC_RESULT_BAD_ARGUMENT;
230 }
231
232 owner_enumerator = _get_owner_enumerator(owner_id);
233 if (owner_enumerator < 0) {
234 return ASC_RESULT_BAD_ARGUMENT;
235 }
236
237 cur_state = component->info.state;
238 if (cur_state != COMPONENT_SUBSCRIBED && cur_state != COMPONENT_STOPED && cur_state != COMPONENT_RUNNING) {
239 result = ASC_RESULT_IMPOSSIBLE;
240 goto cleanup;
241 }
242
243 /* Handle case already in running state */
244 if (cur_state == COMPONENT_RUNNING) {
245 bit_vector_set(component_owners_t, &component->info.owners, owner_enumerator, true);
246 goto cleanup;
247 }
248
249 ops = component->ops;
250 func = ops ? ops->start : NULL;
251
252 result = func ? func(id) : ASC_RESULT_OK;
253 if (result == ASC_RESULT_OK) {
254 bit_vector_set(component_owners_t, &component->info.owners, owner_enumerator, true);
255 component->info.state = COMPONENT_RUNNING;
256 }
257 goto cleanup;
258
259 cleanup:
260 if (result != ASC_RESULT_OK) {
261 component->info.state = COMPONENT_FAIL;
262 log_error("failed to start component=[%s]", component->info.name);
263 }
264 return result;
265 }
266
components_manager_stop(component_id_t id,component_id_t owner_id,bool ignore_self_owner,bool force)267 asc_result_t components_manager_stop(component_id_t id, component_id_t owner_id, bool ignore_self_owner, bool force)
268 {
269 asc_result_t result = ASC_RESULT_OK;
270 component_t *component = components_manager_get_component(id);
271 int owner_enumerator = -1;
272 bool owner = false;
273 bool self_owner = false;
274
275 if (!component) {
276 return ASC_RESULT_BAD_ARGUMENT;
277 }
278
279 owner_enumerator = _get_owner_enumerator(owner_id);
280 if (owner_enumerator < 0) {
281 return ASC_RESULT_BAD_ARGUMENT;
282 }
283
284 if (component->info.state == COMPONENT_FAIL) {
285 result = ASC_RESULT_IMPOSSIBLE;
286 goto cleanup;
287 }
288
289 /* Handle case already in stopped state */
290 if (component->info.state != COMPONENT_RUNNING) {
291 if (force) {
292 bit_vector_clean(component_owners_t, &component->info.owners);
293 } else {
294 if (ignore_self_owner) {
295 bit_vector_set(component_owners_t, &component->info.owners, component->info.enumerator, false);
296 }
297 bit_vector_set(component_owners_t, &component->info.owners, owner_enumerator, false);
298 }
299 goto cleanup;
300 }
301
302 /* Prepare vector */
303 if (force) {
304 bit_vector_clean(component_owners_t, &component->info.owners);
305 } else {
306 owner = bit_vector_get(component_owners_t, &component->info.owners, owner_enumerator);
307 self_owner = bit_vector_get(component_owners_t, &component->info.owners, component->info.enumerator);
308 if (ignore_self_owner) {
309 bit_vector_set(component_owners_t, &component->info.owners, component->info.enumerator, false);
310 }
311 bit_vector_set(component_owners_t, &component->info.owners, owner_enumerator, false);
312 }
313
314 /* Performe stop */
315 if (is_bit_vector_zero(component_owners_t, &component->info.owners)) {
316 component_ops_t *ops = component->ops;
317 lcm_func_t func = ops ? ops->stop : NULL;
318
319 result = func ? func(id) : ASC_RESULT_OK;
320 if (result == ASC_RESULT_OK) {
321 component->info.state = COMPONENT_STOPED;
322 } else {
323 /* Restore status of owners */
324 bit_vector_set(component_owners_t, &component->info.owners, owner_enumerator, owner);
325 bit_vector_set(component_owners_t, &component->info.owners, component->info.enumerator, self_owner);
326 }
327 } else {
328 /* Restore status of self owner */
329 bit_vector_set(component_owners_t, &component->info.owners, component->info.enumerator, self_owner);
330 }
331
332 cleanup:
333 if (result != ASC_RESULT_OK) {
334 component->info.state = COMPONENT_FAIL;
335 log_error("failed to stop component=[%s]", component->info.name);
336 }
337 return result;
338 }
339
_load_lcm_function(int index,component_state_enum_t to_state,component_state_enum_t from_state)340 static lcm_func_t _load_lcm_function(int index, component_state_enum_t to_state, component_state_enum_t from_state)
341 {
342 lcm_func_t func = NULL;
343 component_ops_t *ops = g_component_factory[index].component.ops;
344
345 if (ops) {
346 switch (to_state) {
347 case COMPONENT_INITIALIZED:
348 func = ops->init;
349 break;
350 case COMPONENT_SUBSCRIBED:
351 func = ops->subscribe;
352 break;
353 case COMPONENT_RUNNING:
354 func = ops->start;
355 break;
356 case COMPONENT_STOPED:
357 func = ops->stop;
358 break;
359 case COMPONENT_UNSUBSCRIBED:
360 func = ops->unsubscribe;
361 break;
362 case COMPONENT_LOADED:
363 func = ops->deinit;
364 break;
365 default:
366 g_component_factory[index].component.info.last_result = ASC_RESULT_NOT_SUPPORTED_EXCEPTION;
367 log_fatal("Unsupported LCM state=[%d]", to_state);
368 return NULL;
369 }
370 }
371
372 log_debug("lcm function component=[%s] ops=[%p] is defined=[%d] to=[%d] from=[%d] current=[%d]",
373 g_component_factory[index].component.info.name,
374 (void *)ops, func ? 1 : 0, to_state, from_state,
375 g_component_factory[index].component.info.state);
376
377 return func;
378 }
379
_perform_lcm_action(lcm_func_t func,int index,component_state_enum_t to_state)380 static void _perform_lcm_action(lcm_func_t func, int index, component_state_enum_t to_state)
381 {
382 switch (to_state)
383 {
384 case COMPONENT_RUNNING:
385 if (!g_component_factory[index].component.info.auto_start_disable) {
386 g_component_factory[index].component.info.last_result =
387 components_manager_start(g_component_factory[index].component.info.id, g_component_factory[index].component.info.id);
388 } else {
389 log_debug("%d function is disabled by auto_start_disable==true in component=[%s]", to_state, g_component_factory[index].component.info.name);
390 }
391
392 break;
393 case COMPONENT_STOPED:
394 g_component_factory[index].component.info.last_result =
395 components_manager_stop(g_component_factory[index].component.info.id, g_component_factory[index].component.info.id, false, true);
396 break;
397 default:
398 if (func == NULL) {
399 if (g_component_factory[index].component.info.state != COMPONENT_FAIL) {
400 g_component_factory[index].component.info.state = to_state;
401 }
402 log_debug("%d function function in component=[%s] is not armed", to_state, g_component_factory[index].component.info.name);
403 return;
404 }
405 g_component_factory[index].component.info.last_result = func(g_component_factory[index].component.info.id);
406
407 if (g_component_factory[index].component.info.last_result != ASC_RESULT_OK) {
408 g_component_factory[index].component.info.state = COMPONENT_FAIL;
409 log_error("failed to %d function component=[%s]", to_state, g_component_factory[index].component.info.name);
410 } else {
411 g_component_factory[index].component.info.state = to_state;
412 log_debug("%d function component=[%s] done", to_state, g_component_factory[index].component.info.name);
413 }
414 break;
415 }
416 }
417
components_manager_do_lcm_action(component_state_enum_t to_state,component_state_enum_t from_state)418 static void components_manager_do_lcm_action(component_state_enum_t to_state, component_state_enum_t from_state)
419 {
420 for (int index = 0; index < COMPONENTS_COUNT; index++) {
421 if (g_component_factory[index].component.info.state == COMPONENT_UNLOADED) {
422 continue;
423 }
424 g_component_factory[index].component.info.last_result = ASC_RESULT_OK;
425
426 lcm_func_t func = _load_lcm_function(index, to_state, from_state);
427
428 if (g_component_factory[index].component.info.last_result == ASC_RESULT_NOT_SUPPORTED_EXCEPTION) {
429 return;
430 }
431
432 bool is_stop_start_same_state = false;
433
434 if (g_component_factory[index].component.info.state == to_state && (to_state == COMPONENT_RUNNING || to_state == COMPONENT_STOPED)) {
435 is_stop_start_same_state = true;
436 }
437
438 if (func && !is_stop_start_same_state && from_state != COMPONENT_UNDEFINED && g_component_factory[index].component.info.state != from_state) {
439 log_error("Expected=[%d] state is not match current=[%d] component=[%s]", from_state, g_component_factory[index].component.info.state, g_component_factory[index].component.info.name);
440 g_component_factory[index].component.info.last_result = ASC_RESULT_PARSE_EXCEPTION;
441 continue;
442 }
443 _perform_lcm_action(func, index, to_state);
444 }
445 }
446
_get_owner_enumerator(component_id_t owner_id)447 static int _get_owner_enumerator(component_id_t owner_id)
448 {
449 component_t *owner = components_manager_get_component(owner_id);
450
451 if (owner == NULL) {
452 return -1;
453 }
454 return owner->info.enumerator;
455 }
456
457 /* Component manager is component itself */
458 COMPONENTS_FACTORY_DEFINITION(ManagerCore, NULL)
459