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