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