LCOV - code coverage report
Current view: top level - daemon - dlt-daemon.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 52.9 % 1205 637
Test Date: 2025-12-12 09:13:23 Functions: 74.4 % 43 32

            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
      18              :  * Alexander Wenzel <alexander.aw.wenzel@bmw.de>
      19              :  * Markus Klein <Markus.Klein@esk.fraunhofer.de>
      20              :  * Mikko Rapeli <mikko.rapeli@bmw.de>
      21              :  *
      22              :  * \copyright Copyright © 2011-2015 BMW AG. \n
      23              :  * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
      24              :  *
      25              :  * \file dlt-daemon.c
      26              :  */
      27              : 
      28              : #include <netdb.h>
      29              : #include <ctype.h>
      30              : #include <stdio.h>      /* for printf() and fprintf() */
      31              : #include <sys/socket.h> /* for socket(), connect(), (), and recv() */
      32              : #include <sys/un.h>
      33              : #include <arpa/inet.h>  /* for sockaddr_in and inet_addr() */
      34              : #include <stdlib.h>     /* for atoi() and exit() */
      35              : #include <string.h>     /* for memset() */
      36              : #include <unistd.h>     /* for close() and access */
      37              : #include <fcntl.h>
      38              : #include <signal.h>
      39              : #include <syslog.h>
      40              : #include <errno.h>
      41              : #include <pthread.h>
      42              : #include <grp.h>
      43              : 
      44              : #ifdef linux
      45              : #   include <sys/timerfd.h>
      46              : #endif
      47              : #include <sys/stat.h>
      48              : #include <sys/time.h>
      49              : #include <libgen.h>
      50              : 
      51              : #if defined(linux) && defined(__NR_statx)
      52              : #   include <linux/stat.h>
      53              : #endif
      54              : 
      55              : #ifdef DLT_DAEMON_VSOCK_IPC_ENABLE
      56              : #   ifdef linux
      57              : #       include <linux/vm_sockets.h>
      58              : #   endif
      59              : #   ifdef __QNX__
      60              : #       include <vm_sockets.h>
      61              : #   endif
      62              : #endif
      63              : 
      64              : #include <getopt.h>
      65              : #ifndef CONFIGURATION_FILES_DIR
      66              : #define CONFIGURATION_FILES_DIR "/etc"
      67              : #endif
      68              : #ifndef DLT_USER_IPC_PATH
      69              : #define DLT_USER_IPC_PATH "/tmp"
      70              : #endif
      71              : 
      72              : #include <getopt.h>
      73              : #ifndef CONFIGURATION_FILES_DIR
      74              : #define CONFIGURATION_FILES_DIR "/etc"
      75              : #endif
      76              : #ifndef DLT_USER_IPC_PATH
      77              : #define DLT_USER_IPC_PATH "/tmp"
      78              : #endif
      79              : 
      80              : #include "dlt_types.h"
      81              : #include "dlt-daemon.h"
      82              : #include "dlt-daemon_cfg.h"
      83              : #include "dlt_daemon_common_cfg.h"
      84              : 
      85              : #include "dlt_daemon_socket.h"
      86              : #include "dlt_daemon_unix_socket.h"
      87              : #include "dlt_daemon_serial.h"
      88              : 
      89              : #include "dlt_daemon_client.h"
      90              : #include "dlt_daemon_connection.h"
      91              : #include "dlt_daemon_event_handler.h"
      92              : #include "dlt_daemon_offline_logstorage.h"
      93              : #include "dlt_gateway.h"
      94              : 
      95              : #ifdef UDP_CONNECTION_SUPPORT
      96              : #   include "dlt_daemon_udp_socket.h"
      97              : #endif
      98              : #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) || defined(DLT_SYSTEMD_ENABLE)
      99              : #   include "sd-daemon.h"
     100              : #endif
     101              : 
     102              : /**
     103              :  * \defgroup daemon DLT Daemon
     104              :  * \addtogroup daemon
     105              :  \{
     106              :  */
     107              : 
     108              : #define DLT_DAEMON_APP_ID "DLTD"
     109              : #define DLT_DAEMON_CTX_ID "INTM"
     110              : 
     111              : 
     112              : static int dlt_daemon_log_internal(DltDaemon *daemon,
     113              :                                    DltDaemonLocal *daemon_local, char *str,
     114              :                                    DltLogLevelType level, const char *app_id,
     115              :                                    const char *ctx_id, int verbose);
     116              : 
     117              : static int dlt_daemon_check_numeric_setting(char *token,
     118              :                                             char *value,
     119              :                                             unsigned long *data);
     120              : 
     121              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
     122              : 
     123              : struct DltTraceLoadLogParams {
     124              :     DltDaemon *daemon;
     125              :     DltDaemonLocal *daemon_local;
     126              :     int verbose;
     127              :     char *app_id;
     128              : };
     129              : 
     130              : static DltReturnValue dlt_daemon_output_internal_msg(DltLogLevelType loglevel, const char *text, void *params);
     131              : static void dlt_trace_load_free(DltDaemon* daemon);
     132              : 
     133              : pthread_rwlock_t trace_load_rw_lock;
     134              : #endif
     135              : 
     136              : /* used in main event loop and signal handler */
     137              : int g_exit = 0;
     138              : 
     139              : int g_signo = 0;
     140              : 
     141              : /* used for value from conf file */
     142              : static int value_length = 1024;
     143              : 
     144              : static char dlt_timer_conn_types[DLT_TIMER_UNKNOWN + 1] = {
     145              :     [DLT_TIMER_PACKET] = DLT_CONNECTION_ONE_S_TIMER,
     146              :     [DLT_TIMER_ECU] = DLT_CONNECTION_SIXTY_S_TIMER,
     147              : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
     148              :     [DLT_TIMER_SYSTEMD] = DLT_CONNECTION_SYSTEMD_TIMER,
     149              : #endif
     150              :     [DLT_TIMER_GATEWAY] = DLT_CONNECTION_GATEWAY_TIMER,
     151              :     [DLT_TIMER_UNKNOWN] = DLT_CONNECTION_TYPE_MAX
     152              : };
     153              : 
     154              : static char dlt_timer_names[DLT_TIMER_UNKNOWN + 1][32] = {
     155              :     [DLT_TIMER_PACKET] = "Timing packet",
     156              :     [DLT_TIMER_ECU] = "ECU version",
     157              : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
     158              :     [DLT_TIMER_SYSTEMD] = "Systemd watchdog",
     159              : #endif
     160              :     [DLT_TIMER_GATEWAY] = "Gateway",
     161              :     [DLT_TIMER_UNKNOWN] = "Unknown timer"
     162              : };
     163              : 
     164              : #ifdef __QNX__
     165              : static int dlt_timer_pipes[DLT_TIMER_UNKNOWN][2] = {
     166              :     /* [timer_id] = {read_pipe, write_pipe} */
     167              :     [DLT_TIMER_PACKET] = {DLT_FD_INIT, DLT_FD_INIT},
     168              :     [DLT_TIMER_ECU] = {DLT_FD_INIT, DLT_FD_INIT},
     169              : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
     170              :     [DLT_TIMER_SYSTEMD] = {DLT_FD_INIT, DLT_FD_INIT},
     171              : #endif
     172              :     [DLT_TIMER_GATEWAY] = {DLT_FD_INIT, DLT_FD_INIT}
     173              : };
     174              : 
     175              : static pthread_t timer_threads[DLT_TIMER_UNKNOWN] = {
     176              :     [DLT_TIMER_PACKET] = 0,
     177              :     [DLT_TIMER_ECU] = 0,
     178              : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
     179              :     [DLT_TIMER_SYSTEMD] = 0,
     180              : #endif
     181              :     [DLT_TIMER_GATEWAY] = 0
     182              : };
     183              : 
     184              : static DltDaemonPeriodicData *timer_data[DLT_TIMER_UNKNOWN] = {
     185              :     [DLT_TIMER_PACKET] = NULL,
     186              :     [DLT_TIMER_ECU] = NULL,
     187              : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
     188              :     [DLT_TIMER_SYSTEMD] = NULL,
     189              : #endif
     190              :     [DLT_TIMER_GATEWAY] = NULL
     191              : };
     192              : 
     193              : void close_pipes(int fds[2])
     194              : {
     195              :     if (fds[0] > 0) {
     196              :         close(fds[0]);
     197              :         fds[0] = DLT_FD_INIT;
     198              :     }
     199              : 
     200              :     if (fds[1] > 0) {
     201              :         close(fds[1]);
     202              :         fds[1] = DLT_FD_INIT;
     203              :     }
     204              : }
     205              : 
     206              : #endif // __QNX__
     207              : 
     208              : /**
     209              :  * Print usage information of tool.
     210              :  */
     211            0 : void usage()
     212              : {
     213              :     char version[DLT_DAEMON_TEXTBUFSIZE];
     214            0 :     dlt_get_version(version, DLT_DAEMON_TEXTBUFSIZE);
     215              : 
     216              :     /*printf("DLT logging daemon %s %s\n", _DLT_PACKAGE_VERSION, _DLT_PACKAGE_VERSION_STATE); */
     217              :     /*printf("Compile options: %s %s %s %s",_DLT_SYSTEMD_ENABLE, _DLT_SYSTEMD_WATCHDOG_ENABLE, _DLT_TEST_ENABLE, _DLT_SHM_ENABLE); */
     218              :     printf("%s", version);
     219              :     printf("Usage: dlt-daemon [options]\n");
     220              :     printf("Options:\n");
     221              :     printf("  -d            Daemonize\n");
     222              :     printf("  -h            Usage\n");
     223              :     printf("  -c filename   DLT daemon configuration file (Default: %s/dlt.conf)\n", CONFIGURATION_FILES_DIR);
     224              : 
     225              : #ifdef DLT_DAEMON_USE_FIFO_IPC
     226              :     printf("  -t directory  Directory for local fifo and user-pipes (Default: /tmp)\n");
     227              :     printf("                (Applications wanting to connect to a daemon using a\n");
     228              :     printf("                custom directory need to be started with the environment \n");
     229              :     printf("                variable DLT_PIPE_DIR set appropriately)\n");
     230              : #endif
     231              : 
     232              : #ifdef DLT_SHM_ENABLE
     233              :     printf("  -s filename   The file name to create the share memory (Default: /dlt-shm)\n");
     234              :     printf("                (Applications wanting to connect to a daemon using a\n");
     235              :     printf("                custom shm name need to be started with the environment \n");
     236              :     printf("                variable DLT_SHM_NAME set appropriately)\n");
     237              : #endif
     238              :     printf("  -p port       port to monitor for incoming requests (Default: 3490)\n");
     239              :     printf("                (Applications wanting to connect to a daemon using a custom\n");
     240              :     printf("                port need to be started with the environment variable\n");
     241              :     printf("                DLT_DAEMON_TCP_PORT set appropriately)\n");
     242              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
     243              :     printf("  -a filename   The filename for load default app id log levels (Default: " CONFIGURATION_FILES_DIR "/dlt-log-levels.conf)\n");
     244              : #endif
     245              : 
     246              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
     247              :     printf("  -l filename   The filename for load limits (Default: " CONFIGURATION_FILES_DIR "/dlt-trace-load.conf)\n");
     248              : #endif
     249              : 
     250              : #
     251            0 : } /* usage() */
     252              : 
     253              : /**
     254              :  * Option handling
     255              :  */
     256            9 : int option_handling(DltDaemonLocal *daemon_local, int argc, char *argv[])
     257              : {
     258              :     int c;
     259              :     char options[255];
     260              :     memset(options, 0, sizeof options);
     261              :     const char *const default_options = "hdc:t:p:";
     262              :     strcpy(options, default_options);
     263              : 
     264            9 :     if (daemon_local == 0) {
     265            0 :         fprintf (stderr, "Invalid parameter passed to option_handling()\n");
     266            0 :         return -1;
     267              :     }
     268              : 
     269              :     /* Initialize flags */
     270              :     memset(daemon_local, 0, sizeof(DltDaemonLocal));
     271              : 
     272              :     /* default values */
     273            9 :     daemon_local->flags.port = DLT_DAEMON_TCP_PORT;
     274              : 
     275              : #ifdef DLT_DAEMON_USE_FIFO_IPC
     276            9 :     dlt_log_set_fifo_basedir(DLT_USER_IPC_PATH);
     277              : #endif
     278              : 
     279              : #ifdef DLT_SHM_ENABLE
     280              :     strncpy(dltShmName, "/dlt-shm", NAME_MAX);
     281              : #endif
     282              : 
     283            9 :     opterr = 0;
     284              : 
     285              : #ifdef DLT_SHM_ENABLE
     286              :     strcpy(options + strlen(options), "s:");
     287              : #endif
     288              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
     289              :     strcpy(options + strlen(options), "a:");
     290              : #endif
     291              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
     292              :     strcpy(options + strlen(options), "l:");
     293              : #endif
     294           20 :     while ((c = getopt(argc, argv, options)) != -1)
     295           11 :         switch (c) {
     296            2 :         case 'd':
     297              :         {
     298            2 :             daemon_local->flags.dflag = 1;
     299            2 :             break;
     300              :         }
     301            8 :         case 'c':
     302              :         {
     303            8 :             strncpy(daemon_local->flags.cvalue, optarg, NAME_MAX);
     304              :             break;
     305              :         }
     306              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
     307              :         case 'a':
     308              :         {
     309              :             strncpy(daemon_local->flags.avalue, optarg, NAME_MAX);
     310              :             break;
     311              :         }
     312              : #endif
     313              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
     314              :         case 'l':
     315              :         {
     316              :             strncpy(daemon_local->flags.lvalue, optarg, NAME_MAX);
     317              :             break;
     318              :         }
     319              : #endif
     320              : #ifdef DLT_DAEMON_USE_FIFO_IPC
     321            0 :         case 't':
     322              :         {
     323            0 :             dlt_log_set_fifo_basedir(optarg);
     324            0 :             break;
     325              :         }
     326              : #endif
     327              : 
     328              : #ifdef DLT_SHM_ENABLE
     329              :         case 's':
     330              :         {
     331              :             strncpy(dltShmName, optarg, NAME_MAX);
     332              :             break;
     333              :         }
     334              : #endif
     335            1 :         case 'p':
     336              :         {
     337            1 :             daemon_local->flags.port = (unsigned int) atoi(optarg);
     338              : 
     339            1 :             if (daemon_local->flags.port == 0) {
     340            0 :                 fprintf (stderr, "Invalid port `%s' specified.\n", optarg);
     341            0 :                 return -1;
     342              :             }
     343              : 
     344              :             break;
     345              :         }
     346            0 :         case 'h':
     347              :         {
     348            0 :             usage();
     349            0 :             return -2; /* return no error */
     350              :         }
     351              : 
     352            0 :         case '?':
     353              :         {
     354            0 :             if ((optopt == 'c') || (optopt == 't') || (optopt == 'p')
     355              :     #ifdef DLT_LOG_LEVEL_APP_CONFIG
     356              :                   || (optopt == 'a')
     357              :     #endif
     358              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
     359              :                 || (optopt == 'l')
     360              : #endif
     361              :           )
     362            0 :                 fprintf (stderr, "Option -%c requires an argument.\n", optopt);
     363            0 :             else if (isprint (optopt))
     364            0 :                 fprintf (stderr, "Unknown option `-%c'.\n", optopt);
     365              :             else
     366            0 :                 fprintf (stderr, "Unknown option character `\\x%x'.\n", (uint32_t)optopt);
     367              : 
     368              :             /* unknown or wrong option used, show usage information and terminate */
     369            0 :             usage();
     370            0 :             return -1;
     371              :         }
     372            0 :         default:
     373              :         {
     374            0 :             fprintf (stderr, "Invalid option, this should never occur!\n");
     375            0 :             return -1;
     376              :         }
     377              :         }
     378              : 
     379              :     /* switch() */
     380              : 
     381              : #ifdef DLT_DAEMON_USE_FIFO_IPC
     382              :     int ret;
     383            9 :     size_t base_dir_len = strlen(dltFifoBaseDir);
     384              : 
     385              :     /* Check if base directory path is too long to append suffixes */
     386            9 :     if (base_dir_len > DLT_PATH_MAX - 10) { /* 10 for "/dltpipes\0" */
     387            0 :         dlt_log(LOG_ERR, "FIFO base directory path too long!\n");
     388            0 :         return -1;
     389              :     }
     390              : 
     391            9 :     ret = snprintf(daemon_local->flags.userPipesDir, DLT_PATH_MAX,
     392              :                     "%s/dltpipes", dltFifoBaseDir);
     393            9 :     if (ret < 0 || ret >= DLT_PATH_MAX) {
     394            0 :         dlt_log(LOG_ERR, "Failed to construct userPipesDir path!\n");
     395            0 :         return -1;
     396              :     }
     397              : 
     398            9 :     ret = snprintf(daemon_local->flags.daemonFifoName, DLT_PATH_MAX,
     399              :                     "%s/dlt", dltFifoBaseDir);
     400            9 :     if (ret < 0 || ret >= DLT_PATH_MAX) {
     401            0 :         dlt_log(LOG_ERR, "Failed to construct daemonFifoName path!\n");
     402            0 :         return -1;
     403              :     }
     404              : #endif
     405              : 
     406              : #ifdef DLT_SHM_ENABLE
     407              :     strncpy(daemon_local->flags.dltShmName, dltShmName, NAME_MAX);
     408              : #endif
     409              : 
     410              :     return 0;
     411              : 
     412              : }  /* option_handling() */
     413              : 
     414              : /**
     415              :  * Option file parser
     416              :  */
     417            9 : int option_file_parser(DltDaemonLocal *daemon_local)
     418            9 : {
     419              :     FILE *pFile;
     420            9 :     char line[value_length - 1];
     421            9 :     char token[value_length];
     422            9 :     char value[value_length];
     423              :     char *pch;
     424              :     const char *filename;
     425              :     ssize_t n;
     426              : 
     427              :     /* set default values for configuration */
     428            9 :     daemon_local->flags.sharedMemorySize = DLT_SHM_SIZE;
     429            9 :     daemon_local->flags.sendMessageTime = 0;
     430            9 :     daemon_local->flags.offlineTraceDirectory[0] = 0;
     431            9 :     daemon_local->flags.offlineTraceFileSize = 1000000;
     432            9 :     daemon_local->flags.offlineTraceMaxSize = 4000000;
     433            9 :     daemon_local->flags.offlineTraceFilenameTimestampBased = true;
     434            9 :     daemon_local->flags.loggingMode = DLT_LOG_TO_CONSOLE;
     435            9 :     daemon_local->flags.loggingLevel = LOG_INFO;
     436              : 
     437              : #ifdef DLT_DAEMON_USE_UNIX_SOCKET_IPC
     438              :     n = snprintf(daemon_local->flags.loggingFilename,
     439              :                  sizeof(daemon_local->flags.loggingFilename),
     440              :                  "%s/dlt.log", DLT_USER_IPC_PATH);
     441              : #else /* DLT_DAEMON_USE_FIFO_IPC */
     442            9 :     n = snprintf(daemon_local->flags.loggingFilename,
     443              :                  sizeof(daemon_local->flags.loggingFilename),
     444              :                  "%s/dlt.log", DLT_USER_IPC_PATH);
     445              : #endif
     446              : 
     447            9 :     if (n < 0 || (size_t)n > sizeof(daemon_local->flags.loggingFilename)) {
     448            0 :         dlt_vlog(LOG_WARNING, "%s: snprintf truncation/error(%ld) %s\n",
     449              :                 __func__, n, daemon_local->flags.loggingFilename);
     450              :     }
     451            9 :     daemon_local->flags.enableLoggingFileLimit = false;
     452            9 :     daemon_local->flags.loggingFileSize = 250000;
     453            9 :     daemon_local->flags.loggingFileMaxSize = 1000000;
     454              : 
     455            9 :     daemon_local->timeoutOnSend = 4;
     456            9 :     daemon_local->RingbufferMinSize = DLT_DAEMON_RINGBUFFER_MIN_SIZE;
     457            9 :     daemon_local->RingbufferMaxSize = DLT_DAEMON_RINGBUFFER_MAX_SIZE;
     458            9 :     daemon_local->RingbufferStepSize = DLT_DAEMON_RINGBUFFER_STEP_SIZE;
     459            9 :     daemon_local->daemonFifoSize = 0;
     460            9 :     daemon_local->flags.sendECUSoftwareVersion = 0;
     461            9 :     memset(daemon_local->flags.pathToECUSoftwareVersion, 0, sizeof(daemon_local->flags.pathToECUSoftwareVersion));
     462            9 :     memset(daemon_local->flags.ecuSoftwareVersionFileField, 0, sizeof(daemon_local->flags.ecuSoftwareVersionFileField));
     463            9 :     daemon_local->flags.sendTimezone = 0;
     464            9 :     daemon_local->flags.offlineLogstorageMaxDevices = 0;
     465            9 :     daemon_local->flags.offlineLogstorageDirPath[0] = 0;
     466            9 :     daemon_local->flags.offlineLogstorageTimestamp = 1;
     467            9 :     daemon_local->flags.offlineLogstorageDelimiter = '_';
     468            9 :     daemon_local->flags.offlineLogstorageMaxCounter = UINT_MAX;
     469            9 :     daemon_local->flags.offlineLogstorageMaxCounterIdx = 0;
     470            9 :     daemon_local->flags.offlineLogstorageOptionalCounter = false;
     471            9 :     daemon_local->flags.offlineLogstorageCacheSize = 30000; /* 30MB */
     472            9 :     dlt_daemon_logstorage_set_logstorage_cache_size(
     473              :         daemon_local->flags.offlineLogstorageCacheSize);
     474            9 :     strncpy(daemon_local->flags.ctrlSockPath,
     475              :             DLT_DAEMON_DEFAULT_CTRL_SOCK_PATH,
     476              :             sizeof(daemon_local->flags.ctrlSockPath));
     477              : #ifdef DLT_DAEMON_USE_UNIX_SOCKET_IPC
     478              :     snprintf(daemon_local->flags.appSockPath, DLT_IPC_PATH_MAX, "%s/dlt", DLT_USER_IPC_PATH);
     479              : 
     480              :     if (strlen(DLT_USER_IPC_PATH) > DLT_IPC_PATH_MAX)
     481              :         fprintf(stderr, "Provided path too long...trimming it to path[%s]\n",
     482              :                 daemon_local->flags.appSockPath);
     483              : 
     484              : #else /* DLT_DAEMON_USE_FIFO_IPC */
     485            9 :     memset(daemon_local->flags.daemonFifoGroup, 0, sizeof(daemon_local->flags.daemonFifoGroup));
     486              : #endif
     487            9 :     daemon_local->flags.gatewayMode = 0;
     488            9 :     strncpy(daemon_local->flags.gatewayConfigFile,
     489              :             DLT_GATEWAY_CONFIG_PATH,
     490              :             DLT_DAEMON_FLAG_MAX);
     491            9 :     daemon_local->flags.autoResponseGetLogInfoOption = 7;
     492            9 :     daemon_local->flags.contextLogLevel = DLT_LOG_INFO;
     493            9 :     daemon_local->flags.contextTraceStatus = DLT_TRACE_STATUS_OFF;
     494            9 :     daemon_local->flags.enforceContextLLAndTS = 0; /* default is off */
     495              : #ifdef UDP_CONNECTION_SUPPORT
     496              :     daemon_local->UDPConnectionSetup = MULTICAST_CONNECTION_ENABLED;
     497              :     strncpy(daemon_local->UDPMulticastIPAddress, MULTICASTIPADDRESS, MULTICASTIP_MAX_SIZE - 1);
     498              :     daemon_local->UDPMulticastIPPort = MULTICASTIPPORT;
     499              : #endif
     500            9 :     daemon_local->flags.ipNodes = NULL;
     501            9 :     daemon_local->flags.injectionMode = 1;
     502              : 
     503              :     /* open configuration file */
     504            9 :     if (daemon_local->flags.cvalue[0])
     505            8 :         filename = daemon_local->flags.cvalue;
     506              :     else
     507              :         filename = CONFIGURATION_FILES_DIR "/dlt.conf";
     508              : 
     509              :     /*printf("Load configuration from file: %s\n",filename); */
     510            9 :     pFile = fopen (filename, "r");
     511              : 
     512            9 :     if (pFile != NULL) {
     513              :         while (1) {
     514              :             /* fetch line from configuration file */
     515          112 :             if (fgets (line, value_length - 1, pFile) != NULL) {
     516           49 :                 pch = strtok (line, " =\r\n");
     517           49 :                 token[0] = 0;
     518           49 :                 value[0] = 0;
     519              : 
     520           92 :                 while (pch != NULL) {
     521           86 :                     if (strcmp(pch, "#") == 0)
     522              :                         break;
     523              : 
     524           86 :                     if (token[0] == 0) {
     525           43 :                         strncpy(token, pch, sizeof(token) - 1);
     526           43 :                         token[sizeof(token) - 1] = 0;
     527              :                     }
     528              :                     else {
     529           43 :                         strncpy(value, pch, sizeof(value) - 1);
     530           43 :                         value[sizeof(value) - 1] = 0;
     531           43 :                         break;
     532              :                     }
     533              : 
     534           43 :                     pch = strtok (NULL, " =\r\n");
     535              :                 }
     536              : 
     537           49 :                 if (token[0] && value[0]) {
     538              :                     /* parse arguments here */
     539           43 :                     if (strcmp(token, "Verbose") == 0) {
     540            0 :                         daemon_local->flags.vflag = atoi(value);
     541              :                         /*printf("Option: %s=%s\n",token,value); */
     542              :                     }
     543           43 :                     else if (strcmp(token, "PrintASCII") == 0)
     544              :                     {
     545            0 :                         daemon_local->flags.aflag = atoi(value);
     546              :                         /*printf("Option: %s=%s\n",token,value); */
     547              :                     }
     548           43 :                     else if (strcmp(token, "PrintHex") == 0)
     549              :                     {
     550            0 :                         daemon_local->flags.xflag = atoi(value);
     551              :                         /*printf("Option: %s=%s\n",token,value); */
     552              :                     }
     553           43 :                     else if (strcmp(token, "PrintHeadersOnly") == 0)
     554              :                     {
     555            0 :                         daemon_local->flags.sflag = atoi(value);
     556              :                         /*printf("Option: %s=%s\n",token,value); */
     557              :                     }
     558           43 :                     else if (strcmp(token, "SendSerialHeader") == 0)
     559              :                     {
     560            0 :                         daemon_local->flags.lflag = atoi(value);
     561              :                         /*printf("Option: %s=%s\n",token,value); */
     562              :                     }
     563           43 :                     else if (strcmp(token, "SendContextRegistration") == 0)
     564              :                     {
     565            1 :                         daemon_local->flags.rflag = atoi(value);
     566              :                         /*printf("Option: %s=%s\n",token,value); */
     567              :                     }
     568           42 :                     else if (strcmp(token, "SendContextRegistrationOption") == 0)
     569              :                     {
     570            0 :                         daemon_local->flags.autoResponseGetLogInfoOption = atoi(value);
     571              :                         /*printf("Option: %s=%s\n",token,value); */
     572              :                     }
     573           42 :                     else if (strcmp(token, "SendMessageTime") == 0)
     574              :                     {
     575            0 :                         daemon_local->flags.sendMessageTime = atoi(value);
     576              :                         /*printf("Option: %s=%s\n",token,value); */
     577              :                     }
     578           42 :                     else if (strcmp(token, "RS232SyncSerialHeader") == 0)
     579              :                     {
     580            0 :                         daemon_local->flags.mflag = atoi(value);
     581              :                         /*printf("Option: %s=%s\n",token,value); */
     582              :                     }
     583           42 :                     else if (strcmp(token, "TCPSyncSerialHeader") == 0)
     584              :                     {
     585            0 :                         daemon_local->flags.nflag = atoi(value);
     586              :                         /*printf("Option: %s=%s\n",token,value); */
     587              :                     }
     588           42 :                     else if (strcmp(token, "RS232DeviceName") == 0)
     589              :                     {
     590            0 :                         strncpy(daemon_local->flags.yvalue, value, NAME_MAX);
     591            0 :                         daemon_local->flags.yvalue[NAME_MAX] = 0;
     592              :                         /*printf("Option: %s=%s\n",token,value); */
     593              :                     }
     594           42 :                     else if (strcmp(token, "RS232Baudrate") == 0)
     595              :                     {
     596            0 :                         strncpy(daemon_local->flags.bvalue, value, NAME_MAX);
     597            0 :                         daemon_local->flags.bvalue[NAME_MAX] = 0;
     598              :                         /*printf("Option: %s=%s\n",token,value); */
     599              :                     }
     600           42 :                     else if (strcmp(token, "ECUId") == 0)
     601              :                     {
     602            1 :                         strncpy(daemon_local->flags.evalue, value, NAME_MAX);
     603            1 :                         daemon_local->flags.evalue[NAME_MAX] = 0;
     604              :                         /*printf("Option: %s=%s\n",token,value); */
     605              :                     }
     606           41 :                     else if (strcmp(token, "PersistanceStoragePath") == 0)
     607              :                     {
     608            0 :                         strncpy(daemon_local->flags.ivalue, value, NAME_MAX);
     609            0 :                         daemon_local->flags.ivalue[NAME_MAX] = 0;
     610              :                         /*printf("Option: %s=%s\n",token,value); */
     611              :                     }
     612           41 :                     else if (strcmp(token, "LoggingMode") == 0)
     613              :                     {
     614            1 :                         daemon_local->flags.loggingMode = (DltLoggingMode)atoi(value);
     615              :                         /*printf("Option: %s=%s\n",token,value); */
     616              :                     }
     617           40 :                     else if (strcmp(token, "LoggingLevel") == 0)
     618              :                     {
     619            1 :                         daemon_local->flags.loggingLevel = atoi(value);
     620              :                         /*printf("Option: %s=%s\n",token,value); */
     621              :                     }
     622           39 :                     else if (strcmp(token, "LoggingFilename") == 0)
     623              :                     {
     624              :                         strncpy(daemon_local->flags.loggingFilename,
     625              :                                 value,
     626              :                                 sizeof(daemon_local->flags.loggingFilename) - 1);
     627            1 :                         daemon_local->flags.loggingFilename[sizeof(daemon_local->flags.loggingFilename) - 1] = 0;
     628              :                         /*printf("Option: %s=%s\n",token,value); */
     629              :                     }
     630           38 :                     else if (strcmp(token, "EnableLoggingFileLimit") == 0)
     631              :                     {
     632            0 :                         daemon_local->flags.enableLoggingFileLimit = (bool)atoi(value);
     633              :                     }
     634           38 :                     else if (strcmp(token, "LoggingFileSize") == 0)
     635              :                     {
     636            0 :                         daemon_local->flags.loggingFileSize = atoi(value);
     637              :                     }
     638           38 :                     else if (strcmp(token, "LoggingFileMaxSize") == 0)
     639              :                     {
     640            0 :                         daemon_local->flags.loggingFileMaxSize = atoi(value);
     641              :                     }
     642           38 :                     else if (strcmp(token, "TimeOutOnSend") == 0)
     643              :                     {
     644            1 :                         daemon_local->timeoutOnSend = atoi(value);
     645              :                         /*printf("Option: %s=%s\n",token,value); */
     646              :                     }
     647           37 :                     else if (strcmp(token, "RingbufferMinSize") == 0)
     648              :                     {
     649            1 :                         if (dlt_daemon_check_numeric_setting(token,
     650              :                                 value, &(daemon_local->RingbufferMinSize)) < 0) {
     651            0 :                             fclose (pFile);
     652            0 :                             return -1;
     653              :                         }
     654              :                     }
     655           36 :                     else if (strcmp(token, "RingbufferMaxSize") == 0)
     656              :                     {
     657            1 :                         if (dlt_daemon_check_numeric_setting(token,
     658              :                                 value, &(daemon_local->RingbufferMaxSize)) < 0) {
     659            0 :                             fclose (pFile);
     660            0 :                             return -1;
     661              :                         }
     662              :                     }
     663           35 :                     else if (strcmp(token, "RingbufferStepSize") == 0)
     664              :                     {
     665            1 :                         if (dlt_daemon_check_numeric_setting(token,
     666              :                                 value, &(daemon_local->RingbufferStepSize)) < 0) {
     667            0 :                             fclose (pFile);
     668            0 :                             return -1;
     669              :                         }
     670              :                     }
     671           34 :                     else if (strcmp(token, "SharedMemorySize") == 0)
     672              :                     {
     673            1 :                         daemon_local->flags.sharedMemorySize = atoi(value);
     674              :                         /*printf("Option: %s=%s\n",token,value); */
     675              :                     }
     676           33 :                     else if (strcmp(token, "OfflineTraceDirectory") == 0)
     677              :                     {
     678            0 :                         strncpy(daemon_local->flags.offlineTraceDirectory, value,
     679              :                                 sizeof(daemon_local->flags.offlineTraceDirectory) - 1);
     680              :                         daemon_local->flags.offlineTraceDirectory[sizeof(daemon_local->flags.offlineTraceDirectory) -
     681            0 :                                                                   1] = 0;
     682              :                         /*printf("Option: %s=%s\n",token,value); */
     683              :                     }
     684           33 :                     else if (strcmp(token, "OfflineTraceFileSize") == 0)
     685              :                     {
     686            0 :                         daemon_local->flags.offlineTraceFileSize = atoi(value);
     687              :                         /*printf("Option: %s=%s\n",token,value); */
     688              :                     }
     689           33 :                     else if (strcmp(token, "OfflineTraceMaxSize") == 0)
     690              :                     {
     691            0 :                         daemon_local->flags.offlineTraceMaxSize = atoi(value);
     692              :                         /*printf("Option: %s=%s\n",token,value); */
     693              :                     }
     694           33 :                     else if (strcmp(token, "OfflineTraceFileNameTimestampBased") == 0)
     695              :                     {
     696            0 :                         daemon_local->flags.offlineTraceFilenameTimestampBased = (bool)atoi(value);
     697              :                         /*printf("Option: %s=%s\n",token,value); */
     698              :                     }
     699           33 :                     else if (strcmp(token, "SendECUSoftwareVersion") == 0)
     700              :                     {
     701            0 :                         daemon_local->flags.sendECUSoftwareVersion = atoi(value);
     702              :                         /*printf("Option: %s=%s\n",token,value); */
     703              :                     }
     704           33 :                     else if (strcmp(token, "PathToECUSoftwareVersion") == 0)
     705              :                     {
     706              :                         strncpy(daemon_local->flags.pathToECUSoftwareVersion, value,
     707              :                                 sizeof(daemon_local->flags.pathToECUSoftwareVersion) - 1);
     708              :                         daemon_local->flags.pathToECUSoftwareVersion[sizeof(daemon_local->flags.pathToECUSoftwareVersion)
     709            0 :                                                                      - 1] = 0;
     710              :                         /*printf("Option: %s=%s\n",token,value); */
     711              :                     }
     712           33 :                     else if (strcmp(token, "ECUSoftwareVersionFileField") == 0) {
     713              :                         strncpy(daemon_local->flags.ecuSoftwareVersionFileField, value,
     714              :                                 sizeof(daemon_local->flags.ecuSoftwareVersionFileField) - 1);
     715              :                         daemon_local->flags.ecuSoftwareVersionFileField[sizeof(daemon_local->flags.ecuSoftwareVersionFileField)
     716            0 :                                                                      - 1] = 0;
     717              :                         /*printf("Option: %s=%s\n",token,value); */
     718              :                     }
     719           33 :                     else if (strcmp(token, "SendTimezone") == 0)
     720              :                     {
     721            0 :                         daemon_local->flags.sendTimezone = atoi(value);
     722              :                         /*printf("Option: %s=%s\n",token,value); */
     723              :                     }
     724           33 :                     else if (strcmp(token, "OfflineLogstorageMaxDevices") == 0)
     725              :                     {
     726            6 :                         daemon_local->flags.offlineLogstorageMaxDevices = (int)strtoul(value, NULL, 10);
     727              :                     }
     728           27 :                     else if (strcmp(token, "OfflineLogstorageDirPath") == 0)
     729              :                     {
     730            6 :                         strncpy(daemon_local->flags.offlineLogstorageDirPath,
     731              :                                 value,
     732              :                                 sizeof(daemon_local->flags.offlineLogstorageDirPath) - 1);
     733              :                     }
     734           21 :                     else if (strcmp(token, "OfflineLogstorageTimestamp") == 0)
     735              :                     {
     736              :                         /* Check if set to 0, default otherwise */
     737            6 :                         if (atoi(value) == 0)
     738            6 :                             daemon_local->flags.offlineLogstorageTimestamp = 0;
     739              :                     }
     740           15 :                     else if (strcmp(token, "OfflineLogstorageDelimiter") == 0)
     741              :                     {
     742              :                         /* Check if valid punctuation, default otherwise*/
     743            0 :                         if (ispunct((char)value[0]))
     744            0 :                             daemon_local->flags.offlineLogstorageDelimiter = (char)value[0];
     745              :                     }
     746           15 :                     else if (strcmp(token, "OfflineLogstorageMaxCounter") == 0)
     747              :                     {
     748            0 :                         daemon_local->flags.offlineLogstorageMaxCounter = (unsigned int) atoi(value);
     749            0 :                         daemon_local->flags.offlineLogstorageMaxCounterIdx = (unsigned int) strlen(value);
     750           15 :                     } else if (strcmp(token, "OfflineLogstorageOptionalIndex") == 0) {
     751            6 :                         daemon_local->flags.offlineLogstorageOptionalCounter = atoi(value);
     752              :                     }
     753            9 :                     else if (strcmp(token, "OfflineLogstorageCacheSize") == 0)
     754              :                     {
     755            0 :                         daemon_local->flags.offlineLogstorageCacheSize =
     756            0 :                             (unsigned int)atoi(value);
     757            0 :                         dlt_daemon_logstorage_set_logstorage_cache_size(
     758              :                             daemon_local->flags.offlineLogstorageCacheSize);
     759              :                     }
     760            9 :                     else if (strcmp(token, "ControlSocketPath") == 0)
     761              :                     {
     762              :                         memset(
     763              :                             daemon_local->flags.ctrlSockPath,
     764              :                             0,
     765              :                             DLT_DAEMON_FLAG_MAX);
     766              :                         strncpy(
     767              :                             daemon_local->flags.ctrlSockPath,
     768              :                             value,
     769              :                             DLT_DAEMON_FLAG_MAX - 1);
     770              :                     }
     771            2 :                     else if (strcmp(token, "GatewayMode") == 0)
     772              :                     {
     773            1 :                         daemon_local->flags.gatewayMode = atoi(value);
     774              :                         /*printf("Option: %s=%s\n",token,value); */
     775              :                     }
     776            1 :                     else if (strcmp(token, "GatewayConfigFile") == 0)
     777              :                     {
     778              :                         memset(
     779              :                             daemon_local->flags.gatewayConfigFile,
     780              :                             0,
     781              :                             DLT_DAEMON_FLAG_MAX);
     782              :                         strncpy(
     783              :                             daemon_local->flags.gatewayConfigFile,
     784              :                             value,
     785              :                             DLT_DAEMON_FLAG_MAX - 1);
     786              :                     }
     787            0 :                     else if (strcmp(token, "ContextLogLevel") == 0)
     788              :                     {
     789              :                         int const intval = atoi(value);
     790              : 
     791            0 :                         if ((intval >= DLT_LOG_OFF) && (intval <= DLT_LOG_VERBOSE)) {
     792            0 :                             daemon_local->flags.contextLogLevel = intval;
     793              :                             printf("Option: %s=%s\n", token, value);
     794              :                         }
     795              :                         else {
     796            0 :                             fprintf(stderr,
     797              :                                     "Invalid value for ContextLogLevel: %i. Must be in range [%i..%i]\n",
     798              :                                     intval,
     799              :                                     DLT_LOG_OFF,
     800              :                                     DLT_LOG_VERBOSE);
     801              :                         }
     802              :                     }
     803            0 :                     else if (strcmp(token, "ContextTraceStatus") == 0)
     804              :                     {
     805              :                         int const intval = atoi(value);
     806              : 
     807            0 :                         if ((intval >= DLT_TRACE_STATUS_OFF) && (intval <= DLT_TRACE_STATUS_ON)) {
     808            0 :                             daemon_local->flags.contextTraceStatus = intval;
     809              :                             printf("Option: %s=%s\n", token, value);
     810              :                         }
     811              :                         else {
     812            0 :                             fprintf(stderr,
     813              :                                     "Invalid value for ContextTraceStatus: %i. Must be in range [%i..%i]\n",
     814              :                                     intval,
     815              :                                     DLT_TRACE_STATUS_OFF,
     816              :                                     DLT_TRACE_STATUS_ON);
     817              :                         }
     818              :                     }
     819            0 :                     else if (strcmp(token, "ForceContextLogLevelAndTraceStatus") == 0)
     820              :                     {
     821              :                         int const intval = atoi(value);
     822              : 
     823            0 :                         if ((intval >= 0) && (intval <= 1)) {
     824            0 :                             daemon_local->flags.enforceContextLLAndTS = intval;
     825              :                             printf("Option: %s=%s\n", token, value);
     826              :                         }
     827              :                         else {
     828            0 :                             fprintf(stderr,
     829              :                                     "Invalid value for ForceContextLogLevelAndTraceStatus: %i. Must be 0, 1\n",
     830              :                                     intval);
     831              :                         }
     832              :                     }
     833              : 
     834              : #ifdef DLT_DAEMON_USE_FIFO_IPC
     835            0 :                     else if (strcmp(token, "DaemonFIFOSize") == 0)
     836              :                     {
     837            0 :                         if (dlt_daemon_check_numeric_setting(token,
     838              :                                 value, &(daemon_local->daemonFifoSize)) < 0) {
     839            0 :                             fclose (pFile);
     840            0 :                             return -1;
     841              :                         }
     842              : #ifndef __linux__
     843              :                             printf("Option DaemonFIFOSize is set but only supported on Linux. Ignored.\n");
     844              : #endif
     845              :                     }
     846            0 :                     else if (strcmp(token, "DaemonFifoGroup") == 0)
     847              :                     {
     848              :                         strncpy(daemon_local->flags.daemonFifoGroup, value, NAME_MAX);
     849            0 :                         daemon_local->flags.daemonFifoGroup[NAME_MAX] = 0;
     850              :                     }
     851              : #endif
     852              : #ifdef UDP_CONNECTION_SUPPORT
     853              :                     else if (strcmp(token, "UDPConnectionSetup") == 0)
     854              :                     {
     855              :                         const long longval = strtol(value, NULL, 10);
     856              : 
     857              :                         if ((longval == MULTICAST_CONNECTION_DISABLED)
     858              :                             || (longval == MULTICAST_CONNECTION_ENABLED)) {
     859              :                             daemon_local->UDPConnectionSetup = longval;
     860              :                             printf("Option: %s=%s\n", token, value);
     861              :                         }
     862              :                         else {
     863              :                             daemon_local->UDPConnectionSetup = MULTICAST_CONNECTION_DISABLED;
     864              :                             fprintf(stderr,
     865              :                                     "Invalid value for UDPConnectionSetup set to default %ld\n",
     866              :                                     longval);
     867              :                         }
     868              :                     }
     869              :                     else if (strcmp(token, "UDPMulticastIPAddress") == 0)
     870              :                     {
     871              :                         strncpy(daemon_local->UDPMulticastIPAddress, value,
     872              :                                 MULTICASTIP_MAX_SIZE - 1);
     873              :                     }
     874              :                     else if (strcmp(token, "UDPMulticastIPPort") == 0)
     875              :                     {
     876              :                         daemon_local->UDPMulticastIPPort = strtol(value, NULL, 10);
     877              :                     }
     878              : #endif
     879            0 :                     else if (strcmp(token, "BindAddress") == 0)
     880              :                     {
     881              :                         DltBindAddress_t *newNode = NULL;
     882              :                         DltBindAddress_t *temp = NULL;
     883              : 
     884            0 :                         char *tok = strtok(value, ",;");
     885              : 
     886            0 :                         if (tok != NULL) {
     887            0 :                             daemon_local->flags.ipNodes = calloc(1, sizeof(DltBindAddress_t));
     888              : 
     889            0 :                             if (daemon_local->flags.ipNodes == NULL) {
     890            0 :                                 dlt_vlog(LOG_ERR, "Could not allocate for IP list\n");
     891            0 :                                 fclose(pFile);
     892            0 :                                 return -1;
     893              :                             }
     894              :                             else {
     895            0 :                                 strncpy(daemon_local->flags.ipNodes->ip,
     896              :                                         tok,
     897              :                                         sizeof(daemon_local->flags.ipNodes->ip) - 1);
     898            0 :                                 daemon_local->flags.ipNodes->next = NULL;
     899              :                                 temp = daemon_local->flags.ipNodes;
     900              : 
     901            0 :                                 tok = strtok(NULL, ",;");
     902              : 
     903            0 :                                 while (tok != NULL) {
     904            0 :                                     newNode = calloc(1, sizeof(DltBindAddress_t));
     905              : 
     906            0 :                                     if (newNode == NULL) {
     907            0 :                                         dlt_vlog(LOG_ERR, "Could not allocate for IP list\n");
     908            0 :                                         fclose(pFile);
     909            0 :                                         return -1;
     910              :                                     }
     911              :                                     else {
     912            0 :                                         strncpy(newNode->ip, tok, sizeof(newNode->ip) - 1);
     913              :                                     }
     914              : 
     915            0 :                                     temp->next = newNode;
     916              :                                     temp = temp->next;
     917            0 :                                     tok = strtok(NULL, ",;");
     918              :                                 }
     919              :                             }
     920              :                         }
     921              :                         else {
     922            0 :                             dlt_vlog(LOG_WARNING, "BindAddress option is empty\n");
     923              :                         }
     924              :                     }
     925            0 :                     else if (strcmp(token, "InjectionMode") == 0) {
     926            0 :                         daemon_local->flags.injectionMode = atoi(value);
     927              :                     }
     928              :                     else {
     929            0 :                         fprintf(stderr, "Unknown option: %s=%s\n", token, value);
     930              :                     }
     931              :                 }
     932              :             }
     933              :             else {
     934              :                 break;
     935              :             }
     936              :         }
     937              : 
     938            7 :         fclose (pFile);
     939              :     }
     940              :     else {
     941            2 :         fprintf(stderr, "Cannot open configuration file: %s\n", filename);
     942              :     }
     943              : 
     944              :     return 0;
     945              : }
     946              : 
     947              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
     948              : /**
     949              :  * Load configuration file parser
     950              :  */
     951              : 
     952              : static int compare_app_id_conf(const void *lhs, const void *rhs)
     953              : {
     954              :     return strncmp(((DltDaemonContextLogSettings *)lhs)->apid,
     955              :                    ((DltDaemonContextLogSettings *)rhs)->apid, DLT_ID_SIZE);
     956              : }
     957              : 
     958              : int app_id_default_log_level_config_parser(DltDaemon *daemon,
     959              :                                            DltDaemonLocal *daemon_local) {
     960              :     FILE *pFile;
     961              :     char line[value_length - 1];
     962              :     char app_id_value[value_length];
     963              :     char ctx_id_value[value_length];
     964              :     DltLogLevelType log_level_value;
     965              : 
     966              :     char *pch;
     967              :     const char *filename;
     968              : 
     969              :     /* open configuration file */
     970              :     filename = daemon_local->flags.avalue[0]
     971              :                    ? daemon_local->flags.avalue
     972              :                    : CONFIGURATION_FILES_DIR "/dlt-log-levels.conf";
     973              : 
     974              :     pFile = fopen(filename, "r");
     975              :     if (pFile == NULL) {
     976              :         dlt_vlog(LOG_WARNING, "Cannot open app log level configuration%s\n", filename);
     977              :         return -errno;
     978              :     }
     979              : 
     980              :     /* fetch lines from configuration file */
     981              :     while (fgets(line, value_length - 1, pFile) != NULL) {
     982              :         pch = strtok(line, " \t");
     983              :         memset(app_id_value, 0, value_length);
     984              :         memset(ctx_id_value, 0, value_length);
     985              :         log_level_value = DLT_LOG_MAX;
     986              : 
     987              :         /* ignore comments and new lines*/
     988              :         if (strncmp(pch, "#", 1) == 0 || strncmp(pch, "\n", 1) == 0
     989              :             || strlen(pch) < 1)
     990              :             continue;
     991              : 
     992              :         strncpy(app_id_value, pch, sizeof(app_id_value) - 1);
     993              :         app_id_value[sizeof(app_id_value) - 1] = 0;
     994              :         if (strlen(app_id_value) == 0 || strlen(app_id_value) > DLT_ID_SIZE) {
     995              :             if (app_id_value[strlen(app_id_value) - 1] == '\n') {
     996              :                 dlt_vlog(LOG_WARNING, "Missing log level for apid %s in log settings\n",
     997              :                          app_id_value);
     998              :             } else {
     999              :                 dlt_vlog(LOG_WARNING,
    1000              :                          "Invalid apid for log settings settings: app id: %s\n",
    1001              :                          app_id_value);
    1002              :             }
    1003              : 
    1004              :             continue;
    1005              :         }
    1006              : 
    1007              :         char *pch_next1 = strtok(NULL, " \t");
    1008              :         char *pch_next2 = strtok(NULL, " \t");
    1009              :         char *log_level;
    1010              :         /* no context id given, log level is next token */
    1011              :         if (pch_next2 == NULL || pch_next2[0] == '#') {
    1012              :             log_level = pch_next1;
    1013              :         } else {
    1014              :             /* context id is given, log level is second to next token */
    1015              :             log_level = pch_next2;
    1016              : 
    1017              :             /* next token is token id */
    1018              :             strncpy(ctx_id_value, pch_next1, sizeof(ctx_id_value) - 1);
    1019              :             if (strlen(ctx_id_value) == 0 || strlen(app_id_value) > DLT_ID_SIZE) {
    1020              :                 dlt_vlog(LOG_WARNING,
    1021              :                          "Invalid ctxid for log settings: app id: %s "
    1022              :                          "(skipping line)\n",
    1023              :                          app_id_value);
    1024              :                 continue;
    1025              :             }
    1026              : 
    1027              :             ctx_id_value[sizeof(ctx_id_value) - 1] = 0;
    1028              :         }
    1029              : 
    1030              :         errno = 0;
    1031              :         log_level_value = strtol(log_level, NULL, 10);
    1032              :         if (errno != 0 || log_level_value >= DLT_LOG_MAX ||
    1033              :             log_level_value <= DLT_LOG_DEFAULT) {
    1034              :             dlt_vlog(LOG_WARNING,
    1035              :                      "Invalid log level (%i), app id %s, conversion error: %s\n",
    1036              :                      log_level_value, app_id_value, strerror(errno));
    1037              :             continue;
    1038              :         }
    1039              : 
    1040              :         DltDaemonContextLogSettings *settings =
    1041              :             dlt_daemon_find_configured_app_id_ctx_id_settings(
    1042              :                 daemon, app_id_value, NULL);
    1043              : 
    1044              :         if (settings != NULL &&
    1045              :             strncmp(settings->ctid, ctx_id_value, DLT_ID_SIZE) == 0) {
    1046              :             if (strlen(ctx_id_value) > 0) {
    1047              :                 dlt_vlog(LOG_WARNING,
    1048              :                          "Appid %s with ctxid %s is already configured, skipping "
    1049              :                          "duplicated entry\n",
    1050              :                          app_id_value, ctx_id_value);
    1051              :             } else {
    1052              :                 dlt_vlog(LOG_WARNING,
    1053              :                          "Appid %s is already configured, skipping duplicated entry\n",
    1054              :                          app_id_value);
    1055              :             }
    1056              : 
    1057              :             continue;
    1058              :         }
    1059              : 
    1060              :         /* allocate one more element in the trace load settings */
    1061              :         DltDaemonContextLogSettings *tmp =
    1062              :             realloc(daemon->app_id_log_level_settings,
    1063              :                     (++daemon->num_app_id_log_level_settings) *
    1064              :                         sizeof(DltDaemonContextLogSettings));
    1065              : 
    1066              :         if (tmp == NULL) {
    1067              :             dlt_log(LOG_CRIT, "Failed to allocate memory for app load settings\n");
    1068              :             continue;
    1069              :         }
    1070              : 
    1071              :         daemon->app_id_log_level_settings = tmp;
    1072              : 
    1073              :         /* update newly created entry */
    1074              :         settings = &daemon->app_id_log_level_settings
    1075              :                         [daemon->num_app_id_log_level_settings -1];
    1076              : 
    1077              :         memset(settings, 0, sizeof(DltDaemonContextLogSettings));
    1078              :         memcpy(settings->apid, app_id_value, DLT_ID_SIZE);
    1079              :         memcpy(settings->ctid, ctx_id_value, DLT_ID_SIZE);
    1080              :         settings->log_level = log_level_value;
    1081              : 
    1082              :         /* make sure ids are 0 terminated for printing */
    1083              :         char apid_buf[DLT_ID_SIZE + 1] = {0};
    1084              :         char ctid_buf[DLT_ID_SIZE + 1] = {0};
    1085              :         memcpy(apid_buf, app_id_value, DLT_ID_SIZE);
    1086              :         memcpy(ctid_buf, ctx_id_value, DLT_ID_SIZE);
    1087              : 
    1088              :         /* log with or without context id */
    1089              :         if (strlen(ctid_buf) > 0) {
    1090              :             dlt_vlog(
    1091              :                 LOG_INFO,
    1092              :                 "Configured trace limits for app id %s, context id %s, level %u\n",
    1093              :                 apid_buf, ctid_buf, log_level_value);
    1094              :         } else {
    1095              :             dlt_vlog(LOG_INFO, "Configured trace limits for app id %s, level %u\n",
    1096              :                      apid_buf, log_level_value);
    1097              :         }
    1098              : 
    1099              :     } /* while */
    1100              :     fclose(pFile);
    1101              : 
    1102              :     /* list must be sorted to speed up dlt_daemon_find_configured_app_id_ctx_id_settings */
    1103              :     qsort(daemon->app_id_log_level_settings,
    1104              :             daemon->num_app_id_log_level_settings,
    1105              :             sizeof(DltDaemonContextLogSettings), compare_app_id_conf);
    1106              : 
    1107              :     return 0;
    1108              : }
    1109              : #endif
    1110              : 
    1111              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    1112              : static bool is_ascii_only(const char *str) {
    1113              :     while (*str) {
    1114              :         if ((unsigned char)*str > 127) {
    1115              :             return false;
    1116              :         }
    1117              :         str++;
    1118              :     }
    1119              :     return true;
    1120              : }
    1121              : 
    1122              : /**
    1123              :  * Load configuration file parser
    1124              :  */
    1125              : int trace_load_config_file_parser(DltDaemon *daemon, DltDaemonLocal *daemon_local)
    1126              : {
    1127              :     FILE *pFile;
    1128              :     const int max_tokens = 4;
    1129              :     const int min_tokens = 3;
    1130              :     char tokens[max_tokens][value_length];
    1131              :     char line[value_length - 1];
    1132              :     char app_id_value[value_length];
    1133              :     char ctx_id_value[value_length];
    1134              :     char soft_limit_value[value_length];
    1135              :     char hard_limit_value[value_length];
    1136              :     int i;
    1137              :     uint32_t soft_limit;
    1138              :     uint32_t hard_limit;
    1139              : 
    1140              :     char *pch;
    1141              :     const char *filename;
    1142              : 
    1143              :     bool skipped;
    1144              : 
    1145              :     if (daemon->preconfigured_trace_load_settings != NULL) {
    1146              :         free(daemon->preconfigured_trace_load_settings);
    1147              :         daemon->preconfigured_trace_load_settings = NULL;
    1148              :         daemon->preconfigured_trace_load_settings_count = 0;
    1149              :     }
    1150              :     daemon->preconfigured_trace_load_settings = malloc(sizeof(DltTraceLoadSettings));
    1151              :     if (daemon->preconfigured_trace_load_settings == NULL) {
    1152              :         dlt_log(LOG_CRIT, "Failed to allocate memory for trace load settings\n");
    1153              :         return DLT_RETURN_ERROR;
    1154              :     }
    1155              : 
    1156              :     /* open configuration file */
    1157              :     filename = daemon_local->flags.lvalue[0]
    1158              :                    ? daemon_local->flags.lvalue
    1159              :                    : CONFIGURATION_FILES_DIR "/dlt-trace-load.conf";
    1160              : 
    1161              :     pFile = fopen (filename, "r");
    1162              :     if (pFile == NULL) {
    1163              :         dlt_vlog(LOG_WARNING, "Cannot open trace load configuration file: %s\n",
    1164              :                  filename);
    1165              :         return -errno;
    1166              :     }
    1167              : 
    1168              :     while (1) {
    1169              :         /* fetch line from configuration file */
    1170              :         if (fgets(line, value_length - 1, pFile) == NULL) {
    1171              :             break;
    1172              :         }
    1173              : 
    1174              :         pch = strtok(line, " ");
    1175              :         app_id_value[0] = 0;
    1176              :         ctx_id_value[0] = 0;
    1177              :         soft_limit_value[0] = 0;
    1178              :         hard_limit_value[0] = 0;
    1179              :         soft_limit = 0U;
    1180              :         hard_limit = 0U;
    1181              :         memset(tokens, 0, sizeof(tokens));
    1182              :         i = 0;
    1183              : 
    1184              :         skipped = false;
    1185              :         while (pch != NULL && i < max_tokens) {
    1186              :             /* ignore comments, empty lines and new lines */
    1187              :             if (strncmp(pch, "#", 1) == 0 || strncmp(pch, "\n", 1) == 0 ||
    1188              :                 strncmp(pch, "\r", 1) == 0 || strncmp(pch, " ", 1) == 0) {
    1189              :                 skipped = true;
    1190              :                 break;
    1191              :             }
    1192              :             strncpy(tokens[i], pch, sizeof(tokens[i]) - 1);
    1193              :             pch = strtok(NULL, " ");
    1194              :             ++i;
    1195              :         }
    1196              : 
    1197              :         if (skipped && i < min_tokens)
    1198              :             continue;
    1199              : 
    1200              :         if (pch != NULL
    1201              :             && (pch[0] != '\n')
    1202              :             && (pch[0] != '\t')
    1203              :             && (pch[0] != ' ')
    1204              :             && (pch[0] != '#')) {
    1205              :             dlt_vlog(LOG_WARNING,
    1206              :                      "Invalid trace load settings: too many tokens in line '%s'\n", line);
    1207              :             continue;
    1208              :         }
    1209              : 
    1210              :         bool has_ctx_id = i == max_tokens;
    1211              :         int soft_limit_idx = has_ctx_id ? 2 : 1;
    1212              :         int hard_limit_idx = has_ctx_id ? 3 : 2;
    1213              : 
    1214              :         strncpy(app_id_value, tokens[0], sizeof(app_id_value) - 1);
    1215              :         if ((strlen(app_id_value) == 0)
    1216              :             || (strlen(app_id_value) > DLT_ID_SIZE)
    1217              :             || (!is_ascii_only(app_id_value))) {
    1218              :             dlt_vlog(LOG_WARNING,
    1219              :                      "Invalid apid for trace load settings: app id: '%s'\n", app_id_value);
    1220              :             continue;
    1221              :         }
    1222              : 
    1223              :         if (has_ctx_id) {
    1224              :             strncpy(ctx_id_value, tokens[1], sizeof(ctx_id_value) - 1);
    1225              :             if ((strlen(ctx_id_value) == 0)
    1226              :                 || (strlen(ctx_id_value) > DLT_ID_SIZE)
    1227              :                 || (!is_ascii_only(ctx_id_value))) {
    1228              :                 dlt_vlog(LOG_WARNING,
    1229              :                          "Invalid ctid for trace load settings: context id: '%s'\n", ctx_id_value);
    1230              :                 continue;
    1231              :             }
    1232              :         }
    1233              : 
    1234              :         if (strlen(tokens[soft_limit_idx]) == 0) {
    1235              :             dlt_vlog(LOG_WARNING,
    1236              :                      "Invalid soft_limit for trace load settings: app id: '%.4s', '%s'\n",
    1237              :                      app_id_value, tokens[soft_limit_idx]);
    1238              :             continue;
    1239              :         }
    1240              : 
    1241              :         if (strlen(tokens[hard_limit_idx]) == 0) {
    1242              :             dlt_vlog(LOG_WARNING,
    1243              :                      "Invalid hard_limit for trace load settings: app id: '%.4s', '%s'\n",
    1244              :                      app_id_value, tokens[hard_limit_idx]);
    1245              :             continue;
    1246              :         }
    1247              : 
    1248              :         strncpy(soft_limit_value, tokens[soft_limit_idx],
    1249              :                 sizeof(soft_limit_value) - 1);
    1250              :         strncpy(hard_limit_value, tokens[hard_limit_idx],
    1251              :                 sizeof(hard_limit_value) - 1);
    1252              : 
    1253              :         errno = 0;
    1254              :         char *endptr;
    1255              :         endptr = NULL;
    1256              :         soft_limit = strtoul(soft_limit_value, &endptr, 10);
    1257              :         if ((errno != 0)
    1258              :             || ((soft_limit == 0) && (soft_limit_value[0] != '0'))
    1259              :             || (soft_limit_value[0] == '-')
    1260              :             || ((*endptr != '\n') && (*endptr != '\0'))) {
    1261              :             dlt_vlog(LOG_WARNING,
    1262              :                      "Invalid soft_limit for trace load settings: app id: '%.4s', soft_limit '%s'\n",
    1263              :                      app_id_value, soft_limit_value);
    1264              :             continue;
    1265              :         }
    1266              : 
    1267              :         errno = 0;
    1268              :         endptr = NULL;
    1269              :         hard_limit = strtoul(hard_limit_value, &endptr, 10);
    1270              :         if ((errno != 0)
    1271              :             || ((hard_limit == 0) && (hard_limit_value[0] != '0'))
    1272              :             || (hard_limit_value[0] == '-')
    1273              :             || ((*endptr != '\n') && (*endptr != '\0'))) {
    1274              :             dlt_vlog(LOG_WARNING,
    1275              :                      "Invalid hard_limit for trace load settings: app id: '%.4s', hard_limit '%s'\n",
    1276              :                      app_id_value, hard_limit_value);
    1277              :             continue;
    1278              :         }
    1279              : 
    1280              :         if (soft_limit > hard_limit) {
    1281              :             dlt_vlog(LOG_WARNING,
    1282              :                      "Invalid trace load settings: app id: '%.4s', soft limit %u is greater than hard limit %u\n",
    1283              :                      app_id_value, soft_limit, hard_limit);
    1284              :             continue;
    1285              :         }
    1286              : 
    1287              :         DltTraceLoadSettings *settings = NULL;
    1288              :         int num_settings = 0;
    1289              :         DltReturnValue find_trace_settings_return_value = dlt_daemon_find_preconfigured_trace_load_settings(
    1290              :             daemon, app_id_value, ctx_id_value, &settings, &num_settings,
    1291              :             0);
    1292              :         if (find_trace_settings_return_value != DLT_RETURN_OK || num_settings != 0) {
    1293              :             dlt_vlog(LOG_WARNING,
    1294              :                      "App id '%.4s' is already configured, or an error occurred, skipping entry\n",
    1295              :                      app_id_value);
    1296              :             if (settings != NULL) {
    1297              :                 free(settings);
    1298              :             }
    1299              :             continue;
    1300              :         }
    1301              : 
    1302              :         /* allocate one more element in the trace load settings */
    1303              :         DltTraceLoadSettings *tmp =
    1304              :             realloc(daemon->preconfigured_trace_load_settings,
    1305              :                     (++daemon->preconfigured_trace_load_settings_count) *
    1306              :                         sizeof(DltTraceLoadSettings));
    1307              : 
    1308              :         if (tmp == NULL) {
    1309              :             dlt_log(LOG_CRIT,
    1310              :                     "Failed to allocate memory for trace load settings\n");
    1311              :             return DLT_RETURN_ERROR;
    1312              :         }
    1313              : 
    1314              :         daemon->preconfigured_trace_load_settings = tmp;
    1315              :         settings = &daemon->preconfigured_trace_load_settings
    1316              :                         [daemon->preconfigured_trace_load_settings_count - 1];
    1317              :         memset(settings, 0, sizeof(DltTraceLoadSettings));
    1318              :         settings->soft_limit = soft_limit;
    1319              :         settings->hard_limit = hard_limit;
    1320              : 
    1321              :         memcpy(settings->apid, app_id_value, DLT_ID_SIZE);
    1322              :         if (has_ctx_id) {
    1323              :             memcpy(settings->ctid, ctx_id_value, DLT_ID_SIZE);
    1324              :             dlt_vlog(LOG_INFO,
    1325              :                      "Configured trace limits for app id '%.4s', ctx id '%.4s', soft limit: %u, hard_limit: %u\n",
    1326              :                      app_id_value, ctx_id_value, soft_limit, hard_limit);
    1327              :         } else {
    1328              :             dlt_vlog(LOG_INFO,
    1329              :                      "Configured trace limits for app id '%.4s', soft limit: %u, hard_limit: %u\n",
    1330              :                      app_id_value, soft_limit, hard_limit);
    1331              :         }
    1332              : 
    1333              : 
    1334              : 
    1335              :     } /* while */
    1336              :     fclose(pFile);
    1337              : 
    1338              :     // sort limits to improve search performance
    1339              :     qsort(daemon->preconfigured_trace_load_settings, daemon->preconfigured_trace_load_settings_count,
    1340              :           sizeof(DltTraceLoadSettings),
    1341              :           dlt_daemon_compare_trace_load_settings);
    1342              :     return 0;
    1343              : }
    1344              : #endif
    1345              : 
    1346            9 : int dlt_mkdir_recursive(const char *dir)
    1347              : {
    1348              :     int ret = 0;
    1349              :     char tmp[PATH_MAX + 1];
    1350              :     char *p = NULL;
    1351              :     char *end = NULL;
    1352              :     size_t len;
    1353              : 
    1354              :     strncpy(tmp, dir, PATH_MAX);
    1355            9 :     len = strlen(tmp);
    1356              : 
    1357            9 :     if (tmp[len - 1] == '/')
    1358            0 :         tmp[len - 1] = 0;
    1359              : 
    1360            9 :     end = tmp + len;
    1361              : 
    1362           36 :     for (p = tmp + 1; ((*p) && (ret == 0)) || ((ret == -1 && errno == EEXIST) && (p != end)); p++)
    1363           27 :         if (*p == '/') {
    1364            0 :             *p = 0;
    1365              : 
    1366            0 :             if (access(tmp, F_OK) != 0 && errno == ENOENT) {
    1367            0 :                 ret = mkdir(tmp,
    1368              :                 #ifdef DLT_DAEMON_USE_FIFO_IPC
    1369              :                                 S_IRWXU);
    1370              :                 #else
    1371              :                     S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH  | S_IWOTH /*S_IRWXU*/);
    1372              :                 #endif
    1373              :             }
    1374              : 
    1375            0 :             *p = '/';
    1376              :         }
    1377              : 
    1378              : 
    1379              : 
    1380            9 :     if ((ret == 0) || ((ret == -1) && (errno == EEXIST)))
    1381            9 :         ret = mkdir(tmp,
    1382              :         #ifdef DLT_DAEMON_USE_FIFO_IPC
    1383              :                     S_IRWXU);
    1384              :         #else
    1385              :                     S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH  | S_IWOTH /*S_IRWXU*/);
    1386              :         #endif
    1387              : 
    1388            9 :     if ((ret == -1) && (errno == EEXIST))
    1389              :         ret = 0;
    1390              : 
    1391            9 :     return ret;
    1392              : }
    1393              : 
    1394              : #ifdef DLT_DAEMON_USE_FIFO_IPC
    1395            9 : static DltReturnValue dlt_daemon_create_pipes_dir(char *dir)
    1396              : {
    1397              :     int ret = DLT_RETURN_OK;
    1398              : 
    1399            9 :     if (dir == NULL) {
    1400            0 :         dlt_vlog(LOG_ERR, "%s: Invalid parameter\n", __func__);
    1401            0 :         return DLT_RETURN_WRONG_PARAMETER;
    1402              :     }
    1403              : 
    1404              :     /* create dlt pipes directory */
    1405            9 :     ret = mkdir(dir,
    1406              :                 S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH | S_ISVTX);
    1407              : 
    1408            9 :     if ((ret == -1) && (errno != EEXIST)) {
    1409            0 :         dlt_vlog(LOG_ERR,
    1410              :                  "FIFO user dir %s cannot be created (%s)!\n",
    1411              :                  dir,
    1412              :                  strerror(errno));
    1413              : 
    1414            0 :         return DLT_RETURN_ERROR;
    1415              :     }
    1416              : 
    1417              :     /* S_ISGID cannot be set by mkdir, let's reassign right bits */
    1418            9 :     ret = chmod(dir,
    1419              :                 S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH | S_ISGID |
    1420              :                 S_ISVTX);
    1421              : 
    1422            9 :     if (ret == -1) {
    1423            0 :         dlt_vlog(LOG_ERR,
    1424              :                  "FIFO user dir %s cannot be chmoded (%s)!\n",
    1425              :                  dir,
    1426            0 :                  strerror(errno));
    1427              : 
    1428            0 :         return DLT_RETURN_ERROR;
    1429              :     }
    1430              : 
    1431              :     return ret;
    1432              : }
    1433              : #endif
    1434              : // This will be defined when unit testing, so functions
    1435              : // from this file can be tested without defining main twice
    1436              : #ifndef DLT_DAEMON_UNIT_TESTS_NO_MAIN
    1437              : /**
    1438              :  * Main function of tool.
    1439              :  */
    1440            9 : int main(int argc, char *argv[])
    1441              : {
    1442              :     char version[DLT_DAEMON_TEXTBUFSIZE];
    1443              :     char local_str[DLT_DAEMON_TEXTBUFSIZE];
    1444              :     DltDaemonLocal daemon_local;
    1445              :     DltDaemon daemon;
    1446              :     int back = 0;
    1447              : 
    1448              :     memset(&daemon_local, 0, sizeof(DltDaemonLocal));
    1449              :     memset(&daemon, 0, sizeof(DltDaemon));
    1450              : 
    1451              :     /* Command line option handling */
    1452            9 :     if ((back = option_handling(&daemon_local, argc, argv)) < 0) {
    1453            0 :         if (back != -2)
    1454            0 :             fprintf (stderr, "option_handling() failed!\n");
    1455              : 
    1456            0 :         return -1;
    1457              :     }
    1458              : 
    1459              :     /* Configuration file option handling */
    1460            9 :     if ((back = option_file_parser(&daemon_local)) < 0) {
    1461            0 :         if (back != -2)
    1462            0 :             fprintf (stderr, "option_file_parser() failed!\n");
    1463              : 
    1464            0 :         return -1;
    1465              :     }
    1466              : 
    1467              :     /* Initialize internal logging facility */
    1468            9 :     dlt_log_set_filename(daemon_local.flags.loggingFilename);
    1469            9 :     dlt_log_set_level(daemon_local.flags.loggingLevel);
    1470              :     DltReturnValue log_init_result =
    1471            9 :             dlt_log_init_multiple_logfiles_support(daemon_local.flags.loggingMode,
    1472            9 :                                                    daemon_local.flags.enableLoggingFileLimit,
    1473              :                                                    daemon_local.flags.loggingFileSize,
    1474              :                                                    daemon_local.flags.loggingFileMaxSize);
    1475              : 
    1476            9 :     if (log_init_result != DLT_RETURN_OK) {
    1477            0 :       fprintf(stderr, "Failed to init internal logging\n");
    1478              : 
    1479              : #ifdef WITH_DLT_FILE_LOGGING_SYSLOG_FALLBACK
    1480              :         if (daemon_local.flags.loggingMode == DLT_LOG_TO_FILE) {
    1481              :           fprintf(stderr, "Falling back to syslog mode\n");
    1482              : 
    1483              :           daemon_local.flags.loggingMode = DLT_LOG_TO_SYSLOG;
    1484              :           log_init_result = dlt_log_init(daemon_local.flags.loggingMode);
    1485              :           if (log_init_result != DLT_RETURN_OK) {
    1486              :             fprintf(stderr, "Failed to setup syslog logging, internal logs will "
    1487              :                             "not be available\n");
    1488              :           }
    1489              :       }
    1490              : #endif
    1491              :     }
    1492              : 
    1493              :     /* Print version information */
    1494            9 :     dlt_get_version(version, DLT_DAEMON_TEXTBUFSIZE);
    1495              : 
    1496            9 :     dlt_vlog(LOG_NOTICE, "Starting DLT Daemon; %s\n", version);
    1497              : 
    1498            9 :     PRINT_FUNCTION_VERBOSE(daemon_local.flags.vflag);
    1499              : 
    1500              : /* Make sure the parent user directory is created */
    1501              : const char *dir_to_create;
    1502              : #ifdef DLT_DAEMON_USE_FIFO_IPC
    1503              :     dir_to_create = dltFifoBaseDir;
    1504              : #else
    1505              :     dir_to_create = DLT_USER_IPC_PATH;
    1506              : #endif
    1507            9 :     if (dlt_mkdir_recursive(dir_to_create) != 0) {
    1508            0 :         dlt_vlog(LOG_ERR, "Base dir %s cannot be created!\n", dir_to_create);
    1509            0 :         return -1;
    1510              :     }
    1511              : 
    1512              :     /* --- Daemon init phase 1 begin --- */
    1513            9 :     if (dlt_daemon_local_init_p1(&daemon, &daemon_local, daemon_local.flags.vflag) == -1) {
    1514            0 :         dlt_log(LOG_CRIT, "Initialization of phase 1 failed!\n");
    1515            0 :         return -1;
    1516              :     }
    1517              : 
    1518              :     /* --- Daemon init phase 1 end --- */
    1519              : 
    1520            9 :     if (dlt_daemon_prepare_event_handling(&daemon_local.pEvent)) {
    1521              :         /* TODO: Perform clean-up */
    1522            0 :         dlt_log(LOG_CRIT, "Initialization of event handling failed!\n");
    1523            0 :         return -1;
    1524              :     }
    1525              : 
    1526              :     /* --- Daemon connection init begin */
    1527            9 :     if (dlt_daemon_local_connection_init(&daemon, &daemon_local, daemon_local.flags.vflag) == -1) {
    1528            0 :         dlt_log(LOG_CRIT, "Initialization of local connections failed!\n");
    1529            0 :         return -1;
    1530              :     }
    1531              : 
    1532              :     /* --- Daemon connection init end */
    1533              : 
    1534            9 :     if (dlt_daemon_init_runtime_configuration(&daemon, daemon_local.flags.ivalue, daemon_local.flags.vflag) == -1) {
    1535            0 :         dlt_log(LOG_ERR, "Could not load runtime config\n");
    1536            0 :         return -1;
    1537              :     }
    1538              : 
    1539              :     /*
    1540              :      * Load dlt-runtime.cfg if available.
    1541              :      * This must be loaded before offline setup
    1542              :      */
    1543            9 :     dlt_daemon_configuration_load(&daemon, daemon.runtime_configuration, daemon_local.flags.vflag);
    1544              : 
    1545              :     /* --- Daemon init phase 2 begin --- */
    1546            9 :     if (dlt_daemon_local_init_p2(&daemon, &daemon_local, daemon_local.flags.vflag) == -1) {
    1547            0 :         dlt_log(LOG_CRIT, "Initialization of phase 2 failed!\n");
    1548            0 :         return -1;
    1549              :     }
    1550              : 
    1551              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
    1552              :     /* Load control app id level configuration file without setting `back` to
    1553              :      * prevent exit if file is missing */
    1554              :     if (app_id_default_log_level_config_parser(&daemon, &daemon_local) < 0) {
    1555              :         dlt_vlog(LOG_WARNING, "app_id_default_log_level_config_parser() failed, "
    1556              :                            "no app specific log levels will be configured\n");
    1557              :     }
    1558              : #endif
    1559              : 
    1560              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    1561              :     /* Load control trace load configuration file without setting `back` to prevent exit if file is missing */
    1562              :     pthread_rwlock_init(&trace_load_rw_lock, NULL);
    1563              :     if (trace_load_config_file_parser(&daemon, &daemon_local) < 0) {
    1564              :         dlt_vlog(LOG_WARNING, "trace_load_config_file_parser() failed, using defaults for all app ids!\n");
    1565              :     }
    1566              : #endif
    1567              : 
    1568              :     /* --- Daemon init phase 2 end --- */
    1569              : 
    1570            9 :     if (daemon_local.flags.offlineLogstorageDirPath[0])
    1571            6 :         if (dlt_daemon_logstorage_setup_internal_storage(
    1572              :                 &daemon,
    1573              :                 &daemon_local,
    1574              :                 daemon_local.flags.offlineLogstorageDirPath,
    1575              :                 daemon_local.flags.vflag) == -1)
    1576            0 :             dlt_log(LOG_INFO,
    1577              :                     "Setting up internal offline log storage failed!\n");
    1578              : 
    1579              :     /* create fd for watchdog */
    1580              : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
    1581              :     {
    1582              :         char *watchdogUSec = getenv("WATCHDOG_USEC");
    1583              :         // set a sensible default, in case the environment variable is not set
    1584              :         int watchdogTimeoutSeconds = 30;
    1585              : 
    1586              :         dlt_log(LOG_DEBUG, "Systemd watchdog initialization\n");
    1587              : 
    1588              :         if (watchdogUSec) {
    1589              :             // WATCHDOG_USEC is the timeout in micrsoseconds
    1590              :             // divide this by 2*10^6 to get the interval in seconds
    1591              :             // 2 * because we notify systemd after half the timeout
    1592              :             watchdogTimeoutSeconds = atoi(watchdogUSec) / 2000000;
    1593              :         }
    1594              : 
    1595              :         if (watchdogTimeoutSeconds == 0) {
    1596              :             dlt_log(LOG_WARNING, "Watchdog timeout is too small, need at least 1s, setting 30s timeout\n");
    1597              :             watchdogTimeoutSeconds = 30;
    1598              :         }
    1599              : 
    1600              :         daemon.watchdog_trigger_interval = watchdogTimeoutSeconds;
    1601              :         daemon.watchdog_last_trigger_time = 0U;
    1602              :         create_timer_fd(&daemon_local,
    1603              :                         watchdogTimeoutSeconds,
    1604              :                         watchdogTimeoutSeconds,
    1605              :                         DLT_TIMER_SYSTEMD);
    1606              :     }
    1607              : #endif
    1608              : 
    1609              :     /* create fd for timer timing packets */
    1610            9 :     create_timer_fd(&daemon_local, 1, 1, DLT_TIMER_PACKET);
    1611              : 
    1612              :     /* create fd for timer ecu version */
    1613            9 :     if ((daemon_local.flags.sendECUSoftwareVersion > 0) ||
    1614            9 :         (daemon_local.flags.sendTimezone > 0))
    1615            0 :         create_timer_fd(&daemon_local, 60, 60, DLT_TIMER_ECU);
    1616              : 
    1617              :     /* initiate gateway */
    1618            9 :     if (daemon_local.flags.gatewayMode == 1) {
    1619            1 :         if (dlt_gateway_init(&daemon_local, daemon_local.flags.vflag) == -1) {
    1620            0 :             dlt_log(LOG_CRIT, "Failed to create gateway\n");
    1621            0 :             return -1;
    1622              :         }
    1623              : 
    1624              :         /* create gateway timer */
    1625            1 :         create_timer_fd(&daemon_local,
    1626              :                         daemon_local.pGateway.interval,
    1627              :                         daemon_local.pGateway.interval,
    1628              :                         DLT_TIMER_GATEWAY);
    1629              :     }
    1630              : 
    1631              :     /* For offline tracing we still can use the same states */
    1632              :     /* as for socket sending. Using this trick we see the traces */
    1633              :     /* In the offline trace AND in the socket stream. */
    1634            9 :     if (daemon_local.flags.yvalue[0])
    1635            0 :         dlt_daemon_change_state(&daemon, DLT_DAEMON_STATE_SEND_DIRECT);
    1636              :     else
    1637            9 :         dlt_daemon_change_state(&daemon, DLT_DAEMON_STATE_BUFFER);
    1638              : 
    1639            9 :     dlt_daemon_init_user_information(&daemon,
    1640              :                                      &daemon_local.pGateway,
    1641              :                                      daemon_local.flags.gatewayMode,
    1642              :                                      daemon_local.flags.vflag);
    1643              : 
    1644              :     /*
    1645              :      * Check for app and ctx runtime cfg.
    1646              :      * These cfg must be loaded after ecuId and num_user_lists are available
    1647              :      */
    1648            9 :     if ((dlt_daemon_applications_load(&daemon, daemon.runtime_application_cfg,
    1649            0 :                                       daemon_local.flags.vflag) == 0) &&
    1650            0 :         (dlt_daemon_contexts_load(&daemon, daemon.runtime_context_cfg,
    1651              :                                   daemon_local.flags.vflag) == 0))
    1652            0 :         daemon.runtime_context_cfg_loaded = 1;
    1653              : 
    1654            9 :     dlt_daemon_log_internal(&daemon, &daemon_local,
    1655              :                             "Daemon launched. Starting to output traces...",
    1656              :                             DLT_LOG_INFO, DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID,
    1657              :                             daemon_local.flags.vflag);
    1658              : 
    1659              :     /* Even handling loop. */
    1660         1303 :     while ((back >= 0) && (g_exit >= 0))
    1661         1294 :         back = dlt_daemon_handle_event(&daemon_local.pEvent,
    1662              :                                        &daemon,
    1663              :                                        &daemon_local);
    1664              : 
    1665            9 :     snprintf(local_str, DLT_DAEMON_TEXTBUFSIZE, "Exiting DLT daemon... [%d]",
    1666              :              g_signo);
    1667            9 :     dlt_daemon_log_internal(&daemon, &daemon_local, local_str, DLT_LOG_INFO,
    1668              :                             DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID,
    1669              :                             daemon_local.flags.vflag);
    1670            9 :     dlt_vlog(LOG_NOTICE, "%s%s", local_str, "\n");
    1671              : 
    1672            9 :     dlt_daemon_local_cleanup(&daemon, &daemon_local, daemon_local.flags.vflag);
    1673              : 
    1674              : #ifdef UDP_CONNECTION_SUPPORT
    1675              :     dlt_daemon_udp_close_connection();
    1676              : #endif
    1677              : 
    1678            9 :     dlt_gateway_deinit(&daemon_local.pGateway, daemon_local.flags.vflag);
    1679              : 
    1680            9 :     dlt_daemon_free(&daemon, daemon_local.flags.vflag);
    1681              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    1682              :     dlt_trace_load_free(&daemon);
    1683              : #endif
    1684              : 
    1685            9 :     dlt_log(LOG_NOTICE, "Leaving DLT daemon\n");
    1686              : 
    1687            9 :     dlt_log_free();
    1688              : 
    1689            9 :     return 0;
    1690              : 
    1691              : } /* main() */
    1692              : #endif
    1693              : 
    1694              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    1695              : void dlt_trace_load_free(DltDaemon* daemon)
    1696              : {
    1697              :     if (daemon->preconfigured_trace_load_settings != NULL) {
    1698              :         free(daemon->preconfigured_trace_load_settings);
    1699              :         daemon->preconfigured_trace_load_settings = NULL;
    1700              :     }
    1701              :     pthread_rwlock_destroy(&trace_load_rw_lock);
    1702              : }
    1703              : #endif
    1704              : 
    1705              : 
    1706            9 : int dlt_daemon_local_init_p1(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
    1707              : {
    1708            9 :     PRINT_FUNCTION_VERBOSE(verbose);
    1709              :     int ret = DLT_RETURN_OK;
    1710              : 
    1711            9 :     if ((daemon == 0) || (daemon_local == 0)) {
    1712            0 :         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_local_init_p1()\n");
    1713            0 :         return -1;
    1714              :     }
    1715              : 
    1716              : #if defined(DLT_SYSTEMD_WATCHDOG_ENABLE) || defined(DLT_SYSTEMD_ENABLE)
    1717              :     ret = sd_booted();
    1718              : 
    1719              :     if (ret == 0) {
    1720              :         dlt_log(LOG_CRIT, "System not booted with systemd!\n");
    1721              :     }
    1722              :     else if (ret < 0)
    1723              :     {
    1724              :         dlt_log(LOG_CRIT, "sd_booted failed!\n");
    1725              :         return -1;
    1726              :     }
    1727              :     else {
    1728              :         dlt_log(LOG_INFO, "System booted with systemd\n");
    1729              :     }
    1730              : 
    1731              : #endif
    1732              : 
    1733              : #ifdef DLT_DAEMON_USE_FIFO_IPC
    1734              : 
    1735            9 :     if (dlt_daemon_create_pipes_dir(daemon_local->flags.userPipesDir) == DLT_RETURN_ERROR)
    1736              :         return DLT_RETURN_ERROR;
    1737              : 
    1738              : #endif
    1739              : 
    1740              :     /* Check for daemon mode */
    1741            9 :     if (daemon_local->flags.dflag)
    1742            2 :         dlt_daemon_daemonize(daemon_local->flags.vflag);
    1743              : 
    1744              :     /* initialise structure to use DLT file */
    1745            9 :     ret = dlt_file_init(&(daemon_local->file), daemon_local->flags.vflag);
    1746              : 
    1747            9 :     if (ret == DLT_RETURN_ERROR) {
    1748            0 :         dlt_log(LOG_ERR, "Could not initialize file structure\n");
    1749              :         /* Return value ignored, dlt daemon will exit */
    1750            0 :         dlt_file_free(&(daemon_local->file), daemon_local->flags.vflag);
    1751            0 :         return ret;
    1752              :     }
    1753              : 
    1754            9 :     signal(SIGPIPE, SIG_IGN);
    1755              : 
    1756            9 :     signal(SIGTERM, dlt_daemon_signal_handler); /* software termination signal from kill */
    1757            9 :     signal(SIGHUP, dlt_daemon_signal_handler);  /* hangup signal */
    1758            9 :     signal(SIGQUIT, dlt_daemon_signal_handler);
    1759            9 :     signal(SIGINT, dlt_daemon_signal_handler);
    1760              : #ifdef __QNX__
    1761              :     signal(SIGUSR1, dlt_daemon_signal_handler); /* for timer threads */
    1762              : #endif
    1763              : 
    1764            9 :     return DLT_RETURN_OK;
    1765              : }
    1766              : 
    1767            9 : int dlt_daemon_local_init_p2(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
    1768              : {
    1769            9 :     PRINT_FUNCTION_VERBOSE(verbose);
    1770              : 
    1771            9 :     if ((daemon == 0) || (daemon_local == 0)) {
    1772            0 :         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_local_init_p2()\n");
    1773            0 :         return -1;
    1774              :     }
    1775              : 
    1776              :     /* Daemon data */
    1777            9 :     if (dlt_daemon_init(daemon, daemon_local->RingbufferMinSize, daemon_local->RingbufferMaxSize,
    1778            9 :                         daemon_local->RingbufferStepSize, daemon_local->flags.ivalue,
    1779              :                         daemon_local->flags.contextLogLevel,
    1780              :                         daemon_local->flags.contextTraceStatus, daemon_local->flags.enforceContextLLAndTS,
    1781              :                         daemon_local->flags.vflag) == -1) {
    1782            0 :         dlt_log(LOG_ERR, "Could not initialize daemon data\n");
    1783            0 :         return -1;
    1784              :     }
    1785              : 
    1786              :     /* init offline trace */
    1787            9 :     if (((daemon->mode == DLT_USER_MODE_INTERNAL) || (daemon->mode == DLT_USER_MODE_BOTH)) &&
    1788            0 :         daemon_local->flags.offlineTraceDirectory[0]) {
    1789            0 :         if (multiple_files_buffer_init(&(daemon_local->offlineTrace),
    1790            0 :                                        daemon_local->flags.offlineTraceDirectory,
    1791              :                                        daemon_local->flags.offlineTraceFileSize,
    1792              :                                        daemon_local->flags.offlineTraceMaxSize,
    1793            0 :                                        daemon_local->flags.offlineTraceFilenameTimestampBased,
    1794              :                                        false,
    1795              :                                        DLT_OFFLINETRACE_FILENAME_BASE,
    1796              :                                        DLT_OFFLINETRACE_FILENAME_EXT) == -1) {
    1797            0 :             dlt_log(LOG_ERR, "Could not initialize offline trace\n");
    1798            0 :             return -1;
    1799              :         }
    1800              :     }
    1801              : 
    1802              :     /* Init offline logstorage for MAX devices */
    1803            9 :     if (daemon_local->flags.offlineLogstorageMaxDevices > 0) {
    1804            6 :         size_t max_devices = (size_t)daemon_local->flags.offlineLogstorageMaxDevices;
    1805            6 :         daemon->storage_handle = malloc(sizeof(DltLogStorage) * max_devices);
    1806              : 
    1807            6 :         if (daemon->storage_handle == NULL) {
    1808            0 :             dlt_log(LOG_ERR, "Could not initialize offline logstorage\n");
    1809            0 :             return -1;
    1810              :         }
    1811              : 
    1812              :         memset(daemon->storage_handle, 0, sizeof(DltLogStorage) * max_devices);
    1813              :     }
    1814              : 
    1815              :     /* Set ECU id of daemon */
    1816            9 :     if (daemon_local->flags.evalue[0])
    1817            1 :         dlt_set_id(daemon->ecuid, daemon_local->flags.evalue);
    1818              :     else
    1819            8 :         dlt_set_id(daemon->ecuid, DLT_DAEMON_ECU_ID);
    1820              : 
    1821              :     /* Set flag for optional sending of serial header */
    1822            9 :     daemon->sendserialheader = daemon_local->flags.lflag;
    1823              : 
    1824              : #ifdef DLT_SHM_ENABLE
    1825              : 
    1826              :     /* init shared memory */
    1827              :     if (dlt_shm_init_server(&(daemon_local->dlt_shm), daemon_local->flags.dltShmName,
    1828              :                             daemon_local->flags.sharedMemorySize) == DLT_RETURN_ERROR) {
    1829              :         dlt_log(LOG_ERR, "Could not initialize shared memory\n");
    1830              :         return -1;
    1831              :     }
    1832              : 
    1833              :     daemon_local->recv_buf_shm = (unsigned char *)calloc(1, DLT_SHM_RCV_BUFFER_SIZE);
    1834              : 
    1835              :     if (NULL == daemon_local->recv_buf_shm) {
    1836              :         dlt_log(LOG_ERR, "failed to allocated the buffer to receive shm data\n");
    1837              :         return -1;
    1838              :     }
    1839              : 
    1840              : #endif
    1841              : 
    1842              :     /* prepare main loop */
    1843            9 :     if (dlt_message_init(&(daemon_local->msg), daemon_local->flags.vflag) == DLT_RETURN_ERROR) {
    1844            0 :         dlt_log(LOG_ERR, "Could not initialize message\n");
    1845            0 :         return -1;
    1846              :     }
    1847              : 
    1848              :     /* configure sending timing packets */
    1849            9 :     if (daemon_local->flags.sendMessageTime)
    1850            0 :         daemon->timingpackets = 1;
    1851              : 
    1852              :     /* Get ECU version info from a file. If it fails, use dlt_version as fallback. */
    1853            9 :     if (dlt_daemon_local_ecu_version_init(daemon, daemon_local, daemon_local->flags.vflag) < 0) {
    1854            9 :         daemon->ECUVersionString = malloc(DLT_DAEMON_TEXTBUFSIZE);
    1855              : 
    1856            9 :         if (daemon->ECUVersionString == 0) {
    1857            0 :             dlt_log(LOG_WARNING, "Could not allocate memory for version string\n");
    1858            0 :             return -1;
    1859              :         }
    1860              : 
    1861            9 :         dlt_get_version(daemon->ECUVersionString, DLT_DAEMON_TEXTBUFSIZE);
    1862              :     }
    1863              : 
    1864              :     /* Set to allows one to maintain logstorage loglevel as default */
    1865            9 :     daemon->maintain_logstorage_loglevel = DLT_MAINTAIN_LOGSTORAGE_LOGLEVEL_ON;
    1866              : 
    1867            9 :     return 0;
    1868              : }
    1869              : 
    1870            9 : static int dlt_daemon_init_serial(DltDaemonLocal *daemon_local)
    1871              : {
    1872              :     /* create and open serial connection from/to client */
    1873              :     /* open serial connection */
    1874              :     int fd = -1;
    1875              : 
    1876            9 :     if (daemon_local->flags.yvalue[0] == '\0')
    1877              :         return 0;
    1878              : 
    1879            0 :     fd = open(daemon_local->flags.yvalue, O_RDWR);
    1880              : 
    1881            0 :     if (fd < 0) {
    1882            0 :         dlt_vlog(LOG_ERR, "Failed to open serial device %s\n",
    1883              :                  daemon_local->flags.yvalue);
    1884              : 
    1885            0 :         daemon_local->flags.yvalue[0] = 0;
    1886            0 :         return -1;
    1887              :     }
    1888              : 
    1889            0 :     if (isatty(fd)) {
    1890              :         int speed = DLT_DAEMON_SERIAL_DEFAULT_BAUDRATE;
    1891              : 
    1892            0 :         if (daemon_local->flags.bvalue[0])
    1893            0 :             speed = atoi(daemon_local->flags.bvalue);
    1894              : 
    1895            0 :         daemon_local->baudrate = dlt_convert_serial_speed(speed);
    1896              : 
    1897            0 :         if (dlt_setup_serial(fd, (speed_t) daemon_local->baudrate) < 0) {
    1898            0 :             close(fd);
    1899            0 :             daemon_local->flags.yvalue[0] = 0;
    1900              : 
    1901            0 :             dlt_vlog(LOG_ERR, "Failed to configure serial device %s (%s) \n",
    1902            0 :                      daemon_local->flags.yvalue, strerror(errno));
    1903              : 
    1904            0 :             return -1;
    1905              :         }
    1906              : 
    1907            0 :         if (daemon_local->flags.vflag)
    1908            0 :             dlt_log(LOG_DEBUG, "Serial init done\n");
    1909              :     }
    1910              :     else {
    1911            0 :         close(fd);
    1912            0 :         fprintf(stderr,
    1913              :                 "Device is not a serial device, device = %s (%s) \n",
    1914              :                 daemon_local->flags.yvalue,
    1915            0 :                 strerror(errno));
    1916            0 :         daemon_local->flags.yvalue[0] = 0;
    1917            0 :         return -1;
    1918              :     }
    1919              : 
    1920            0 :     return dlt_connection_create(daemon_local,
    1921              :                                  &daemon_local->pEvent,
    1922              :                                  fd,
    1923              :                                  POLLIN,
    1924              :                                  DLT_CONNECTION_CLIENT_MSG_SERIAL);
    1925              : }
    1926              : 
    1927              : #ifdef DLT_DAEMON_USE_FIFO_IPC
    1928            9 : static int dlt_daemon_init_fifo(DltDaemonLocal *daemon_local)
    1929              : {
    1930              :     int ret;
    1931              :     int fd = -1;
    1932              :     int fifo_size;
    1933              : 
    1934              :     /* open named pipe(FIFO) to receive DLT messages from users */
    1935            9 :     umask(0);
    1936              : 
    1937              :     /* Try to delete existing pipe, ignore result of unlink */
    1938            9 :     const char *tmpFifo = daemon_local->flags.daemonFifoName;
    1939            9 :     unlink(tmpFifo);
    1940              : 
    1941            9 :     ret = mkfifo(tmpFifo, S_IRUSR | S_IWUSR | S_IWGRP);
    1942              : 
    1943            9 :     if (ret == -1) {
    1944            0 :         dlt_vlog(LOG_WARNING, "FIFO user %s cannot be created (%s)!\n",
    1945            0 :                  tmpFifo, strerror(errno));
    1946            0 :         return -1;
    1947              :     } /* if */
    1948              : 
    1949              :     /* Set group of daemon FIFO */
    1950            9 :     if (daemon_local->flags.daemonFifoGroup[0] != 0) {
    1951            0 :         errno = 0;
    1952            0 :         struct group *group_dlt = getgrnam(daemon_local->flags.daemonFifoGroup);
    1953              : 
    1954            0 :         if (group_dlt) {
    1955            0 :             ret = chown(tmpFifo, (uid_t)-1, group_dlt->gr_gid);
    1956              : 
    1957            0 :             if (ret == -1)
    1958            0 :                 dlt_vlog(LOG_ERR, "FIFO user %s cannot be chowned to group %s (%s)\n",
    1959              :                          tmpFifo, daemon_local->flags.daemonFifoGroup,
    1960              :                          strerror(errno));
    1961              :         }
    1962            0 :         else if ((errno == 0) || (errno == ENOENT) || (errno == EBADF) || (errno == EPERM))
    1963              :         {
    1964            0 :             dlt_vlog(LOG_ERR, "Group name %s is not found (%s)\n",
    1965              :                      daemon_local->flags.daemonFifoGroup,
    1966              :                      strerror(errno));
    1967              :         }
    1968              :         else {
    1969            0 :             dlt_vlog(LOG_ERR, "Failed to get group id of %s (%s)\n",
    1970              :                      daemon_local->flags.daemonFifoGroup,
    1971              :                      strerror(errno));
    1972              :         }
    1973              :     }
    1974              : 
    1975              :     fd = open(tmpFifo, O_RDWR);
    1976              : 
    1977            9 :     if (fd == -1) {
    1978            0 :         dlt_vlog(LOG_WARNING, "FIFO user %s cannot be opened (%s)!\n",
    1979            0 :                  tmpFifo, strerror(errno));
    1980            0 :         return -1;
    1981              :     } /* if */
    1982              : 
    1983              : #ifdef __linux__
    1984              :     /* F_SETPIPE_SZ and F_GETPIPE_SZ are only supported for Linux.
    1985              :      * For other OSes it depends on its system e.g. pipe manager.
    1986              :      */
    1987            9 :     if (daemon_local->daemonFifoSize != 0) {
    1988              :         /* Set Daemon FIFO size */
    1989            0 :         if (fcntl(fd, F_SETPIPE_SZ, daemon_local->daemonFifoSize) == -1)
    1990            0 :             dlt_vlog(LOG_ERR, "set FIFO size error: %s\n", strerror(errno));
    1991              :     }
    1992              : 
    1993              :     /* Get Daemon FIFO size */
    1994            9 :     if ((fifo_size = fcntl(fd, F_GETPIPE_SZ, 0)) == -1)
    1995            0 :         dlt_vlog(LOG_ERR, "get FIFO size error: %s\n", strerror(errno));
    1996              :     else
    1997            9 :         dlt_vlog(LOG_INFO, "FIFO size: %d\n", fifo_size);
    1998              : #endif
    1999              : 
    2000              :     /* Early init, to be able to catch client (app) connections
    2001              :      * as soon as possible. This registration is automatically ignored
    2002              :      * during next execution.
    2003              :      */
    2004            9 :     return dlt_connection_create(daemon_local,
    2005              :                                  &daemon_local->pEvent,
    2006              :                                  fd,
    2007              :                                  POLLIN,
    2008              :                                  DLT_CONNECTION_APP_MSG);
    2009              : }
    2010              : #endif
    2011              : 
    2012              : #ifdef DLT_DAEMON_VSOCK_IPC_ENABLE
    2013              : static int dlt_daemon_init_vsock(DltDaemonLocal *daemon_local)
    2014              : {
    2015              :     int fd;
    2016              :     struct sockaddr_vm addr;
    2017              : 
    2018              :     fd = socket(AF_VSOCK, SOCK_STREAM, 0);
    2019              :     if (fd == -1) {
    2020              :         dlt_vlog(LOG_ERR, "Failed to create VSOCK socket: %s\n", strerror(errno));
    2021              :         return -1;
    2022              :     }
    2023              : 
    2024              :     memset(&addr, 0, sizeof(addr));
    2025              :     addr.svm_family = AF_VSOCK;
    2026              :     addr.svm_port = DLT_VSOCK_PORT;
    2027              :     addr.svm_cid = VMADDR_CID_ANY;
    2028              : 
    2029              :     if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) != 0) {
    2030              :         dlt_vlog(LOG_ERR, "Failed to bind VSOCK socket: %s\n", strerror(errno));
    2031              :         close(fd);
    2032              :         return -1;
    2033              :     }
    2034              : 
    2035              :     if (listen(fd, 1) != 0) {
    2036              :         dlt_vlog(LOG_ERR, "Failed to listen on VSOCK socket: %s\n", strerror(errno));
    2037              :         close(fd);
    2038              :         return -1;
    2039              :     }
    2040              : 
    2041              :     return dlt_connection_create(daemon_local,
    2042              :                                  &daemon_local->pEvent,
    2043              :                                  fd,
    2044              :                                  POLLIN,
    2045              :                                  DLT_CONNECTION_APP_CONNECT);
    2046              : }
    2047              : #endif
    2048              : 
    2049              : #ifdef DLT_DAEMON_USE_UNIX_SOCKET_IPC
    2050              : static DltReturnValue dlt_daemon_init_app_socket(DltDaemonLocal *daemon_local)
    2051              : {
    2052              :     /* socket access permission set to srw-rw-rw- (666) */
    2053              :     int mask = S_IXUSR | S_IXGRP | S_IXOTH;
    2054              :     DltReturnValue ret = DLT_RETURN_OK;
    2055              :     int fd = -1;
    2056              : 
    2057              :     if (daemon_local == NULL) {
    2058              :         dlt_vlog(LOG_ERR, "%s: Invalid function parameters\n", __func__);
    2059              :         return DLT_RETURN_ERROR;
    2060              :     }
    2061              : 
    2062              : #ifdef ANDROID
    2063              :     /* on android if we want to use security contexts on Unix sockets,
    2064              :      * they should be created by init (see dlt-daemon.rc in src/daemon)
    2065              :      * and recovered through the below API */
    2066              :     ret = dlt_daemon_unix_android_get_socket(&fd, daemon_local->flags.appSockPath);
    2067              :     if (ret < DLT_RETURN_OK) {
    2068              :         /* we failed to get app socket created by init.
    2069              :          * To avoid blocking users to launch dlt-daemon only through
    2070              :          * init on android (e.g: by hand for debugging purpose), try to
    2071              :          * create app socket by ourselves */
    2072              :         ret = dlt_daemon_unix_socket_open(&fd,
    2073              :                                           daemon_local->flags.appSockPath,
    2074              :                                           SOCK_STREAM,
    2075              :                                           mask);
    2076              :     }
    2077              : #else
    2078              :     ret = dlt_daemon_unix_socket_open(&fd,
    2079              :                                       daemon_local->flags.appSockPath,
    2080              :                                       SOCK_STREAM,
    2081              :                                       mask);
    2082              : #endif
    2083              :     if (ret == DLT_RETURN_OK) {
    2084              :         if (dlt_connection_create(daemon_local,
    2085              :                                   &daemon_local->pEvent,
    2086              :                                   fd,
    2087              :                                   POLLIN,
    2088              :                                   DLT_CONNECTION_APP_CONNECT)) {
    2089              :             dlt_log(LOG_CRIT, "Could not create connection for app socket.\n");
    2090              :             return DLT_RETURN_ERROR;
    2091              :         }
    2092              :     }
    2093              :     else {
    2094              :         dlt_log(LOG_CRIT, "Could not create and open app socket.\n");
    2095              :         return DLT_RETURN_ERROR;
    2096              :     }
    2097              : 
    2098              :     return ret;
    2099              : }
    2100              : #endif
    2101              : 
    2102            9 : static DltReturnValue dlt_daemon_initialize_control_socket(DltDaemonLocal *daemon_local)
    2103              : {
    2104              :     /* socket access permission set to srw-rw---- (660)  */
    2105              :     int mask = S_IXUSR | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH;
    2106              :     DltReturnValue ret = DLT_RETURN_OK;
    2107            9 :     int fd = -1;
    2108              : 
    2109            9 :     if (daemon_local == NULL) {
    2110            0 :         dlt_vlog(LOG_ERR, "%s: Invalid function parameters\n", __func__);
    2111            0 :         return -1;
    2112              :     }
    2113              : 
    2114              : #ifdef ANDROID
    2115              :     /* on android if we want to use security contexts on Unix sockets,
    2116              :      * they should be created by init (see dlt-daemon.rc in src/daemon)
    2117              :      * and recovered through the below API */
    2118              :     ret = dlt_daemon_unix_android_get_socket(&fd, daemon_local->flags.ctrlSockPath);
    2119              :     if (ret < DLT_RETURN_OK) {
    2120              :         /* we failed to get app socket created by init.
    2121              :          * To avoid blocking users to launch dlt-daemon only through
    2122              :          * init on android (e.g by hand for debugging purpose), try to
    2123              :          * create app socket by ourselves */
    2124              :         ret = dlt_daemon_unix_socket_open(&fd,
    2125              :                                           daemon_local->flags.ctrlSockPath,
    2126              :                                           SOCK_STREAM,
    2127              :                                           mask);
    2128              :     }
    2129              : #else
    2130            9 :     ret = dlt_daemon_unix_socket_open(&fd,
    2131            9 :                                       daemon_local->flags.ctrlSockPath,
    2132              :                                       SOCK_STREAM,
    2133              :                                       mask);
    2134              : #endif
    2135            9 :     if (ret == DLT_RETURN_OK) {
    2136            9 :         if (dlt_connection_create(daemon_local,
    2137              :                                   &daemon_local->pEvent,
    2138              :                                   fd,
    2139              :                                   POLLIN,
    2140              :                                   DLT_CONNECTION_CONTROL_CONNECT) < DLT_RETURN_OK) {
    2141            0 :             dlt_log(LOG_ERR, "Could not initialize control socket.\n");
    2142              :             ret = DLT_RETURN_ERROR;
    2143              :         }
    2144              :     }
    2145              : 
    2146              :     return ret;
    2147              : }
    2148              : 
    2149            9 : int dlt_daemon_local_connection_init(DltDaemon *daemon,
    2150              :                                      DltDaemonLocal *daemon_local,
    2151              :                                      int verbose)
    2152              : {
    2153            9 :     int fd = -1;
    2154              : 
    2155            9 :     PRINT_FUNCTION_VERBOSE(verbose);
    2156              : 
    2157            9 :     if ((daemon == NULL) || (daemon_local == NULL)) {
    2158            0 :         dlt_vlog(LOG_ERR, "%s: Invalid function parameters\n", __func__);
    2159            0 :         return -1;
    2160              :     }
    2161              : 
    2162            9 :     DltBindAddress_t *head = daemon_local->flags.ipNodes;
    2163              : 
    2164              : #ifdef DLT_DAEMON_USE_UNIX_SOCKET_IPC
    2165              :     /* create and open socket to receive incoming connections from user application */
    2166              :     if (dlt_daemon_init_app_socket(daemon_local) < DLT_RETURN_OK) {
    2167              :         dlt_log(LOG_ERR, "Unable to initialize app socket.\n");
    2168              :         return DLT_RETURN_ERROR;
    2169              :     }
    2170              : 
    2171              : #else /* DLT_DAEMON_USE_FIFO_IPC */
    2172              : 
    2173            9 :     if (dlt_daemon_init_fifo(daemon_local)) {
    2174            0 :         dlt_log(LOG_ERR, "Unable to initialize fifo.\n");
    2175            0 :         return DLT_RETURN_ERROR;
    2176              :     }
    2177              : 
    2178              : #endif
    2179              : 
    2180              : #ifdef DLT_DAEMON_VSOCK_IPC_ENABLE
    2181              :     if (dlt_daemon_init_vsock(daemon_local) != 0) {
    2182              :         dlt_log(LOG_ERR, "Unable to initialize app VSOCK socket.\n");
    2183              :         return DLT_RETURN_ERROR;
    2184              :     }
    2185              : #endif
    2186              : 
    2187              :     /* create and open socket to receive incoming connections from client */
    2188            9 :     daemon_local->client_connections = 0;
    2189              : 
    2190            9 :     if (head == NULL) { /* no IP set in BindAddress option, will use "0.0.0.0" as default */
    2191              : 
    2192            9 :         if (dlt_daemon_socket_open(&fd, daemon_local->flags.port, "0.0.0.0") == DLT_RETURN_OK) {
    2193            9 :             if (dlt_connection_create(daemon_local,
    2194              :                                       &daemon_local->pEvent,
    2195              :                                       fd,
    2196              :                                       POLLIN,
    2197              :                                       DLT_CONNECTION_CLIENT_CONNECT)) {
    2198            0 :                 dlt_log(LOG_ERR, "Could not initialize main socket.\n");
    2199            0 :                 return DLT_RETURN_ERROR;
    2200              :             }
    2201              :         }
    2202              :         else {
    2203            0 :             dlt_log(LOG_ERR, "Could not initialize main socket.\n");
    2204            0 :             return DLT_RETURN_ERROR;
    2205              :         }
    2206              :     }
    2207              :     else {
    2208              :         bool any_open = false;
    2209            0 :         while (head != NULL) { /* open socket for each IP in the bindAddress list */
    2210              : 
    2211            0 :             if (dlt_daemon_socket_open(&fd, daemon_local->flags.port, head->ip) == DLT_RETURN_OK) {
    2212            0 :                 if (dlt_connection_create(daemon_local,
    2213              :                                           &daemon_local->pEvent,
    2214              :                                           fd,
    2215              :                                           POLLIN,
    2216              :                                           DLT_CONNECTION_CLIENT_CONNECT)) {
    2217            0 :                     dlt_vlog(LOG_ERR, "Could not create connection, for binding %s\n", head->ip);
    2218              :                 } else {
    2219              :                     any_open = true;
    2220              :                 }
    2221              :             }
    2222              :             else {
    2223            0 :                 dlt_vlog(LOG_ERR, "Could not open main socket, for binding %s\n", head->ip);
    2224              :             }
    2225              : 
    2226            0 :             head = head->next;
    2227              :         }
    2228              : 
    2229            0 :         if (!any_open) {
    2230            0 :             dlt_vlog(LOG_ERR, "Failed create main socket for any configured binding\n");
    2231            0 :             return DLT_RETURN_ERROR;
    2232              :         }
    2233              :     }
    2234              : 
    2235              : #ifdef UDP_CONNECTION_SUPPORT
    2236              : 
    2237              :     if (daemon_local->UDPConnectionSetup == MULTICAST_CONNECTION_ENABLED) {
    2238              :         if (dlt_daemon_udp_connection_setup(daemon_local) < 0) {
    2239              :             dlt_log(LOG_ERR, "UDP fd creation failed\n");
    2240              :             return DLT_RETURN_ERROR;
    2241              :         }
    2242              :         else {
    2243              :             dlt_log(LOG_INFO, "UDP fd creation success\n");
    2244              :         }
    2245              :     }
    2246              : 
    2247              : #endif
    2248              : 
    2249              :     /* create and open unix socket to receive incoming connections from
    2250              :      * control application */
    2251            9 :     if (dlt_daemon_initialize_control_socket(daemon_local) < DLT_RETURN_OK) {
    2252            0 :         dlt_log(LOG_ERR, "Could not initialize control socket.\n");
    2253            0 :         return DLT_RETURN_ERROR;
    2254              :     }
    2255              : 
    2256              :     /* Init serial */
    2257            9 :     if (dlt_daemon_init_serial(daemon_local) < 0) {
    2258            0 :         dlt_log(LOG_ERR, "Could not initialize daemon data\n");
    2259            0 :         return DLT_RETURN_ERROR;
    2260              :     }
    2261              : 
    2262              :     return 0;
    2263              : }
    2264              : 
    2265            0 : static char* file_read_everything(FILE* const file, const size_t sizeLimit)
    2266              : {
    2267            0 :     if (!file) {
    2268              :         return NULL;
    2269              :     }
    2270              : 
    2271              :     /* Get the file size. Bail out if stat fails. */
    2272            0 :     const int fd = fileno(file);
    2273            0 :     struct stat s_buf = {0};
    2274            0 :     if (fstat(fd, &s_buf) < 0) {
    2275            0 :         dlt_log(LOG_WARNING, "failed to stat file size\n");
    2276            0 :         fclose(file);
    2277            0 :         return NULL;
    2278              :     }
    2279              : 
    2280              :     /* Size limit includes NULL terminator. */
    2281            0 :     const off_t size = s_buf.st_size;
    2282            0 :     if (size < 0 || (size_t)size >= sizeLimit) {
    2283            0 :         dlt_log(LOG_WARNING, "file size invalid\n");
    2284            0 :         fclose(file);
    2285            0 :         return NULL;
    2286              :     }
    2287              : 
    2288            0 :     char* const string = malloc((size_t)size + 1);
    2289            0 :     if (!string) {
    2290            0 :         dlt_log(LOG_WARNING, "failed to allocate string for file contents\n");
    2291            0 :         fclose(file);
    2292            0 :         return NULL;
    2293              :     }
    2294              : 
    2295              :     off_t offset = 0;
    2296            0 :     while (!feof(file)) {
    2297            0 :         offset += (off_t)fread(string + offset, 1, (size_t)size, file);
    2298              : 
    2299            0 :         if (ferror(file)) {
    2300            0 :             dlt_log(LOG_WARNING, "failed to read file\n");
    2301            0 :             free(string);
    2302            0 :             fclose(file);
    2303            0 :             return NULL;
    2304              :         }
    2305              : 
    2306            0 :         if (offset > size) {
    2307            0 :             dlt_log(LOG_WARNING, "file too long for buffer\n");
    2308            0 :             free(string);
    2309            0 :             fclose(file);
    2310            0 :             return NULL;
    2311              :         }
    2312              :     }
    2313              : 
    2314            0 :     string[offset] = '\0'; /* append null termination at end of string */
    2315              : 
    2316            0 :     return string;
    2317              : }
    2318              : 
    2319            0 : static char* file_read_field(FILE* const file, const char* const fieldName)
    2320              : {
    2321            0 :     if (!file) {
    2322              :         return NULL;
    2323              :     }
    2324              : 
    2325              :     const char* const kDelimiters = "\r\n\"\'=";
    2326            0 :     const size_t fieldNameLen = strlen(fieldName);
    2327              : 
    2328              :     char* result = NULL;
    2329              : 
    2330            0 :     char* buffer = NULL;
    2331            0 :     size_t bufferSize = 0;
    2332              : 
    2333              :     while (true) {
    2334              :         ssize_t lineSize = getline(&buffer, &bufferSize, file);
    2335            0 :         if (lineSize < 0 || !buffer) {
    2336              :             /* end of file */
    2337              :             break;
    2338              :         }
    2339              : 
    2340              :         char* line = buffer;
    2341              : 
    2342              :         /* trim trailing delimiters */
    2343            0 :         while (lineSize >= 1 && strchr(kDelimiters, line[lineSize - 1]) != NULL) {
    2344            0 :             line[lineSize - 1] = '\0';
    2345            0 :             --lineSize;
    2346              :         }
    2347              : 
    2348              :         /* check fieldName */
    2349            0 :         if (strncmp(line, fieldName, fieldNameLen) == 0 &&
    2350            0 :             (size_t)lineSize >= (fieldNameLen + 1) &&
    2351            0 :             strchr(kDelimiters, line[fieldNameLen]) != NULL) {
    2352              :             /* trim fieldName */
    2353              :             line += fieldNameLen;
    2354              : 
    2355              :             /* trim delimiter */
    2356            0 :             ++line;
    2357              : 
    2358              :             /* trim leading delimiters */
    2359            0 :             while (*line != '\0' && strchr(kDelimiters, *line) != NULL) {
    2360            0 :                 ++line;
    2361              :                 --lineSize;
    2362              :             }
    2363              : 
    2364            0 :             result = strdup(line);
    2365            0 :             break;
    2366              :         }
    2367              :     }
    2368              : 
    2369            0 :     free(buffer);
    2370              : 
    2371            0 :     return result;
    2372              : }
    2373              : 
    2374            9 : int dlt_daemon_local_ecu_version_init(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
    2375              : {
    2376              :     FILE *f = NULL;
    2377              : 
    2378            9 :     PRINT_FUNCTION_VERBOSE(verbose);
    2379              : 
    2380              :     /* By default, version string is null. */
    2381            9 :     daemon->ECUVersionString = NULL;
    2382              : 
    2383              :     /* Open the file. Bail out if error occurs */
    2384            9 :     f = fopen(daemon_local->flags.pathToECUSoftwareVersion, "r");
    2385              : 
    2386            9 :     if (f == NULL) {
    2387              :         /* Error level notice, because this might be deliberate choice */
    2388            9 :         dlt_log(LOG_NOTICE, "Failed to open ECU Software version file.\n");
    2389            9 :         return -1;
    2390              :     }
    2391              : 
    2392            0 :     if (daemon_local->flags.ecuSoftwareVersionFileField[0] != '\0') {
    2393            0 :         daemon->ECUVersionString = file_read_field(f, daemon_local->flags.ecuSoftwareVersionFileField);
    2394              :     } else {
    2395            0 :         daemon->ECUVersionString = file_read_everything(f, DLT_DAEMON_TEXTBUFSIZE);
    2396              :     }
    2397              : 
    2398            0 :     fclose(f);
    2399              : 
    2400            0 :     return (daemon->ECUVersionString != NULL) ? 0 : -1;
    2401              : }
    2402              : 
    2403            9 : void dlt_daemon_local_cleanup(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
    2404              : {
    2405            9 :     PRINT_FUNCTION_VERBOSE(verbose);
    2406              : 
    2407            9 :     if ((daemon == 0) || (daemon_local == 0)) {
    2408            0 :         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_local_cleanup()\n");
    2409            0 :         return;
    2410              :     }
    2411              : 
    2412              :     /* Don't receive event anymore */
    2413            9 :     dlt_event_handler_cleanup_connections(&daemon_local->pEvent);
    2414              : 
    2415            9 :     dlt_message_free(&(daemon_local->msg), daemon_local->flags.vflag);
    2416              : 
    2417              :     /* free shared memory */
    2418            9 :     if (daemon_local->flags.offlineTraceDirectory[0])
    2419            0 :         multiple_files_buffer_free(&(daemon_local->offlineTrace));
    2420              : 
    2421              :     /* Ignore result */
    2422            9 :     dlt_file_free(&(daemon_local->file), daemon_local->flags.vflag);
    2423              : 
    2424              : #ifdef DLT_DAEMON_USE_FIFO_IPC
    2425              :     /* Try to delete existing pipe, ignore result of unlink() */
    2426            9 :     unlink(daemon_local->flags.daemonFifoName);
    2427              : #else /* DLT_DAEMON_USE_UNIX_SOCKET_IPC */
    2428              :     /* Try to delete existing pipe, ignore result of unlink() */
    2429              : #ifdef DLT_DAEMON_USE_UNIX_SOCKET_IPC
    2430              :     if (unlink(daemon_local->flags.appSockPath) != 0) {
    2431              :         dlt_vlog(LOG_WARNING, "%s: unlink() failed: %s\n",
    2432              :                 __func__, strerror(errno));
    2433              :     }
    2434              : #endif
    2435              : #endif
    2436              : 
    2437              : #ifdef DLT_SHM_ENABLE
    2438              :     /* free shared memory */
    2439              :     dlt_shm_free_server(&(daemon_local->dlt_shm), daemon_local->flags.dltShmName);
    2440              :     free(daemon_local->recv_buf_shm);
    2441              :     daemon_local->recv_buf_shm = NULL;
    2442              : #endif
    2443              : 
    2444            9 :     if (daemon_local->flags.offlineLogstorageMaxDevices > 0) {
    2445              :         /* disconnect all logstorage devices */
    2446            6 :         dlt_daemon_logstorage_cleanup(daemon,
    2447              :                                       daemon_local,
    2448              :                                       daemon_local->flags.vflag);
    2449              : 
    2450            6 :         free(daemon->storage_handle);
    2451              :     }
    2452              : 
    2453            9 :     if (daemon->ECUVersionString != NULL)
    2454            9 :         free(daemon->ECUVersionString);
    2455              : 
    2456            9 :     if (unlink(daemon_local->flags.ctrlSockPath) != 0) {
    2457            1 :         dlt_vlog(LOG_WARNING, "%s: unlink() failed: %s\n",
    2458            1 :                 __func__, strerror(errno));
    2459              :     }
    2460              : 
    2461              :     /* free IP list */
    2462            9 :     free(daemon_local->flags.ipNodes);
    2463              : }
    2464              : 
    2465            9 : void dlt_daemon_exit_trigger()
    2466              : {
    2467              :     /* stop event loop */
    2468            9 :     g_exit = -1;
    2469              : 
    2470              : #ifdef DLT_DAEMON_USE_FIFO_IPC
    2471            9 :     char tmp[DLT_PATH_MAX] = { 0 };
    2472              : 
    2473              :     ssize_t n;
    2474            9 :     n = snprintf(tmp, DLT_PATH_MAX, "%s/dlt", dltFifoBaseDir);
    2475            9 :     if (n < 0 || (size_t)n > DLT_PATH_MAX) {
    2476            0 :         dlt_vlog(LOG_WARNING, "%s: snprintf truncation/error(%ld) %s\n",
    2477              :                 __func__, n, tmp);
    2478              :     }
    2479              : 
    2480            9 :     (void)unlink(tmp);
    2481              : #endif
    2482              : 
    2483              : #ifdef __QNX__
    2484              :     dlt_daemon_cleanup_timers();
    2485              : #endif
    2486              : 
    2487            9 : }
    2488              : 
    2489            9 : void dlt_daemon_signal_handler(int sig)
    2490              : {
    2491            9 :     g_signo = sig;
    2492              : 
    2493            9 :     switch (sig) {
    2494            9 :         case SIGHUP:
    2495              :         case SIGTERM:
    2496              :         case SIGINT:
    2497              :         case SIGQUIT:
    2498              :         {
    2499              :             /* finalize the server */
    2500            9 :             dlt_vlog(LOG_NOTICE, "Exiting DLT daemon due to signal: %s\n",
    2501              :                      strsignal(sig));
    2502            9 :             dlt_daemon_exit_trigger();
    2503            9 :             break;
    2504              :         }
    2505              :         default:
    2506              :         {
    2507              :             /* This case should never happen! */
    2508              :             break;
    2509              :         }
    2510              :     } /* switch */
    2511              : 
    2512            9 : } /* dlt_daemon_signal_handler() */
    2513              : 
    2514              : #ifdef __QNX__
    2515              : void dlt_daemon_cleanup_timers()
    2516              : {
    2517              :     int i = 0;
    2518              :     while (i < DLT_TIMER_UNKNOWN) {
    2519              :         /* Remove FIFO of every timer and kill timer thread */
    2520              :         if (0 != timer_threads[i]) {
    2521              :             pthread_kill(timer_threads[i], SIGUSR1);
    2522              :             pthread_join(timer_threads[i], NULL);
    2523              :             timer_threads[i] = 0;
    2524              : 
    2525              :             close_pipes(dlt_timer_pipes[i]);
    2526              : 
    2527              :             /* Free data of every timer */
    2528              :             if (NULL != timer_data[i]) {
    2529              :                 free(timer_data[i]);
    2530              :                 timer_data[i] = NULL;
    2531              :             }
    2532              :         }
    2533              :         i++;
    2534              :     }
    2535              : }
    2536              : #endif
    2537              : 
    2538            2 : void dlt_daemon_daemonize(int verbose)
    2539              : {
    2540              :     int i;
    2541              :     int fd;
    2542              : 
    2543            2 :     PRINT_FUNCTION_VERBOSE(verbose);
    2544              : 
    2545            2 :     dlt_log(LOG_NOTICE, "Daemon mode\n");
    2546              : 
    2547              :     /* Daemonize */
    2548            2 :     i = fork();
    2549              : 
    2550            4 :     if (i < 0) {
    2551            0 :         dlt_log(LOG_CRIT, "Unable to fork(), exiting DLT daemon\n");
    2552            0 :         exit(-1); /* fork error */
    2553              :     }
    2554              : 
    2555            4 :     if (i > 0)
    2556            2 :         exit(0); /* parent exits */
    2557              : 
    2558              :     /* child (daemon) continues */
    2559              : 
    2560              :     /* Process independency */
    2561              : 
    2562              :     /* obtain a new process group */
    2563            2 :     if (setsid() == -1) {
    2564            0 :         dlt_log(LOG_CRIT, "setsid() failed, exiting DLT daemon\n");
    2565            0 :         exit(-1); /* fork error */
    2566              :     }
    2567              : 
    2568              :     /* Open standard descriptors stdin, stdout, stderr */
    2569              :     fd = open("/dev/null", O_RDWR);
    2570              : 
    2571            2 :     if (fd != -1) {
    2572              :         /* Redirect STDOUT to /dev/null */
    2573            2 :         if (dup2(fd, STDOUT_FILENO) < 0)
    2574            0 :             dlt_vlog(LOG_WARNING, "Failed to direct stdout to /dev/null. Error: %s\n", strerror(errno));
    2575              : 
    2576              :         /* Redirect STDERR to /dev/null */
    2577            2 :         if (dup2(fd, STDERR_FILENO) < 0)
    2578            0 :             dlt_vlog(LOG_WARNING, "Failed to direct stderr to /dev/null. Error: %s\n", strerror(errno));
    2579              : 
    2580            2 :         close(fd);
    2581              :     }
    2582              :     else {
    2583            0 :         dlt_log(LOG_CRIT, "Error opening /dev/null, exiting DLT daemon\n");
    2584            0 :         exit(-1); /* fork error */
    2585              :     }
    2586              : 
    2587              :     /* Set umask */
    2588            2 :     umask(DLT_DAEMON_UMASK);
    2589              : 
    2590              :     /* Change to root directory */
    2591            2 :     if (chdir("/") < 0)
    2592            0 :         dlt_log(LOG_WARNING, "Failed to chdir to root\n");
    2593              : 
    2594              :     /* Catch signals */
    2595            2 :     signal(SIGCHLD, SIG_IGN); /* ignore child */
    2596            2 :     signal(SIGTSTP, SIG_IGN); /* ignore tty signals */
    2597            2 :     signal(SIGTTOU, SIG_IGN);
    2598            2 :     signal(SIGTTIN, SIG_IGN);
    2599              : 
    2600            2 : } /* dlt_daemon_daemonize() */
    2601              : 
    2602              : /* This function logs str to the configured output sink (socket, serial, offline trace).
    2603              :  * To avoid recursion this function must be called only from DLT highlevel functions.
    2604              :  * E. g. calling it to output a failure when the open of the offline trace file fails
    2605              :  * would cause an endless loop because dlt_daemon_log_internal() would itself again try
    2606              :  * to open the offline trace file.
    2607              :  * This is a dlt-daemon only function. The libdlt has no equivalent function available. */
    2608           40 : int dlt_daemon_log_internal(DltDaemon *daemon, DltDaemonLocal *daemon_local,
    2609              :                             char *str, DltLogLevelType level,
    2610              :                             const char *app_id, const char *ctx_id, int verbose)
    2611              : {
    2612           40 :     DltMessage msg = { 0 };
    2613              :     static uint8_t uiMsgCount = 0;
    2614              :     DltStandardHeaderExtra *pStandardExtra = NULL;
    2615              :     uint32_t uiType;
    2616              :     uint16_t uiSize;
    2617              :     uint32_t uiExtraSize;
    2618              : 
    2619           40 :     PRINT_FUNCTION_VERBOSE(verbose);
    2620              : 
    2621              :     /* Set storageheader */
    2622           40 :     msg.storageheader = (DltStorageHeader *)(msg.headerbuffer);
    2623           40 :     dlt_set_storageheader(msg.storageheader, daemon->ecuid);
    2624              : 
    2625              :     /* Set standardheader */
    2626           40 :     msg.standardheader = (DltStandardHeader *)(msg.headerbuffer + sizeof(DltStorageHeader));
    2627           40 :     msg.standardheader->htyp = DLT_HTYP_UEH | DLT_HTYP_WEID | DLT_HTYP_WSID | DLT_HTYP_WTMS |
    2628              :         DLT_HTYP_PROTOCOL_VERSION1;
    2629           40 :     msg.standardheader->mcnt = uiMsgCount++;
    2630              : 
    2631              :     uiExtraSize = (uint32_t) (DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp) +
    2632              :         (DLT_IS_HTYP_UEH(msg.standardheader->htyp) ? sizeof(DltExtendedHeader) : 0));
    2633           40 :     msg.headersize = (int32_t)((size_t)sizeof(DltStorageHeader) + (size_t)sizeof(DltStandardHeader) + (size_t)uiExtraSize);
    2634              : 
    2635              :     /* Set extraheader */
    2636              :     pStandardExtra =
    2637              :         (DltStandardHeaderExtra *)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader));
    2638           40 :     dlt_set_id(pStandardExtra->ecu, daemon->ecuid);
    2639           40 :     pStandardExtra->tmsp = DLT_HTOBE_32(dlt_uptime());
    2640           40 :     pStandardExtra->seid = DLT_HTOBE_32((uint32_t)getpid());
    2641              : 
    2642              :     /* Set extendedheader */
    2643           40 :     msg.extendedheader =
    2644           40 :         (DltExtendedHeader *)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) +
    2645           40 :                               DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp));
    2646           40 :     msg.extendedheader->msin = (uint8_t)(DLT_MSIN_VERB | (DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT) |
    2647              :         ((level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN));
    2648           40 :     msg.extendedheader->noar = 1;
    2649           40 :     dlt_set_id(msg.extendedheader->apid, app_id);
    2650           40 :     dlt_set_id(msg.extendedheader->ctid, ctx_id);
    2651              : 
    2652              :     /* Set payload data... */
    2653           40 :     uiType = DLT_TYPE_INFO_STRG;
    2654           40 :     uiSize = (uint16_t) (strlen(str) + 1);
    2655           40 :     msg.datasize = (int32_t)((size_t)sizeof(uint32_t) + (size_t)sizeof(uint16_t) + (size_t)uiSize);
    2656              : 
    2657           40 :     msg.databuffer = (uint8_t *)malloc((size_t) msg.datasize);
    2658           40 :     msg.databuffersize = (int32_t)msg.datasize;
    2659              : 
    2660           40 :     if (msg.databuffer == 0) {
    2661            0 :         dlt_log(LOG_WARNING, "Can't allocate buffer for get log info message\n");
    2662            0 :         return -1;
    2663              :     }
    2664              : 
    2665           40 :     msg.datasize = 0;
    2666              :     memcpy((uint8_t *)(msg.databuffer + msg.datasize), (uint8_t *)(&uiType), sizeof(uint32_t));
    2667           40 :     msg.datasize += (int32_t)sizeof(uint32_t);
    2668           40 :     memcpy((uint8_t *)(msg.databuffer + msg.datasize), (uint8_t *)(&uiSize), sizeof(uint16_t));
    2669           40 :     msg.datasize += (int32_t)sizeof(uint16_t);
    2670           40 :     memcpy((uint8_t *)(msg.databuffer + msg.datasize), str, uiSize);
    2671           40 :     msg.datasize += (int32_t)uiSize;
    2672              : 
    2673              :     /* Calc length */
    2674           40 :     msg.standardheader->len = DLT_HTOBE_16((size_t)msg.headersize - sizeof(DltStorageHeader) + (size_t)msg.datasize);
    2675              : 
    2676           40 :     dlt_daemon_client_send(DLT_DAEMON_SEND_TO_ALL, daemon,daemon_local,
    2677              :                            msg.headerbuffer, sizeof(DltStorageHeader),
    2678              :                            msg.headerbuffer + sizeof(DltStorageHeader),
    2679              :                            (size_t)(msg.headersize - (int32_t)sizeof(DltStorageHeader)),
    2680           40 :                            msg.databuffer, (size_t)msg.datasize, verbose);
    2681              : 
    2682           40 :     free(msg.databuffer);
    2683              : 
    2684           40 :     return 0;
    2685              : }
    2686              : 
    2687            3 : int dlt_daemon_check_numeric_setting(char *token,
    2688              :                                     char *value,
    2689              :                                     unsigned long *data)
    2690            3 : {
    2691            3 :     char value_check[value_length];
    2692            3 :     value_check[0] = 0;
    2693            3 :     sscanf(value, "%lu%s", data, value_check);
    2694            3 :     if (value_check[0] || !isdigit(value[0])) {
    2695            0 :         fprintf(stderr, "Invalid input [%s] detected in option %s\n",
    2696              :                 value,
    2697              :                 token);
    2698            0 :         return -1;
    2699              :     }
    2700              :     return 0;
    2701              : }
    2702              : 
    2703            4 : int dlt_daemon_process_client_connect(DltDaemon *daemon,
    2704              :                                       DltDaemonLocal *daemon_local,
    2705              :                                       DltReceiver *receiver,
    2706              :                                       int verbose)
    2707              : {
    2708              :     socklen_t cli_size;
    2709              :     struct sockaddr_un cli;
    2710              : 
    2711              :     int in_sock = -1;
    2712            4 :     char local_str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' };
    2713              : 
    2714            4 :     PRINT_FUNCTION_VERBOSE(verbose);
    2715              : 
    2716            4 :     if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
    2717            0 :         dlt_log(LOG_ERR,
    2718              :                 "Invalid function parameters used for function "
    2719              :                 "dlt_daemon_process_client_connect()\n");
    2720            0 :         return -1;
    2721              :     }
    2722              : 
    2723              :     /* event from TCP server socket, new connection */
    2724            4 :     cli_size = sizeof(cli);
    2725              : 
    2726            4 :     if ((in_sock = accept(receiver->fd, (struct sockaddr *)&cli, &cli_size)) < 0) {
    2727            0 :         if (errno == ECONNABORTED) // Caused by nmap -v -p 3490 -Pn <IP of dlt-daemon>
    2728              :             return 0;
    2729            0 :         dlt_vlog(LOG_ERR, "accept() for socket %d failed: %s\n", receiver->fd, strerror(errno));
    2730            0 :         return -1;
    2731              :     }
    2732              : 
    2733              :     /* check if file file descriptor was already used, and make it invalid if it
    2734              :      * is reused. */
    2735              :     /* This prevents sending messages to wrong file descriptor */
    2736            4 :     dlt_daemon_applications_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
    2737            4 :     dlt_daemon_contexts_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
    2738              : 
    2739              :     /* Set socket timeout in reception */
    2740              :     struct timeval timeout_send;
    2741            4 :     timeout_send.tv_sec = daemon_local->timeoutOnSend;
    2742            4 :     timeout_send.tv_usec = 0;
    2743              : 
    2744            4 :     if (setsockopt (in_sock,
    2745              :                     SOL_SOCKET,
    2746              :                     SO_SNDTIMEO,
    2747              :                     (char *)&timeout_send,
    2748              :                     sizeof(timeout_send)) < 0)
    2749            0 :         dlt_log(LOG_WARNING, "setsockopt failed\n");
    2750              : 
    2751            4 :     if (dlt_connection_create(daemon_local,
    2752              :                               &daemon_local->pEvent,
    2753              :                               in_sock,
    2754              :                               POLLIN,
    2755              :                               DLT_CONNECTION_CLIENT_MSG_TCP)) {
    2756            0 :         dlt_log(LOG_ERR, "Failed to register new client. \n");
    2757            0 :         close(in_sock);
    2758            0 :         return -1;
    2759              :     }
    2760              : 
    2761              :     /* send connection info about connected */
    2762            4 :     dlt_daemon_control_message_connection_info(in_sock,
    2763              :                                                daemon,
    2764              :                                                daemon_local,
    2765              :                                                DLT_CONNECTION_STATUS_CONNECTED,
    2766              :                                                "",
    2767              :                                                verbose);
    2768              : 
    2769              :     /* send ecu version string */
    2770            4 :     if (daemon_local->flags.sendECUSoftwareVersion > 0) {
    2771              :         if (daemon_local->flags.sendECUSoftwareVersion > 0)
    2772            0 :             dlt_daemon_control_get_software_version(DLT_DAEMON_SEND_TO_ALL,
    2773              :                                                     daemon,
    2774              :                                                     daemon_local,
    2775              :                                                     daemon_local->flags.vflag);
    2776              : 
    2777            0 :         if (daemon_local->flags.sendTimezone > 0)
    2778            0 :             dlt_daemon_control_message_timezone(DLT_DAEMON_SEND_TO_ALL,
    2779              :                                                 daemon,
    2780              :                                                 daemon_local,
    2781              :                                                 daemon_local->flags.vflag);
    2782              :     }
    2783              : 
    2784            4 :     snprintf(local_str, DLT_DAEMON_TEXTBUFSIZE,
    2785              :              "New client connection #%d established, Total Clients : %d",
    2786              :              in_sock, daemon_local->client_connections);
    2787              : 
    2788            4 :     dlt_daemon_log_internal(daemon, daemon_local, local_str, DLT_LOG_INFO,
    2789              :                             DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID,
    2790              :                             daemon_local->flags.vflag);
    2791            4 :     dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
    2792              : 
    2793            4 :     if (daemon_local->client_connections == 1) {
    2794            2 :         if (daemon_local->flags.vflag)
    2795            0 :             dlt_log(LOG_DEBUG, "Send ring-buffer to client\n");
    2796              : 
    2797            2 :         dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_BUFFER);
    2798              : 
    2799            2 :         if (dlt_daemon_send_ringbuffer_to_client(daemon, daemon_local, verbose) == -1) {
    2800            0 :             dlt_log(LOG_WARNING, "Can't send contents of ringbuffer to clients\n");
    2801            0 :             close(in_sock);
    2802              :             in_sock = -1;
    2803            0 :             return -1;
    2804              :         }
    2805              : 
    2806              :         /* send new log state to all applications */
    2807            2 :         daemon->connectionState = 1;
    2808            2 :         dlt_daemon_user_send_all_log_state(daemon, verbose);
    2809              : 
    2810              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    2811              :         /* Reset number of received bytes from FIFO */
    2812              :         daemon->bytes_recv = 0;
    2813              : #endif
    2814              :     }
    2815              : 
    2816              :     return 0;
    2817              : }
    2818              : 
    2819              : /**
    2820              :  * Create a sanitized copy of the message for control processing
    2821              :  * This breaks the taint chain by creating a new clean message structure
    2822              :  * Uses allow list validation for all path-containing messages
    2823              :  * @param tainted_msg The tainted message from receiver
    2824              :  * @param secure_msg The secure message to populate (output)
    2825              :  * @return 0 on success, -1 on validation failure
    2826              :  */
    2827            2 : static int dlt_daemon_create_secure_message(DltMessage *tainted_msg, DltMessage *secure_msg)
    2828              : {
    2829              :     uint32_t service_id;
    2830              :     DltServiceOfflineLogstorage *tainted_req;
    2831              :     DltServiceOfflineLogstorage *secure_req;
    2832              :     char secure_mount_point[DLT_MOUNT_PATH_MAX];
    2833              :     size_t i;
    2834              : 
    2835            2 :     if ((tainted_msg == NULL) || (secure_msg == NULL))
    2836              :         return -1;
    2837              : 
    2838              :     /* Initialize secure message with clean data */
    2839              :     memset(secure_msg, 0, sizeof(DltMessage));
    2840              : 
    2841              :     /* Copy safe, non-tainted fields from message structure */
    2842            2 :     secure_msg->headersize = tainted_msg->headersize;
    2843            2 :     secure_msg->datasize = tainted_msg->datasize;
    2844            2 :     secure_msg->found_serialheader = tainted_msg->found_serialheader;
    2845            2 :     secure_msg->resync_offset = tainted_msg->resync_offset;
    2846              : 
    2847              :     /* Copy header buffers (these don't contain user-controlled paths) */
    2848            2 :     if (tainted_msg->headersize > 0 && tainted_msg->headersize < (int32_t)sizeof(secure_msg->headerbuffer)) {
    2849           78 :         for (i = 0; i < (size_t)tainted_msg->headersize; i++) {
    2850           76 :             secure_msg->headerbuffer[i] = tainted_msg->headerbuffer[i];
    2851              :         }
    2852              :     }
    2853              : 
    2854              :     /* Set up header pointers */
    2855            2 :     secure_msg->storageheader = (DltStorageHeader *)(secure_msg->headerbuffer);
    2856            2 :     secure_msg->standardheader = (DltStandardHeader *)(secure_msg->headerbuffer + sizeof(DltStorageHeader));
    2857              :     if (DLT_IS_HTYP_UEH(secure_msg->standardheader->htyp)) {
    2858              :         secure_msg->extendedheader = (DltExtendedHeader *)(secure_msg->headerbuffer +
    2859              :                                                            sizeof(DltStorageHeader) +
    2860              :                                                            sizeof(DltStandardHeader) +
    2861              :                                                            DLT_STANDARD_HEADER_EXTRA_SIZE(secure_msg->standardheader->htyp));
    2862              :     }
    2863              : 
    2864              :     /* Point to the same databuffer initially */
    2865            2 :     secure_msg->databuffer = tainted_msg->databuffer;
    2866            2 :     secure_msg->databuffersize = tainted_msg->databuffersize;
    2867              : 
    2868            2 :     if (tainted_msg->databuffer == NULL || tainted_msg->datasize < (int32_t)sizeof(uint32_t))
    2869              :         return 0;
    2870              : 
    2871              :     /* Get service ID */
    2872            2 :     service_id = DLT_ENDIAN_GET_32(tainted_msg->standardheader->htyp,
    2873              :                                    *((uint32_t *)(tainted_msg->databuffer)));
    2874              : 
    2875              :     /* Sanitize logstorage messages with path validation */
    2876            2 :     if (service_id == DLT_SERVICE_ID_OFFLINE_LOGSTORAGE) {
    2877              :         /* Cast to logstorage request structure */
    2878              :         tainted_req = (DltServiceOfflineLogstorage *)(tainted_msg->databuffer);
    2879              :         if (tainted_req == NULL)
    2880              :             return -1;
    2881              : 
    2882              :         /* Ensure null-termination */
    2883            2 :         tainted_req->mount_point[DLT_MOUNT_PATH_MAX - 1] = '\0';
    2884              : 
    2885              :         /* Get path length */
    2886            2 :         size_t path_len = strnlen(tainted_req->mount_point, DLT_MOUNT_PATH_MAX);
    2887              : 
    2888              :         /* Validate basic path requirements */
    2889            2 :         if (path_len == 0) {
    2890              :             /* Empty path only allowed for sync all caches operation */
    2891            2 :             if (tainted_req->connection_type != DLT_OFFLINE_LOGSTORAGE_SYNC_CACHES) {
    2892            0 :                 dlt_vlog(LOG_WARNING, "Rejected logstorage message with empty path\n");
    2893            0 :                 return -1;
    2894              :             }
    2895              :         } else {
    2896              :             /* Path must be absolute (start with /) */
    2897            0 :             if (tainted_req->mount_point[0] != '/') {
    2898            0 :                 dlt_vlog(LOG_WARNING, "Rejected logstorage message with non-absolute path\n");
    2899            0 :                 return -1;
    2900              :             }
    2901              :         }
    2902              : 
    2903              :         /* Now sanitize the databuffer */
    2904              :         secure_req = (DltServiceOfflineLogstorage *)(secure_msg->databuffer);
    2905              : 
    2906              :         /* Explicitly sanitize: copy path to secure local buffer using allow list */
    2907              :         memset(secure_mount_point, 0, sizeof(secure_mount_point));
    2908            2 :         for (i = 0; i < DLT_MOUNT_PATH_MAX - 1 && tainted_req->mount_point[i] != '\0'; i++) {
    2909              :             char c = tainted_req->mount_point[i];
    2910              :             /* Apply allow list - only safe characters allowed */
    2911            0 :             if ((c >= 'a' && c <= 'z') ||
    2912            0 :                 (c >= 'A' && c <= 'Z') ||
    2913              :                 (c >= '0' && c <= '9') ||
    2914              :                 c == '/' || c == '-' || c == '_' || c == '.') {
    2915            0 :                 secure_mount_point[i] = c;
    2916              :             } else {
    2917            0 :                 dlt_vlog(LOG_WARNING, "Rejected logstorage message with invalid character in path at position %zu\n", i);
    2918            0 :                 return -1;
    2919              :             }
    2920              :         }
    2921            2 :         secure_mount_point[DLT_MOUNT_PATH_MAX - 1] = '\0';
    2922              : 
    2923              :         /* Check for path traversal attempts (defense in depth) */
    2924            2 :         if (strstr(secure_mount_point, "..") != NULL) {
    2925            0 :             dlt_vlog(LOG_WARNING, "Rejected logstorage message with path traversal attempt\n");
    2926            0 :             return -1;
    2927              :         }
    2928              : 
    2929              :         /* Deny consecutive slashes */
    2930            2 :         if (strstr(secure_mount_point, "//") != NULL) {
    2931            0 :             dlt_vlog(LOG_WARNING, "Rejected logstorage message with consecutive slashes in path\n");
    2932            0 :             return -1;
    2933              :         }
    2934              : 
    2935              :         /* Copy secure data to the secure message's databuffer */
    2936         2050 :         for (i = 0; i < DLT_MOUNT_PATH_MAX; i++) {
    2937         2048 :             secure_req->mount_point[i] = secure_mount_point[i];
    2938              :         }
    2939              :     }
    2940              : 
    2941              :     return 0;
    2942              : }
    2943              : 
    2944            8 : int dlt_daemon_process_client_messages(DltDaemon *daemon,
    2945              :                                        DltDaemonLocal *daemon_local,
    2946              :                                        DltReceiver *receiver,
    2947              :                                        int verbose)
    2948              : {
    2949              :     int bytes_to_be_removed = 0;
    2950              :     int must_close_socket = -1;
    2951              : 
    2952            8 :     PRINT_FUNCTION_VERBOSE(verbose);
    2953              : 
    2954            8 :     if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
    2955            0 :         dlt_log(LOG_ERR,
    2956              :                 "Invalid function parameters used for function "
    2957              :                 "dlt_daemon_process_client_messages()\n");
    2958            0 :         return -1;
    2959              :     }
    2960              : 
    2961            8 :     must_close_socket = dlt_receiver_receive(receiver);
    2962              : 
    2963            8 :     if (must_close_socket < 0) {
    2964            0 :         dlt_daemon_close_socket(receiver->fd,
    2965              :                                 daemon,
    2966              :                                 daemon_local,
    2967              :                                 verbose);
    2968            0 :         return -1;
    2969              :     }
    2970              : 
    2971              :     /* Process all received messages */
    2972           18 :     while (dlt_message_read(&(daemon_local->msg),
    2973           18 :                             (uint8_t *)receiver->buf,
    2974           18 :                             (unsigned int) receiver->bytesRcvd,
    2975              :                             daemon_local->flags.nflag,
    2976           18 :                             daemon_local->flags.vflag) == DLT_MESSAGE_ERROR_OK) {
    2977              :         /* Check for control message */
    2978           10 :         if ((0 < receiver->fd) &&
    2979           10 :             DLT_MSG_IS_CONTROL_REQUEST(&(daemon_local->msg)))
    2980           10 :             dlt_daemon_client_process_control(receiver->fd,
    2981              :                                               daemon,
    2982              :                                               daemon_local,
    2983              :                                               &(daemon_local->msg),
    2984              :                                               daemon_local->flags.vflag);
    2985              : 
    2986           10 :         bytes_to_be_removed = (int)((size_t)daemon_local->msg.headersize +
    2987           10 :                        (size_t)daemon_local->msg.datasize -
    2988              :                        (size_t)sizeof(DltStorageHeader));
    2989              : 
    2990           10 :         if (daemon_local->msg.found_serialheader)
    2991              :             bytes_to_be_removed += (int) sizeof(dltSerialHeader);
    2992              : 
    2993           10 :         if (daemon_local->msg.resync_offset)
    2994            0 :             bytes_to_be_removed += daemon_local->msg.resync_offset;
    2995              : 
    2996           10 :         if (dlt_receiver_remove(receiver, bytes_to_be_removed) == -1) {
    2997            0 :             dlt_log(LOG_WARNING,
    2998              :                     "Can't remove bytes from receiver for sockets\n");
    2999            0 :             return -1;
    3000              :         }
    3001              :     } /* while */
    3002              : 
    3003            8 :     if (dlt_receiver_move_to_begin(receiver) == -1) {
    3004            0 :         dlt_log(LOG_WARNING,
    3005              :                 "Can't move bytes to beginning of receiver buffer for sockets\n");
    3006            0 :         return -1;
    3007              :     }
    3008              : 
    3009            8 :     if (must_close_socket == 0)
    3010              :         /* FIXME: Why the hell do we need to close the socket
    3011              :          * on control message reception ??
    3012              :          */
    3013            1 :         dlt_daemon_close_socket(receiver->fd,
    3014              :                                 daemon,
    3015              :                                 daemon_local,
    3016              :                                 verbose);
    3017              : 
    3018              :     return 0;
    3019              : }
    3020              : 
    3021            0 : int dlt_daemon_process_client_messages_serial(DltDaemon *daemon,
    3022              :                                               DltDaemonLocal *daemon_local,
    3023              :                                               DltReceiver *receiver,
    3024              :                                               int verbose)
    3025              : {
    3026              :     int bytes_to_be_removed = 0;
    3027              : 
    3028            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    3029              : 
    3030            0 :     if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
    3031            0 :         dlt_log(LOG_ERR,
    3032              :                 "Invalid function parameters used for function "
    3033              :                 "dlt_daemon_process_client_messages_serial()\n");
    3034            0 :         return -1;
    3035              :     }
    3036              : 
    3037            0 :     if (dlt_receiver_receive(receiver) <= 0) {
    3038            0 :         dlt_log(LOG_WARNING,
    3039              :                 "dlt_receiver_receive_fd() for messages from serial interface "
    3040              :                 "failed!\n");
    3041            0 :         return -1;
    3042              :     }
    3043              : 
    3044              :     /* Process all received messages */
    3045            0 :     while (dlt_message_read(&(daemon_local->msg),
    3046            0 :                             (uint8_t *)receiver->buf,
    3047            0 :                             (unsigned int) receiver->bytesRcvd,
    3048              :                             daemon_local->flags.mflag,
    3049            0 :                             daemon_local->flags.vflag) == DLT_MESSAGE_ERROR_OK) {
    3050              :         /* Check for control message */
    3051            0 :         if (DLT_MSG_IS_CONTROL_REQUEST(&(daemon_local->msg))) {
    3052            0 :             DltMessage secure_msg = {0};
    3053              :             /* Create sanitized message to break taint chain */
    3054            0 :             if (dlt_daemon_create_secure_message(&(daemon_local->msg), &secure_msg) < 0)
    3055            0 :                 continue;
    3056              : 
    3057            0 :             if (dlt_daemon_client_process_control(receiver->fd,
    3058              :                                                   daemon,
    3059              :                                                   daemon_local,
    3060              :                                                   &(daemon_local->msg),
    3061              :                                                   daemon_local->flags.vflag)
    3062              :                 == -1) {
    3063            0 :                 dlt_log(LOG_WARNING, "Can't process control messages\n");
    3064            0 :                 return -1;
    3065              :             }
    3066              :         }
    3067              : 
    3068            0 :         bytes_to_be_removed = (int)((size_t)daemon_local->msg.headersize +
    3069            0 :                             (size_t)daemon_local->msg.datasize -
    3070              :                             sizeof(DltStorageHeader));
    3071              : 
    3072            0 :         if (daemon_local->msg.found_serialheader)
    3073              :             bytes_to_be_removed += (int) sizeof(dltSerialHeader);
    3074              : 
    3075            0 :         if (daemon_local->msg.resync_offset)
    3076            0 :             bytes_to_be_removed += daemon_local->msg.resync_offset;
    3077              : 
    3078            0 :         if (dlt_receiver_remove(receiver, bytes_to_be_removed) == -1) {
    3079            0 :             dlt_log(LOG_WARNING,
    3080              :                     "Can't remove bytes from receiver for serial connection\n");
    3081            0 :             return -1;
    3082              :         }
    3083              :     } /* while */
    3084              : 
    3085            0 :     if (dlt_receiver_move_to_begin(receiver) == -1) {
    3086            0 :         dlt_log(LOG_WARNING,
    3087              :                 "Can't move bytes to beginning of receiver buffer for serial "
    3088              :                 "connection\n");
    3089            0 :         return -1;
    3090              :     }
    3091              : 
    3092              :     return 0;
    3093              : }
    3094              : 
    3095            2 : int dlt_daemon_process_control_connect(
    3096              :     DltDaemon *daemon,
    3097              :     DltDaemonLocal *daemon_local,
    3098              :     DltReceiver *receiver,
    3099              :     int verbose)
    3100              : {
    3101              :     socklen_t ctrl_size;
    3102              :     struct sockaddr_un ctrl;
    3103              :     int in_sock = -1;
    3104              : 
    3105            2 :     PRINT_FUNCTION_VERBOSE(verbose);
    3106              : 
    3107            2 :     if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
    3108            0 :         dlt_log(LOG_ERR,
    3109              :                 "Invalid function parameters used for function "
    3110              :                 "dlt_daemon_process_control_connect()\n");
    3111            0 :         return -1;
    3112              :     }
    3113              : 
    3114              :     /* event from UNIX server socket, new connection */
    3115            2 :     ctrl_size = sizeof(ctrl);
    3116              : 
    3117            2 :     if ((in_sock = accept(receiver->fd, (struct sockaddr *)&ctrl, &ctrl_size)) < 0) {
    3118            0 :         dlt_vlog(LOG_ERR, "accept() on UNIX control socket %d failed: %s\n", receiver->fd, strerror(errno));
    3119            0 :         return -1;
    3120              :     }
    3121              : 
    3122              :     /* check if file file descriptor was already used, and make it invalid if it
    3123              :      *  is reused */
    3124              :     /* This prevents sending messages to wrong file descriptor */
    3125            2 :     dlt_daemon_applications_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
    3126            2 :     dlt_daemon_contexts_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
    3127              : 
    3128            2 :     if (dlt_connection_create(daemon_local,
    3129              :                               &daemon_local->pEvent,
    3130              :                               in_sock,
    3131              :                               POLLIN,
    3132              :                               DLT_CONNECTION_CONTROL_MSG)) {
    3133            0 :         dlt_log(LOG_ERR, "Failed to register new client. \n");
    3134              :         /* TODO: Perform clean-up */
    3135            0 :         return -1;
    3136              :     }
    3137              : 
    3138            2 :     if (verbose)
    3139            0 :         dlt_vlog(LOG_INFO, "New connection to control client established\n");
    3140              : 
    3141              :     return 0;
    3142              : }
    3143              : 
    3144              : #if defined DLT_DAEMON_USE_UNIX_SOCKET_IPC || defined DLT_DAEMON_VSOCK_IPC_ENABLE
    3145              : int dlt_daemon_process_app_connect(
    3146              :     DltDaemon *daemon,
    3147              :     DltDaemonLocal *daemon_local,
    3148              :     DltReceiver *receiver,
    3149              :     int verbose)
    3150              : {
    3151              :     int in_sock = -1;
    3152              : 
    3153              :     PRINT_FUNCTION_VERBOSE(verbose);
    3154              : 
    3155              :     if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
    3156              :         dlt_vlog(LOG_ERR,
    3157              :                  "%s: Invalid parameters\n",
    3158              :                  __func__);
    3159              :         return DLT_RETURN_WRONG_PARAMETER;
    3160              :     }
    3161              : 
    3162              :     /* event from server socket, new connection */
    3163              : 
    3164              :     if ((in_sock = accept(receiver->fd, NULL, NULL)) < 0) {
    3165              :         dlt_vlog(LOG_ERR, "accept() on UNIX socket %d failed: %s\n", receiver->fd, strerror(errno));
    3166              :         return -1;
    3167              :     }
    3168              : 
    3169              :     /* check if file file descriptor was already used, and make it invalid if it
    3170              :      * is reused. This prevents sending messages to wrong file descriptor */
    3171              :     dlt_daemon_applications_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
    3172              :     dlt_daemon_contexts_invalidate_fd(daemon, daemon->ecuid, in_sock, verbose);
    3173              : 
    3174              :     if (dlt_connection_create(daemon_local,
    3175              :                               &daemon_local->pEvent,
    3176              :                               in_sock,
    3177              :                               POLLIN,
    3178              :                               DLT_CONNECTION_APP_MSG)) {
    3179              :         dlt_log(LOG_ERR, "Failed to register new application. \n");
    3180              :         close(in_sock);
    3181              :         return -1;
    3182              :     }
    3183              : 
    3184              :     if (verbose)
    3185              :         dlt_vlog(LOG_INFO, "New connection to application established\n");
    3186              : 
    3187              :     return 0;
    3188              : }
    3189              : #endif
    3190              : 
    3191            4 : int dlt_daemon_process_control_messages(
    3192              :     DltDaemon *daemon,
    3193              :     DltDaemonLocal *daemon_local,
    3194              :     DltReceiver *receiver,
    3195              :     int verbose)
    3196              : {
    3197              :     int bytes_to_be_removed = 0;
    3198              : 
    3199            4 :     PRINT_FUNCTION_VERBOSE(verbose);
    3200              : 
    3201            4 :     if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
    3202            0 :         dlt_log(LOG_ERR,
    3203              :                 "Invalid function parameters used for function "
    3204              :                 "dlt_daemon_process_control_messages()\n");
    3205            0 :         return -1;
    3206              :     }
    3207              : 
    3208            4 :     if (dlt_receiver_receive(receiver) <= 0) {
    3209            2 :         dlt_daemon_close_socket(receiver->fd,
    3210              :                                 daemon,
    3211              :                                 daemon_local,
    3212              :                                 verbose);
    3213              :         /* FIXME: Why the hell do we need to close the socket
    3214              :          * on control message reception ??
    3215              :          */
    3216            2 :         return 0;
    3217              :     }
    3218              : 
    3219              :     /* Process all received messages */
    3220            4 :     while (dlt_message_read(
    3221              :                &(daemon_local->msg),
    3222            4 :                (uint8_t *)receiver->buf,
    3223            4 :                (unsigned int) receiver->bytesRcvd,
    3224              :                daemon_local->flags.nflag,
    3225            4 :                daemon_local->flags.vflag) == DLT_MESSAGE_ERROR_OK) {
    3226              :         /* Check for control message */
    3227            2 :         if ((receiver->fd > 0) &&
    3228            2 :             DLT_MSG_IS_CONTROL_REQUEST(&(daemon_local->msg))) {
    3229            2 :             DltMessage secure_msg = {0};
    3230              :             /* Create sanitized message to break taint chain */
    3231            2 :             if (dlt_daemon_create_secure_message(&(daemon_local->msg), &secure_msg) < 0)
    3232            0 :                 continue;
    3233              : 
    3234            2 :             if (dlt_daemon_client_process_control(receiver->fd,
    3235              :                                                   daemon,
    3236              :                                                   daemon_local,
    3237              :                                                   &secure_msg,
    3238              :                                               daemon_local->flags.vflag)
    3239              :                 == -1) {
    3240            0 :                 dlt_log(LOG_WARNING, "Can't process control messages\n");
    3241            0 :                 return -1;
    3242              :             }
    3243              :         }
    3244              : 
    3245            2 :         bytes_to_be_removed = (int) ((size_t)daemon_local->msg.headersize +
    3246            2 :                             (size_t)daemon_local->msg.datasize -
    3247              :                             sizeof(DltStorageHeader));
    3248              : 
    3249            2 :         if (daemon_local->msg.found_serialheader)
    3250              :             bytes_to_be_removed += (int) sizeof(dltSerialHeader);
    3251              : 
    3252            2 :         if (daemon_local->msg.resync_offset)
    3253            0 :             bytes_to_be_removed += daemon_local->msg.resync_offset;
    3254              : 
    3255            2 :         if (dlt_receiver_remove(receiver, bytes_to_be_removed) == -1) {
    3256            0 :             dlt_log(LOG_WARNING,
    3257              :                     "Can't remove bytes from receiver for sockets\n");
    3258            0 :             return -1;
    3259              :         }
    3260              :     } /* while */
    3261              : 
    3262            2 :     if (dlt_receiver_move_to_begin(receiver) == -1) {
    3263            0 :         dlt_log(LOG_WARNING, "Can't move bytes to beginning of receiver buffer for sockets\n");
    3264            0 :         return -1;
    3265              :     }
    3266              : 
    3267              :     return 0;
    3268              : }
    3269              : 
    3270            0 : static int dlt_daemon_process_user_message_not_sup(DltDaemon *daemon,
    3271              :                                                    DltDaemonLocal *daemon_local,
    3272              :                                                    DltReceiver *receiver,
    3273              :                                                    int verbose)
    3274              : {
    3275            0 :     DltUserHeader *userheader = (DltUserHeader *)(receiver->buf);
    3276              :     (void)daemon;
    3277              :     (void)daemon_local;
    3278              : 
    3279            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    3280              : 
    3281            0 :     dlt_vlog(LOG_ERR, "Invalid user message type received: %u!\n",
    3282              :              userheader->message);
    3283              : 
    3284              :     /* remove user header */
    3285            0 :     if (dlt_receiver_remove(receiver, sizeof(DltUserHeader)) == -1)
    3286            0 :         dlt_log(LOG_WARNING,
    3287              :                 "Can't remove bytes from receiver for user messages\n");
    3288              : 
    3289            0 :     return -1;
    3290              : }
    3291              : 
    3292              : static dlt_daemon_process_user_message_func process_user_func[DLT_USER_MESSAGE_NOT_SUPPORTED] = {
    3293              :     dlt_daemon_process_user_message_not_sup,
    3294              :     dlt_daemon_process_user_message_log,
    3295              :     dlt_daemon_process_user_message_register_application,
    3296              :     dlt_daemon_process_user_message_unregister_application,
    3297              :     dlt_daemon_process_user_message_register_context,
    3298              :     dlt_daemon_process_user_message_unregister_context,
    3299              :     dlt_daemon_process_user_message_not_sup,
    3300              :     dlt_daemon_process_user_message_not_sup,
    3301              :     dlt_daemon_process_user_message_overflow,
    3302              :     dlt_daemon_process_user_message_set_app_ll_ts,
    3303              :     dlt_daemon_process_user_message_not_sup,
    3304              :     dlt_daemon_process_user_message_not_sup,
    3305              :     dlt_daemon_process_user_message_not_sup,
    3306              :     dlt_daemon_process_user_message_marker,
    3307              :     dlt_daemon_process_user_message_not_sup,
    3308              :     dlt_daemon_process_user_message_not_sup
    3309              : };
    3310              : 
    3311         1246 : int dlt_daemon_process_user_messages(DltDaemon *daemon,
    3312              :                                      DltDaemonLocal *daemon_local,
    3313              :                                      DltReceiver *receiver,
    3314              :                                      int verbose)
    3315              : {
    3316              :     int offset = 0;
    3317              :     int run_loop = 1;
    3318              :     int32_t min_size = (int32_t) sizeof(DltUserHeader);
    3319              :     DltUserHeader *userheader;
    3320              :     int recv;
    3321              : 
    3322         1246 :     PRINT_FUNCTION_VERBOSE(verbose);
    3323              : 
    3324         1246 :     if ((daemon == NULL) || (daemon_local == NULL) || (receiver == NULL)) {
    3325            0 :         dlt_log(LOG_ERR,
    3326              :                 "Invalid function parameters used for function "
    3327              :                 "dlt_daemon_process_user_messages()\n");
    3328            0 :         return -1;
    3329              :     }
    3330              : 
    3331         1246 :     recv = dlt_receiver_receive(receiver);
    3332              : 
    3333         1246 :     if (recv <= 0 && receiver->type == DLT_RECEIVE_SOCKET) {
    3334            0 :         dlt_daemon_close_socket(receiver->fd,
    3335              :                                 daemon,
    3336              :                                 daemon_local,
    3337              :                                 verbose);
    3338            0 :         return 0;
    3339              :     }
    3340         1246 :     else if (recv < 0) {
    3341            0 :         dlt_log(LOG_WARNING,
    3342              :                 "dlt_receiver_receive_fd() for user messages failed!\n");
    3343            0 :         return -1;
    3344              :     }
    3345              : 
    3346              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    3347              :     /* Count up number of received bytes from FIFO */
    3348              :     if (receiver->bytesRcvd > receiver->lastBytesRcvd)
    3349              :     {
    3350              :         daemon->bytes_recv += receiver->bytesRcvd - receiver->lastBytesRcvd;
    3351              :     }
    3352              : #endif
    3353              : 
    3354              :     /* look through buffer as long as data is in there */
    3355         7143 :     while ((receiver->bytesRcvd >= min_size) && run_loop) {
    3356              : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
    3357              :         /* this loop may be running long, so we have to exit it at some point to be able to
    3358              :          * to process other events, like feeding the watchdog
    3359              :          */
    3360              :         bool watchdog_triggered= dlt_daemon_trigger_systemd_watchdog_if_necessary(daemon);
    3361              :         if (watchdog_triggered) {
    3362              :             dlt_vlog(LOG_WARNING, "%s yields due to watchdog.\n", __func__);
    3363              :             run_loop = 0; // exit loop in next iteration
    3364              :         }
    3365              : #endif
    3366              : 
    3367              :         dlt_daemon_process_user_message_func func = NULL;
    3368              : 
    3369              :         offset = 0;
    3370         5897 :         userheader = (DltUserHeader *)(receiver->buf + offset);
    3371              : 
    3372         5897 :         while (!dlt_user_check_userheader(userheader) &&
    3373            0 :                (offset + min_size <= receiver->bytesRcvd)) {
    3374              :             /* resync if necessary */
    3375            0 :             offset++;
    3376            0 :             userheader = (DltUserHeader *)(receiver->buf + offset);
    3377              :         }
    3378              : 
    3379              :         /* Check for user header pattern */
    3380         5897 :         if (!dlt_user_check_userheader(userheader))
    3381              :             break;
    3382              : 
    3383              :         /* Set new start offset */
    3384         5897 :         if (offset > 0) {
    3385            0 :             if (dlt_receiver_remove(receiver, offset) == -1) {
    3386            0 :                 dlt_log(LOG_WARNING,
    3387              :                         "Can't remove offset from receiver\n");
    3388            0 :                 return -1;
    3389              :             }
    3390              :         }
    3391              : 
    3392         5897 :         if (userheader->message >= DLT_USER_MESSAGE_NOT_SUPPORTED)
    3393              :             func = dlt_daemon_process_user_message_not_sup;
    3394              :         else
    3395         5897 :             func = process_user_func[userheader->message];
    3396              : 
    3397         5897 :         if (func(daemon,
    3398              :                  daemon_local,
    3399              :                  receiver,
    3400              :                  daemon_local->flags.vflag) == -1)
    3401              :             run_loop = 0;
    3402              :     }
    3403              : 
    3404              :     /* keep not read data in buffer */
    3405         1246 :     if (dlt_receiver_move_to_begin(receiver) == -1) {
    3406            0 :         dlt_log(LOG_WARNING,
    3407              :                 "Can't move bytes to beginning of receiver buffer for user "
    3408              :                 "messages\n");
    3409            0 :         return -1;
    3410              :     }
    3411              : 
    3412              :     return 0;
    3413              : }
    3414              : 
    3415            0 : int dlt_daemon_process_user_message_overflow(DltDaemon *daemon,
    3416              :                                              DltDaemonLocal *daemon_local,
    3417              :                                              DltReceiver *rec,
    3418              :                                              int verbose)
    3419              : {
    3420              :     uint32_t len = sizeof(DltUserControlMsgBufferOverflow);
    3421              :     DltUserControlMsgBufferOverflow userpayload;
    3422              : 
    3423            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    3424              : 
    3425            0 :     if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
    3426            0 :         dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n",
    3427              :                  __func__);
    3428            0 :         return -1;
    3429              :     }
    3430              : 
    3431            0 :     if (dlt_receiver_check_and_get(rec,
    3432              :                                    &userpayload,
    3433              :                                    len,
    3434              :                                    DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0)
    3435              :         /* Not enough bytes received */
    3436              :         return -1;
    3437              : 
    3438              :     /* Store in daemon, that a message buffer overflow has occured */
    3439              :     /* look if TCP connection to client is available or it least message can be put into buffer */
    3440            0 :     if (dlt_daemon_control_message_buffer_overflow(DLT_DAEMON_SEND_TO_ALL,
    3441              :                                                    daemon,
    3442              :                                                    daemon_local,
    3443              :                                                    userpayload.overflow_counter,
    3444              :                                                    userpayload.apid,
    3445              :                                                    verbose))
    3446              :         /* there was an error when storing message */
    3447              :         /* add the counter of lost messages to the daemon counter */
    3448            0 :         daemon->overflow_counter += userpayload.overflow_counter;
    3449              : 
    3450              :     return 0;
    3451              : }
    3452              : 
    3453            0 : int dlt_daemon_send_message_overflow(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
    3454              : {
    3455              :     int ret;
    3456            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    3457              : 
    3458            0 :     if ((daemon == 0) || (daemon_local == 0)) {
    3459            0 :         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_user_message_overflow()\n");
    3460            0 :         return DLT_DAEMON_ERROR_UNKNOWN;
    3461              :     }
    3462              : 
    3463              :     /* Store in daemon, that a message buffer overflow has occured */
    3464              :     if ((ret =
    3465            0 :              dlt_daemon_control_message_buffer_overflow(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local,
    3466              :                                                         daemon->overflow_counter,
    3467              :                                                         "", verbose)))
    3468              :         return ret;
    3469              : 
    3470              :     return DLT_DAEMON_ERROR_OK;
    3471              : }
    3472              : 
    3473            7 : int dlt_daemon_process_user_message_register_application(DltDaemon *daemon,
    3474              :                                                          DltDaemonLocal *daemon_local,
    3475              :                                                          DltReceiver *rec,
    3476              :                                                          int verbose)
    3477              : {
    3478              :     uint32_t len = sizeof(DltUserControlMsgRegisterApplication);
    3479              :     uint32_t to_remove = 0;
    3480              :     DltDaemonApplication *application = NULL;
    3481              :     DltDaemonApplication *old_application = NULL;
    3482              :     pid_t old_pid = 0;
    3483            7 :     char description[DLT_DAEMON_DESCSIZE + 1] = { '\0' };
    3484              :     DltUserControlMsgRegisterApplication userapp;
    3485              :     char *origin;
    3486              :     int fd = -1;
    3487              : 
    3488            7 :     PRINT_FUNCTION_VERBOSE(verbose);
    3489              : 
    3490            7 :     if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
    3491            0 :         dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n",
    3492              :                  __func__);
    3493            0 :         return -1;
    3494              :     }
    3495              : 
    3496              :     memset(&userapp, 0, sizeof(DltUserControlMsgRegisterApplication));
    3497            7 :     origin = rec->buf;
    3498              : 
    3499              :     /* Adding temp variable to check the return value */
    3500              :     int temp = 0;
    3501              : 
    3502              :     /* We shall not remove data before checking that everything is there. */
    3503            7 :     temp = dlt_receiver_check_and_get(rec,
    3504              :                                            &userapp,
    3505              :                                            len,
    3506              :                                            DLT_RCV_SKIP_HEADER);
    3507              : 
    3508            7 :     if (temp < 0)
    3509              :         /* Not enough bytes received */
    3510              :         return -1;
    3511              :     else {
    3512            7 :         to_remove = (uint32_t) temp;
    3513              :     }
    3514              : 
    3515            7 :     len = userapp.description_length;
    3516              : 
    3517            7 :     if (len > DLT_DAEMON_DESCSIZE) {
    3518              :         len = DLT_DAEMON_DESCSIZE;
    3519            0 :         dlt_log(LOG_WARNING, "Application description exceeds limit\n");
    3520              :     }
    3521              : 
    3522              :     /* adjust buffer pointer */
    3523            7 :     rec->buf += to_remove + sizeof(DltUserHeader);
    3524              : 
    3525            7 :     if (dlt_receiver_check_and_get(rec, description, len, DLT_RCV_NONE) < 0) {
    3526            0 :         dlt_log(LOG_ERR, "Unable to get application description\n");
    3527              :         /* in case description was not readable, set dummy description */
    3528              :         memcpy(description, "Unknown", sizeof("Unknown"));
    3529              : 
    3530              :         /* unknown len of original description, set to 0 to not remove in next
    3531              :          * step. Because message buffer is re-adjusted the corrupted description
    3532              :          * is ignored. */
    3533              :         len = 0;
    3534              :     }
    3535              : 
    3536              :     /* adjust to_remove */
    3537            7 :     to_remove += (uint32_t) sizeof(DltUserHeader) + len;
    3538              :     /* point to begin of message */
    3539            7 :     rec->buf = origin;
    3540              : 
    3541              :     /* We can now remove data. */
    3542            7 :     if (dlt_receiver_remove(rec, (int) to_remove) != DLT_RETURN_OK) {
    3543            0 :         dlt_log(LOG_WARNING, "Can't remove bytes from receiver\n");
    3544            0 :         return -1;
    3545              :     }
    3546              : 
    3547            7 :     old_application = dlt_daemon_application_find(daemon, userapp.apid, daemon->ecuid, verbose);
    3548              : 
    3549            7 :     if (old_application != NULL)
    3550            0 :         old_pid = old_application->pid;
    3551              : 
    3552            7 :     if (rec->type == DLT_RECEIVE_SOCKET)
    3553            0 :         fd = rec->fd; /* For sockets, an app specific fd has already been created with accept(). */
    3554              : 
    3555            7 :     application = dlt_daemon_application_add(daemon,
    3556              :                                              userapp.apid,
    3557              :                                              userapp.pid,
    3558              :                                              description,
    3559              :                                              fd,
    3560              :                                              daemon->ecuid,
    3561              :                                              verbose);
    3562              : 
    3563              :     /* send log state to new application */
    3564            7 :     dlt_daemon_user_send_log_state(daemon, application, verbose);
    3565              : 
    3566            7 :     if (application == NULL) {
    3567            0 :         dlt_vlog(LOG_WARNING, "Can't add ApplicationID '%.4s' for PID %d\n",
    3568              :                  userapp.apid, userapp.pid);
    3569            0 :         return -1;
    3570              :     }
    3571            7 :     else if (old_pid != application->pid)
    3572              :     {
    3573            7 :         char local_str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' };
    3574              : 
    3575            7 :         snprintf(local_str,
    3576              :                  DLT_DAEMON_TEXTBUFSIZE,
    3577              :                  "ApplicationID '%.4s' registered for PID %d, Description=%s",
    3578            7 :                  application->apid,
    3579              :                  application->pid,
    3580              :                  application->application_description);
    3581            7 :         dlt_daemon_log_internal(daemon, daemon_local, local_str, DLT_LOG_INFO,
    3582              :                                 DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID,
    3583              :                                 daemon_local->flags.vflag);
    3584            7 :         dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
    3585              :     }
    3586              : 
    3587              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    3588              :     if (dlt_daemon_user_send_trace_load_config(daemon, application, verbose) != DLT_RETURN_OK)
    3589              :         dlt_vlog(LOG_WARNING, "Cannot send trace config to Apid: %.4s, PID: %d\n",
    3590              :                  application->apid, application->pid);
    3591              : #endif
    3592              : 
    3593              :     return 0;
    3594              : }
    3595              : 
    3596           38 : int dlt_daemon_process_user_message_register_context(DltDaemon *daemon,
    3597              :                                                      DltDaemonLocal *daemon_local,
    3598              :                                                      DltReceiver *rec,
    3599              :                                                      int verbose)
    3600              : {
    3601              :     uint32_t to_remove = 0;
    3602              :     uint32_t len = sizeof(DltUserControlMsgRegisterContext);
    3603              :     DltUserControlMsgRegisterContext userctxt;
    3604           38 :     char description[DLT_DAEMON_DESCSIZE + 1] = { '\0' };
    3605              :     DltDaemonApplication *application = NULL;
    3606              :     DltDaemonContext *context = NULL;
    3607              :     DltServiceGetLogInfoRequest *req = NULL;
    3608              :     char *origin;
    3609              : 
    3610              :     DltMessage msg;
    3611              : 
    3612           38 :     PRINT_FUNCTION_VERBOSE(verbose);
    3613              : 
    3614           38 :     if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
    3615            0 :         dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n",
    3616              :                  __func__);
    3617            0 :         return -1;
    3618              :     }
    3619              : 
    3620              :     memset(&userctxt, 0, sizeof(DltUserControlMsgRegisterContext));
    3621           38 :     origin = rec->buf;
    3622              : 
    3623              :     /* Adding temp variable to check the return value */
    3624              :     int temp = 0;
    3625              : 
    3626           38 :     temp = dlt_receiver_check_and_get(rec,
    3627              :                                            &userctxt,
    3628              :                                            len,
    3629              :                                            DLT_RCV_SKIP_HEADER);
    3630              : 
    3631           38 :     if (temp < 0)
    3632              :         /* Not enough bytes received */
    3633              :         return -1;
    3634              :     else {
    3635           38 :         to_remove = (uint32_t) temp;
    3636              :     }
    3637              : 
    3638           38 :     len = userctxt.description_length;
    3639              : 
    3640           38 :     if (len > DLT_DAEMON_DESCSIZE) {
    3641            0 :         dlt_vlog(LOG_WARNING, "Context description exceeds limit: %u\n", len);
    3642              :         len = DLT_DAEMON_DESCSIZE;
    3643              :     }
    3644              : 
    3645              :     /* adjust buffer pointer */
    3646           38 :     rec->buf += to_remove + sizeof(DltUserHeader);
    3647              : 
    3648           38 :     if (dlt_receiver_check_and_get(rec, description, len, DLT_RCV_NONE) < 0) {
    3649            0 :         dlt_log(LOG_ERR, "Unable to get context description\n");
    3650              :         /* in case description was not readable, set dummy description */
    3651              :         memcpy(description, "Unknown", sizeof("Unknown"));
    3652              : 
    3653              :         /* unknown len of original description, set to 0 to not remove in next
    3654              :          * step. Because message buffer is re-adjusted the corrupted description
    3655              :          * is ignored. */
    3656              :         len = 0;
    3657              :     }
    3658              : 
    3659              :     /* adjust to_remove */
    3660           38 :     to_remove += (uint32_t) sizeof(DltUserHeader) + len;
    3661              :     /* point to begin of message */
    3662           38 :     rec->buf = origin;
    3663              : 
    3664              :     /* We can now remove data. */
    3665           38 :     if (dlt_receiver_remove(rec, (int) to_remove) != DLT_RETURN_OK) {
    3666            0 :         dlt_log(LOG_WARNING, "Can't remove bytes from receiver\n");
    3667            0 :         return -1;
    3668              :     }
    3669              : 
    3670           38 :     application = dlt_daemon_application_find(daemon,
    3671              :                                               userctxt.apid,
    3672           38 :                                               daemon->ecuid,
    3673              :                                               verbose);
    3674              : 
    3675           38 :     if (application == 0) {
    3676            0 :         dlt_vlog(LOG_WARNING,
    3677              :                  "ApID '%.4s' not found for new ContextID '%.4s' in %s\n",
    3678              :                  userctxt.apid,
    3679              :                  userctxt.ctid,
    3680              :                  __func__);
    3681              : 
    3682            0 :         return 0;
    3683              :     }
    3684              : 
    3685              :     /* Set log level */
    3686           38 :     if (userctxt.log_level == DLT_USER_LOG_LEVEL_NOT_SET) {
    3687           38 :         userctxt.log_level = DLT_LOG_DEFAULT;
    3688              :     } else {
    3689              :         /* Plausibility check */
    3690            0 :         if ((userctxt.log_level < DLT_LOG_DEFAULT) ||
    3691              :                 (userctxt.log_level > DLT_LOG_VERBOSE)) {
    3692              :             return -1;
    3693              :         }
    3694              :     }
    3695              : 
    3696              :     /* Set trace status */
    3697           38 :     if (userctxt.trace_status == DLT_USER_TRACE_STATUS_NOT_SET) {
    3698           38 :         userctxt.trace_status = DLT_TRACE_STATUS_DEFAULT;
    3699              :     } else {
    3700              :         /* Plausibility check */
    3701            0 :         if ((userctxt.trace_status < DLT_TRACE_STATUS_DEFAULT) ||
    3702              :                 (userctxt.trace_status > DLT_TRACE_STATUS_ON)) {
    3703              :             return -1;
    3704              :         }
    3705              :     }
    3706              : 
    3707           38 :     context = dlt_daemon_context_add(daemon,
    3708              :                                      userctxt.apid,
    3709              :                                      userctxt.ctid,
    3710           38 :                                      userctxt.log_level,
    3711           38 :                                      userctxt.trace_status,
    3712              :                                      userctxt.log_level_pos,
    3713              :                                      application->user_handle,
    3714              :                                      description,
    3715              :                                      daemon->ecuid,
    3716              :                                      verbose);
    3717              : 
    3718           38 :     if (context == 0) {
    3719            0 :         dlt_vlog(LOG_WARNING,
    3720              :                  "Can't add ContextID '%.4s' for ApID '%.4s'\n in %s",
    3721              :                  userctxt.ctid, userctxt.apid, __func__);
    3722            0 :         return -1;
    3723              :     }
    3724              :     else {
    3725           38 :         char local_str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' };
    3726              : 
    3727           38 :         snprintf(local_str,
    3728              :                  DLT_DAEMON_TEXTBUFSIZE,
    3729              :                  "ContextID '%.4s' registered for ApID '%.4s', Description=%s",
    3730           38 :                  context->ctid,
    3731           38 :                  context->apid,
    3732              :                  context->context_description);
    3733              : 
    3734           38 :         if (verbose)
    3735            0 :             dlt_daemon_log_internal(daemon, daemon_local, local_str,
    3736              :                                     DLT_LOG_INFO, DLT_DAEMON_APP_ID,
    3737              :                                     DLT_DAEMON_CTX_ID, verbose);
    3738              : 
    3739           38 :         dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
    3740              :     }
    3741              : 
    3742           38 :     if (daemon_local->flags.offlineLogstorageMaxDevices)
    3743              :         /* Store log level set for offline logstorage into context structure*/
    3744           33 :         context->storage_log_level =
    3745           33 :             (int8_t) dlt_daemon_logstorage_get_loglevel(daemon,
    3746           33 :                                                (int8_t) daemon_local->flags.offlineLogstorageMaxDevices,
    3747              :                                                userctxt.apid,
    3748              :                                                userctxt.ctid);
    3749              :     else
    3750            5 :         context->storage_log_level = DLT_LOG_DEFAULT;
    3751              : 
    3752              :     /* Create automatic get log info response for registered context */
    3753           38 :     if (daemon_local->flags.rflag) {
    3754              :         /* Prepare request for get log info with one application and one context */
    3755            0 :         if (dlt_message_init(&msg, verbose) == -1) {
    3756            0 :             dlt_log(LOG_WARNING, "Can't initialize message");
    3757            0 :             return -1;
    3758              :         }
    3759              : 
    3760            0 :         msg.datasize = sizeof(DltServiceGetLogInfoRequest);
    3761              : 
    3762            0 :         if (msg.databuffer && (msg.databuffersize < msg.datasize)) {
    3763            0 :             free(msg.databuffer);
    3764            0 :             msg.databuffer = 0;
    3765              :         }
    3766              : 
    3767            0 :         if (msg.databuffer == 0) {
    3768            0 :             msg.databuffer = (uint8_t *)malloc((size_t)msg.datasize);
    3769            0 :             msg.databuffersize = msg.datasize;
    3770              :         }
    3771              : 
    3772            0 :         if (msg.databuffer == 0) {
    3773            0 :             dlt_log(LOG_WARNING, "Can't allocate buffer for get log info message\n");
    3774            0 :             return -1;
    3775              :         }
    3776              : 
    3777              :         req = (DltServiceGetLogInfoRequest *)msg.databuffer;
    3778              : 
    3779            0 :         req->service_id = DLT_SERVICE_ID_GET_LOG_INFO;
    3780            0 :         req->options = (uint8_t) daemon_local->flags.autoResponseGetLogInfoOption;
    3781            0 :         dlt_set_id(req->apid, userctxt.apid);
    3782            0 :         dlt_set_id(req->ctid, userctxt.ctid);
    3783            0 :         dlt_set_id(req->com, "remo");
    3784              : 
    3785            0 :         dlt_daemon_control_get_log_info(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, &msg, verbose);
    3786              : 
    3787            0 :         dlt_message_free(&msg, verbose);
    3788              :     }
    3789              : 
    3790           38 :     if (context->user_handle >= DLT_FD_MINIMUM) {
    3791           38 :         if ((userctxt.log_level == DLT_LOG_DEFAULT) || (userctxt.trace_status == DLT_TRACE_STATUS_DEFAULT)) {
    3792              :             /* This call also replaces the default values with the values defined for default */
    3793           38 :             if (dlt_daemon_user_send_log_level(daemon, context, verbose) == -1) {
    3794            0 :                 dlt_vlog(LOG_WARNING, "Can't send current log level as response to %s for (%.4s;%.4s)\n",
    3795              :                          __func__,
    3796              :                          context->apid,
    3797              :                          context->ctid);
    3798            0 :                 return -1;
    3799              :             }
    3800              :         }
    3801              :     }
    3802              : 
    3803              :     return 0;
    3804              : }
    3805              : 
    3806            6 : int dlt_daemon_process_user_message_unregister_application(DltDaemon *daemon,
    3807              :                                                            DltDaemonLocal *daemon_local,
    3808              :                                                            DltReceiver *rec,
    3809              :                                                            int verbose)
    3810              : {
    3811              :     uint32_t len = sizeof(DltUserControlMsgUnregisterApplication);
    3812              :     DltUserControlMsgUnregisterApplication userapp;
    3813              :     DltDaemonApplication *application = NULL;
    3814              :     DltDaemonContext *context;
    3815              :     int i, offset_base;
    3816              :     DltDaemonRegisteredUsers *user_list = NULL;
    3817              : 
    3818            6 :     PRINT_FUNCTION_VERBOSE(verbose);
    3819              : 
    3820            6 :     if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
    3821            0 :         dlt_vlog(LOG_ERR,
    3822              :                  "Invalid function parameters used for %s\n",
    3823              :                  __func__);
    3824            0 :         return -1;
    3825              :     }
    3826              : 
    3827            6 :     if (dlt_receiver_check_and_get(rec,
    3828              :                                    &userapp,
    3829              :                                    len,
    3830              :                                    DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0)
    3831              :         /* Not enough bytes received */
    3832              :         return -1;
    3833              : 
    3834            6 :     user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
    3835              : 
    3836            6 :     if (user_list == NULL)
    3837              :         return -1;
    3838              : 
    3839            6 :     if (user_list->num_applications > 0) {
    3840              :         /* Delete this application and all corresponding contexts
    3841              :          * for this application from internal table.
    3842              :          */
    3843            6 :         application = dlt_daemon_application_find(daemon,
    3844              :                                                   userapp.apid,
    3845              :                                                   daemon->ecuid,
    3846              :                                                   verbose);
    3847              : 
    3848            6 :         if (application) {
    3849              :             /* Calculate start offset within contexts[] */
    3850              :             offset_base = 0;
    3851              : 
    3852            6 :             for (i = 0; i < (application - (user_list->applications)); i++)
    3853            0 :                 offset_base += user_list->applications[i].num_contexts;
    3854              : 
    3855            6 :             for (i = (application->num_contexts) - 1; i >= 0; i--) {
    3856            0 :                 context = &(user_list->contexts[offset_base + i]);
    3857              : 
    3858            0 :                 if (context) {
    3859              :                     /* Delete context */
    3860            0 :                     if (dlt_daemon_context_del(daemon,
    3861              :                                                context,
    3862              :                                                daemon->ecuid,
    3863              :                                                verbose) == -1) {
    3864            0 :                         dlt_vlog(LOG_WARNING,
    3865              :                                  "Can't delete CtID '%.4s' for ApID '%.4s' in %s\n",
    3866            0 :                                  context->ctid,
    3867            0 :                                  context->apid,
    3868              :                                  __func__);
    3869            0 :                         return -1;
    3870              :                     }
    3871              :                 }
    3872              :             }
    3873              : 
    3874              :             /* Delete this application entry from internal table*/
    3875            6 :             if (dlt_daemon_application_del(daemon,
    3876              :                                            application,
    3877              :                                            daemon->ecuid,
    3878              :                                            verbose) == -1) {
    3879            0 :                 dlt_vlog(LOG_WARNING,
    3880              :                          "Can't delete ApID '%.4s' in %s\n",
    3881            0 :                          application->apid,
    3882              :                          __func__);
    3883            0 :                 return -1;
    3884              :             }
    3885              :             else {
    3886            6 :                 char local_str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' };
    3887              : 
    3888              :                 snprintf(local_str,
    3889              :                          DLT_DAEMON_TEXTBUFSIZE,
    3890              :                          "Unregistered ApID '%.4s'",
    3891              :                          userapp.apid);
    3892            6 :                 dlt_daemon_log_internal(daemon, daemon_local, local_str,
    3893              :                                         DLT_LOG_INFO, DLT_DAEMON_APP_ID,
    3894              :                                         DLT_DAEMON_CTX_ID, verbose);
    3895            6 :                 dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
    3896              :             }
    3897              :         }
    3898              :     }
    3899              : 
    3900              :     return 0;
    3901              : }
    3902              : 
    3903           37 : int dlt_daemon_process_user_message_unregister_context(DltDaemon *daemon,
    3904              :                                                        DltDaemonLocal *daemon_local,
    3905              :                                                        DltReceiver *rec,
    3906              :                                                        int verbose)
    3907              : {
    3908              :     uint32_t len = sizeof(DltUserControlMsgUnregisterContext);
    3909              :     DltUserControlMsgUnregisterContext userctxt;
    3910              :     DltDaemonContext *context;
    3911              : 
    3912           37 :     PRINT_FUNCTION_VERBOSE(verbose);
    3913              : 
    3914           37 :     if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
    3915            0 :         dlt_vlog(LOG_ERR,
    3916              :                  "Invalid function parameters used for %s\n",
    3917              :                  __func__);
    3918              : 
    3919            0 :         return -1;
    3920              :     }
    3921              : 
    3922           37 :     if (dlt_receiver_check_and_get(rec,
    3923              :                                    &userctxt,
    3924              :                                    len,
    3925              :                                    DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0)
    3926              :         /* Not enough bytes received */
    3927              :         return -1;
    3928              : 
    3929           37 :     context = dlt_daemon_context_find(daemon,
    3930              :                                       userctxt.apid,
    3931              :                                       userctxt.ctid,
    3932           37 :                                       daemon->ecuid,
    3933              :                                       verbose);
    3934              : 
    3935              :     /* In case the daemon is loaded with predefined contexts and its context
    3936              :      * unregisters, the context information will not be deleted from daemon's
    3937              :      * table until its parent application is unregistered.
    3938              :      */
    3939           37 :     if (context && (context->predefined == false)) {
    3940              :         /* Delete this connection entry from internal table*/
    3941           37 :         if (dlt_daemon_context_del(daemon, context, daemon->ecuid, verbose) == -1) {
    3942            0 :             dlt_vlog(LOG_WARNING,
    3943              :                      "Can't delete CtID '%.4s' for ApID '%.4s' in %s\n",
    3944              :                      userctxt.ctid,
    3945              :                      userctxt.apid,
    3946              :                      __func__);
    3947            0 :             return -1;
    3948              :         }
    3949              :         else {
    3950           37 :             char local_str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' };
    3951              : 
    3952              :             snprintf(local_str,
    3953              :                      DLT_DAEMON_TEXTBUFSIZE,
    3954              :                      "Unregistered CtID '%.4s' for ApID '%.4s'",
    3955              :                      userctxt.ctid,
    3956              :                      userctxt.apid);
    3957              : 
    3958           37 :             if (verbose)
    3959            0 :                 dlt_daemon_log_internal(daemon, daemon_local, local_str,
    3960              :                                         DLT_LOG_INFO, DLT_DAEMON_APP_ID,
    3961              :                                         DLT_DAEMON_CTX_ID, verbose);
    3962              : 
    3963           37 :             dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
    3964              :         }
    3965              :     }
    3966              : 
    3967              :     /* Create automatic unregister context response for unregistered context */
    3968           37 :     if (daemon_local->flags.rflag)
    3969            0 :         dlt_daemon_control_message_unregister_context(DLT_DAEMON_SEND_TO_ALL,
    3970              :                                                       daemon,
    3971              :                                                       daemon_local,
    3972              :                                                       userctxt.apid,
    3973              :                                                       userctxt.ctid,
    3974              :                                                       "remo",
    3975              :                                                       verbose);
    3976              : 
    3977              :     return 0;
    3978              : }
    3979              : 
    3980         5809 : int dlt_daemon_process_user_message_log(DltDaemon *daemon,
    3981              :                                         DltDaemonLocal *daemon_local,
    3982              :                                         DltReceiver *rec,
    3983              :                                         int verbose)
    3984              : {
    3985              :     int ret = 0;
    3986              :     int size = 0;
    3987              : 
    3988         5809 :     PRINT_FUNCTION_VERBOSE(verbose);
    3989              : 
    3990         5809 :     if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
    3991            0 :         dlt_vlog(LOG_ERR, "%s: invalid function parameters.\n", __func__);
    3992            0 :         return DLT_DAEMON_ERROR_UNKNOWN;
    3993              :     }
    3994              : 
    3995              : #ifdef DLT_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_ENABLE
    3996              :     daemon->received_message_since_last_watchdog_interval = 1;
    3997              : #endif
    3998              : #ifdef DLT_SHM_ENABLE
    3999              : 
    4000              :     /** In case of SHM, the header still received via fifo/unix_socket receiver,
    4001              :      * so we need to remove header from the receiver.
    4002              :      */
    4003              :     if (dlt_receiver_remove(rec, sizeof(DltUserHeader)) < 0)
    4004              :         /* Not enough bytes received to remove*/
    4005              :         return DLT_DAEMON_ERROR_UNKNOWN;
    4006              : 
    4007              :     while (1) {
    4008              : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
    4009              :         bool watchdog_triggered = dlt_daemon_trigger_systemd_watchdog_if_necessary(daemon);
    4010              :         if (watchdog_triggered) {
    4011              :             dlt_vlog(LOG_WARNING, "%s yields due to watchdog.\n", __func__);
    4012              :             break;
    4013              :         }
    4014              : #endif
    4015              : 
    4016              :         /* get log message from SHM then store into receiver buffer */
    4017              :         size = dlt_shm_pull(&(daemon_local->dlt_shm),
    4018              :                             daemon_local->recv_buf_shm,
    4019              :                             DLT_SHM_RCV_BUFFER_SIZE);
    4020              : 
    4021              :         if (size <= 0)
    4022              :             break;
    4023              : 
    4024              :         ret = dlt_message_read(&(daemon_local->msg),
    4025              :                                daemon_local->recv_buf_shm, size, 0, verbose);
    4026              : 
    4027              :         if (DLT_MESSAGE_ERROR_OK != ret) {
    4028              :             dlt_shm_remove(&(daemon_local->dlt_shm));
    4029              :             dlt_log(LOG_WARNING, "failed to read messages from shm.\n");
    4030              :             return DLT_DAEMON_ERROR_UNKNOWN;
    4031              :         }
    4032              : 
    4033              : #if defined(DLT_LOG_LEVEL_APP_CONFIG) || defined(DLT_TRACE_LOAD_CTRL_ENABLE)
    4034              :         DltDaemonApplication *app = dlt_daemon_application_find(
    4035              :             daemon, daemon_local->msg.extendedheader->apid, daemon->ecuid, verbose);
    4036              : #endif
    4037              : 
    4038              :         /* discard non-allowed levels if enforcement is on */
    4039              :         bool keep_message = enforce_context_ll_and_ts_keep_message(
    4040              :             daemon_local
    4041              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
    4042              :             , app
    4043              : #endif
    4044              :         );
    4045              : 
    4046              :         // check trace_load
    4047              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    4048              :         keep_message &= trace_load_keep_message(app, size, daemon, daemon_local, verbose);
    4049              : #endif
    4050              : 
    4051              :         if (keep_message)
    4052              :           dlt_daemon_client_send_message_to_all_client(daemon, daemon_local, verbose);
    4053              : 
    4054              :         if (DLT_DAEMON_ERROR_OK != ret)
    4055              :             dlt_log(LOG_ERR, "failed to send message to client.\n");
    4056              :     }
    4057              : 
    4058              : #else
    4059         5809 :     ret = dlt_message_read(&(daemon_local->msg),
    4060         5809 :                            (unsigned char *)rec->buf + sizeof(DltUserHeader),
    4061         5809 :                            (unsigned int) ((unsigned int) rec->bytesRcvd - sizeof(DltUserHeader)),
    4062              :                            0,
    4063              :                            verbose);
    4064              : 
    4065         5809 :     if (ret != DLT_MESSAGE_ERROR_OK) {
    4066            0 :         if (ret != DLT_MESSAGE_ERROR_SIZE)
    4067              :             /* This is a normal usecase: The daemon reads the data in 10kb chunks.
    4068              :              * Thus the last trace in this chunk is probably not complete and will be completed
    4069              :              * with the next chunk read. This happens always when the FIFO is filled with more than 10kb before
    4070              :              * the daemon is able to read from the FIFO.
    4071              :              * Thus the loglevel of this message is set to DEBUG.
    4072              :              * A cleaner solution would be to check more in detail whether the message is not complete (normal usecase)
    4073              :              * or the headers are corrupted (error case). */
    4074            0 :             dlt_log(LOG_DEBUG, "Can't read messages from receiver\n");
    4075              : 
    4076            0 :         return DLT_DAEMON_ERROR_UNKNOWN;
    4077              :     }
    4078              : 
    4079              : #if defined(DLT_LOG_LEVEL_APP_CONFIG) || defined(DLT_TRACE_LOAD_CTRL_ENABLE)
    4080              :     DltDaemonApplication *app = dlt_daemon_application_find(
    4081              :         daemon, daemon_local->msg.extendedheader->apid, daemon->ecuid, verbose);
    4082              : #endif
    4083              : 
    4084              :     /* discard non-allowed levels if enforcement is on */
    4085            0 :     bool keep_message = enforce_context_ll_and_ts_keep_message(
    4086              :         daemon_local
    4087              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
    4088              :         , app
    4089              : #endif
    4090              :     );
    4091              : 
    4092              :     // check trace_load
    4093              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    4094              :     keep_message &=
    4095              :         trace_load_keep_message(app, size, daemon, daemon_local, verbose);
    4096              : #endif
    4097              : 
    4098            0 :     if (keep_message)
    4099         5809 :       dlt_daemon_client_send_message_to_all_client(daemon, daemon_local, verbose);
    4100              : 
    4101              :     /* keep not read data in buffer */
    4102         5809 :     size = (int) ((size_t)daemon_local->msg.headersize +
    4103         5809 :         (size_t)daemon_local->msg.datasize - sizeof(DltStorageHeader) +
    4104              :         sizeof(DltUserHeader));
    4105              : 
    4106         5809 :     if (daemon_local->msg.found_serialheader)
    4107              :         size += (int) sizeof(dltSerialHeader);
    4108              : 
    4109         5809 :     if (dlt_receiver_remove(rec, size) != DLT_RETURN_OK) {
    4110            0 :         dlt_log(LOG_WARNING, "failed to remove bytes from receiver.\n");
    4111            0 :         return DLT_DAEMON_ERROR_UNKNOWN;
    4112              :     }
    4113              : 
    4114              : #endif
    4115              : 
    4116              :     return DLT_DAEMON_ERROR_OK;
    4117              : }
    4118              : 
    4119            0 : bool enforce_context_ll_and_ts_keep_message(DltDaemonLocal *daemon_local
    4120              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
    4121              :                                             , DltDaemonApplication *app
    4122              : #endif
    4123              : )
    4124              : {
    4125         5809 :     if (!daemon_local->flags.enforceContextLLAndTS ||
    4126            0 :         !daemon_local->msg.extendedheader) {
    4127              :         return true;
    4128              :     }
    4129              : 
    4130              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
    4131              :     if (app == NULL) {
    4132              :         return true;
    4133              :     }
    4134              : #endif
    4135              : 
    4136            0 :     const int mtin = DLT_GET_MSIN_MTIN(daemon_local->msg.extendedheader->msin);
    4137              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
    4138              :     if (app->num_context_log_level_settings > 0) {
    4139              :         DltDaemonContextLogSettings *log_settings =
    4140              :             dlt_daemon_find_app_log_level_config(app, daemon_local->msg.extendedheader->ctid);
    4141              : 
    4142              :         if (log_settings != NULL) {
    4143              :             return mtin <= log_settings->log_level;
    4144              :         }
    4145              :     }
    4146              : #endif
    4147            0 :     return mtin <= daemon_local->flags.contextLogLevel;
    4148              : }
    4149              : 
    4150              : 
    4151              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    4152              : bool trace_load_keep_message(DltDaemonApplication *app,
    4153              :                              const int size, DltDaemon *const daemon,
    4154              :                              DltDaemonLocal *const daemon_local,
    4155              :                              int verbose)
    4156              : {
    4157              :     bool keep_message = true;
    4158              :     if (app == NULL || !daemon_local->msg.extendedheader) {
    4159              :         return keep_message;
    4160              :     }
    4161              : 
    4162              :     DltMessage* msg = &daemon_local->msg;
    4163              :     const int mtin = DLT_GET_MSIN_MTIN(msg->extendedheader->msin);
    4164              : 
    4165              :     struct DltTraceLoadLogParams params = {
    4166              :         daemon,
    4167              :         daemon_local,
    4168              :         verbose,
    4169              :         app->apid,
    4170              :     };
    4171              : 
    4172              :     DltDaemonContext *context = dlt_daemon_context_find(
    4173              :         daemon,
    4174              :         app->apid,
    4175              :         msg->extendedheader->ctid,
    4176              :         daemon->ecuid,
    4177              :         verbose);
    4178              : 
    4179              : 
    4180              :     if (context == NULL) {
    4181              :         context = dlt_daemon_context_add(
    4182              :             daemon,
    4183              :             app->apid,
    4184              :             msg->extendedheader->ctid,
    4185              :             daemon->default_log_level,
    4186              :             daemon->default_trace_status,
    4187              :             0,
    4188              :             app->user_handle,
    4189              :             "",
    4190              :             daemon->ecuid,
    4191              :             verbose);
    4192              :         if (context == NULL) {
    4193              :             dlt_vlog(LOG_WARNING,
    4194              :                      "Can't add ContextID '%.4s' for ApID '%.4s' in %s\n",
    4195              :                      msg->extendedheader->ctid, app->apid, __func__);
    4196              :             return false;
    4197              :         }
    4198              :     }
    4199              : 
    4200              :     pthread_rwlock_wrlock(&trace_load_rw_lock);
    4201              :     keep_message = dlt_check_trace_load(
    4202              :         context->trace_load_settings, mtin, msg->headerextra.tmsp, size,
    4203              :         dlt_daemon_output_internal_msg, (void *)(&params));
    4204              :     pthread_rwlock_unlock(&trace_load_rw_lock);
    4205              : 
    4206              :     return keep_message;
    4207              : }
    4208              : #endif
    4209              : 
    4210            0 : int dlt_daemon_process_user_message_set_app_ll_ts(DltDaemon *daemon,
    4211              :                                                   DltDaemonLocal *daemon_local,
    4212              :                                                   DltReceiver *rec,
    4213              :                                                   int verbose)
    4214              : {
    4215              :     uint32_t len = sizeof(DltUserControlMsgAppLogLevelTraceStatus);
    4216              :     DltUserControlMsgAppLogLevelTraceStatus userctxt;
    4217              :     DltDaemonApplication *application;
    4218              :     DltDaemonContext *context;
    4219              :     int i, offset_base;
    4220              :     int8_t old_log_level, old_trace_status;
    4221              :     DltDaemonRegisteredUsers *user_list = NULL;
    4222              : 
    4223            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    4224              : 
    4225            0 :     if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
    4226            0 :         dlt_vlog(LOG_ERR,
    4227              :                  "Invalid function parameters used for %s\n",
    4228              :                  __func__);
    4229            0 :         return DLT_RETURN_ERROR;
    4230              :     }
    4231              : 
    4232            0 :     user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
    4233              : 
    4234            0 :     if (user_list == NULL)
    4235              :         return DLT_RETURN_ERROR;
    4236              : 
    4237              :     memset(&userctxt, 0, len);
    4238              : 
    4239            0 :     if (dlt_receiver_check_and_get(rec,
    4240              :                                    &userctxt,
    4241              :                                    len,
    4242              :                                    DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0)
    4243              :         /* Not enough bytes received */
    4244              :         return DLT_RETURN_ERROR;
    4245              : 
    4246            0 :     if (user_list->num_applications > 0) {
    4247              :         /* Get all contexts with application id matching the received application id */
    4248            0 :         application = dlt_daemon_application_find(daemon,
    4249              :                                                   userctxt.apid,
    4250              :                                                   daemon->ecuid,
    4251              :                                                   verbose);
    4252              : 
    4253            0 :         if (application) {
    4254              :             /* Calculate start offset within contexts[] */
    4255              :             offset_base = 0;
    4256              : 
    4257            0 :             for (i = 0; i < (application - (user_list->applications)); i++)
    4258            0 :                 offset_base += user_list->applications[i].num_contexts;
    4259              : 
    4260            0 :             for (i = 0; i < application->num_contexts; i++) {
    4261            0 :                 context = &(user_list->contexts[offset_base + i]);
    4262              : 
    4263            0 :                 if (context) {
    4264            0 :                     old_log_level = context->log_level;
    4265            0 :                     context->log_level = (int8_t) userctxt.log_level; /* No endianess conversion necessary*/
    4266              : 
    4267            0 :                     old_trace_status = context->trace_status;
    4268            0 :                     context->trace_status = (int8_t) userctxt.trace_status;   /* No endianess conversion necessary */
    4269              : 
    4270              :                     /* The following function sends also the trace status */
    4271            0 :                     if ((context->user_handle >= DLT_FD_MINIMUM) &&
    4272            0 :                         (dlt_daemon_user_send_log_level(daemon,
    4273              :                                                         context,
    4274              :                                                         verbose) != 0)) {
    4275            0 :                         context->log_level = old_log_level;
    4276            0 :                         context->trace_status = old_trace_status;
    4277              :                     }
    4278              :                 }
    4279              :             }
    4280              :         }
    4281              :     }
    4282              : 
    4283              :     return DLT_RETURN_OK;
    4284              : }
    4285              : 
    4286            0 : int dlt_daemon_process_user_message_log_mode(DltDaemon *daemon,
    4287              :                                              DltDaemonLocal *daemon_local,
    4288              :                                              DltReceiver *rec,
    4289              :                                              int verbose)
    4290              : {
    4291              :     DltUserControlMsgLogMode userctxt;
    4292              :     uint32_t len = sizeof(DltUserControlMsgLogMode);
    4293              : 
    4294            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    4295              : 
    4296            0 :     if ((daemon == 0) || (daemon_local == 0)) {
    4297            0 :         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_process_log_mode()\n");
    4298            0 :         return -1;
    4299              :     }
    4300              : 
    4301              :     memset(&userctxt, 0, len);
    4302              : 
    4303            0 :     if (dlt_receiver_check_and_get(rec,
    4304              :                                    &userctxt,
    4305              :                                    len,
    4306              :                                    DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0)
    4307              :         /* Not enough bytes received */
    4308              :         return -1;
    4309              : 
    4310              :     /* set the new log mode */
    4311            0 :     daemon->mode = userctxt.log_mode;
    4312              : 
    4313              :     /* write configuration persistantly */
    4314            0 :     dlt_daemon_configuration_save(daemon, daemon->runtime_configuration, verbose);
    4315              : 
    4316            0 :     return 0;
    4317              : }
    4318              : 
    4319            0 : int dlt_daemon_process_user_message_marker(DltDaemon *daemon,
    4320              :                                            DltDaemonLocal *daemon_local,
    4321              :                                            DltReceiver *rec,
    4322              :                                            int verbose)
    4323              : {
    4324              :     uint32_t len = sizeof(DltUserControlMsgLogMode);
    4325              :     DltUserControlMsgLogMode userctxt;
    4326            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    4327              : 
    4328            0 :     if ((daemon == NULL) || (daemon_local == NULL) || (rec == NULL)) {
    4329            0 :         dlt_vlog(LOG_ERR, "Invalid function parameters used for %s\n",
    4330              :                  __func__);
    4331            0 :         return -1;
    4332              :     }
    4333              : 
    4334              :     memset(&userctxt, 0, len);
    4335              : 
    4336            0 :     if (dlt_receiver_check_and_get(rec,
    4337              :                                    &userctxt,
    4338              :                                    len,
    4339              :                                    DLT_RCV_SKIP_HEADER | DLT_RCV_REMOVE) < 0)
    4340              :         /* Not enough bytes received */
    4341              :         return -1;
    4342              : 
    4343              :     /* Create automatic unregister context response for unregistered context */
    4344            0 :     dlt_daemon_control_message_marker(DLT_DAEMON_SEND_TO_ALL, daemon, daemon_local, verbose);
    4345              : 
    4346            0 :     return 0;
    4347              : }
    4348              : 
    4349            2 : int dlt_daemon_send_ringbuffer_to_client(DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
    4350              : {
    4351              :     int ret;
    4352              :     static uint8_t data[DLT_DAEMON_RCVBUFSIZE];
    4353              :     int length;
    4354              : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
    4355              :     uint32_t curr_time = 0U;
    4356              : #endif
    4357              : 
    4358            2 :     PRINT_FUNCTION_VERBOSE(verbose);
    4359              : 
    4360            2 :     if ((daemon == 0) || (daemon_local == 0)) {
    4361            0 :         dlt_log(LOG_ERR, "Invalid function parameters used for function dlt_daemon_send_ringbuffer_to_client()\n");
    4362            0 :         return DLT_DAEMON_ERROR_UNKNOWN;
    4363              :     }
    4364              : 
    4365            2 :     if (dlt_buffer_get_message_count(&(daemon->client_ringbuffer)) <= 0) {
    4366            0 :         dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_DIRECT);
    4367            0 :         return DLT_DAEMON_ERROR_OK;
    4368              :     }
    4369              : 
    4370            4 :     while ((length = dlt_buffer_copy(&(daemon->client_ringbuffer), data, sizeof(data))) > 0) {
    4371              : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
    4372              :         dlt_daemon_trigger_systemd_watchdog_if_necessary(daemon);
    4373              : #endif
    4374              : 
    4375            4 :         if ((ret =
    4376            4 :                  dlt_daemon_client_send(DLT_DAEMON_SEND_FORCE, daemon, daemon_local, 0, 0, data, length, 0, 0,
    4377              :                                         verbose)))
    4378            0 :             return ret;
    4379              : 
    4380            4 :         dlt_buffer_remove(&(daemon->client_ringbuffer));
    4381              : 
    4382            4 :         if (daemon->state != DLT_DAEMON_STATE_SEND_BUFFER)
    4383            0 :             dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_BUFFER);
    4384              : 
    4385            4 :         if (dlt_buffer_get_message_count(&(daemon->client_ringbuffer)) <= 0) {
    4386            2 :             dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_SEND_DIRECT);
    4387            2 :             return DLT_DAEMON_ERROR_OK;
    4388              :         }
    4389              :     }
    4390              : 
    4391              :     return DLT_DAEMON_ERROR_OK;
    4392              : }
    4393              : 
    4394              : #ifdef __QNX__
    4395              : static void *timer_thread(void *data)
    4396              : {
    4397              :     int pexit = 0;
    4398              :     unsigned int sleep_ret = 0;
    4399              : 
    4400              :     DltDaemonPeriodicData* timer_thread_data = (DltDaemonPeriodicData*) data;
    4401              : 
    4402              :     /* Timer will start in starts_in sec*/
    4403              :     if ((sleep_ret = sleep(timer_thread_data->starts_in))) {
    4404              :         dlt_vlog(LOG_NOTICE, "Sleep remains [%u] for starting!"
    4405              :                 "Stop thread of timer [%d]\n",
    4406              :                 sleep_ret, timer_thread_data->timer_id);
    4407              :          close_pipes(dlt_timer_pipes[timer_thread_data->timer_id]);
    4408              :          return NULL;
    4409              :     }
    4410              : 
    4411              :     while (1) {
    4412              :         if ((dlt_timer_pipes[timer_thread_data->timer_id][1] > 0) &&
    4413              :                 (0 > write(dlt_timer_pipes[timer_thread_data->timer_id][1], "1", 1))) {
    4414              :             dlt_vlog(LOG_ERR, "Failed to send notification for timer [%s]!\n",
    4415              :                     dlt_timer_names[timer_thread_data->timer_id]);
    4416              :             pexit = 1;
    4417              :         }
    4418              : 
    4419              :         if (pexit || g_exit) {
    4420              :             dlt_vlog(LOG_NOTICE, "Received signal!"
    4421              :                     "Stop thread of timer [%d]\n",
    4422              :                     timer_thread_data->timer_id);
    4423              :             close_pipes(dlt_timer_pipes[timer_thread_data->timer_id]);
    4424              :             return NULL;
    4425              :         }
    4426              : 
    4427              :         if ((sleep_ret = sleep(timer_thread_data->period_sec))) {
    4428              :             dlt_vlog(LOG_NOTICE, "Sleep remains [%u] for interval!"
    4429              :                     "Stop thread of timer [%d]\n",
    4430              :                     sleep_ret, timer_thread_data->timer_id);
    4431              :              close_pipes(dlt_timer_pipes[timer_thread_data->timer_id]);
    4432              :              return NULL;
    4433              :         }
    4434              :     }
    4435              : }
    4436              : #endif
    4437              : 
    4438           10 : int create_timer_fd(DltDaemonLocal *daemon_local,
    4439              :                     int period_sec,
    4440              :                     int starts_in,
    4441              :                     DltTimers timer_id)
    4442              : {
    4443              :     int local_fd = DLT_FD_INIT;
    4444              :     char *timer_name = NULL;
    4445              : 
    4446           10 :     if (timer_id >= DLT_TIMER_UNKNOWN) {
    4447            0 :         dlt_log(DLT_LOG_ERROR, "Unknown timer.");
    4448            0 :         return -1;
    4449              :     }
    4450              : 
    4451           10 :     timer_name = dlt_timer_names[timer_id];
    4452              : 
    4453           10 :     if (daemon_local == NULL) {
    4454            0 :         dlt_log(DLT_LOG_ERROR, "Daemon local structure is NULL");
    4455            0 :         return -1;
    4456              :     }
    4457              : 
    4458           10 :     if ((period_sec <= 0) || (starts_in <= 0)) {
    4459              :         /* timer not activated via the service file */
    4460            0 :         dlt_vlog(LOG_INFO, "<%s> not set: period=0\n", timer_name);
    4461              :         local_fd = DLT_FD_INIT;
    4462              :     }
    4463              :     else {
    4464              : #ifdef linux
    4465              :         struct itimerspec l_timer_spec;
    4466           10 :         local_fd = timerfd_create(CLOCK_MONOTONIC, 0);
    4467              : 
    4468           10 :         if (local_fd < 0)
    4469            0 :             dlt_vlog(LOG_WARNING, "<%s> timerfd_create failed: %s\n",
    4470            0 :                      timer_name, strerror(errno));
    4471              : 
    4472           10 :         l_timer_spec.it_interval.tv_sec = period_sec;
    4473           10 :         l_timer_spec.it_interval.tv_nsec = 0;
    4474           10 :         l_timer_spec.it_value.tv_sec = starts_in;
    4475           10 :         l_timer_spec.it_value.tv_nsec = 0;
    4476              : 
    4477           10 :         if (timerfd_settime(local_fd, 0, &l_timer_spec, NULL) < 0) {
    4478            0 :             dlt_vlog(LOG_WARNING, "<%s> timerfd_settime failed: %s\n",
    4479            0 :                      timer_name, strerror(errno));
    4480              :             local_fd = DLT_FD_INIT;
    4481              :         }
    4482              : #elif __QNX__
    4483              :         /*
    4484              :          * Since timerfd is not valid in QNX, new threads are introduced
    4485              :          * to manage timers and communicate with main thread when timer expires.
    4486              :          */
    4487              :         if(0 != pipe(dlt_timer_pipes[timer_id])) {
    4488              :             dlt_vlog(LOG_ERR, "Failed to create pipe for timer [%s]",
    4489              :                     dlt_timer_names[timer_id]);
    4490              :             return -1;
    4491              :         }
    4492              :         if (NULL == timer_data[timer_id]) {
    4493              :             timer_data[timer_id] = calloc(1, sizeof(DltDaemonPeriodicData));
    4494              :             if (NULL == timer_data[timer_id]) {
    4495              :                 dlt_vlog(LOG_ERR, "Failed to allocate memory for timer_data [%s]!\n",
    4496              :                          dlt_timer_names[timer_id]);
    4497              :                 close_pipes(dlt_timer_pipes[timer_id]);
    4498              :                 return -1;
    4499              :             }
    4500              :         }
    4501              : 
    4502              :         timer_data[timer_id]->timer_id = timer_id;
    4503              :         timer_data[timer_id]->period_sec = period_sec;
    4504              :         timer_data[timer_id]->starts_in = starts_in;
    4505              :         timer_data[timer_id]->wakeups_missed = 0;
    4506              : 
    4507              :         if (0 != pthread_create(&timer_threads[timer_id], NULL,
    4508              :                             &timer_thread, (void*)timer_data[timer_id])) {
    4509              :             dlt_vlog(LOG_ERR, "Failed to create new thread for timer [%s]!\n",
    4510              :                                      dlt_timer_names[timer_id]);
    4511              :             /* Clean up timer before returning */
    4512              :             close_pipes(dlt_timer_pipes[timer_id]);
    4513              :             free(timer_data[timer_id]);
    4514              :             timer_data[timer_id] = NULL;
    4515              : 
    4516              :             return -1;
    4517              :         }
    4518              :         local_fd = dlt_timer_pipes[timer_id][0];
    4519              : #endif
    4520              :     }
    4521              : 
    4522           10 :     return dlt_connection_create(daemon_local,
    4523              :                                  &daemon_local->pEvent,
    4524              :                                  local_fd,
    4525              :                                  POLLIN,
    4526           10 :                                  dlt_timer_conn_types[timer_id]);
    4527              : }
    4528              : 
    4529              : /* Close connection function */
    4530            5 : int dlt_daemon_close_socket(int sock, DltDaemon *daemon, DltDaemonLocal *daemon_local, int verbose)
    4531              : {
    4532            5 :     char local_str[DLT_DAEMON_TEXTBUFSIZE] = { '\0' };
    4533              : 
    4534            5 :     PRINT_FUNCTION_VERBOSE(verbose);
    4535              : 
    4536            5 :     if ((daemon_local == NULL) || (daemon == NULL)) {
    4537            0 :         dlt_log(LOG_ERR, "dlt_daemon_close_socket: Invalid input parmeters\n");
    4538            0 :         return -1;
    4539              :     }
    4540              : 
    4541              :     /* Closure is done while unregistering has for any connection */
    4542            5 :     dlt_event_handler_unregister_connection(&daemon_local->pEvent,
    4543              :                                             daemon_local,
    4544              :                                             sock);
    4545              : 
    4546            5 :     if (daemon_local->client_connections == 0) {
    4547              :         /* send new log state to all applications */
    4548            3 :         daemon->connectionState = 0;
    4549            3 :         dlt_daemon_user_send_all_log_state(daemon, verbose);
    4550              : 
    4551              :         /* For offline tracing we still can use the same states */
    4552              :         /* as for socket sending. Using this trick we see the traces */
    4553              :         /* In the offline trace AND in the socket stream. */
    4554            3 :         if (daemon_local->flags.yvalue[0] == 0)
    4555            3 :             dlt_daemon_change_state(daemon, DLT_DAEMON_STATE_BUFFER);
    4556              :     }
    4557              : 
    4558            5 :     dlt_daemon_control_message_connection_info(DLT_DAEMON_SEND_TO_ALL,
    4559              :                                                daemon,
    4560              :                                                daemon_local,
    4561              :                                                DLT_CONNECTION_STATUS_DISCONNECTED,
    4562              :                                                "",
    4563              :                                                verbose);
    4564              : 
    4565            5 :     snprintf(local_str, DLT_DAEMON_TEXTBUFSIZE,
    4566              :              "Client connection #%d closed. Total Clients : %d",
    4567              :              sock,
    4568              :              daemon_local->client_connections);
    4569            5 :     dlt_daemon_log_internal(daemon, daemon_local, local_str, DLT_LOG_INFO,
    4570              :                             DLT_DAEMON_APP_ID, DLT_DAEMON_CTX_ID,
    4571              :                             daemon_local->flags.vflag);
    4572            5 :     dlt_vlog(LOG_DEBUG, "%s%s", local_str, "\n");
    4573              : 
    4574            5 :     return 0;
    4575              : }
    4576              : 
    4577              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    4578              : 
    4579              : static DltReturnValue dlt_daemon_output_internal_msg(
    4580              :     const DltLogLevelType loglevel, const char *const text, void* const params) {
    4581              :     struct DltTraceLoadLogParams* log_params = (struct DltTraceLoadLogParams*)params;
    4582              :     return dlt_daemon_log_internal(
    4583              :         log_params->daemon, log_params->daemon_local, (char *)text, loglevel,
    4584              :         log_params->app_id, DLT_TRACE_LOAD_CONTEXT_ID, log_params->verbose);
    4585              : }
    4586              : #endif
    4587              : 
    4588              : 
    4589              : /**
    4590              :  \}
    4591              :  */
        

Generated by: LCOV version 2.0-1