LCOV - code coverage report
Current view: top level - daemon - dlt-daemon.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 27.3 % 1700 464
Test Date: 2026-02-03 07:35:37 Functions: 47.8 % 46 22

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

Generated by: LCOV version 2.0-1