Line data Source code
1 : /*
2 : * SPDX license identifier: MPL-2.0
3 : *
4 : * Copyright (C) 2011-2015, BMW AG
5 : *
6 : * This file is part of COVESA Project DLT - Diagnostic Log and Trace.
7 : *
8 : * This Source Code Form is subject to the terms of the
9 : * Mozilla Public License (MPL), v. 2.0.
10 : * If a copy of the MPL was not distributed with this file,
11 : * You can obtain one at http://mozilla.org/MPL/2.0/.
12 : *
13 : * For further information see http://www.covesa.org/.
14 : */
15 :
16 : /*!
17 : * \author Alexander Wenzel <alexander.aw.wenzel@bmw.de>
18 : *
19 : * \copyright Copyright © 2011-2015 BMW AG. \n
20 : * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
21 : *
22 : * \file dlt_daemon_common.c
23 : */
24 :
25 : /*******************************************************************************
26 : ** **
27 : ** SRC-MODULE: dlt_daemon_common.c **
28 : ** **
29 : ** TARGET : linux **
30 : ** **
31 : ** PROJECT : DLT **
32 : ** **
33 : ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de **
34 : ** Markus Klein **
35 : ** **
36 : ** PURPOSE : **
37 : ** **
38 : ** REMARKS : **
39 : ** **
40 : ** PLATFORM DEPENDANT [yes/no]: yes **
41 : ** **
42 : ** TO BE CHANGED BY USER [yes/no]: no **
43 : ** **
44 : *******************************************************************************/
45 :
46 : /*******************************************************************************
47 : ** Author Identity **
48 : ********************************************************************************
49 : ** **
50 : ** Initials Name Company **
51 : ** -------- ------------------------- ---------------------------------- **
52 : ** aw Alexander Wenzel BMW **
53 : ** mk Markus Klein Fraunhofer ESK **
54 : *******************************************************************************/
55 :
56 : /*******************************************************************************
57 : ** Revision Control History **
58 : *******************************************************************************/
59 :
60 : /*
61 : * $LastChangedRevision: 1670 $
62 : * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $
63 : * $LastChangedBy$
64 : * Initials Date Comment
65 : * aw 13.01.2010 initial
66 : */
67 :
68 : #include <stdbool.h>
69 : #include <stdio.h>
70 : #include <stdlib.h>
71 : #include <string.h>
72 : #include <syslog.h>
73 : #include <errno.h>
74 : #include <unistd.h>
75 : #include <fcntl.h>
76 :
77 : #include <sys/socket.h> /* send() */
78 :
79 : #include "dlt_types.h"
80 : #include "dlt_log.h"
81 : #include "dlt_daemon_common.h"
82 : #include "dlt_daemon_common_cfg.h"
83 : #include "dlt_user_shared.h"
84 : #include "dlt_user_shared_cfg.h"
85 : #include "dlt-daemon.h"
86 :
87 : #include "dlt_daemon_socket.h"
88 : #include "dlt_daemon_serial.h"
89 :
90 : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
91 : # include <systemd/sd-daemon.h>
92 : #endif
93 :
94 : char *app_recv_buffer = NULL; /* pointer to receiver buffer for application msges */
95 :
96 0 : static int dlt_daemon_cmp_apid(const void *m1, const void *m2)
97 : {
98 132 : if ((m1 == NULL) || (m2 == NULL))
99 : return -1;
100 :
101 : DltDaemonApplication *mi1 = (DltDaemonApplication *)m1;
102 : DltDaemonApplication *mi2 = (DltDaemonApplication *)m2;
103 :
104 132 : return memcmp(mi1->apid, mi2->apid, DLT_ID_SIZE);
105 : }
106 :
107 471 : static int dlt_daemon_cmp_apid_ctid(const void *m1, const void *m2)
108 : {
109 471 : if ((m1 == NULL) || (m2 == NULL))
110 : return -1;
111 :
112 : int ret, cmp;
113 : DltDaemonContext *mi1 = (DltDaemonContext *)m1;
114 : DltDaemonContext *mi2 = (DltDaemonContext *)m2;
115 :
116 471 : cmp = memcmp(mi1->apid, mi2->apid, DLT_ID_SIZE);
117 :
118 471 : if (cmp < 0)
119 : ret = -1;
120 471 : else if (cmp == 0)
121 471 : ret = memcmp(mi1->ctid, mi2->ctid, DLT_ID_SIZE);
122 : else
123 : ret = 1;
124 :
125 : return ret;
126 : }
127 :
128 474 : DltDaemonRegisteredUsers *dlt_daemon_find_users_list(DltDaemon *daemon,
129 : char *ecu,
130 : int verbose)
131 : {
132 474 : PRINT_FUNCTION_VERBOSE(verbose);
133 :
134 : int i = 0;
135 :
136 474 : if ((daemon == NULL) || (ecu == NULL)) {
137 0 : dlt_vlog(LOG_ERR, "%s: Wrong parameters", __func__);
138 0 : return (DltDaemonRegisteredUsers *)NULL;
139 : }
140 :
141 476 : for (i = 0; i < daemon->num_user_lists; i++)
142 444 : if (strncmp(ecu, daemon->user_list[i].ecu, DLT_ID_SIZE) == 0)
143 442 : return &daemon->user_list[i];
144 :
145 32 : dlt_vlog(LOG_ERR, "Cannot find user list for ECU: %4s\n", ecu);
146 32 : return (DltDaemonRegisteredUsers *)NULL;
147 : }
148 :
149 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
150 :
151 : static int dlt_daemon_cmp_log_settings(const void *lhs, const void *rhs) {
152 : if ((lhs == NULL) || (rhs == NULL))
153 : return -1;
154 :
155 : DltDaemonContextLogSettings *settings1 = (DltDaemonContextLogSettings *)lhs;
156 : DltDaemonContextLogSettings *settings2 = (DltDaemonContextLogSettings *)rhs;
157 :
158 : int cmp = memcmp(settings1->apid, settings2->apid, DLT_ID_SIZE);
159 :
160 : if (cmp < 0)
161 : return -1;
162 : else if (cmp == 0)
163 : return memcmp(settings1->ctid, settings2->ctid, DLT_ID_SIZE);
164 : else
165 : return 1;
166 : }
167 :
168 : /**
169 : * Find configuration for app/ctx id specific log settings configuration
170 : * @param daemon pointer to dlt daemon struct
171 : * @param apid application id to use
172 : * @param ctid context id to use, can be NULL
173 : * @return pointer to log settings if found, otherwise NULL
174 : */
175 : DltDaemonContextLogSettings *dlt_daemon_find_configured_app_id_ctx_id_settings(
176 : const DltDaemon *daemon, const char *apid, const char *ctid) {
177 : DltDaemonContextLogSettings *app_id_settings = NULL;
178 : for (int i = 0; i < daemon->num_app_id_log_level_settings; ++i) {
179 : DltDaemonContextLogSettings *settings = &daemon->app_id_log_level_settings[i];
180 :
181 : if (strncmp(apid, settings->apid, DLT_ID_SIZE) != 0) {
182 : if (app_id_settings != NULL)
183 : return app_id_settings;
184 : continue;
185 : }
186 :
187 : if (strlen(settings->ctid) == 0) {
188 : app_id_settings = settings;
189 : }
190 :
191 : if (ctid == NULL || strlen(ctid) == 0) {
192 : if (app_id_settings != NULL) {
193 : return app_id_settings;
194 : }
195 : } else {
196 : if (strncmp(ctid, settings->ctid, DLT_ID_SIZE) == 0) {
197 : return settings;
198 : }
199 : }
200 : }
201 :
202 : return app_id_settings;
203 : }
204 :
205 : /**
206 : * Find configured log levels in a given DltDaemonApplication for the passed context id.
207 : * @param app The application settings which contain the previously loaded ap id settings
208 : * @param ctid The context id to find.
209 : * @return Pointer to DltDaemonApplicationLogSettings containing the log level
210 : * for the requested application or NULL if none found.
211 : */
212 : DltDaemonContextLogSettings *dlt_daemon_find_app_log_level_config(
213 : const DltDaemonApplication *const app, const char *const ctid) {
214 :
215 : if (NULL == ctid)
216 : return NULL;
217 :
218 : DltDaemonContextLogSettings settings;
219 : memcpy(settings.apid, app->apid, DLT_ID_SIZE);
220 : memcpy(settings.ctid, ctid, DLT_ID_SIZE);
221 :
222 : DltDaemonContextLogSettings* log_settings = NULL;
223 : log_settings =
224 : (DltDaemonContextLogSettings *)bsearch(
225 : &settings, app->context_log_level_settings,
226 : (size_t)app->num_context_log_level_settings,
227 : sizeof(DltDaemonContextLogSettings),
228 : dlt_daemon_cmp_log_settings);
229 : return log_settings;
230 : }
231 :
232 : #endif
233 :
234 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
235 : int dlt_daemon_compare_trace_load_settings(const void *a, const void *b) {
236 : const DltTraceLoadSettings *s1 = (const DltTraceLoadSettings *)a;
237 : const DltTraceLoadSettings *s2 = (const DltTraceLoadSettings *)b;
238 :
239 : int cmp = strncmp(s1->apid, s2->apid, DLT_ID_SIZE);
240 : if (cmp != 0) {
241 : return cmp;
242 : }
243 :
244 : return strncmp(s1->ctid, s2->ctid, DLT_ID_SIZE);
245 : }
246 :
247 : DltReturnValue dlt_daemon_find_preconfigured_trace_load_settings(
248 : DltDaemon *const daemon, const char *apid, const char *ctid, DltTraceLoadSettings **settings, int *num_settings, int verbose)
249 : {
250 : PRINT_FUNCTION_VERBOSE(verbose);
251 : int i;
252 : *num_settings = 0;
253 : *settings = NULL;
254 :
255 : if ((daemon == NULL) || (apid == NULL)) {
256 : dlt_vlog(LOG_ERR, "%s: Wrong parameters", __func__);
257 : return DLT_RETURN_WRONG_PARAMETER;
258 : }
259 :
260 : if (NULL == daemon->preconfigured_trace_load_settings || daemon->preconfigured_trace_load_settings_count == 0) {
261 : return DLT_RETURN_OK;
262 : }
263 :
264 : for (i = 0; i < daemon->preconfigured_trace_load_settings_count; ++i) {
265 : // check if we can exit already, the trace load settings are sorted
266 : // and if the apid does not match anymore, but we already have settings
267 : // means we collected all settings
268 : if (strncmp(apid, daemon->preconfigured_trace_load_settings[i].apid, DLT_ID_SIZE) != 0) {
269 : if ((*num_settings) != 0)
270 : break;
271 : continue;
272 : }
273 :
274 : // If a ctid is passed, we only want to return entries where both match
275 : if (ctid != NULL && strlen(ctid) > 0) {
276 : if (strncmp(ctid, daemon->preconfigured_trace_load_settings[i].ctid, DLT_ID_SIZE) != 0) {
277 : continue;
278 : }
279 : }
280 :
281 : // Reallocate memory for the settings array with an additional slot for the new setting
282 : DltTraceLoadSettings *temp = realloc(*settings, (*num_settings + 1) * sizeof(DltTraceLoadSettings));
283 : if (temp == NULL) {
284 : dlt_vlog(LOG_ERR, "Failed to allocate memory for trace load settings\n");
285 : free(*settings); // Free any previously allocated memory
286 : *settings = NULL;
287 : *num_settings = 0;
288 : return DLT_RETURN_ERROR;
289 : }
290 : *settings = temp;
291 : // Copy preconfigured trace load settings into the app settings
292 : (*settings)[*num_settings] = daemon->preconfigured_trace_load_settings[i];
293 : (*num_settings)++;
294 : }
295 :
296 : qsort(*settings, (size_t)*num_settings, sizeof(DltTraceLoadSettings),
297 : dlt_daemon_compare_trace_load_settings);
298 : return DLT_RETURN_OK;
299 : }
300 : #endif
301 :
302 9 : int dlt_daemon_init_runtime_configuration(DltDaemon *daemon, const char *runtime_directory, int verbose)
303 : {
304 9 : PRINT_FUNCTION_VERBOSE(verbose);
305 : size_t append_length = 0;
306 :
307 9 : if (daemon == NULL)
308 : return DLT_RETURN_ERROR;
309 :
310 : /* Default */
311 9 : daemon->mode = DLT_USER_MODE_EXTERNAL;
312 :
313 9 : if (runtime_directory == NULL)
314 : return DLT_RETURN_ERROR;
315 :
316 : /* prepare filenames for configuration */
317 : append_length = PATH_MAX - sizeof(DLT_RUNTIME_APPLICATION_CFG);
318 :
319 9 : if (runtime_directory[0]) {
320 0 : strncpy(daemon->runtime_application_cfg, runtime_directory, append_length);
321 0 : daemon->runtime_application_cfg[append_length] = 0;
322 : }
323 : else {
324 9 : strncpy(daemon->runtime_application_cfg, DLT_RUNTIME_DEFAULT_DIRECTORY, append_length);
325 9 : daemon->runtime_application_cfg[append_length] = 0;
326 : }
327 :
328 9 : strcat(daemon->runtime_application_cfg, DLT_RUNTIME_APPLICATION_CFG); /* strcat uncritical here, because max length already checked */
329 :
330 : append_length = PATH_MAX - sizeof(DLT_RUNTIME_CONTEXT_CFG);
331 :
332 9 : if (runtime_directory[0]) {
333 0 : strncpy(daemon->runtime_context_cfg, runtime_directory, append_length);
334 0 : daemon->runtime_context_cfg[append_length] = 0;
335 : }
336 : else {
337 9 : strncpy(daemon->runtime_context_cfg, DLT_RUNTIME_DEFAULT_DIRECTORY, append_length);
338 9 : daemon->runtime_context_cfg[append_length] = 0;
339 : }
340 :
341 9 : strcat(daemon->runtime_context_cfg, DLT_RUNTIME_CONTEXT_CFG); /* strcat uncritical here, because max length already checked */
342 :
343 : append_length = PATH_MAX - sizeof(DLT_RUNTIME_CONFIGURATION);
344 :
345 9 : if (runtime_directory[0]) {
346 0 : strncpy(daemon->runtime_configuration, runtime_directory, append_length);
347 0 : daemon->runtime_configuration[append_length] = 0;
348 : }
349 : else {
350 9 : strncpy(daemon->runtime_configuration, DLT_RUNTIME_DEFAULT_DIRECTORY, append_length);
351 9 : daemon->runtime_configuration[append_length] = 0;
352 : }
353 :
354 9 : strcat(daemon->runtime_configuration, DLT_RUNTIME_CONFIGURATION); /* strcat uncritical here, because max length already checked */
355 :
356 9 : return DLT_RETURN_OK;
357 : }
358 :
359 17 : int dlt_daemon_init(DltDaemon *daemon,
360 : unsigned long RingbufferMinSize,
361 : unsigned long RingbufferMaxSize,
362 : unsigned long RingbufferStepSize,
363 : const char *runtime_directory,
364 : int InitialContextLogLevel,
365 : int InitialContextTraceStatus,
366 : int ForceLLTS,
367 : int verbose)
368 : {
369 17 : PRINT_FUNCTION_VERBOSE(verbose);
370 :
371 17 : if ((daemon == NULL) || (runtime_directory == NULL))
372 : return -1;
373 :
374 17 : daemon->user_list = NULL;
375 17 : daemon->num_user_lists = 0;
376 :
377 17 : daemon->default_log_level = (int8_t) InitialContextLogLevel;
378 17 : daemon->default_trace_status = (int8_t) InitialContextTraceStatus;
379 17 : daemon->force_ll_ts = (int8_t) ForceLLTS;
380 :
381 17 : daemon->overflow_counter = 0;
382 :
383 17 : daemon->runtime_context_cfg_loaded = 0;
384 :
385 17 : daemon->connectionState = 0; /* no logger connected */
386 :
387 17 : daemon->state = DLT_DAEMON_STATE_INIT; /* initial logging state */
388 :
389 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
390 : daemon->preconfigured_trace_load_settings = NULL;
391 : daemon->bytes_sent = 0;
392 : daemon->bytes_recv = 0;
393 : #endif
394 :
395 17 : daemon->sendserialheader = 0;
396 17 : daemon->timingpackets = 0;
397 :
398 17 : dlt_set_id(daemon->ecuid, "");
399 :
400 : /* initialize ring buffer for client connection */
401 17 : dlt_vlog(LOG_INFO, "Ringbuffer configuration: %lu/%lu/%lu\n",
402 : RingbufferMinSize, RingbufferMaxSize, RingbufferStepSize);
403 :
404 17 : if (dlt_buffer_init_dynamic(&(daemon->client_ringbuffer),
405 : (uint32_t) RingbufferMinSize,
406 : (uint32_t) RingbufferMaxSize,
407 : (uint32_t) RingbufferStepSize) < DLT_RETURN_OK)
408 : return -1;
409 :
410 17 : daemon->storage_handle = NULL;
411 : #ifdef DLT_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_ENABLE
412 : daemon->received_message_since_last_watchdog_interval = 0;
413 : #endif
414 17 : return 0;
415 : }
416 :
417 9 : int dlt_daemon_free(DltDaemon *daemon, int verbose)
418 : {
419 : int i = 0;
420 : DltDaemonRegisteredUsers *user_list = NULL;
421 :
422 9 : PRINT_FUNCTION_VERBOSE(verbose);
423 :
424 9 : if ((daemon == NULL) || (daemon->user_list == NULL))
425 : return -1;
426 :
427 : /* free all registered user information */
428 19 : for (i = 0; i < daemon->num_user_lists; i++) {
429 10 : user_list = &daemon->user_list[i];
430 :
431 10 : if (user_list != NULL) {
432 : /* ignore return values */
433 10 : dlt_daemon_contexts_clear(daemon, user_list->ecu, verbose);
434 10 : dlt_daemon_applications_clear(daemon, user_list->ecu, verbose);
435 : }
436 : }
437 :
438 9 : free(daemon->user_list);
439 :
440 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
441 : if (daemon->app_id_log_level_settings != NULL) {
442 : free(daemon->app_id_log_level_settings);
443 : }
444 : #endif
445 :
446 9 : if (app_recv_buffer)
447 9 : free(app_recv_buffer);
448 :
449 : /* free ringbuffer */
450 9 : dlt_buffer_free_dynamic(&(daemon->client_ringbuffer));
451 :
452 9 : return 0;
453 : }
454 :
455 18 : int dlt_daemon_init_user_information(DltDaemon *daemon,
456 : DltGateway *gateway,
457 : int gateway_mode,
458 : int verbose)
459 : {
460 : int nodes = 1;
461 : int i = 1;
462 :
463 18 : PRINT_FUNCTION_VERBOSE(verbose);
464 :
465 18 : if ((daemon == NULL) || ((gateway_mode == 1) && (gateway == NULL)))
466 : return DLT_RETURN_ERROR;
467 :
468 18 : if (gateway_mode == 0) {
469 : /* initialize application list */
470 17 : daemon->user_list = calloc((size_t) nodes, sizeof(DltDaemonRegisteredUsers));
471 :
472 17 : if (daemon->user_list == NULL) {
473 0 : dlt_log(LOG_ERR, "Allocating memory for user information");
474 0 : return DLT_RETURN_ERROR;
475 : }
476 :
477 17 : dlt_set_id(daemon->user_list[0].ecu, daemon->ecuid);
478 17 : daemon->num_user_lists = 1;
479 : }
480 : else { /* gateway is active */
481 1 : nodes += gateway->num_connections;
482 :
483 : /* initialize application list */
484 1 : daemon->user_list = calloc((size_t) nodes, sizeof(DltDaemonRegisteredUsers));
485 :
486 1 : if (daemon->user_list == NULL) {
487 0 : dlt_log(LOG_ERR, "Allocating memory for user information");
488 0 : return DLT_RETURN_ERROR;
489 : }
490 :
491 1 : dlt_set_id(daemon->user_list[0].ecu, daemon->ecuid);
492 1 : daemon->num_user_lists = nodes;
493 :
494 2 : for (i = 1; i < nodes; i++)
495 1 : dlt_set_id(daemon->user_list[i].ecu, gateway->connections[i - 1].ecuid);
496 : }
497 :
498 : return DLT_RETURN_OK;
499 : }
500 :
501 15 : int dlt_daemon_applications_invalidate_fd(DltDaemon *daemon,
502 : char *ecu,
503 : int fd,
504 : int verbose)
505 : {
506 : int i;
507 : DltDaemonRegisteredUsers *user_list = NULL;
508 :
509 15 : PRINT_FUNCTION_VERBOSE(verbose);
510 :
511 15 : if ((daemon == NULL) || (ecu == NULL))
512 : return DLT_RETURN_ERROR;
513 :
514 15 : user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
515 :
516 15 : if (user_list != NULL) {
517 26 : for (i = 0; i < user_list->num_applications; i++)
518 11 : if (user_list->applications[i].user_handle == fd)
519 0 : user_list->applications[i].user_handle = DLT_FD_INIT;
520 :
521 : return DLT_RETURN_OK;
522 : }
523 :
524 : return DLT_RETURN_ERROR;
525 : }
526 :
527 10 : int dlt_daemon_applications_clear(DltDaemon *daemon, char *ecu, int verbose)
528 : {
529 : int i;
530 : DltDaemonRegisteredUsers *user_list = NULL;
531 :
532 10 : PRINT_FUNCTION_VERBOSE(verbose);
533 :
534 10 : if ((daemon == NULL) || (daemon->user_list == NULL) || (ecu == NULL))
535 : return DLT_RETURN_WRONG_PARAMETER;
536 :
537 10 : user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
538 :
539 10 : if (user_list == NULL)
540 : return DLT_RETURN_ERROR;
541 :
542 11 : for (i = 0; i < user_list->num_applications; i++)
543 1 : if (user_list->applications[i].application_description != NULL) {
544 :
545 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
546 : if (user_list->applications[i].context_log_level_settings)
547 : free(user_list->applications[i].context_log_level_settings);
548 : #endif
549 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
550 : if (user_list->applications[i].trace_load_settings) {
551 : free(user_list->applications[i].trace_load_settings);
552 : user_list->applications[i].trace_load_settings = NULL;
553 : user_list->applications[i].trace_load_settings_count = 0;
554 : }
555 : #endif
556 1 : free(user_list->applications[i].application_description);
557 1 : user_list->applications[i].application_description = NULL;
558 : }
559 :
560 10 : if (user_list->applications != NULL)
561 7 : free(user_list->applications);
562 :
563 10 : user_list->applications = NULL;
564 10 : user_list->num_applications = 0;
565 :
566 10 : return 0;
567 : }
568 :
569 15 : static void dlt_daemon_application_reset_user_handle(DltDaemon *daemon,
570 : DltDaemonApplication *application,
571 : int verbose)
572 : {
573 : DltDaemonRegisteredUsers *user_list;
574 : DltDaemonContext *context;
575 : int i;
576 :
577 15 : if (application->user_handle == DLT_FD_INIT)
578 : return;
579 :
580 6 : user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
581 6 : if (user_list != NULL) {
582 6 : for (i = 0; i < user_list->num_contexts; i++) {
583 0 : context = &user_list->contexts[i];
584 0 : if (context->user_handle == application->user_handle)
585 0 : context->user_handle = DLT_FD_INIT;
586 : }
587 : }
588 :
589 6 : if (application->owns_user_handle)
590 6 : close(application->user_handle);
591 :
592 6 : application->user_handle = DLT_FD_INIT;
593 6 : application->owns_user_handle = false;
594 : }
595 :
596 10 : DltDaemonApplication *dlt_daemon_application_add(DltDaemon *daemon,
597 : char *apid,
598 : pid_t pid,
599 : char *description,
600 : int fd,
601 : char *ecu,
602 : int verbose)
603 : {
604 : DltDaemonApplication *application;
605 : DltDaemonApplication *old;
606 : int new_application;
607 : int dlt_user_handle;
608 : bool owns_user_handle;
609 : DltDaemonRegisteredUsers *user_list = NULL;
610 : #ifdef DLT_DAEMON_USE_FIFO_IPC
611 : (void)fd; /* To avoid compiler warning : unused variable */
612 : char filename[DLT_DAEMON_COMMON_TEXTBUFSIZE];
613 : #endif
614 :
615 10 : if ((daemon == NULL) || (apid == NULL) || (apid[0] == '\0') || (ecu == NULL))
616 : return (DltDaemonApplication *)NULL;
617 :
618 10 : user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
619 :
620 10 : if (user_list == NULL)
621 : return (DltDaemonApplication *)NULL;
622 :
623 10 : if (user_list->applications == NULL) {
624 10 : user_list->applications = (DltDaemonApplication *)
625 10 : malloc(sizeof(DltDaemonApplication) * DLT_DAEMON_APPL_ALLOC_SIZE);
626 :
627 10 : if (user_list->applications == NULL)
628 : return (DltDaemonApplication *)NULL;
629 : }
630 :
631 : new_application = 0;
632 :
633 : /* Check if application [apid] is already available */
634 10 : application = dlt_daemon_application_find(daemon, apid, ecu, verbose);
635 :
636 10 : if (application == NULL) {
637 10 : user_list->num_applications += 1;
638 :
639 10 : if (user_list->num_applications != 0) {
640 10 : if ((user_list->num_applications % DLT_DAEMON_APPL_ALLOC_SIZE) == 0) {
641 : /* allocate memory in steps of DLT_DAEMON_APPL_ALLOC_SIZE, e.g. 100 */
642 0 : old = user_list->applications;
643 0 : user_list->applications = (DltDaemonApplication *)
644 0 : malloc(sizeof(DltDaemonApplication) *
645 0 : ((user_list->num_applications / DLT_DAEMON_APPL_ALLOC_SIZE) + 1) *
646 : DLT_DAEMON_APPL_ALLOC_SIZE);
647 :
648 0 : if (user_list->applications == NULL) {
649 0 : user_list->applications = old;
650 0 : user_list->num_applications -= 1;
651 0 : return (DltDaemonApplication *)NULL;
652 : }
653 :
654 0 : memcpy(user_list->applications,
655 : old,
656 0 : sizeof(DltDaemonApplication) * user_list->num_applications);
657 0 : free(old);
658 : }
659 : }
660 :
661 10 : application = &(user_list->applications[user_list->num_applications - 1]);
662 :
663 10 : dlt_set_id(application->apid, apid);
664 10 : application->pid = 0;
665 10 : application->application_description = NULL;
666 10 : application->num_contexts = 0;
667 10 : application->user_handle = DLT_FD_INIT;
668 10 : application->owns_user_handle = false;
669 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
670 : application->trace_load_settings = NULL;
671 : application->trace_load_settings_count = 0;
672 : #endif
673 :
674 : new_application = 1;
675 :
676 : }
677 0 : else if ((pid != application->pid) && (application->pid != 0))
678 : {
679 :
680 0 : dlt_vlog(LOG_WARNING,
681 : "Duplicate registration of ApplicationID: '%.4s'; registering from PID %d, existing from PID %d\n",
682 : apid,
683 : pid,
684 : application->pid);
685 : }
686 :
687 : /* Store application description and pid of application */
688 10 : if (application->application_description) {
689 0 : free(application->application_description);
690 0 : application->application_description = NULL;
691 : }
692 :
693 10 : if (description != NULL) {
694 10 : application->application_description = malloc(strlen(description) + 1);
695 :
696 10 : if (application->application_description) {
697 10 : memcpy(application->application_description, description, strlen(description) + 1);
698 : } else {
699 0 : dlt_log(LOG_ERR, "Cannot allocate memory to store application description\n");
700 0 : free(application);
701 0 : return (DltDaemonApplication *)NULL;
702 : }
703 : }
704 :
705 10 : if (application->pid != pid) {
706 9 : dlt_daemon_application_reset_user_handle(daemon, application, verbose);
707 9 : application->pid = 0;
708 : }
709 :
710 : /* open user pipe only if it is not yet opened */
711 10 : if ((application->user_handle == DLT_FD_INIT) && (pid != 0)) {
712 : dlt_user_handle = DLT_FD_INIT;
713 : owns_user_handle = false;
714 :
715 : #if defined DLT_DAEMON_USE_UNIX_SOCKET_IPC || defined DLT_DAEMON_VSOCK_IPC_ENABLE
716 : if (fd >= DLT_FD_MINIMUM) {
717 : dlt_user_handle = fd;
718 : owns_user_handle = false;
719 : }
720 : #endif
721 : #ifdef DLT_DAEMON_USE_FIFO_IPC
722 : if (dlt_user_handle < DLT_FD_MINIMUM) {
723 : snprintf(filename,
724 : DLT_DAEMON_COMMON_TEXTBUFSIZE,
725 : "%s/dltpipes/dlt%d",
726 : dltFifoBaseDir,
727 : pid);
728 :
729 : dlt_user_handle = open(filename, O_WRONLY | O_NONBLOCK);
730 :
731 9 : if (dlt_user_handle < 0) {
732 0 : int prio = (errno == ENOENT) ? LOG_INFO : LOG_WARNING;
733 0 : dlt_vlog(prio, "open() failed to %s, errno=%d (%s)!\n", filename, errno, strerror(errno));
734 : } else {
735 : owns_user_handle = true;
736 : }
737 : }
738 : #endif
739 : /* check if file descriptor was already used, and make it invalid if it
740 : * is reused. This prevents sending messages to wrong file descriptor */
741 9 : dlt_daemon_applications_invalidate_fd(daemon, ecu, dlt_user_handle, verbose);
742 9 : dlt_daemon_contexts_invalidate_fd(daemon, ecu, dlt_user_handle, verbose);
743 :
744 9 : application->user_handle = dlt_user_handle;
745 9 : application->owns_user_handle = owns_user_handle;
746 9 : application->pid = pid;
747 : }
748 :
749 : /* Sort */
750 10 : if (new_application) {
751 10 : qsort(user_list->applications,
752 10 : (size_t) user_list->num_applications,
753 : sizeof(DltDaemonApplication),
754 : dlt_daemon_cmp_apid);
755 :
756 : /* Find new position of application with apid*/
757 10 : application = dlt_daemon_application_find(daemon, apid, ecu, verbose);
758 : }
759 :
760 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
761 : application->num_context_log_level_settings = 0;
762 : application->context_log_level_settings = NULL;
763 : #endif
764 : #if DLT_TRACE_LOAD_CTRL_ENABLE
765 : if (application->trace_load_settings == NULL) {
766 : DltTraceLoadSettings* pre_configured_trace_load_settings = NULL;
767 : int num_settings = 0;
768 : DltReturnValue find_trace_settings_return_value = dlt_daemon_find_preconfigured_trace_load_settings(
769 : daemon,
770 : application->apid,
771 : NULL /*load settings for all contexts*/,
772 : &pre_configured_trace_load_settings,
773 : &num_settings,
774 : verbose);
775 :
776 : DltTraceLoadSettings *app_level = NULL;
777 : if ((find_trace_settings_return_value == DLT_RETURN_OK) &&
778 : (pre_configured_trace_load_settings != NULL) &&
779 : (num_settings != 0)) {
780 : application->trace_load_settings = pre_configured_trace_load_settings;
781 : application->trace_load_settings_count = num_settings;
782 : app_level = dlt_find_runtime_trace_load_settings(
783 : application->trace_load_settings,
784 : application->trace_load_settings_count, application->apid,
785 : NULL);
786 : }
787 :
788 : // app is not configured, set daemon defaults
789 : if (app_level == NULL) {
790 : DltTraceLoadSettings *temp = realloc(application->trace_load_settings,
791 : (application->trace_load_settings_count + 1) *
792 : sizeof(DltTraceLoadSettings));
793 :
794 : if (temp != NULL) {
795 : application->trace_load_settings = temp;
796 : ++application->trace_load_settings_count;
797 :
798 : app_level = &application->trace_load_settings[application->trace_load_settings_count - 1];
799 : memset(app_level, 0, sizeof(DltTraceLoadSettings));
800 : app_level[0].hard_limit = DLT_TRACE_LOAD_DAEMON_HARD_LIMIT_DEFAULT;
801 : app_level[0].soft_limit = DLT_TRACE_LOAD_DAEMON_SOFT_LIMIT_DEFAULT;
802 : memcpy(&app_level[0].apid, apid, DLT_ID_SIZE);
803 : memset(&app_level[0].tl_stat, 0, sizeof(DltTraceLoadStat));
804 : } else {
805 : dlt_vlog(DLT_LOG_FATAL, "Failed to allocate memory for trace load settings\n");
806 : }
807 :
808 : // We inserted the application id at the end, to make sure
809 : // Lookups are working properly later on, we have to sort the list again.
810 : qsort(application->trace_load_settings,
811 : (size_t)application->trace_load_settings_count,
812 : sizeof(DltTraceLoadSettings),
813 : dlt_daemon_compare_trace_load_settings);
814 : }
815 : }
816 :
817 : #endif
818 :
819 : return application;
820 : }
821 :
822 6 : int dlt_daemon_application_del(DltDaemon *daemon,
823 : DltDaemonApplication *application,
824 : char *ecu,
825 : int verbose)
826 : {
827 : int pos;
828 : DltDaemonRegisteredUsers *user_list = NULL;
829 :
830 6 : PRINT_FUNCTION_VERBOSE(verbose);
831 :
832 6 : if ((daemon == NULL) || (application == NULL) || (ecu == NULL))
833 : return -1;
834 :
835 6 : user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
836 :
837 6 : if (user_list == NULL)
838 : return -1;
839 :
840 6 : if (user_list->num_applications > 0) {
841 6 : dlt_daemon_application_reset_user_handle(daemon, application, verbose);
842 :
843 : /* Free description of application to be deleted */
844 6 : if (application->application_description) {
845 6 : free(application->application_description);
846 6 : application->application_description = NULL;
847 : }
848 :
849 : #if DLT_TRACE_LOAD_CTRL_ENABLE
850 : if (application->trace_load_settings != NULL) {
851 : free(application->trace_load_settings);
852 : application->trace_load_settings = NULL;
853 : application->trace_load_settings_count = 0;
854 : }
855 : #endif
856 6 : pos = (int) (application - (user_list->applications));
857 :
858 : /* move all applications above pos to pos */
859 6 : memmove(&(user_list->applications[pos]),
860 6 : &(user_list->applications[pos + 1]),
861 6 : sizeof(DltDaemonApplication) * ((user_list->num_applications - 1) - pos));
862 :
863 : /* Clear last application */
864 6 : memset(&(user_list->applications[user_list->num_applications - 1]),
865 : 0,
866 : sizeof(DltDaemonApplication));
867 :
868 6 : user_list->num_applications--;
869 : }
870 :
871 : return 0;
872 : }
873 :
874 149 : DltDaemonApplication *dlt_daemon_application_find(DltDaemon *daemon,
875 : char *apid,
876 : char *ecu,
877 : int verbose)
878 : {
879 : DltDaemonApplication application;
880 : DltDaemonRegisteredUsers *user_list = NULL;
881 :
882 149 : PRINT_FUNCTION_VERBOSE(verbose);
883 :
884 149 : if ((daemon == NULL) || (daemon->user_list == NULL) || (apid == NULL) ||
885 149 : (apid[0] == '\0') || (ecu == NULL))
886 : return (DltDaemonApplication *)NULL;
887 :
888 149 : user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
889 :
890 149 : if ((user_list == NULL) || (user_list->num_applications == 0))
891 : return (DltDaemonApplication *)NULL;
892 :
893 : /* Check, if apid is smaller than smallest apid or greater than greatest apid */
894 132 : if ((memcmp(apid, user_list->applications[0].apid, DLT_ID_SIZE) < 0) ||
895 132 : (memcmp(apid,
896 132 : user_list->applications[user_list->num_applications - 1].apid,
897 : DLT_ID_SIZE) > 0))
898 : return (DltDaemonApplication *)NULL;
899 :
900 132 : dlt_set_id(application.apid, apid);
901 132 : return (DltDaemonApplication *)bsearch(&application,
902 132 : user_list->applications,
903 132 : (size_t) user_list->num_applications,
904 : sizeof(DltDaemonApplication),
905 : dlt_daemon_cmp_apid);
906 : }
907 :
908 9 : int dlt_daemon_applications_load(DltDaemon *daemon, const char *filename, int verbose)
909 : {
910 : FILE *fd;
911 : ID4 apid;
912 : char buf[DLT_DAEMON_COMMON_TEXTBUFSIZE];
913 : char *ret;
914 : char *pb;
915 :
916 9 : PRINT_FUNCTION_VERBOSE(verbose);
917 :
918 9 : if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0'))
919 : return -1;
920 :
921 9 : fd = fopen(filename, "r");
922 :
923 9 : if (fd == NULL) {
924 9 : dlt_vlog(LOG_WARNING,
925 : "%s: cannot open file %s: %s\n",
926 : __func__,
927 : filename,
928 9 : strerror(errno));
929 :
930 9 : return -1;
931 : }
932 :
933 0 : while (!feof(fd)) {
934 : /* Clear buf */
935 : memset(buf, 0, sizeof(buf));
936 :
937 : /* Get line */
938 : ret = fgets(buf, sizeof(buf), fd);
939 :
940 0 : if (NULL == ret) {
941 : /* fgets always null pointer if the last byte of the file is a new line
942 : * We need to check here if there was an error or was it feof.*/
943 0 : if (ferror(fd)) {
944 0 : dlt_vlog(LOG_WARNING,
945 : "%s: fgets(buf,sizeof(buf),fd) returned NULL. %s\n",
946 : __func__,
947 0 : strerror(errno));
948 0 : fclose(fd);
949 0 : return -1;
950 : }
951 0 : else if (feof(fd))
952 : {
953 0 : fclose(fd);
954 0 : return 0;
955 : }
956 : else {
957 0 : dlt_vlog(LOG_WARNING,
958 : "%s: fgets(buf,sizeof(buf),fd) returned NULL. Unknown error.\n",
959 : __func__);
960 0 : fclose(fd);
961 0 : return -1;
962 : }
963 : }
964 :
965 0 : if (strcmp(buf, "") != 0) {
966 : /* Split line */
967 0 : pb = strtok(buf, ":");
968 :
969 0 : if (pb != NULL) {
970 0 : dlt_set_id(apid, pb);
971 0 : pb = strtok(NULL, ":");
972 :
973 0 : if (pb != NULL) {
974 : /* pb contains now the description */
975 : /* pid is unknown at loading time */
976 0 : if (dlt_daemon_application_add(daemon,
977 : apid,
978 : 0,
979 : pb,
980 : -1,
981 0 : daemon->ecuid,
982 : verbose) == 0) {
983 0 : dlt_vlog(LOG_WARNING,
984 : "%s: dlt_daemon_application_add failed for %4s\n",
985 : __func__,
986 : apid);
987 0 : fclose(fd);
988 0 : return -1;
989 : }
990 : }
991 : }
992 : }
993 : }
994 :
995 0 : fclose(fd);
996 :
997 0 : return 0;
998 : }
999 :
1000 0 : int dlt_daemon_applications_save(DltDaemon *daemon, const char *filename, int verbose)
1001 : {
1002 : FILE *fd;
1003 : int i;
1004 :
1005 : char apid[DLT_ID_SIZE + 1]; /* DLT_ID_SIZE+1, because the 0-termination is required here */
1006 : DltDaemonRegisteredUsers *user_list = NULL;
1007 :
1008 0 : PRINT_FUNCTION_VERBOSE(verbose);
1009 :
1010 0 : if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0'))
1011 : return -1;
1012 :
1013 : memset(apid, 0, sizeof(apid));
1014 :
1015 0 : user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
1016 :
1017 0 : if (user_list == NULL)
1018 : return -1;
1019 :
1020 0 : if ((user_list->applications != NULL) && (user_list->num_applications > 0)) {
1021 0 : fd = fopen(filename, "w");
1022 :
1023 0 : if (fd != NULL) {
1024 0 : for (i = 0; i < user_list->num_applications; i++) {
1025 0 : dlt_set_id(apid, user_list->applications[i].apid);
1026 :
1027 0 : if ((user_list->applications[i].application_description) &&
1028 0 : (user_list->applications[i].application_description[0] != '\0'))
1029 : fprintf(fd,
1030 : "%s:%s:\n",
1031 : apid,
1032 : user_list->applications[i].application_description);
1033 : else
1034 : fprintf(fd, "%s::\n", apid);
1035 : }
1036 :
1037 0 : fclose(fd);
1038 : }
1039 : else {
1040 0 : dlt_vlog(LOG_ERR, "%s: open %s failed! No application information stored.\n",
1041 : __func__,
1042 : filename);
1043 : }
1044 : }
1045 :
1046 : return 0;
1047 : }
1048 :
1049 41 : DltDaemonContext *dlt_daemon_context_add(DltDaemon *daemon,
1050 : char *apid,
1051 : char *ctid,
1052 : int8_t log_level,
1053 : int8_t trace_status,
1054 : int log_level_pos,
1055 : int user_handle,
1056 : char *description,
1057 : char *ecu,
1058 : int verbose)
1059 : {
1060 : DltDaemonApplication *application;
1061 : DltDaemonContext *context;
1062 : DltDaemonContext *old;
1063 : int new_context = 0;
1064 : DltDaemonRegisteredUsers *user_list = NULL;
1065 :
1066 41 : PRINT_FUNCTION_VERBOSE(verbose);
1067 :
1068 41 : if ((daemon == NULL) || (apid == NULL) || (apid[0] == '\0') ||
1069 41 : (ctid == NULL) || (ctid[0] == '\0') || (ecu == NULL))
1070 : return (DltDaemonContext *)NULL;
1071 :
1072 41 : if ((log_level < DLT_LOG_DEFAULT) || (log_level > DLT_LOG_VERBOSE))
1073 : return (DltDaemonContext *)NULL;
1074 :
1075 41 : if ((trace_status < DLT_TRACE_STATUS_DEFAULT) || (trace_status > DLT_TRACE_STATUS_ON))
1076 : return (DltDaemonContext *)NULL;
1077 :
1078 41 : user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
1079 :
1080 41 : if (user_list == NULL)
1081 : return (DltDaemonContext *)NULL;
1082 :
1083 41 : if (user_list->contexts == NULL) {
1084 10 : user_list->contexts = (DltDaemonContext *)calloc(1, sizeof(DltDaemonContext) * DLT_DAEMON_CONTEXT_ALLOC_SIZE);
1085 :
1086 10 : if (user_list->contexts == NULL)
1087 : return (DltDaemonContext *)NULL;
1088 : }
1089 :
1090 : /* Check if application [apid] is available */
1091 41 : application = dlt_daemon_application_find(daemon, apid, ecu, verbose);
1092 :
1093 41 : if (application == NULL)
1094 : return (DltDaemonContext *)NULL;
1095 :
1096 : /* Check if context [apid, ctid] is already available */
1097 41 : context = dlt_daemon_context_find(daemon, apid, ctid, ecu, verbose);
1098 :
1099 41 : if (context == NULL) {
1100 41 : user_list->num_contexts += 1;
1101 :
1102 41 : if (user_list->num_contexts != 0) {
1103 41 : if ((user_list->num_contexts % DLT_DAEMON_CONTEXT_ALLOC_SIZE) == 0) {
1104 : /* allocate memory for context in steps of DLT_DAEMON_CONTEXT_ALLOC_SIZE, e.g 100 */
1105 0 : old = user_list->contexts;
1106 0 : user_list->contexts = (DltDaemonContext *)calloc(1, (size_t) sizeof(DltDaemonContext) *
1107 0 : ((user_list->num_contexts /
1108 0 : DLT_DAEMON_CONTEXT_ALLOC_SIZE) + 1) *
1109 : DLT_DAEMON_CONTEXT_ALLOC_SIZE);
1110 :
1111 0 : if (user_list->contexts == NULL) {
1112 0 : user_list->contexts = old;
1113 0 : user_list->num_contexts -= 1;
1114 0 : return (DltDaemonContext *)NULL;
1115 : }
1116 :
1117 0 : memcpy(user_list->contexts,
1118 : old,
1119 0 : (size_t) sizeof(DltDaemonContext) * user_list->num_contexts);
1120 0 : free(old);
1121 : }
1122 : }
1123 :
1124 41 : context = &(user_list->contexts[user_list->num_contexts - 1]);
1125 : memset(context, 0, sizeof(DltDaemonContext));
1126 :
1127 41 : dlt_set_id(context->apid, apid);
1128 41 : dlt_set_id(context->ctid, ctid);
1129 :
1130 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
1131 : context->trace_load_settings = NULL;
1132 : #endif
1133 :
1134 41 : application->num_contexts++;
1135 : new_context = 1;
1136 : }
1137 :
1138 : /* Set context description */
1139 41 : if (context->context_description) {
1140 0 : free(context->context_description);
1141 0 : context->context_description = NULL;
1142 : }
1143 :
1144 41 : if (description != NULL) {
1145 41 : context->context_description = malloc(strlen(description) + 1);
1146 :
1147 41 : if (context->context_description) {
1148 41 : memcpy(context->context_description, description, strlen(description) + 1);
1149 : }
1150 : }
1151 :
1152 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
1153 : /* configure initial log level */
1154 : DltDaemonContextLogSettings *settings = NULL;
1155 : settings = dlt_daemon_find_configured_app_id_ctx_id_settings(
1156 : daemon, context->apid, ctid);
1157 :
1158 : if (settings != NULL) {
1159 : /* set log level */
1160 : log_level = settings->log_level;
1161 :
1162 : DltDaemonContextLogSettings *ct_settings = NULL;
1163 : ct_settings = dlt_daemon_find_app_log_level_config(application, ctid);
1164 :
1165 : /* ct_settings != null: context and app id combination already exists */
1166 : if (ct_settings == NULL) {
1167 : /* copy the configuration into the DltDaemonApplication for faster access later */
1168 : DltDaemonContextLogSettings *tmp =
1169 : realloc(application->context_log_level_settings,
1170 : (++application->num_context_log_level_settings) *
1171 : sizeof(DltDaemonContextLogSettings));
1172 : application->context_log_level_settings = tmp;
1173 :
1174 : ct_settings =
1175 : &application->context_log_level_settings[application->num_context_log_level_settings - 1];
1176 : memcpy(ct_settings, settings, sizeof(DltDaemonContextLogSettings));
1177 : memcpy(ct_settings->ctid, ctid, DLT_ID_SIZE);
1178 : }
1179 : }
1180 : #endif
1181 :
1182 41 : if ((strncmp(daemon->ecuid, ecu, DLT_ID_SIZE) == 0) && (daemon->force_ll_ts)) {
1183 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
1184 : if (log_level > daemon->default_log_level && settings == NULL)
1185 : #else
1186 0 : if (log_level > daemon->default_log_level)
1187 : #endif
1188 : log_level = daemon->default_log_level;
1189 :
1190 0 : if (trace_status > daemon->default_trace_status)
1191 : trace_status = daemon->default_trace_status;
1192 :
1193 0 : dlt_vlog(LOG_NOTICE,
1194 : "Adapting ll_ts for context: %.4s:%.4s with %i %i\n",
1195 : apid,
1196 : ctid,
1197 : log_level,
1198 : trace_status);
1199 : }
1200 :
1201 : /* Store log level and trace status,
1202 : * if this is a new context, or
1203 : * if this is an old context and the runtime cfg was not loaded */
1204 41 : if ((new_context == 1) ||
1205 0 : ((new_context == 0) && (daemon->runtime_context_cfg_loaded == 0))) {
1206 41 : context->log_level = log_level;
1207 41 : context->trace_status = trace_status;
1208 : }
1209 :
1210 41 : context->log_level_pos = log_level_pos;
1211 41 : context->user_handle = user_handle;
1212 :
1213 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
1214 : DltTraceLoadSettings* tl_settings = dlt_find_runtime_trace_load_settings(
1215 : application->trace_load_settings,
1216 : application->trace_load_settings_count,
1217 : application->apid,
1218 : context->ctid);
1219 : if (tl_settings == NULL) {
1220 : dlt_vlog(LOG_WARNING, "failed to find trace load settings for application %s context %s\n",
1221 : application->apid, context->ctid);
1222 : } else {
1223 : context->trace_load_settings = tl_settings;
1224 : }
1225 : #endif
1226 :
1227 :
1228 : /* In case a context is loaded from runtime config file,
1229 : * the user_handle is 0 and we mark that context as predefined.
1230 : */
1231 41 : if (context->user_handle == 0)
1232 0 : context->predefined = true;
1233 : else
1234 41 : context->predefined = false;
1235 :
1236 : /* Sort */
1237 41 : if (new_context) {
1238 41 : qsort(user_list->contexts,
1239 41 : (size_t) user_list->num_contexts,
1240 : sizeof(DltDaemonContext),
1241 : dlt_daemon_cmp_apid_ctid);
1242 :
1243 : /* Find new position of context with apid, ctid */
1244 41 : context = dlt_daemon_context_find(daemon, apid, ctid, ecu, verbose);
1245 : }
1246 :
1247 : return context;
1248 : }
1249 :
1250 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
1251 : static void dlt_daemon_free_context_log_settings(
1252 : DltDaemonApplication *application,
1253 : DltDaemonContext *context)
1254 : {
1255 : DltDaemonContextLogSettings *ct_settings;
1256 : int i;
1257 : int skipped = 0;
1258 :
1259 : ct_settings = dlt_daemon_find_app_log_level_config(application, context->ctid);
1260 : if (ct_settings == NULL) {
1261 : return;
1262 : }
1263 :
1264 : /* move all data forward */
1265 : for (i = 0; i < application->num_context_log_level_settings; ++i) {
1266 : /* skip given context to delete it */
1267 : if (i + skipped < application->num_context_log_level_settings &&
1268 : strncmp(application->context_log_level_settings[i+skipped].ctid, context->ctid, DLT_ID_SIZE) == 0) {
1269 : ++skipped;
1270 : continue;
1271 : }
1272 :
1273 : memcpy(&application->context_log_level_settings[i-skipped],
1274 : &application->context_log_level_settings[i],
1275 : sizeof(DltDaemonContextLogSettings));
1276 : }
1277 :
1278 : application->num_context_log_level_settings -= skipped;
1279 :
1280 : /* if size is equal to zero, and ptr is not NULL, then realloc is equivalent to free(ptr) */
1281 : application->context_log_level_settings = realloc(application->context_log_level_settings,
1282 : sizeof(DltDaemonContextLogSettings) * (application->num_context_log_level_settings));
1283 :
1284 : }
1285 : #endif
1286 :
1287 37 : int dlt_daemon_context_del(DltDaemon *daemon,
1288 : DltDaemonContext *context,
1289 : char *ecu,
1290 : int verbose)
1291 : {
1292 : int pos;
1293 : DltDaemonApplication *application;
1294 : DltDaemonRegisteredUsers *user_list = NULL;
1295 :
1296 37 : PRINT_FUNCTION_VERBOSE(verbose);
1297 :
1298 37 : if ((daemon == NULL) || (context == NULL) || (ecu == NULL))
1299 : return -1;
1300 :
1301 37 : user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
1302 :
1303 37 : if (user_list == NULL)
1304 : return -1;
1305 :
1306 37 : if (user_list->num_contexts > 0) {
1307 37 : application = dlt_daemon_application_find(daemon, context->apid, ecu, verbose);
1308 :
1309 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
1310 : dlt_daemon_free_context_log_settings(application, context);
1311 : #endif
1312 : /* Free description of context to be deleted */
1313 37 : if (context->context_description) {
1314 37 : free(context->context_description);
1315 37 : context->context_description = NULL;
1316 : }
1317 :
1318 37 : pos = (int) (context - (user_list->contexts));
1319 :
1320 : /* move all contexts above pos to pos */
1321 37 : memmove(&(user_list->contexts[pos]),
1322 37 : &(user_list->contexts[pos + 1]),
1323 37 : sizeof(DltDaemonContext) * ((user_list->num_contexts - 1) - pos));
1324 :
1325 : /* Clear last context */
1326 37 : memset(&(user_list->contexts[user_list->num_contexts - 1]),
1327 : 0,
1328 : sizeof(DltDaemonContext));
1329 :
1330 37 : user_list->num_contexts--;
1331 :
1332 : /* Check if application [apid] is available */
1333 37 : if (application != NULL)
1334 37 : application->num_contexts--;
1335 : }
1336 :
1337 : return 0;
1338 : }
1339 :
1340 157 : DltDaemonContext *dlt_daemon_context_find(DltDaemon *daemon,
1341 : char *apid,
1342 : char *ctid,
1343 : char *ecu,
1344 : int verbose)
1345 : {
1346 : DltDaemonContext context;
1347 : DltDaemonRegisteredUsers *user_list = NULL;
1348 :
1349 157 : PRINT_FUNCTION_VERBOSE(verbose);
1350 :
1351 157 : if ((daemon == NULL) || (apid == NULL) || (apid[0] == '\0') ||
1352 157 : (ctid == NULL) || (ctid[0] == '\0') || (ecu == NULL))
1353 : return (DltDaemonContext *)NULL;
1354 :
1355 157 : user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
1356 :
1357 157 : if ((user_list == NULL) || (user_list->num_contexts == 0))
1358 : return (DltDaemonContext *)NULL;
1359 :
1360 : /* Check, if apid is smaller than smallest apid or greater than greatest apid */
1361 112 : if ((memcmp(apid, user_list->contexts[0].apid, DLT_ID_SIZE) < 0) ||
1362 112 : (memcmp(apid,
1363 112 : user_list->contexts[user_list->num_contexts - 1].apid,
1364 : DLT_ID_SIZE) > 0))
1365 : return (DltDaemonContext *)NULL;
1366 :
1367 112 : dlt_set_id(context.apid, apid);
1368 112 : dlt_set_id(context.ctid, ctid);
1369 :
1370 112 : return (DltDaemonContext *)bsearch(&context,
1371 112 : user_list->contexts,
1372 112 : (size_t) user_list->num_contexts,
1373 : sizeof(DltDaemonContext),
1374 : dlt_daemon_cmp_apid_ctid);
1375 : }
1376 :
1377 15 : int dlt_daemon_contexts_invalidate_fd(DltDaemon *daemon,
1378 : char *ecu,
1379 : int fd,
1380 : int verbose)
1381 : {
1382 : int i;
1383 : DltDaemonRegisteredUsers *user_list = NULL;
1384 :
1385 15 : PRINT_FUNCTION_VERBOSE(verbose);
1386 :
1387 15 : if ((daemon == NULL) || (ecu == NULL))
1388 : return -1;
1389 :
1390 15 : user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
1391 :
1392 15 : if (user_list != NULL) {
1393 39 : for (i = 0; i < user_list->num_contexts; i++)
1394 24 : if (user_list->contexts[i].user_handle == fd)
1395 0 : user_list->contexts[i].user_handle = DLT_FD_INIT;
1396 :
1397 : return 0;
1398 : }
1399 :
1400 : return -1;
1401 : }
1402 :
1403 10 : int dlt_daemon_contexts_clear(DltDaemon *daemon, char *ecu, int verbose)
1404 : {
1405 : int i;
1406 : DltDaemonRegisteredUsers *users = NULL;
1407 :
1408 10 : PRINT_FUNCTION_VERBOSE(verbose);
1409 :
1410 10 : if ((daemon == NULL) || (ecu == NULL))
1411 : return DLT_RETURN_WRONG_PARAMETER;
1412 :
1413 10 : users = dlt_daemon_find_users_list(daemon, ecu, verbose);
1414 :
1415 10 : if (users == NULL)
1416 : return DLT_RETURN_ERROR;
1417 :
1418 11 : for (i = 0; i < users->num_contexts; i++)
1419 1 : if (users->contexts[i].context_description != NULL) {
1420 1 : free(users->contexts[i].context_description);
1421 1 : users->contexts[i].context_description = NULL;
1422 : }
1423 :
1424 10 : if (users->contexts) {
1425 7 : free(users->contexts);
1426 7 : users->contexts = NULL;
1427 : }
1428 :
1429 11 : for (i = 0; i < users->num_applications; i++)
1430 1 : users->applications[i].num_contexts = 0;
1431 :
1432 10 : users->num_contexts = 0;
1433 :
1434 10 : return 0;
1435 : }
1436 :
1437 0 : int dlt_daemon_contexts_load(DltDaemon *daemon, const char *filename, int verbose)
1438 : {
1439 : FILE *fd;
1440 : ID4 apid, ctid;
1441 : char buf[DLT_DAEMON_COMMON_TEXTBUFSIZE];
1442 : char *ret;
1443 : char *pb;
1444 : int ll, ts;
1445 :
1446 0 : PRINT_FUNCTION_VERBOSE(verbose);
1447 :
1448 0 : if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0'))
1449 : return -1;
1450 :
1451 0 : fd = fopen(filename, "r");
1452 :
1453 0 : if (fd == NULL) {
1454 0 : dlt_vlog(LOG_WARNING,
1455 : "DLT runtime-context load, cannot open file %s: %s\n",
1456 : filename,
1457 0 : strerror(errno));
1458 :
1459 0 : return -1;
1460 : }
1461 :
1462 0 : while (!feof(fd)) {
1463 : /* Clear buf */
1464 : memset(buf, 0, sizeof(buf));
1465 :
1466 : /* Get line */
1467 : ret = fgets(buf, sizeof(buf), fd);
1468 :
1469 0 : if (NULL == ret) {
1470 : /* fgets always returns null pointer if the last byte of the file is a new line.
1471 : * We need to check here if there was an error or was it feof.*/
1472 0 : if (ferror(fd)) {
1473 0 : dlt_vlog(LOG_WARNING,
1474 : "%s fgets(buf,sizeof(buf),fd) returned NULL. %s\n",
1475 : __func__,
1476 0 : strerror(errno));
1477 0 : fclose(fd);
1478 0 : return -1;
1479 : }
1480 0 : else if (feof(fd))
1481 : {
1482 0 : fclose(fd);
1483 0 : return 0;
1484 : }
1485 : else {
1486 0 : dlt_vlog(LOG_WARNING,
1487 : "%s fgets(buf,sizeof(buf),fd) returned NULL. Unknown error.\n",
1488 : __func__);
1489 0 : fclose(fd);
1490 0 : return -1;
1491 : }
1492 : }
1493 :
1494 0 : if (strcmp(buf, "") != 0) {
1495 : /* Split line */
1496 0 : pb = strtok(buf, ":");
1497 :
1498 0 : if (pb != NULL) {
1499 0 : dlt_set_id(apid, pb);
1500 0 : pb = strtok(NULL, ":");
1501 :
1502 0 : if (pb != NULL) {
1503 0 : dlt_set_id(ctid, pb);
1504 0 : pb = strtok(NULL, ":");
1505 :
1506 0 : if (pb != NULL) {
1507 0 : sscanf(pb, "%d", &ll);
1508 0 : pb = strtok(NULL, ":");
1509 :
1510 0 : if (pb != NULL) {
1511 0 : sscanf(pb, "%d", &ts);
1512 0 : pb = strtok(NULL, ":");
1513 :
1514 0 : if (pb != NULL) {
1515 : /* pb contains now the description */
1516 :
1517 : /* log_level_pos, and user_handle are unknown at loading time */
1518 0 : if (dlt_daemon_context_add(daemon,
1519 : apid,
1520 : ctid,
1521 0 : (int8_t)ll,
1522 0 : (int8_t)ts,
1523 : 0,
1524 : 0,
1525 : pb,
1526 0 : daemon->ecuid,
1527 : verbose) == NULL) {
1528 0 : dlt_vlog(LOG_WARNING,
1529 : "%s dlt_daemon_context_add failed\n",
1530 : __func__);
1531 0 : fclose(fd);
1532 0 : return -1;
1533 : }
1534 : }
1535 : }
1536 : }
1537 : }
1538 : }
1539 : }
1540 : }
1541 :
1542 0 : fclose(fd);
1543 :
1544 0 : return 0;
1545 : }
1546 :
1547 0 : int dlt_daemon_contexts_save(DltDaemon *daemon, const char *filename, int verbose)
1548 : {
1549 : FILE *fd;
1550 : int i;
1551 :
1552 : char apid[DLT_ID_SIZE + 1], ctid[DLT_ID_SIZE + 1]; /* DLT_ID_SIZE+1, because the 0-termination is required here */
1553 : DltDaemonRegisteredUsers *user_list = NULL;
1554 :
1555 0 : PRINT_FUNCTION_VERBOSE(verbose);
1556 :
1557 0 : if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0'))
1558 : return -1;
1559 :
1560 0 : user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
1561 :
1562 0 : if (user_list == NULL)
1563 : return -1;
1564 :
1565 : memset(apid, 0, sizeof(apid));
1566 : memset(ctid, 0, sizeof(ctid));
1567 :
1568 0 : if ((user_list->contexts) && (user_list->num_contexts > 0)) {
1569 0 : fd = fopen(filename, "w");
1570 :
1571 0 : if (fd != NULL) {
1572 0 : for (i = 0; i < user_list->num_contexts; i++) {
1573 0 : dlt_set_id(apid, user_list->contexts[i].apid);
1574 0 : dlt_set_id(ctid, user_list->contexts[i].ctid);
1575 :
1576 0 : if ((user_list->contexts[i].context_description) &&
1577 0 : (user_list->contexts[i].context_description[0] != '\0'))
1578 0 : fprintf(fd, "%s:%s:%d:%d:%s:\n", apid, ctid,
1579 0 : (int)(user_list->contexts[i].log_level),
1580 0 : (int)(user_list->contexts[i].trace_status),
1581 : user_list->contexts[i].context_description);
1582 : else
1583 0 : fprintf(fd, "%s:%s:%d:%d::\n", apid, ctid,
1584 0 : (int)(user_list->contexts[i].log_level),
1585 0 : (int)(user_list->contexts[i].trace_status));
1586 : }
1587 :
1588 0 : fclose(fd);
1589 : }
1590 : else {
1591 0 : dlt_vlog(LOG_ERR,
1592 : "%s: Cannot open %s. No context information stored\n",
1593 : __func__,
1594 : filename);
1595 : }
1596 : }
1597 :
1598 : return 0;
1599 : }
1600 :
1601 0 : int dlt_daemon_configuration_save(DltDaemon *daemon, const char *filename, int verbose)
1602 : {
1603 : FILE *fd;
1604 :
1605 0 : PRINT_FUNCTION_VERBOSE(verbose);
1606 :
1607 0 : if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0'))
1608 : return -1;
1609 :
1610 0 : fd = fopen(filename, "w");
1611 :
1612 0 : if (fd != NULL) {
1613 : fprintf(fd, "# 0 = off, 1 = external, 2 = internal, 3 = both\n");
1614 0 : fprintf(fd, "LoggingMode = %d\n", daemon->mode);
1615 :
1616 0 : fclose(fd);
1617 : }
1618 :
1619 : return 0;
1620 : }
1621 :
1622 9 : int dlt_daemon_configuration_load(DltDaemon *daemon, const char *filename, int verbose)
1623 : {
1624 9 : if ((daemon == NULL) || (filename == NULL))
1625 : return -1;
1626 :
1627 : FILE *pFile;
1628 : char line[1024];
1629 : char token[1024];
1630 : char value[1024];
1631 : char *pch;
1632 :
1633 9 : PRINT_FUNCTION_VERBOSE(verbose);
1634 :
1635 9 : pFile = fopen (filename, "r");
1636 :
1637 9 : if (pFile != NULL) {
1638 : while (1) {
1639 : /* fetch line from configuration file */
1640 18 : if (fgets (line, 1024, pFile) != NULL) {
1641 9 : pch = strtok (line, " =\r\n");
1642 9 : token[0] = 0;
1643 9 : value[0] = 0;
1644 :
1645 18 : while (pch != NULL) {
1646 9 : if (strcmp(pch, "#") == 0)
1647 : break;
1648 :
1649 9 : if (token[0] == 0) {
1650 : strncpy(token, pch, sizeof(token) - 1);
1651 9 : token[sizeof(token) - 1] = 0;
1652 : }
1653 : else {
1654 : strncpy(value, pch, sizeof(value) - 1);
1655 0 : value[sizeof(value) - 1] = 0;
1656 0 : break;
1657 : }
1658 :
1659 9 : pch = strtok (NULL, " =\r\n");
1660 : }
1661 :
1662 9 : if (token[0] && value[0]) {
1663 : /* parse arguments here */
1664 0 : if (strcmp(token, "LoggingMode") == 0) {
1665 0 : daemon->mode = atoi(value);
1666 0 : dlt_vlog(LOG_INFO, "Runtime Option: %s=%d\n", token,
1667 : daemon->mode);
1668 : }
1669 : else {
1670 0 : dlt_vlog(LOG_WARNING, "Unknown option: %s=%s\n", token,
1671 : value);
1672 : }
1673 : }
1674 : }
1675 : else {
1676 : break;
1677 : }
1678 : }
1679 :
1680 9 : fclose (pFile);
1681 : }
1682 : else {
1683 0 : dlt_vlog(LOG_INFO, "Cannot open configuration file: %s\n", filename);
1684 : }
1685 :
1686 : return 0;
1687 : }
1688 :
1689 41 : int dlt_daemon_user_send_log_level(DltDaemon *daemon, DltDaemonContext *context, int verbose)
1690 : {
1691 : DltUserHeader userheader;
1692 : DltUserControlMsgLogLevel usercontext;
1693 : DltReturnValue ret;
1694 : DltDaemonApplication *app;
1695 :
1696 41 : PRINT_FUNCTION_VERBOSE(verbose);
1697 :
1698 41 : if ((daemon == NULL) || (context == NULL)) {
1699 0 : dlt_vlog(LOG_ERR, "NULL parameter in %s", __func__);
1700 0 : return -1;
1701 : }
1702 :
1703 41 : if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_LEVEL) < DLT_RETURN_OK) {
1704 0 : dlt_vlog(LOG_ERR, "Failed to set userheader in %s", __func__);
1705 0 : return -1;
1706 : }
1707 :
1708 41 : if ((context->storage_log_level != DLT_LOG_DEFAULT) &&
1709 34 : (daemon->maintain_logstorage_loglevel != DLT_MAINTAIN_LOGSTORAGE_LOGLEVEL_OFF))
1710 32 : usercontext.log_level = (uint8_t) (context->log_level >
1711 : context->storage_log_level ? context->log_level : context->storage_log_level);
1712 : else /* Storage log level is not updated (is DEFAULT) then no device is yet connected so ignore */
1713 9 : usercontext.log_level =
1714 9 : (uint8_t) ((context->log_level == DLT_LOG_DEFAULT) ? daemon->default_log_level : context->log_level);
1715 :
1716 41 : usercontext.trace_status =
1717 41 : (uint8_t) ((context->trace_status == DLT_TRACE_STATUS_DEFAULT) ? daemon->default_trace_status : context->trace_status);
1718 :
1719 41 : usercontext.log_level_pos = context->log_level_pos;
1720 :
1721 41 : dlt_vlog(LOG_NOTICE, "Send log-level to context: %.4s:%.4s [%i -> %i] [%i -> %i]\n",
1722 41 : context->apid,
1723 41 : context->ctid,
1724 41 : context->log_level,
1725 41 : usercontext.log_level,
1726 : context->trace_status,
1727 : usercontext.trace_status);
1728 :
1729 : /* log to FIFO */
1730 41 : errno = 0;
1731 41 : ret = dlt_user_log_out2_with_timeout(context->user_handle,
1732 : &(userheader), sizeof(DltUserHeader),
1733 : &(usercontext), sizeof(DltUserControlMsgLogLevel));
1734 :
1735 41 : if (ret < DLT_RETURN_OK) {
1736 0 : dlt_vlog(LOG_ERR, "Failed to send data to application in %s: %s",
1737 : __func__,
1738 0 : errno != 0 ? strerror(errno) : "Unknown error");
1739 :
1740 0 : if (errno == EPIPE || errno == EBADF) {
1741 0 : app = dlt_daemon_application_find(daemon, context->apid, daemon->ecuid, verbose);
1742 0 : if (app != NULL)
1743 0 : dlt_daemon_application_reset_user_handle(daemon, app, verbose);
1744 : }
1745 : }
1746 :
1747 41 : return (ret == DLT_RETURN_OK) ? DLT_RETURN_OK : DLT_RETURN_ERROR;
1748 : }
1749 :
1750 9 : int dlt_daemon_user_send_log_state(DltDaemon *daemon, DltDaemonApplication *app, int verbose)
1751 : {
1752 : DltUserHeader userheader;
1753 : DltUserControlMsgLogState logstate;
1754 : DltReturnValue ret;
1755 :
1756 9 : PRINT_FUNCTION_VERBOSE(verbose);
1757 :
1758 9 : if ((daemon == NULL) || (app == NULL))
1759 : return -1;
1760 :
1761 9 : if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_STATE) < DLT_RETURN_OK)
1762 : return -1;
1763 :
1764 9 : logstate.log_state = daemon->connectionState;
1765 :
1766 : /* log to FIFO */
1767 9 : ret = dlt_user_log_out2_with_timeout(app->user_handle,
1768 : &(userheader), sizeof(DltUserHeader),
1769 : &(logstate), sizeof(DltUserControlMsgLogState));
1770 :
1771 9 : if (ret < DLT_RETURN_OK) {
1772 0 : if (errno == EPIPE || errno == EBADF)
1773 0 : dlt_daemon_application_reset_user_handle(daemon, app, verbose);
1774 : }
1775 :
1776 9 : return (ret == DLT_RETURN_OK) ? DLT_RETURN_OK : DLT_RETURN_ERROR;
1777 : }
1778 :
1779 0 : void dlt_daemon_control_reset_to_factory_default(DltDaemon *daemon,
1780 : const char *filename,
1781 : const char *filename1,
1782 : int InitialContextLogLevel,
1783 : int InitialContextTraceStatus,
1784 : int InitialEnforceLlTsStatus,
1785 : int verbose)
1786 : {
1787 : FILE *fd;
1788 :
1789 0 : PRINT_FUNCTION_VERBOSE(verbose);
1790 :
1791 0 : if ((daemon == NULL) || (filename == NULL) || (filename1 == NULL)) {
1792 0 : dlt_log(LOG_WARNING, "Wrong parameter: Null pointer\n");
1793 0 : return;
1794 : }
1795 :
1796 0 : if ((filename[0] == '\0') || (filename1[0] == '\0')) {
1797 0 : dlt_log(LOG_WARNING, "Wrong parameter: Empty string\n");
1798 0 : return;
1799 : }
1800 :
1801 : /* Check for runtime cfg file and delete it, if available */
1802 0 : fd = fopen(filename, "r");
1803 :
1804 0 : if (fd != NULL) {
1805 : /* Close and delete file */
1806 0 : fclose(fd);
1807 0 : if (unlink(filename) != 0) {
1808 0 : dlt_vlog(LOG_WARNING, "%s: unlink() failed: %s\n",
1809 0 : __func__, strerror(errno));
1810 : }
1811 : }
1812 :
1813 0 : fd = fopen(filename1, "r");
1814 :
1815 0 : if (fd != NULL) {
1816 : /* Close and delete file */
1817 0 : fclose(fd);
1818 0 : if (unlink(filename1) != 0) {
1819 0 : dlt_vlog(LOG_WARNING, "%s: unlink() failed: %s\n",
1820 0 : __func__, strerror(errno));
1821 : }
1822 : }
1823 :
1824 0 : daemon->default_log_level = (int8_t) InitialContextLogLevel;
1825 0 : daemon->default_trace_status = (int8_t) InitialContextTraceStatus;
1826 0 : daemon->force_ll_ts = (int8_t) InitialEnforceLlTsStatus;
1827 :
1828 : /* Reset all other things (log level, trace status, etc.
1829 : * to default values */
1830 :
1831 : /* Inform user libraries about changed default log level/trace status */
1832 0 : dlt_daemon_user_send_default_update(daemon, verbose);
1833 : }
1834 :
1835 0 : void dlt_daemon_user_send_default_update(DltDaemon *daemon, int verbose)
1836 : {
1837 : int32_t count;
1838 : DltDaemonContext *context;
1839 : DltDaemonRegisteredUsers *user_list = NULL;
1840 :
1841 0 : PRINT_FUNCTION_VERBOSE(verbose);
1842 :
1843 0 : if (daemon == NULL) {
1844 0 : dlt_log(LOG_WARNING, "Wrong parameter: Null pointer\n");
1845 0 : return;
1846 : }
1847 :
1848 0 : user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
1849 :
1850 0 : if (user_list == NULL)
1851 : return;
1852 :
1853 0 : for (count = 0; count < user_list->num_contexts; count++) {
1854 0 : context = &(user_list->contexts[count]);
1855 :
1856 0 : if (context != NULL) {
1857 0 : if ((context->log_level == DLT_LOG_DEFAULT) ||
1858 0 : (context->trace_status == DLT_TRACE_STATUS_DEFAULT)) {
1859 0 : if (context->user_handle >= DLT_FD_MINIMUM)
1860 0 : if (dlt_daemon_user_send_log_level(daemon,
1861 : context,
1862 : verbose) == -1)
1863 0 : dlt_vlog(LOG_WARNING, "Cannot update default of %.4s:%.4s\n", context->apid, context->ctid);
1864 : }
1865 : }
1866 : }
1867 : }
1868 :
1869 0 : void dlt_daemon_user_send_all_log_level_update(DltDaemon *daemon,
1870 : int enforce_context_ll_and_ts,
1871 : int8_t context_log_level,
1872 : int8_t log_level,
1873 : int verbose)
1874 : {
1875 : int32_t count = 0;
1876 : DltDaemonContext *context = NULL;
1877 : DltDaemonRegisteredUsers *user_list = NULL;
1878 :
1879 0 : PRINT_FUNCTION_VERBOSE(verbose);
1880 :
1881 0 : if (daemon == NULL)
1882 : return;
1883 :
1884 0 : user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
1885 :
1886 0 : if (user_list == NULL)
1887 : return;
1888 :
1889 0 : for (count = 0; count < user_list->num_contexts; count++) {
1890 0 : context = &(user_list->contexts[count]);
1891 :
1892 0 : if (context) {
1893 0 : if (context->user_handle >= DLT_FD_MINIMUM) {
1894 0 : context->log_level = log_level;
1895 :
1896 0 : if (enforce_context_ll_and_ts) {
1897 : #ifdef DLT_LOG_LEVEL_APP_CONFIG
1898 : DltDaemonContextLogSettings *settings =
1899 : dlt_daemon_find_configured_app_id_ctx_id_settings(
1900 : daemon, context->apid, context->ctid);
1901 : if (settings != NULL) {
1902 : if (log_level > settings->log_level) {
1903 : context->log_level = settings->log_level;
1904 : }
1905 : } else
1906 : #endif
1907 0 : if (log_level > context_log_level) {
1908 0 : context->log_level = (int8_t)context_log_level;
1909 : }
1910 : }
1911 :
1912 0 : if (dlt_daemon_user_send_log_level(daemon,
1913 : context,
1914 : verbose) == -1)
1915 0 : dlt_vlog(LOG_WARNING,
1916 : "Cannot send log level %.4s:%.4s -> %i\n",
1917 0 : context->apid,
1918 0 : context->ctid,
1919 0 : context->log_level);
1920 : }
1921 : }
1922 : }
1923 : }
1924 :
1925 0 : void dlt_daemon_user_send_all_trace_status_update(DltDaemon *daemon, int8_t trace_status, int verbose)
1926 : {
1927 : int32_t count = 0;
1928 : DltDaemonContext *context = NULL;
1929 : DltDaemonRegisteredUsers *user_list = NULL;
1930 :
1931 0 : PRINT_FUNCTION_VERBOSE(verbose);
1932 :
1933 0 : if (daemon == NULL)
1934 : return;
1935 :
1936 0 : user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
1937 :
1938 0 : if (user_list == NULL)
1939 : return;
1940 :
1941 0 : dlt_vlog(LOG_NOTICE, "All trace status is updated -> %i\n", trace_status);
1942 :
1943 0 : for (count = 0; count < user_list->num_contexts; count++) {
1944 0 : context = &(user_list->contexts[count]);
1945 :
1946 0 : if (context) {
1947 0 : if (context->user_handle >= DLT_FD_MINIMUM) {
1948 0 : context->trace_status = trace_status;
1949 :
1950 0 : if (dlt_daemon_user_send_log_level(daemon, context, verbose) == -1)
1951 0 : dlt_vlog(LOG_WARNING,
1952 : "Cannot send trace status %.4s:%.4s -> %i\n",
1953 0 : context->apid,
1954 0 : context->ctid,
1955 0 : context->trace_status);
1956 : }
1957 : }
1958 : }
1959 : }
1960 :
1961 5 : void dlt_daemon_user_send_all_log_state(DltDaemon *daemon, int verbose)
1962 : {
1963 : int32_t count;
1964 : DltDaemonApplication *app;
1965 : DltDaemonRegisteredUsers *user_list = NULL;
1966 :
1967 5 : PRINT_FUNCTION_VERBOSE(verbose);
1968 :
1969 5 : if (daemon == NULL) {
1970 0 : dlt_log(LOG_WARNING, "Wrong parameter: Null pointer\n");
1971 0 : return;
1972 : }
1973 :
1974 5 : user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
1975 :
1976 5 : if (user_list == NULL)
1977 : return;
1978 :
1979 7 : for (count = 0; count < user_list->num_applications; count++) {
1980 2 : app = &(user_list->applications[count]);
1981 :
1982 2 : if (app != NULL) {
1983 2 : if (app->user_handle >= DLT_FD_MINIMUM)
1984 2 : if (dlt_daemon_user_send_log_state(daemon, app, verbose) == -1)
1985 0 : dlt_vlog(LOG_WARNING, "Cannot send log state to Apid: %.4s, PID: %d\n", app->apid, app->pid);
1986 : }
1987 : }
1988 : }
1989 :
1990 16 : void dlt_daemon_change_state(DltDaemon *daemon, DltDaemonState newState)
1991 : {
1992 16 : switch (newState) {
1993 0 : case DLT_DAEMON_STATE_INIT:
1994 0 : dlt_log(LOG_INFO, "Switched to init state.\n");
1995 0 : daemon->state = DLT_DAEMON_STATE_INIT;
1996 0 : break;
1997 12 : case DLT_DAEMON_STATE_BUFFER:
1998 12 : dlt_log(LOG_INFO, "Switched to buffer state for socket connections.\n");
1999 12 : daemon->state = DLT_DAEMON_STATE_BUFFER;
2000 12 : break;
2001 0 : case DLT_DAEMON_STATE_BUFFER_FULL:
2002 0 : dlt_log(LOG_INFO, "Switched to buffer full state.\n");
2003 0 : daemon->state = DLT_DAEMON_STATE_BUFFER_FULL;
2004 0 : break;
2005 2 : case DLT_DAEMON_STATE_SEND_BUFFER:
2006 2 : dlt_log(LOG_INFO, "Switched to send buffer state for socket connections.\n");
2007 2 : daemon->state = DLT_DAEMON_STATE_SEND_BUFFER;
2008 2 : break;
2009 2 : case DLT_DAEMON_STATE_SEND_DIRECT:
2010 2 : dlt_log(LOG_INFO, "Switched to send direct state.\n");
2011 2 : daemon->state = DLT_DAEMON_STATE_SEND_DIRECT;
2012 2 : break;
2013 : }
2014 16 : }
2015 :
2016 : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
2017 : bool dlt_daemon_trigger_systemd_watchdog_if_necessary(DltDaemon *daemon) {
2018 : if (daemon->watchdog_trigger_interval == 0) {
2019 : return false;
2020 : }
2021 :
2022 : const unsigned int uptime_seconds = dlt_uptime() / 10000;
2023 : const unsigned int seconds_since_last_trigger = uptime_seconds - daemon->watchdog_last_trigger_time;
2024 : if (seconds_since_last_trigger < daemon->watchdog_trigger_interval) {
2025 : return false;
2026 : }
2027 : if (sd_notify(0, "WATCHDOG=1") < 0) {
2028 : dlt_vlog(LOG_WARNING, "%s: Could not reset systemd watchdog\n", __func__);
2029 : return false;
2030 : }
2031 : else
2032 : daemon->watchdog_last_trigger_time = uptime_seconds;
2033 :
2034 : return true;
2035 : }
2036 :
2037 : #endif
2038 :
2039 : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
2040 : int dlt_daemon_user_send_trace_load_config(DltDaemon *const daemon, DltDaemonApplication *app, const int verbose)
2041 : {
2042 : DltUserHeader userheader;
2043 : DltUserControlMsgTraceSettingMsg* trace_load_settings_user_msg;
2044 : uint32_t trace_load_settings_count;
2045 : DltReturnValue ret;
2046 :
2047 :
2048 : PRINT_FUNCTION_VERBOSE(verbose);
2049 :
2050 : if ((daemon == NULL) || (app == NULL)) return -1;
2051 :
2052 : if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_TRACE_LOAD) < DLT_RETURN_OK) return -1;
2053 :
2054 : DltTraceLoadSettings* app_settings = app->trace_load_settings;
2055 :
2056 : if (app_settings != NULL) {
2057 : trace_load_settings_count = app->trace_load_settings_count;
2058 : trace_load_settings_user_msg = malloc(sizeof(DltUserControlMsgTraceSettingMsg) * trace_load_settings_count);
2059 : for (uint32_t i = 0U; i < trace_load_settings_count; i++) {
2060 : // App id is not transmitted as the user library only
2061 : // has one application ID
2062 : memcpy(trace_load_settings_user_msg[i].ctid, app_settings[i].ctid, DLT_ID_SIZE);
2063 : trace_load_settings_user_msg[i].soft_limit = app_settings[i].soft_limit;
2064 : trace_load_settings_user_msg[i].hard_limit = app_settings[i].hard_limit;
2065 :
2066 : if (app_settings[i].ctid[0] == '\0') {
2067 : dlt_vlog(LOG_NOTICE, "Sending trace load config to app %.4s, soft limit %u, hard limit %u\n",
2068 : app->apid,
2069 : app_settings[i].soft_limit,
2070 : app_settings[i].hard_limit);
2071 : } else {
2072 : dlt_vlog(LOG_NOTICE, "Sending trace load config to app %.4s, ctid %.4s, soft limit %u, hard limit %u\n",
2073 : app->apid,
2074 : app_settings[i].ctid,
2075 : app_settings[i].soft_limit,
2076 : app_settings[i].hard_limit);
2077 : }
2078 :
2079 : }
2080 : }
2081 : else {
2082 : dlt_vlog(LOG_INFO,
2083 : "No trace load settings for application %s, setting daemon defaults.\n", app->apid);
2084 :
2085 : trace_load_settings_count = 1;
2086 : trace_load_settings_user_msg = malloc(sizeof(DltUserControlMsgTraceSettingMsg));
2087 :
2088 : memset(trace_load_settings_user_msg, 0, sizeof(DltTraceLoadSettings));
2089 : trace_load_settings_user_msg[0].soft_limit = DLT_TRACE_LOAD_DAEMON_SOFT_LIMIT_DEFAULT;
2090 : trace_load_settings_user_msg[0].hard_limit = DLT_TRACE_LOAD_DAEMON_HARD_LIMIT_DEFAULT;
2091 : }
2092 :
2093 : /* log to FIFO */
2094 : ret = dlt_user_log_out3_with_timeout(app->user_handle,
2095 : &(userheader), sizeof(DltUserHeader),
2096 : &(trace_load_settings_count), sizeof(uint32_t),
2097 : trace_load_settings_user_msg, sizeof(DltUserControlMsgTraceSettingMsg) * trace_load_settings_count);
2098 :
2099 : if (ret < DLT_RETURN_OK) {
2100 : if (errno == EPIPE || errno == EBADF)
2101 : dlt_daemon_application_reset_user_handle(daemon, app, verbose);
2102 : }
2103 :
2104 : free(trace_load_settings_user_msg);
2105 :
2106 : return ret;
2107 : }
2108 : #endif
|