LCOV - code coverage report
Current view: top level - daemon - dlt-daemon.c (source / functions) Hit Total Coverage
Test: dlt_final_coverage.info Lines: 606 1152 52.6 %
Date: 2024-11-20 10:17:27 Functions: 31 42 73.8 %

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

Generated by: LCOV version 1.14