LCOV - code coverage report
Current view: top level - daemon - dlt-daemon.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 26.9 % 1708 460
Test Date: 2026-10-08 05:11:40 Functions: 46.8 % 47 22

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

Generated by: LCOV version 2.0-1